The Sequential Execution Trap and Marker Entities
When a function file runs in Minecraft Bedrock, the engine processes each command from top to bottom within a single game tick. If you attempt to swap Player A and Player B by running two standard teleport commands back to back, the first command moves Player A to Player B's location. When the second command executes a fraction of a millisecond later, both players are already standing on the exact same block. Moving Player B to Player A now results in no movement at all, leaving both players stacked at Player B's original coordinates while Player A's starting position is lost forever.
To solve this, you need an intermediate spatial reference that does not move when the players move. In Bedrock Edition, the standard approach is to summon a lightweight entity—most commonly an armor stand or a custom dummy entity—at one or more player positions before any teleportation occurs. The entity acts as a physical bookmark in the world. Once the bookmark is placed and tagged, you are free to move the first player to the second player, and then move the second player to the bookmark before cleaning up the temporary entity.
For this recipe to remain invisible and seamless to players, the marker entity should be configured or modified immediately upon spawning so it does not obstruct vision, trigger pressure plates, or take damage. While a custom behavior pack entity with no collision box and no rendering is ideal for large projects, a vanilla armor stand made invisible or killed within the same tick works reliably for pure function packs. Because the summon, the teleports, and the kill command all happen inside the same function execution, the client never renders the armor stand on screen.
| Command Element | Role in Rearrangement | Behavior Notes |
|---|---|---|
| execute as @a at @s | Branches execution context | Sets both the command executor and the coordinate origin to each targeted player individually. |
| tag @s add ... | Locks selection state | Prevents a player from being selected twice during a multi-step swap or random roll. |
| minecraft:armor_stand | Spatial bookmark | Holds coordinates and rotation in the world while players are moved around. |
| c=1, r=... | Target limiters | Ensures teleport commands only ever resolve to a single destination entity. |
| scoreboard players operation | Index matching | Allows mathematical rotation of player IDs for round-robin position cycling. |
Two-Player Direct Position Swap
The simplest rearrangement is a direct swap between two random or designated players. To make this work reliably in a world where more than two players might be connected (such as spectators or lobby players), you must first isolate your two active participants using entity tags. Never rely on `@r` directly inside your teleport commands, because `@r` re-evaluates on every line and could pick the same player twice or pick a third player halfway through the function.
Begin by assigning a unique tag to Player 1 and a different unique tag to Player 2, using the `tag=!` exclusion argument so the second selection cannot pick the first player. Once both players are tagged, execute at Player 1's location to summon an armor stand with a custom name or tag. This captures Player 1's exact X, Y, and Z coordinates.
With the bookmark in place, teleport Player 1 directly to Player 2. Next, teleport Player 2 to the bookmarked armor stand. Finally, remove the temporary tags from both players and kill the armor stand. Because all eight lines run inside a single `.mcfunction` file, the swap is instantaneous and atomic—neither player sees the armor stand, and there is zero frame delay between the two movements.
# Select two distinct active players for the swap
tag @r[tag=arena_active] add swap_target_a
tag @r[tag=arena_active,tag=!swap_target_a] add swap_target_b
# Only proceed if a second player was actually found
execute if entity @a[tag=swap_target_b] at @a[tag=swap_target_a,c=1] run summon minecraft:armor_stand ~ ~ ~ ~ ~ swap_marker
# Perform the two-way teleport
execute if entity @e[type=minecraft:armor_stand,name=swap_marker] run tp @a[tag=swap_target_a,c=1] @a[tag=swap_target_b,c=1]
execute if entity @e[type=minecraft:armor_stand,name=swap_marker] run tp @a[tag=swap_target_b,c=1] @e[type=minecraft:armor_stand,name=swap_marker,c=1]
# Clean up the marker and reset player tags
kill @e[type=minecraft:armor_stand,name=swap_marker]
tag @a remove swap_target_a
tag @a remove swap_target_bMulti-Player Round-Robin Cycle
When you have three or more players and want everyone to move to someone else's spot—so Player 1 goes to Player 2, Player 2 goes to Player 3, and the last player wraps around to Player 1's old spot—simple tags are no longer enough. You need an ordered chain. The cleanest way to build a dynamic chain in Bedrock commands is to combine scoreboard IDs with an anchor entity at the start of the chain.
In this two-function pattern, a main controller function resets a counter and runs a helper function as every active player. The helper function assigns each player a sequential number (`0`, `1`, `2`, and so on) by copying a global counter into their personal score and then incrementing the global counter by one. The player who receives ID `0` is the head of the chain; the helper function immediately summons a bookmark armor stand at their feet.
To shift everyone along the chain, the helper function calculates who is next. During each player's execution turn, their ID is copied to a temporary score, reduced by one, and compared against the other players. If a player has ID `1`, they look for the player with ID `0` and teleport them to their current spot. Because this runs in ascending order (`0`, then `1`, then `2`), Player `0` moves to Player `1` before Player `1` moves to Player `2`. At the very end of the controller function, the player who still has the highest ID (the tail of the chain, who has not moved yet) is teleported to the armor stand left behind by Player `0`, closing the loop.
# Initialize scoreboard objectives if not already present
scoreboard objectives add swap_id dummy
scoreboard objectives add swap_math dummy
# Reset the global counter
scoreboard players set #counter swap_math 0
# Assign sequential IDs and execute step logic per player
execute as @a[tag=arena_active] at @s run function rearrange/cycle_step
# Move the final player in the chain to Player 0's original marker
execute as @a[tag=arena_active,tag=!has_teleported] run tp @s @e[type=minecraft:armor_stand,name=cycle_origin,c=1]
# Clean up markers and state tags
kill @e[type=minecraft:armor_stand,name=cycle_origin]
tag @a remove has_teleportedThe Chain Step Helper Function
The helper function `cycle_step.mcfunction` is called once per player from the main cycle function. Because it is invoked via `execute as @a[tag=arena_active] at @s`, the `@s` selector inside this file refers to the current player being indexed, and `~ ~ ~` refers to their exact coordinates at the moment their turn in the loop begins.
When the first player runs this file, `#counter` is `0`. They receive a `swap_id` of `0` and summon the `cycle_origin` armor stand. When the second player runs this file, `#counter` has been incremented to `1`. They receive a `swap_id` of `1`. We then subtract `1` from their ID to get `0`, find the player whose `swap_id` matches `0`, and pull that previous player to the current player's coordinates. Tagging the pulled player with `has_teleported` makes it easy for the main function to identify the one remaining player at the end of the loop who never got pulled forward.
# Assign the current counter value to this player
scoreboard players operation @s swap_id = #counter swap_math
# If this is the very first player (ID 0), drop the origin marker
execute if score @s swap_id matches 0 run summon minecraft:armor_stand ~ ~ ~ ~ ~ cycle_origin
# Calculate the ID of the previous player in the chain (current ID - 1)
scoreboard players operation #prev_id swap_math = @s swap_id
scoreboard players remove #prev_id swap_math 1
# Pull the previous player to this player's current location
execute as @a[tag=arena_active] if score @s swap_id = #prev_id swap_math run tag @s add pull_target
tp @a[tag=pull_target,c=1] ~ ~ ~
tag @a[tag=pull_target] add has_teleported
tag @a remove pull_target
# Increment the global counter for the next player in line
scoreboard players add #counter swap_math 1Total Random Shuffle Across Saved Positions
Sometimes you want to shuffle everyone across the existing set of player locations completely at random—allowing two players to swap, three others to cycle, or even permitting a player to occasionally land back on their own spot. Instead of chaining players directly to one another, you decouple the positions from the players entirely.
First, every active player summons an untagged marker armor stand at their feet and tags it as an available slot. Once all slots are created, a second command runs as every active player and teleports them to a randomly selected (`@r[type=minecraft:armor_stand]`) marker that still has the available tag. Immediately after teleporting, the player executes a command at their new location to strip the available tag from the nearest marker (`c=1,r=1`).
Because the marker loses its tag the instant a player claims it, the next player in the execution loop cannot pick that same marker. By the time the last player runs their step, only one tagged marker remains, guaranteeing a one-to-one redistribution with no two players ever ending up on the same spot.
# Step 1: Every active player drops a spatial bookmark
execute as @a[tag=arena_active] at @s run summon minecraft:armor_stand ~ ~ ~ ~ ~ shuffle_node
tag @e[type=minecraft:armor_stand,name=shuffle_node] add slot_free
# Step 2: Each player claims one random free slot
execute as @a[tag=arena_active] run function rearrange/claim_random_slot
# Step 3: Remove all temporary markers
kill @e[type=minecraft:armor_stand,name=shuffle_node]Claiming a Slot and Preserving Rotation
To finish the random shuffle, the `claim_random_slot.mcfunction` helper file picks one random armor stand from the pool of free slots, tags it as the current target, teleports the executing player to it, and removes it from the free pool. Doing the selection with `tag @r[type=...] add current_slot` before the `tp` command ensures you know exactly which armor stand to strip `slot_free` from, even if two players started the shuffle standing inside the same block space.
One detail to keep in mind during any rearrangement is camera facing direction. When you run `tp @s @e[type=minecraft:armor_stand,c=1]`, the player inherits both the position and the rotation of the destination entity. Because `summon minecraft:armor_stand ~ ~ ~` spawns the armor stand facing default south (`0` yaw, `0` pitch) unless specified otherwise, players will have their cameras snapped south upon swapping. If you want players to inherit the exact view angle of the person they are replacing, use the ` facing ` clause or copy rotation during the summon, or use `tp @s ~ ~ ~` inside an `execute at` block so the player keeps their own personal camera angle while changing only their X, Y, and Z coordinates.
# Pick one random unclaimed marker from the pool
tag @r[type=minecraft:armor_stand,name=shuffle_node,tag=slot_free] add claimed_now
# Teleport the current player to the chosen marker's coordinates while keeping the player's own camera rotation
execute at @e[type=minecraft:armor_stand,tag=claimed_now,c=1] run tp @s ~ ~ ~
# Mark this slot as used so subsequent players cannot pick it
tag @e[type=minecraft:armor_stand,tag=claimed_now] remove slot_free
tag @e[type=minecraft:armor_stand,tag=claimed_now] remove claimed_nowHandling Unloaded Chunks and Dimensional Boundaries
Position rearrangement works without extra setup when all participating players are within the same loaded area, such as a minigame arena. However, in survival challenges like a world-wide Death Swap where two players might be thousands of blocks apart or in different dimensions (Overworld versus the Nether), chunk loading becomes a critical factor.
When you summon a marker armor stand at Player A's position and then immediately teleport Player A to Player B five thousand blocks away, Player A's original chunks may remain loaded for the remainder of that single game tick, allowing Player B to teleport to the armor stand right away. However, if you introduce any delay between the two teleports (such as waiting several ticks for a countdown effect), Player A's departure will cause their original chunks to unload. Once a chunk is unloaded, `@e[type=minecraft:armor_stand,name=swap_marker]` can no longer find the entity, and the second teleport will fail.
To prevent cross-world or cross-dimension swaps from failing, either execute the entire summon-swap-kill sequence inside a single function within the same tick, or register a temporary `tickingarea` around each player's coordinates before moving them and remove the ticking area once the rearrangement is complete.
Which versions this applies to
Applies to Minecraft Bedrock Edition 1.19.50 and newer (uses the modern 'execute as ... at ... run' syntax). Requires behavior pack 'min_engine_version' set to at least [1, 19, 50] in manifest.json so functions parse the updated execute command structure. No experimental toggles are required.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Function call fails in Content Log with: 'Syntax error: Unexpected "as": at "execute >>as<< @a"' | Your behavior pack's manifest.json has a min_engine_version older than 1.19.50, causing the game to parse your .mcfunction files using the legacy pre-1.19.50 execute syntax. | Open BP/manifest.json and update "min_engine_version" under the "header" object to at least [1, 19, 50], then reload the world. |
| Command output says: 'No targets matched selector' on the second teleport, and both players end up stacked in the same location. | You either forgot to include 'c=1' when targeting players, or your summon command failed because 'mobgriefing' or world spawn rules blocked the entity, or the players were not given the required 'arena_active' tag before running the function. | Ensure at least two players have the 'arena_active' tag before triggering the function, and verify the armor stand is being summoned before the first player is moved. |
| Chat gets spammed with 'Teleported Player to ...' and 'Summoned new Armor Stand' every time positions rearrange. | The world's command feedback gamerule is enabled by default, broadcasting function side-effects to players. | Run '/gamerule sendcommandfeedback false' and '/gamerule commandblockoutput false' once in your world setup function. |
| In the random shuffle, two players occasionally end up at the exact same spot while one marker armor stand is left unused. | You stripped the 'slot_free' tag using a distance selector like 'r=1' after teleporting, and two markers happened to be within 1 block of each other, removing the tag from the wrong armor stand. | Tag the chosen random armor stand directly with a unique temporary tag (like 'claimed_now') before teleporting, and remove 'slot_free' using that specific tag selector rather than a radius check. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
