Skip to content

Instantly share code, notes, and snippets.

@timraay
Created August 15, 2022 21:45
Show Gist options
  • Save timraay/8c9e463b06235e684b7d239f8c0340d3 to your computer and use it in GitHub Desktop.
Save timraay/8c9e463b06235e684b7d239f8c0340d3 to your computer and use it in GitHub Desktop.
Guide to understanding the new Bedrock /execute command syntax

Complete /execute tutorial


As of Bedrock v1.19.10 a new /execute command is now available through the Additional Creator Features experimental toggle. Just like when Java edition first got this new syntax back in the Aquatic Update, it caused some trouble, because it introduces some new concepts and changes the way you should be using /execute.

This guide aims to explain these concepts to you, allowing you to easily adapt to the changes and use them to their fullest potential. Readers are expected to have some basic knowledge of the old /execute syntax.


DISCLAIMER: The new /execute syntax is currently an experimental feature and will likely be expanded in future updates. This guide on the other hand might not. This guide was last updated at 15/08/2022.


Navigation


Command Context

What is context?

Context is information passed to each command behind the scenes. For instance, whenever you use relative coordinates (~ or ^), it will take the position and rotation that is stored within the command's context to calculate the resulting coordinates.

By default, a command's context is inherited from the executor. Are you executing a command from chat? It will take your position and rotation. Are you executing from a command block? It uses the block's position instead (and the rotation will be x0 y0).

Modifying context

The /execute command's primary purpose has always been to allow users to modify this context. Let's have a look at the below commands using the old /execute syntax, and assume they are all ran by command blocks:

# Summon a creeper at the CMD block
/summon creeper ~ ~ ~
# Summon a creeper at every player
/execute @a ~ ~ ~ summon creeper ~ ~ ~
# Summon a creeper at 0,0,0 for every player in the world
/execute @a 0 0 0 summon creeper ~ ~ ~

In both the 2nd and 3rd command, we essentially tell the game to run a /summon command for every player, either at their location, or in case of the 3rd command at 0,0,0. In both cases, it runs new commands at a different location than the original.

The executor @s

We know both position and rotation are stored inside context, but so is the "executor". The executor is the entity running the command (if applicable), but using /execute it can (and will) be changed.

The current executor can always be targeted with the @s variable. Opposed to the otherwise commonly used @p or @e[c=1], this is a more safe and most importantly performant way to select targets.

# Bad
/execute @a ~ ~ ~ say @p
                      ^^
# Good
/execute @a ~ ~ ~ say @s

Both commands will do the same (unless of an unlikely case where right after teleporting multiple player the nearest player won't always be the player itself), but the thing to take away is that when we start using the new /execute syntax you can no longer avoid @s. On top of that, it performs better, makes your code easier to understand, and is more convenient to write.

NOTE: Context is preserved when calling functions. If you call a function, all of the context used for calling that function will be applied to every command inside that function.

The new /execute command

The new /execute command gives the user better control over which context to keep and replace. It is still able to do everything the old command is capable of however. If you wanted to replicate its behavior, it would look like this:

# Old syntax
/execute @a ~ ~-1 ~ detect 0 0 0 bedrock 0 setblock ~ ~ ~ stone
# New syntax
/execute as @a at @s positioned ~ ~-1 ~ if block 0 0 0 bedrock 0 run setblock ~ ~ ~ stone

Now, this seems like a mouthful. Fear not however, most likely your commands won't all have to look like this from on.

Dynamic structure

The beauty of this new syntax is that you get to choose over which "components" you need. You can put them in whatever order you need, and use them multiple times. The below commands are all completely valid.

# Set a block at each player's location
/execute at @a run setblock ~ ~ ~ stone
# If the block 10 blocks below the nearest player's location is bedrock, summon a creeper at each player's location
/execute at @p if block ~ ~-10 ~ bedrock 0 at @a run summon creeper ~ ~ ~

Changing the executor

Using the as <target> component you can change the command's executor. This changes whichever entity @s references to.

# Have each player say their own name
/execute as @a run say @s

Changing the position and rotation

Using the at <target> component you can change the command's position and rotation to match that of an entity.

# Place a block below each player's feet
/execute at @a run setblock ~ ~-1 ~ stone

WARNING: You will commonly combine as and at. It is essential you understand how to use the @s selector for this. Running /execute as @a at @p is NOT the same as /execute as @a at @s and will yield unwanted behavior.

Another option is positioned as <target>, which changes the position but leaves the rotation as-is.

# Place a block at each player's location, one meter into the direction the player closest to the CMD block was facing.
/execute at @p positioned as @a run setblock ^ ^ ^1

NOTE: At the moment you rarely ever will need to use positioned as <target>, due to the lack of any meaningful components to change the rotation only. Java Edition also has rotated ... and facing ... components which can be used to change rotation in various ways, which I suspect and hope will soon make their way into Bedrock soon.

Using positioned <coords> you can change the the position without having to reference an entity.

# Summon a creeper 10 blocks above the CMD block
/execute positioned ~ ~10 ~ run summon creeper ~ ~ ~

Adding conditions

The new syntax also adds various new ways to add implement conditions into your commands, which may very well be the most exciting thing about this new syntax. We'll have a deep dive into these in the following section.

Running a command!

Once you've added all the components you need, you can add the run <command> component and it will run that command. This is generally the last in your chain of components, but it is not required, which might be useful if you want to detect the output of certain conditions through a chain command block.

Conditions in commands

A condition is nothing more than a term that has to be validated before the command can be ran. There are several ways you could do this:

  • With target selectors:
    # NOTE: Old execute syntax
    /execute @a[scores={test=1}] ~ ~ ~ say I have a test score of 1!
  • Using the (old) /execute's detect keyword:
    # NOTE: Old execute syntax
    /execute @a ~ ~ ~ detect ~ ~-1 ~ bedrock 0 say I am standing on bedrock!
  • With conditional command blocks.

None of these are very convenient however, and often bring unwanted side effects, like having to add /execute in front of your command, which then changes the context again. Let's say you want each player that does NOT have a creeper within 10 blocks them to say a message in chat:

# Correct but inconvenient. Requires extra commands.
/execute @e[type=creeper] ~ ~ ~ tag @a[r=10] add hasCreepersNearby
/execute @a[tag=!hasCreepersNearby] ~ ~ ~ say There are no creepers nearby!
/tag @a remove hasCreepersNearby

The issue really is that the old /execute command does multiple things, even when you don't want it to do all of them.

There are some commands like /testforblocks that are essentially conditions, but they require a conditional command block to capture the result of that condition, which when using functions also isn't ideal.

Conditions in the new /execute command

Since the old command was always used to evaluate conditions, it only makes sense that the new command enhances that capability and improves on the previous limitations. It does so with the following two components, if ... and unless .... Both work the same, with the only difference being that unless ... checks if the condition is false instead of true.

Validating whether an entity exists

Using if entity <target> you can check if an entity exists without having to change context or invoke a certain command.

# Send a message if a creeper is found
/execute if entity @e[type=creeper,c=1] run say There's a creeper somewhere!

Validating whether a block is at location

Using if block <coords> <identifier> (<data>|<blockstates>) you can check if a block exists at a specific position. Its arguments are identical to that of the /testforblock command.

# Have a player send a message when they stand on bedrock
/execute as @a at @s if block ~ ~-1 ~ bedrock 0 run say I'm standing on bedrock!

Validating whether a region of blocks matches another

Using if blocks <corner1> <corner2> <source> (masked|all) you can check if an area of blocks matches those of another area. Its arguments are identical to that of the /testforblocks commands.

# Have each player who stands on the same block as the one that's on 0,0,0 send a message
/execute as @a at @s if blocks ~ ~-1 ~ ~ ~-1 ~ 0 0 0 all run say I'm standing on the same block that's on 0,0,0!

Validating whether a score is a certain value

Using if score ... you can check and compare scores in various ways. These bring some massive improvements, especially if you're using functions:

  • You can test scores of so-called "fake players" (previously required conditional CMD blocks), which improves your code in various ways.
  • You can easily compare scores between entities (previously required multiple scoreboard operations).

If you want to compare an existing value to a predefined range of values, you can use if score <name> <scoreboard> matches <range>.

# Setup
/scoreboard objectives add kills dummy
/scoreboard players set team1 kills 15

# Send a message if team 1 has 10 or more kills
/execute if score team1 kills matches 10.. run say Team 1 has 10 or more kills!

We can also compare it to another score using if score <name> <scoreboard> <operator> <name> <scoreboard>.

# Setup
/scoreboard objectives add kills dummy
/scoreboard players set team1 kills 15
/scoreboard players set team2 kills 12

# Send a message if team 1 has 10 or more kills
/execute if score team1 kills > team2 kills run say Team 1 has more kills than team 2!

Bad practices

  • Putting another execute command after a run statement. Redundant.
    # Bad
    /execute as @a run execute at @s run summon creeper ~ ~ ~
                   ^^^^^^^^^^^
    # Good
    /execute as @a at @s run summon creeper ~ ~ ~
  • Using the run component immediately after /execute. Redundant.
    # Bad
    /execute run say Hihi
    ^^^^^^^^^^^^
    # Good
    /say Hihi
  • Using as @s. If you need to check if the executor is an entity, use if entity @s instead. Redundant otherwise.
    # Bad
    /execute as @s run say I am not a command block or function!
             ^^^^^
    # Good
    /execute if entity @s run say I am not a command block or function!
  • Using @p or @e[c=1] as a substitute to @s. Leads to worse performance and makes your code harder to both read and write.
    # Bad
    /execute at @a if score @p test matches 10.. run setblock ~ ~-1 ~ stone
                            ^^
    # Good
    /execute as @a at @s if score @s test matches 10.. run setblock ~ ~-1 ~
    
    # Best
    /execute at @a[scores={test=10..}] run setblock ~ ~-1 ~
  • Not using fake players for global storage. Leads to worse performance and makes your code harder to both read and write.
    # Bad
    /execute if score @e[type=armor_stand,name=team1] kills matches 10..
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    # Good
    /execute if score team1 kills matches 10..
  • Using the same argument selectors and context-changing components repeatedly. Depending on the scale can lead to significantly worse performance.
    # Bad
    /execute as @a run function foo/bar
    # -- Function foo/bar.mcfunction
    /execute at @s[tag=myTag,scores={kills=10..,lives=1}] run setblock ~ ~ ~ wool 1
    /execute at @s[tag=myTag,scores={kills=10..,lives=2}] run setblock ~ ~ ~ wool 2
    /execute at @s[tag=myTag,scores={kills=10..,lives=3}] run setblock ~ ~ ~ wool 3
    /execute at @s[tag=myTag,scores={kills=10..,lives=4}] run setblock ~ ~ ~ wool 4
    /execute at @s[tag=myTag,scores={kills=10..,lives=5}] run setblock ~ ~ ~ wool 5
             ^^    ^^^^^^^^^         ^^^^^^^^^^
    # Good
    /execute as @a[tag=myTag,scores={kills=10..}] at @s run function foo/bar
    # -- Function foo/bar.mcfunction
    /execute if score @s lives matches 1 run setblock ~ ~ ~ wool 1
    /execute if score @s lives matches 2 run setblock ~ ~ ~ wool 2
    /execute if score @s lives matches 3 run setblock ~ ~ ~ wool 3
    /execute if score @s lives matches 4 run setblock ~ ~ ~ wool 4
    /execute if score @s lives matches 5 run setblock ~ ~ ~ wool 5

Documentation

Minecraft: Bedrock Edition Creator Documentation

Fandom Minecraft Wiki Documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment