Skip to content

Instantly share code, notes, and snippets.

@Aeldrion
Last active September 8, 2021 12:00
Show Gist options
  • Save Aeldrion/419e3da12666280cbfd2dabf567dc36c to your computer and use it in GitHub Desktop.
Save Aeldrion/419e3da12666280cbfd2dabf567dc36c to your computer and use it in GitHub Desktop.
How not to use the execute command

How not to use execute

A guide for Minecraft: Java Edition 1.13+ commands


This is a summary of unnecessary additions or misconceptions I often see when players attempt to use the execute command in Minecraft: Java Edition. These additions often make commands less readable, more confusing, less efficient and show that the coder doesn't always fully understand what they are working with.

as @s

The as subcommand redefines who is running the command. This affects things like whose name appears if a say command runs. More importantly, it redefines @s as the targeted entity (or entities, one by one, if the selector targets multiple entities). as @s means "I want the entity who is currently executing this command to execute this command". It does absolutely nothing, unless there is no executing entity in the first place, in which case it stops the command, which can be achieved using if entity @s anyway.

I have also seen people using as @s with additional target selector arguments, e.g. as @s[gamemode=creative]. This will only continue the command if the current executing entity verifies these arguments. This should be avoided, as if entity @s[...] is the intended subcommand for this situation. Though it is longer to write, it is both more understandable to other readers and more efficient.

positioned ~ ~ ~

This one is no different than the previous remark: you're trying to define a parameter to what it already is. Here the executing position is set to the current executing position. This is redundant and should be omitted.

run execute

execute subcommands can be chained within a single execute command before run is specified.

execute as @a run execute at @s run execute if entity @e[type=minecraft:cow, distance=..3] run say Hi!
# can be simplified into
execute as @a at @s if entity @e[type=minecraft:cow, distance=..3] run say Hi!

run execute can systematically be removed from any command without any effect on functionality. Likewise, execute run without any subcommands is useless and should be omitted.

as @e at @s, but position is irrelevant

Oftentimes people use the at subcommand when position is not being used in the command itself or in later execute subcommands. For example:

execute as @e[type=minecraft:creeper] at @s run data modify entity @s ExplosionRadius set value 0s

The at @s subcommand could be completely omitted without loss of functionality. If anything, it would make the command faster to run. Only use at if you actually need to use the entity's position, for example if you are targetting an entity based on distance, or if you want to place blocks or produce particles nearby:

# This command does not require position information
execute as @e[type=minecraft:creeper] run data modify entity @s ExplosionRadius set value 0s

# These commands require position information
execute as @a[scores={deaths=1..}] at @s if block ~ ~-1 ~ minecraft:stone run setblock ~ ~-1 ~ minecraft:grass_block
execute as @e[type=minecraft:iron_golem] at @s if entity @e[type=minecraft:zombie, distance=..3] run kill @s
execute as @e[type=minecraft:chicken] at @s run particle minecraft:flame ~ ~ ~ 0.2 0.2 0.2 0 10 force

as @e at @s, but changing the executing entity is irrelevant

Another error I see often is systematically using as to target an entity's position before using at @s, instead of using at directly. I usually interpret this as an attempt to translate Bedrock's execute command, or Java's old execute command, to the current syntax. As a reminder, as is only useful when you need to define the executing entity, and target it later with @s for example. at is only useful when you need to run commands at entity's position specifically. You don't need both when the only thing that is relevant to your command is where it runs, for example for placing blocks, summoning entities, targeting nearby entities, playing particles or sound effects, etc.

Let's take the last command from the previous block for example:

execute as @e[type=minecraft:chicken] at @s run particle minecraft:flame ~ ~ ~ 0.2 0.2 0.2 0 10 force

Nothing is targeting the chicken itself after the first as subcommand. as is unneeded here:

execute at @e[type=minecraft:chicken] run particle minecraft:flame ~ ~ ~ 0.2 0.2 0.2 0 10 force

if entity, but you're trying to target the entities you've been testing for immediately after

Some command writers want to make sure that the entities they are targeting in a command do exist before running said command. This often leads to very long commands with redundant information and unnecessary checks:

execute if entity @a[nbt={SelectedItem: {id: "minecraft:feather"}}] as @a[nbt={SelectedItem: {id: "minecraft:feather"}}] run ...
execute at @a if entity @e[type=minecraft:skeleton, distance=..5, name=Hi, predicate=foo:bar, scores={example=4}, nbt={HandItems: [{id: "minecraft:bow"}]}] run kill @e[type=minecraft:skeleton, distance=..5, name=Hi, predicate=foo:bar, scores={example=4}, nbt={HandItems: [{id: "minecraft:bow"}]}]

At best, no one is targeted by the first entity selector, and nothing changes at all. At worst, someone is targeted by the first entity selector, and then the command proceeds to check for the entire NBT data of every player in the world, twice. This also makes commands much longer than they should be. It is especially difficult to deal with when you have tag checks, score checks and predicate checks that add up in two similar entity selectors in the same command, in which case everything you modify in one selector also has to be modified in the other selector.

Don't test that the entity exists, directly target it. If it doesn't, don't worry, the command will error out silently and won't mess with anything:

execute as @a[nbt={SelectedItem: {id: "minecraft:feather"}}] run ...
execute at @a run kill @e[type=minecraft:skeleton, distance=..5, name=Hi, predicate=foo:bar, scores={example=4}, nbt={HandItems: [{id: "minecraft:bow"}]}]

as @e at @e

This one most of the time comes from a misunderstanding of how both of these subcommands operate. When you do execute as @e ..., the command (or the remaining subcommands) are ran independently for each entity that is being targeted. For example:

execute as @e run say Hi

will run the command say Hi as many times as there are entities in the world. Imagine that every time you do as @e, each entity corresponds to a branch in a tree. These branches can branch out in many more branches if you have another subcommand that targets multiple entities (i.e. as ..., at ..., rotated as ... or positioned as ...). At the end of every branch is a command. With enough entities in your world, two @e selectors in the same execute command will result in a big fat chonky tree that will probably crash your game.

If you have a thousand entities in your world, for example

execute as @e at @e run say Hi!

will run a million commands (I wouldn't recommend it). If the command itself has an @e selector:

execute as @e at @e run teleport @e ~ ~1 ~

it will try to target one thousand entities one million times, which takes a few billion operations. Use @s when you need it:

execute as @e at @s run say Hi!
execute as @e at @s run teleport @s ~ ~1 ~

(note that the first command doesn't need at @s here as previously pointed out).

The same applies, of course, to @a selectors or @e selectors with target selector arguments.

in, because you don't understand what it does

I have also met several users who couldn't get their commands working because they were using execute in to try to check in what dimension the command is running in, or to check in what dimension a player is in. execute in is not testing anything: it is setting in what dimension the command will run. To check for the current dimension, or to target entities in a specific dimension, you should use predicates:

// data/mypack/predicates/in_end.json
{
  "condition": "minecraft:entity_properties",
  "entity": "this",
  "predicate": {
    "dimension": "minecraft:the_end
  }
}
execute as @a[predicate=mypack:in_end] run say I am in the end

Or you can use distance checks within the current dimension:

execute in minecraft:the_end as @a[distance=0..] run say I am in the end

Equally confusing, sometimes people use execute if entity ... in <dimension> to test that an entity is in a dimension. What this actually does is test if the targeted entity does exist, then change the dimension in which the command should run.

as @e, but the command after that can already target multiple entities

There are many commands that cannot operate on several entities at the same time, for example data. In this case, it is necessary to use execute as before and to target each entity with @s in the command itself. For example:

execute as @e[type=minecraft:creeper] run data modify entity @s ExplosionRadius set value 0s

This is fortunately not the case for every single command, but nonetheless many people use execute as in the same way when it isn't needed. Again, this makes the command longer, less readable and less efficient.

execute as @a run scoreboard players reset @s deaths
# can be simplified into
scoreboard players reset @a deaths
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment