Skip to content

Control actions

Loops, branches, error handling, routines, signals between clients, and stopping.

Twelve actions that decide what runs, what stops, and how clients of one account talk to each other.

Three limits apply across this page. Nesting of loops and branches is capped at 10 levels deep. A while runs at most 1000 iterations unless you raise maxIterations. And every firing has a total action budget, so a loop cannot run forever even if its condition never turns false. When the budget runs out the firing stops with the warning "stopped after 1000 steps (the per-run limit)" and the step fails.

repeat

Runs a block of actions a fixed number of times.

FieldTypeRequiredNotes
countinteger, 1–1000noNumber of passes. See the warning below.
childrenarray of actions, max 200yesThe body.

Inside the body, {{round}} is the current pass (1-based) and {{round0}} the same 0-based.

repeat 8 times
dig nearest wheat within 16 blocks, 1 time(s)
log harvest pass {{round}}

Omitting count means one pass, not "forever". The editor always writes a count, so this only comes up if you drive the API directly, and the worker logs a warning when it has to make that assumption.

while

Runs a block for as long as a condition holds.

FieldTypeRequiredNotes
condconditionyesRe-tested before each pass.
childrenarray of actions, max 200yesThe body.
maxIterationsinteger, 1–10000noDefault 1000. A hard safety cap.
while test free slots more than 2 (max 500x)
dig nearest stone within 8 blocks, 1 time(s)

A loop that reaches maxIterations while its condition still holds stops there, warns in the console and counts as a failed step.

if

Runs one block or another depending on a condition.

FieldTypeRequiredNotes
condconditionyesThe test.
thenarray of actions, max 200yesRuns when the condition holds.
elsearray of actions, max 200noRuns when it does not.
if test has item cooked_beef
notify owner: food in the bag
else
notify owner: no food left

try

Runs a block, and at the first action in it that fails, stops the block and runs a fallback block instead.

FieldTypeRequiredNotes
bodyarray of actions, max 200yesWhat to attempt.
onFailarray of actions, max 200noWhat to do when it fails.
try
open container nearest container x y z · radius 6
put by name x 0 into container — all of it ☑
else on failure
notify owner: no chest in reach

"Fails" covers both a hard error and a step that reports it could not do its job, such as a container action with no window open, or a wait_until that timed out with failOnTimeout. The steps after the one that failed do not run, also when it failed inside a loop or an if in the body. For a single central alert instead of a try around everything, use the flow_error trigger.

To the step after it, the whole try is one step. It counts as failed when onFail ran and its last step failed, or when the body failed and there is no onFail. A try whose onFail recovered counts as a success, so last_action_failed right after it is not set. A try inside another try that ends failed stops the outer body too.

break

Leaves the nearest enclosing repeat or while early.

No fields.

while test it is daytime (in game) (max 1000x)
if test health below 8
break out of loop
attack nearest hostile mob

Outside a loop it does nothing: the flow goes on, the step does not count as a failure (a try around it does not run its fallback), and the console notes it once per run. It exits one loop, not all of them. To end the whole firing, use stop_flow.

call_routine

Runs the actions of a routine trigger in the same flow, then continues.

FieldTypeRequiredNotes
nameroutine nameyes[a-z0-9_]{1,40}. Must match a routine trigger in this flow.
run routine stow

The unit of reuse: write a login sequence or a "dump into the chest" block once and call it from several triggers. A routine that calls itself is a stack, not a loop: recursion is capped at runtime, and the firing's action budget still applies.

stop_flow

Ends this firing and leaves the client online.

No fields.

if test players online at most 1
stop this flow run

The middle option of the three: break leaves one loop, stop_flow ends the firing, stop_client disconnects.

cancel_goal

Ends every goal the client is working on, such as obtain or farm. Each one fails with "cancelled", and none of them resumes.

No fields.

on chat matching ^!halt$
cancel running goals

This is the hard stop. stop_moving only pauses a goal: it holds where it is until the next movement or goal step has run, then carries on. stop_flow and stop_client also end every goal.

stop_client

Stops the client entirely. It disconnects and gives its plan slot back.

No fields.

on health below 4
stop client

A stop fires the before_stop trigger first, so a "dump into a chest before going" flow still runs. Restarting the client is then a manual action, or a schedule.

reconnect

Disconnects and connects again.

No fields.

on kicked
wait 30 seconds
reconnect

The client already reconnects on its own after an unexpected disconnect. Use this when you want a reconnect on your own terms, to clear a stuck server-side state, or to rejoin a queue.

The rest of the flow does not run after it, even from inside a loop: reconnect ends the firing, then the client reconnects.

signal

Tells the account's other clients something. Only clients whose flow is listening react.

FieldTypeRequiredNotes
channellowercase name, [a-z0-9_]{1,40}yesWhat it is about: raid, regroup, ready.
messagestring, up to 256 charsnoFree text for the listeners. Variables are expanded, as in chat.
toarray of client names, max 50noOnly these clients. Leave out for every listener.
reachworld | server | accountnoDefault world. See below.
send signal raid message come here

A listener is a client whose flow has an on signal trigger or a wait_signal step for that channel. Every other client ignores the signal without a trace, not even a console line.

reach picks who can hear:

  • world: clients in the sender's actual world, the same server and the same dimension.
  • server: clients on the same server address, on any backend or in any dimension.
  • account: every running client of the account.

A signal never leaves the account that owns the sending client, and clients shared into your account with you never receive it. to uses client names, case does not matter, and a name reaches every client that has it.

Limits: 2 signals a second and 60 a minute per sending client. Over that, the step fails and nothing is sent. Signals are events, not state: a client that starts after one never sees it.

Known limits:

  • reach: server spans every backend of a Bungee or Velocity network, since they share one address. Use world to keep a signal to one backend.
  • reach: world tells worlds apart by the world's seed and dimension. Before game version 1.15 there is no seed, so it falls back to server address and dimension. Two backends cloned from the same world count as one world.

In Try it no real signal is sent; the step is only described.

wait_signal

Waits until other clients have sent a signal. The rendezvous.

FieldTypeRequiredNotes
channellowercase name, [a-z0-9_]{1,40}yesWait for this channel.
countinteger, 1–50noDefault 1. Wait until this many different clients have signalled.
fromarray of client names, max 50noOnly count these senders.
timeoutMsinteger, 1000–600000noDefault 30000.
failOnTimeoutbooleannoOff by default, as on wait_chat.
wait for signal ready from 5 client(s)

The count is of different clients: one client sending three times counts once. Signals that arrived before the step started do not count, so the wait begins when the step does. The last signal's details land in {{signal_from}}, {{signal_message}}, {{signal_x}}, {{signal_y}}, {{signal_z}} and {{signal_dimension}}. In Try it the step resolves as if the full count arrived.

Example: a group attack

One leader calls the others; every listener walks to the leader, fights, and reports back. Clients with no signal trigger do nothing.

on hostile mob within 20 blocks
send signal raid message reach world
while test hostile mob near 20 (max 1000x)
try
attack nearest mob · chase on within 20 blocks
else on failure
wait 250 milliseconds
on signal raid only from clients leader
go to at coords x {{signal_x}} y {{signal_y}} z {{signal_z}}
while test hostile mob near 20 (max 1000x)
try
attack nearest mob · chase on within 20 blocks
else on failure
wait 250 milliseconds
send signal ready message reach world

The first trigger goes on the client named leader; the second on the others.

Example: a rendezvous

The leader waits for five clients to report ready, then tells them all to go.

when run manually or by webhook
wait for signal ready from 5 client(s) · give up after 60 seconds
send signal push message reach world