Class Draw

java.lang.Object
com.botwithus.bot.api.draw.Draw
All Implemented Interfaces:
DrawTarget

public final class Draw extends Object implements DrawTarget
Debug-drawing facade. Singleton per GameAPI; obtain via api.draw().
Draw draw = api.draw();
draw.rect("target-box", x, y, w, h).color(Colors.GREEN).thickness(2).ttl(1200).submit();
draw.component("inv-slot", 1473, 5).color(Colors.CYAN).submit();
draw.npc(npc).color(Colors.RED).label(name).submit();   // follows the NPC
draw.clear("target-box");

try (DrawFrame frame = draw.frame()) {      // one round-trip on close
    frame.line("a", 0, 0, 100, 100).submit();
    frame.text("b", 10, 20, "hello").submit();
}

Use frame() for anything more than a couple of commands a tick. Each DrawBuilder.submit() straight off this facade is its own round-trip; twenty primitives a tick over twenty round-trips is not a reasonable thing to do to the pipe. A frame collapses the primitives into one debug_draw_set_batch. Highlights stay one call each wherever they are submitted — no batch on this wire can carry one — so a frame saves nothing on those; see DrawFrame.flush().

Marking something that moves is a highlight, not a rect. DrawTarget.npc(com.botwithus.bot.api.snapshot.Npc) and its siblings send the producer's semantic highlights, which re-resolve the thing they mark every tick — so the box follows a walking NPC and sits at its real height. A world-space rect at the same tile looks identical on the first frame and is wrong on the second.

Keys are the identity here — there is no handle to leak and nothing to free. They are scoped to this connection, so two scripts on two clients may both use "target-box"; a long-lived script that reuses a key carelessly can still stomp its own drawings, which is the only collision that exists.

  • Constructor Details

  • Method Details

    • submit

      public String submit(DrawCommand command)
      Route a fully-built command, answering the key it is stored under.

      The plumbing seam the fluent builders call, and the escape hatch for a caller holding a DrawCommand it built or stored itself.

      One round-trip. A command the producer refuses raises the transport's unchecked RPC error, carrying the producer's message — unlike a batched submit, which reports refusals as a count. The two failure shapes differ because the wire's do.

      Which method carries it is decided here, by type. This is the one place the two families of DrawCommand meet a wire call, and it is an exhaustive switch rather than a flag so a third family could not be added without this seam being told about it.

      Specified by:
      submit in interface DrawTarget
    • frame

      public DrawFrame frame()
      Open a batch. Every command submitted to the returned frame is held until it is flushed or closed, and then sent as one debug_draw_set_batch — plus one highlight_* call per highlight, which no batch can carry.

      Use it in try-with-resources; closing flushes. A frame carrying more than DrawLimits.MAX_BATCH_ITEMS primitives is split across the fewest whole batches that will hold it rather than truncated or refused — see DrawFrame.flush(), which also states exactly what is applied when a flush fails part-way.

    • clear

      public int clear(String... keys)
      Remove the named commands, answering how many went. Unknown keys are not an error.
    • clear

      public int clear(List<String> keys)
      Remove the named commands, answering how many went.
    • clearAll

      public int clearAll()
      Remove everything this connection drew, answering how many went. Never touches another client's drawings.
    • list

      public List<DrawEntry> list()
      Every command this connection currently holds.

      Costs one round-trip per 128 retained commands. DrawEntry.remainingTtlMs() is time left, not the TTL you sent.

    • isEnabled

      public boolean isEnabled()
      Whether the producer is currently drawing at all.
    • setEnabled

      public boolean setEnabled(boolean enabled)
      Switch drawing on or off, answering the state that took effect. This is process-wide on the producer, not per connection: turning it off hides every client's drawings, not only this script's.
    • stats

      public DrawStats stats()
      The producer's overlay counters and renderer health. The place to look when a command was accepted but nothing appeared — see DrawStats.