Minecraft Blogs / Tutorial

Function Data Packs for Dummies #8 | The Command Environment (/execute)

  • 7,317 views, 1 today
  • 28
  • 10
  • 7
Bertiecrafter's Avatar Bertiecrafter
Retired Moderator
Level 70 : Legendary Engineer
778
This series of tutorials will teach you how to create your very own data packs, assuming you know absolutely nothing about commands. Although data packs could just contain files that replace built-in assets like resource packs, these posts will focus on adding new features and mechanics to the game. In every part I assume you've read the previous parts.

What is the Command Environment?

If you would run "/tp ~ ~ ~5", the actual execution is influenced by many variables.
- Player(s) to teleport = You
- Starting position = Your position (This is used to calculate the destination coordinates.)
- Starting rotation = Your rotation (The head rotation remains the same when you teleport.)
- Dimension = Your dimension (The destination dimension matches the starting dimension.)

According to the single mention on the entire wiki page, the officialish term for these variables is "Command Variables".
In programming, these kind of variables are called "Environment Variables". The piece of software that runs (compiled) code is often called the "Runtime Environment". And simply because I thought "Environment" sounded fancier than "variables", I'm going to use "Command Environment" throughout this blog post as name for "the collection of all command variables".


Why would I want to mess with it?

Datapack functions by default always run at world spawn as the "Server" entity, whatever that might be. If you were to run "/say hi" in the tick function of your datapack it would output "[​Server] hi". If you were to run "/setblock ~ ~ ~ diamond_block" it would place a diamond block at world spawn. These are a couple use cases, where it's necessary to be able to influence this.
- Teleport players in a certain direction
- Spawning particles near player and other entities
- Changing blocks around the player.
- Detect blocks near entities
- Spawn entities around the player
- Set spawnpoint relatively
- Only specify the target selector once and use @s in all the other places
- etc...


How do I change the Command Environment?

You can change all these variables with /execute. The syntax is:
/execute [instruction] [instruction] ... run <command without />Let's have a look at the different instructions. Instructions that aren't included in this list will be covered in later tutorials.

as <target selector>

Executes the rest of this command for each of the selected entities. After this instruction, @s will be set to one of the selected entities. Does not change the location of execution. Example:
/execute as @a run tellraw @a {"selector":"@s"}
Makes everyone (first @a) output their name (@s) in chat, for everyone (second @a) to see.
This is different from: /tellraw @a {"selector":"@a"} which just outputs a list of all names on one line.

align <axes>

Aligns the position to the block grid. Useful if you want to perfectly spawn an entity at a certain position. The axes argument is a string with one or more letters indicating an axis, like "xz", "x" or "xyz". Note that it does not align to the center of the block, but one of the bottom corners.
/execute align xyz run summon armor_stand ~0.5 ~ ~0.5
Summons an armor stand in the horizontal middle of the block you're standing in. The y coordinate matches the bottom of the block you're standing in or in other words, on top of the block your standing on.

anchored (eyes|feet)
Alters the point of view used with relative coordinates according to the TNB frame (using ^x ^y ^z), the facing instruction in /execute and the facing subcommand in /tp. The default is "feet". Entities that are less than a block tall still have an "eyes" anchor point 1 block above them. Does not change the actual position. In the following examples, both the player and zombie are at the same Y level.
/tp @s ~ ~ ~ facing entity @e[type=zombie,limit=1] feet
/tp @s ~ ~ ~ facing entity @e[type=zombie,limit=1] eyes
/execute anchored eyes run tp @s ~ ~ ~ facing entity @e[type=zombie,limit=1] feet
/execute anchored eyes run tp @s ~ ~ ~ facing entity @e[type=zombie,limit=1] eyes
1. The feet of the player are on the same Y-level as the feet of the zombie, resulting in the head being rotated to a straight horizontal position. The player is now looking into the eyes of the zombie instead of its feet.
2. The feet of the player are one block lower than the eyes of the zombie, resulting in the head being tilted upwards. The player is now looking above the zombie into the sky, instead of at its eyes.
3. The eyes of the player are one block higher than the feet of the zombie, resulting in the head being tilted downwards. The player is now successfully looking at the feet of the zombie.
4. The eyes of the player are at the same Y-level as eyes of the zombie, resulting in the head being rotated to a straight horizontal position. The player is now successfully looking at the eyes of the zombie.

rotated (<rx> <ry>|as <target>)
Sets the direction to a certain angle or copies the rotation from a target.
/execute rotated 0 0 run setblock ^ ^ ^1 diamond_block
Always equal to "setblock ~ ~ ~1 diamond_block" regardless of player direction, because we overwrote the rotation with the "rotated" instruction.

facing (<x> <y> <z>|entity <target> (eyes|feet))
Adjusts the direction to face a certain location or entity.
/execute anchored eyes facing entity @e[type=minecraft:elder_guardian,limit=1,sort=nearest] feet run particle minecraft:end_rod ^ ^ ^3 0 0 0 0.001 1 force
Spawns a glowing white particle (the end rod particle) 3 blocks out in the direction of the nearest elder guardian. Useful, because you can't see where the elder guardian is otherwise. Note the "anchored" instruction to set the heads rotation to the correct angle, see examples for the "anchored" instruction above. Of course, giving all elder guardians a glowing effect would be way more effective, but also less nerdy.

in <dimension>
Sets the dimension of execution. Note that for most commands the location must be loaded in, which becomes way more of a problem when you decide to do cross-dimension stuff. Note that coordinates are not changed. For example, you can use setblock to build a portal in the nether, while in the overwold. However, this portal would link back to a different position in the overworld, because each block in the nether is 8 blocks in the overworld.
/execute in minecraft:the_nether run tp ~ ~ ~
Instantly teleports to the nether from any dimension. Again, this works differently from a nether portal, because a portal to the nether spawns you at 1/8th of the overworld coordinates (with an offset to ensure a suitable spawn location). This command just places you at your current coordinates in the nether.

positioned (<x> <y> <z>|as <target>)
Set location to the specified coordinates or copy the location from the target. This one is so simple there will be no example. Since most commands affected by location have their own location arguments, this instruction is only useful if a function is called by the /execute command. All commands inside the function can then simply use ~ ~ ~ as coordinates.

at <target>
Changes position, rotation and dimension to the target. Commonly used by lazy developers, but also a good way to prevent forgetting the "in" instruction for dimensions when using other location instructions.

Conventions

Most use cases so far are far-fetched. Most commands have a target selector or positional argument built in (like /tp or /gamemode). The primary use case for /execute is executing at the position of a different entity. This originates from the original /execute command that didn't have any chaining of instructions. The old command just had one target selector and an argument for the command to run. The location would be set to the target as well and since there was no @s either, the only use of /execute back then was the primary use case described above.
Nowadays, this most common use case is implemented using:
/execute as <entity> at @s run ...Note the order of instructions. If you would swap them, the command would execute at your position for each of the targets.

Usually the tick function in my datapack is full of those "execute as at" commands running other function files. It allows me to define the executing entity and location only once and then simply use "@s" or "~ ~ ~" throughout the function. Without /execute, I would have to repeat the target selector (which sometimes gets very nasty) and specific location every time it's needed. Because I often run a function using /execute, I place comments above my function files describing who @s targets and where it's executed. It's recommended that you do this as well, it will save you hours of debugging when things break!

tick.mcfunction:
#As/At: Server
execute as @a[gamemode=creative,y=0,dy=20] at @s run function bertiecrafter:pack/back_to_top  
back_to_top.mcfunction:
#As/At: Player who almost fell into the void

#If "As" differs from "At", you should put both on separate lines like this:

#As: Player who almost fell into the void
#At: Player who almost fell into the void

tp ~ 100 ~
tellraw @a {"selector":"@s","extra":[{"text":" almost fell out of the world!"}]}
Note how the tp command can now just use relative coordinates and neither command requires a complex target selector, because we already specified our command environment in the execute command in tick.mcfunction.

Matters Order!

Wait, I mean "Order Matters!". In short, every instruction modifies the variables set by the instructions in front. This means that an "align" instruction followed by a "positioned" instruction is different from the other way around. Swapping the "as" and "at" instructions in the example above will be disastrous. And don't even try placing an "anchored" instruction after a "facing" instruction, unless you are a mad scientist.

Challenge Yourself

After every tutorial, I'll include a section where you are challenged to apply what you've learned. I recommend you playing with what you've learned, it helps you getting familiar with new concepts and be able to find solutions to problems. You don't have to do exactly what's written below, you can always challenge yourself in a different way.

Let's make zombies rise from the ground!
First off, we must sink newly spawned zombies into the ground. Start by adding an /execute command to the tick function of your data pack, targetting all zombies at their locations. It should run a "sink" function. The sink function simply contains a single /tp command to teleport the zombies 2 blocks down. Remember to add "As/At" comments to the functions and that the /tp command doesn't require a target selector, because we already targeted the zombies in the /execute command. We didn't cover conditional instructions yet, so I'll give you the instructions that you should insert into the /execute command. Keep in mind that order matters, so insert the following in the right place.
unless block ~ ~-1 ~ minecraft:air unless block ~ ~-2 ~ minecraft:air unless block ~ ~-3 ~ minecraft:airThese instructions will prevent zombies from sinking that don't have blocks beneath them, like in mob spawners made by players.
If you reload the datapack, you'll notice that all zombies will keep teleporting until they fall out of the world. To prevent this, add a "tag @s add ..." command to the sink function and add a "tag=!..." target selector argument to the target selector in the /execute command. The sink command will now only execute once for every zombie, because each zombie gets a tag after and won't be selected next time the tick function runs.

Both tags and conditional instructions will be fully covered in the next tutorial.

Another problem is that the zombies will start taking damage. Place an /effect command in the tick function that keeps giving all zombies with the tag instant damage. Damage heals undead mobs.

To make the zombies rise, add another /execute command to the tick function. It should execute for every player at their positions, but then select all zombies near the players (using the distance target selector argument). Don't worry, it's okay to have two pairs of "as ..... at @s" in one /execute command. Of course, the command should run a "rise" function. The rise function should give the zombies levitation 3 for 1 second and remove the tag. Remember to add "As/At" comments and to use the "@s" target selector for the /effect and /tag commands. Also don't forget to only select zombies with the tag in the /execute command in the tick function.

Extra Challenge:
Create an entity tag (JSON file) that groups all humanoid hostile mobs together (like skeletons, zombies, zombie pigmen, wither skeletons, etc) and replace "type=minecraft:zombie" with "type=#your_namespace:your_tag" in the tick function.

What's next?

Next up we're going to look at more ways of checking all kinds of stuff. This might seem lame, but all data packs consist of is checking loads of things 20 times a second and only executing commands or functions for certain entities if they pass those checks.
Subscribe if you want to get notified of new posts.

Function Data Packs for Dummies #8 | The Command Environment (/execute)
Function Data Packs for Dummies #8 | The Command Environment (/execute)
Tags

Create an account or sign in to comment.

Dunk__
01/13/2021 4:03 am
Level 38 : Artisan Pixel Painter
Dunk__'s Avatar
I still don't know how to make a custom tag
1
Bertiecrafter
01/13/2021 7:33 am
Level 70 : Legendary Engineer
Bertiecrafter's Avatar
Read my reply on your previous comment and please do not place the same comment in multiple places. If you don't understand my reply, feel free to ask a direct question that I can answer (on the original comment, not this one).
1
daitallica
02/23/2020 5:40 pm
Level 34 : Artisan Procrastinator
daitallica's Avatar
Cracking series

Really looking forward to seeing more!
3
Mizab
02/20/2020 11:58 am
Level 63 : High Grandmaster Programmer
Mizab's Avatar
Excellent job mate. Nicely explained :)
3
Bertiecrafter
02/20/2020 4:37 am
Level 70 : Legendary Engineer
history
Bertiecrafter's Avatar
Thank you Zero_4793, Mizab, Aspirin60, daitallica, Cyprezz, PMC, Wundercroft, Luracasmus, RX808, AstroVulpix, TofuChild36, green_subway, Vellaris, SanctuaryThief, JohThePro, SUPERIONtheKnight, Zamanbre, NovaModz, MrDead8, hogbits, Unavalible_User, LeoEluf and Kefaku for the diamonds!
2
Zero_4793
02/20/2020 4:37 am
Level 54 : Grandmaster Technomancer
Zero_4793's Avatar
I haven't actually read any of this series yet, as i know most of this. But i love that you are making such an indepth tutorial for new Creators. And i will begin to follow this as you reach my uncharted territory.
4
Bertiecrafter
02/20/2020 4:38 am
Level 70 : Legendary Engineer
Bertiecrafter's Avatar
Don't worry, we will go deeper eventually. Thank you for showing interest =)
3
Planet Minecraft

Website

© 2010 - 2024
www.planetminecraft.com

Welcome