You can't grant access to only the /teleport
command, but you can prepare a /trigger
for them to use.
First create three scoreboards for the coordinates:
/scoreboard objectives add x trigger
/scoreboard objectives add y trigger
/scoreboard objectives add z trigger
The trigger
type is what allows them to be set by non-OPs.
Then you enable them for use by everyone:
/scoreboard players enable @a x
/scoreboard players enable @a y
/scoreboard players enable @a z
This should be done in a clock, because using a trigger automatically disables it for that player.
Now the players can use commands like these to set their goal coordinates:
/trigger x
/trigger x add 123
/trigger x set 456
The first of these adds 1 to the scoreboard value for that player, the rest should be obvious.
Next you need something to actually start the teleportation. You can use this with yet another trigger of which you constantly check whether someone set it to 1 for himself, you can use the classical renamed item on the ground, you can do it whenever someone jumps 100 times on the spot, etc. Instructions for all of these can be found elsewhere. I assume here that whatever mechanism you use tags the player with "toTeleport
".
Now to the actual teleportation: You can't just say /teleport @p <his_scoreboard_value_x>
etc., so you have to use an entity of which you can set the coordinates in NBT. An armour stand is a nice dummy entity:
/execute at @p[tag=toTeleport] run summon armor_stand ~ ~ ~ {Marker:1,NoGravity:1,NoAI:1,Invisible:1,Tags:["teleportHelper"]}
This assumes that whatever detection system you use to initialise the teleportation gives the player the toTeleport
tag.
And this is the trick: Unlike players, other entities can be teleported anywhere using their Pos
NBT tag, which you can set to arbitrary numbers using /execute store
:
/execute store result entity @e[tag=teleportHelper,limit=1] Pos[0] double 1 run scoreboard players get @p[tag=toTeleport] x
/execute store result entity @e[tag=teleportHelper,limit=1] Pos[1] double 1 run scoreboard players get @p[tag=toTeleport] y
/execute store result entity @e[tag=teleportHelper,limit=1] Pos[2] double 1 run scoreboard players get @p[tag=toTeleport] z
These three commands have to be in a chain (preferably your regular looping command block chain), followed by this command:
/tp @p[tag=toTeleport] @e[tag=teleportHelper,limit=1]
It's important that you teleport the player to the armour stand in the same tick that you set the Pos
tag in, otherwise the chunk might unload and the teleportation would fail.
Then you just clean up everything:
/kill @e[tag=teleportHelper]
/tag remove @p[tag=toTeleport] toTeleport
This system should work fine in multiplayer, even if two players activate it at the exact same time, one will just be teleported one game tick later.
Thanks to vdvman1 in the Eigencraft Discord chat who told me that /trigger
works with numbers and that you can teleport to far away entities if they were loaded at the start of the tick.
This is an optimized version of the above using functions that will also handle multiplayer better, it will allow any number of players to teleport in the same tick, to their own individual destinations. Written by vdvman1.
# run once
scoreboard objectives add x trigger
scoreboard objectives add y trigger
scoreboard objectives add z trigger
scoreboard objectives add tp trigger
# run every tick
execute as @a run function tp_trigger
# tp_trigger.mcfunction
scoreboard players enable @s x
scoreboard players enable @s y
scoreboard players enable @s z
execute if score @s tp matches 1.. run function tp_activate
# tp_activate.mcfunction
scoreboard players set @s tp 0
scoreboard players enable @s tp
scoreboard players operation #current x = @s x
scoreboard players operation #current y = @s y
scoreboard players operation #current z = @s z
tag @s add tp_trigger_source
summon area_effect_cloud ~ ~ ~ {Tags:["tp_trigger_target"]}
execute as @e[type=area_effect_cloud,tag=tp_trigger_target,limit=1] run function set_pos.mcfunction
tag @s remove tp_trigger_source
# set_pos.mcfunction
execute store result entity @s Pos[0] double 1 run scoreboard players get #current x
execute store result entity @s Pos[1] double 1 run scoreboard players get #current y
execute store result entity @s Pos[2] double 1 run scoreboard players get #current z
execute at @s run tp @a[tag=tp_trigger_source,limit=1] ~ ~ ~