-
Notifications
You must be signed in to change notification settings - Fork 2
Control Flow
This page encompasses all the fun things normally associated with programming: loops, if statements, and more.
Many control flow elements rely on boolean checks. An important prerequisite for this section is variables. Boolean checks are a subset of operations, so they can access the same variables and can't have numbers on the left. The following operations are supported:
-
=
-- equal -
!=
-- not equal -
<
-- less than -
>
-- greater than -
<=
-- less than or equal to -
>=
-- greater than or equal to
In addition, you can check if a variable is in a range using x in 1..10
. If one end of the range is open, this is equivalent to a <=
or >=
. There is currently no way to check if a variable is not in a range.
The most basic check, the if statement compiles to an execute command. If the body of the if statement is more than one line, it extracts it into another function and calls that function in the if statement.
Minescript uses the unless
subcommand of execute
to make all supported boolean checks work for constant values.
if x >= 1 { ... }
if x > 1 { ... }
if y <= x { ... }
if x in 1..10 { ... }
if y != 1 { ... }
execute if score %x dummy matches 1.. run ...
execute unless score %x dummy matches ..1 run ...
execute if score %y dummy <= %x dummy
execute if score %x dummy matches 1..10 run ...
execute unless score %y dummy matches 1 run ...
Just like in commands, minescript allows you to invert boolean checks using the unless
keyword. Minescript takes care of any double negatives that might show up do to how it handles certain checks.
unless x >= 1 { ... }
unless x > 1 { ... }
execute unless score %x dummy matches 1.. run ...
execute if score %x dummy matches ..1 run ...
Loops are a powerful tool, but sadly, Minecraft doesn't make them easy to use. Loops can quickly increase the number of commands being run. If this gets too high, it could cause undefined behavior as loops are stopped in the middle of running and intermediate steps to functions are left unfinished.
When the while loop is called, it checks the given condition and enters a separate function containing the loop's body. The last command in this function checks the condition again and restarts the function if the check succeeds.
x = 0;
while x <= 10 {
x++;
}
main function:
scoreboard players set %x dummy 0
execute if score %x dummy matches ..10 run function datapack:auxiliary
auxiliary:
scoreboard players add %x dummy 1
execute if score %x dummy matches ..10 run function datapack:auxiliary
This loop is identical to the while loop, except the condition is not checked the first time the loop body is called. You can create this loop either of two ways:
do while x < 10 {
...
}
do_while x < 10 {
...
}
This loop is identical to the while loop, except the condition is inverted just like in an unless
statement. There is also a do
variant that doesn't check the condition the first time the loop is called.
This loop only allows the x in range
format. It initializes the variable and handles the incrementing for you;
for x in 1..10 {
...
}
is equivalent to
x = 1
do while x in 1..10 {
x++
...
}
The For Loop doesn't make any guarantees about namespace collisions; If the body of your loop, including function calls and inner loops, has any affect on the variable used in the loop, it could disrupt the loop. If you set the variable of the loop to
_
, the compiler will replace it with a hash unique to your loop.
For multiple if statements in sequence, it may be more idiomatic to use a switch statement. In the following example, switch
makes code more readable.
function random_flower_a {
@rand flower_type in 0..2
if flower_type = 0 { @raw "setblock ~ ~1 ~ dandelion" }
if flower_type = 1 { @raw "setblock ~ ~1 ~ poppy" }
if flower_type = 2 { @raw "setblock ~ ~1 ~ blue_orchid" }
}
function random_flower_b {
switch @rand 0..2 {
case 0 { @raw "setblock ~ ~1 ~ dandelion" }
case 1 { @raw "setblock ~ ~1 ~ poppy" }
case 2 { @raw "setblock ~ ~1 ~ blue_orchid" }
}
}
These two examples effectively compile to the same code, except the variable name in the second function is obfuscated. Unlike switch
statements in some other languages, minescript doesn't "short-circuit"
Not all control flow elements use the boolean check. Some use other formats built into minecraft's execute
command.
if @s[type=cow] { ... }
unless @s[type=cow] { ... }
These compile to simple execute commands:
execute if entity @s[type=cow] run ...
execute unless entity @s[type=cow] run ...