package net.minecraft.server.commands; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.tree.LiteralCommandNode; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; import java.util.Locale; import java.util.Set; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.coordinates.Coordinates; import net.minecraft.commands.arguments.coordinates.RotationArgument; import net.minecraft.commands.arguments.coordinates.Vec3Argument; import net.minecraft.commands.arguments.coordinates.WorldCoordinates; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PathfinderMob; import net.minecraft.world.entity.RelativeMovement; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec2; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; public class TeleportCommand { private static final SimpleCommandExceptionType INVALID_POSITION = new SimpleCommandExceptionType(Component.translatable("commands.teleport.invalidPosition")); public static void register(CommandDispatcher dispatcher) { LiteralCommandNode literalCommandNode = dispatcher.register( Commands.literal("teleport") .requires(commandSourceStack -> commandSourceStack.hasPermission(2)) .then( Commands.argument("location", Vec3Argument.vec3()) .executes( commandContext -> teleportToPos( commandContext.getSource(), Collections.singleton(commandContext.getSource().getEntityOrException()), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), WorldCoordinates.current(), null ) ) ) .then( Commands.argument("destination", EntityArgument.entity()) .executes( commandContext -> teleportToEntity( commandContext.getSource(), Collections.singleton(commandContext.getSource().getEntityOrException()), EntityArgument.getEntity(commandContext, "destination") ) ) ) .then( Commands.argument("targets", EntityArgument.entities()) .then( Commands.argument("location", Vec3Argument.vec3()) .executes( commandContext -> teleportToPos( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), null, null ) ) .then( Commands.argument("rotation", RotationArgument.rotation()) .executes( commandContext -> teleportToPos( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), RotationArgument.getRotation(commandContext, "rotation"), null ) ) ) .then( Commands.literal("facing") .then( Commands.literal("entity") .then( Commands.argument("facingEntity", EntityArgument.entity()) .executes( commandContext -> teleportToPos( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), null, new TeleportCommand.LookAtEntity(EntityArgument.getEntity(commandContext, "facingEntity"), EntityAnchorArgument.Anchor.FEET) ) ) .then( Commands.argument("facingAnchor", EntityAnchorArgument.anchor()) .executes( commandContext -> teleportToPos( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), null, new TeleportCommand.LookAtEntity( EntityArgument.getEntity(commandContext, "facingEntity"), EntityAnchorArgument.getAnchor(commandContext, "facingAnchor") ) ) ) ) ) ) .then( Commands.argument("facingLocation", Vec3Argument.vec3()) .executes( commandContext -> teleportToPos( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), commandContext.getSource().getLevel(), Vec3Argument.getCoordinates(commandContext, "location"), null, new TeleportCommand.LookAtPosition(Vec3Argument.getVec3(commandContext, "facingLocation")) ) ) ) ) ) .then( Commands.argument("destination", EntityArgument.entity()) .executes( commandContext -> teleportToEntity( commandContext.getSource(), EntityArgument.getEntities(commandContext, "targets"), EntityArgument.getEntity(commandContext, "destination") ) ) ) ) ); dispatcher.register(Commands.literal("tp").requires(commandSourceStack -> commandSourceStack.hasPermission(2)).redirect(literalCommandNode)); } private static int teleportToEntity(CommandSourceStack source, Collection targets, Entity destination) throws CommandSyntaxException { for (Entity entity : targets) { performTeleport( source, entity, (ServerLevel)destination.level(), destination.getX(), destination.getY(), destination.getZ(), EnumSet.noneOf(RelativeMovement.class), destination.getYRot(), destination.getXRot(), null ); } if (targets.size() == 1) { source.sendSuccess( () -> Component.translatable("commands.teleport.success.entity.single", ((Entity)targets.iterator().next()).getDisplayName(), destination.getDisplayName()), true ); } else { source.sendSuccess(() -> Component.translatable("commands.teleport.success.entity.multiple", targets.size(), destination.getDisplayName()), true); } return targets.size(); } private static int teleportToPos( CommandSourceStack source, Collection targets, ServerLevel level, Coordinates position, @Nullable Coordinates rotation, @Nullable TeleportCommand.LookAt facing ) throws CommandSyntaxException { Vec3 vec3 = position.getPosition(source); Vec2 vec2 = rotation == null ? null : rotation.getRotation(source); Set set = EnumSet.noneOf(RelativeMovement.class); if (position.isXRelative()) { set.add(RelativeMovement.X); } if (position.isYRelative()) { set.add(RelativeMovement.Y); } if (position.isZRelative()) { set.add(RelativeMovement.Z); } if (rotation == null) { set.add(RelativeMovement.X_ROT); set.add(RelativeMovement.Y_ROT); } else { if (rotation.isXRelative()) { set.add(RelativeMovement.X_ROT); } if (rotation.isYRelative()) { set.add(RelativeMovement.Y_ROT); } } for (Entity entity : targets) { if (rotation == null) { performTeleport(source, entity, level, vec3.x, vec3.y, vec3.z, set, entity.getYRot(), entity.getXRot(), facing); } else { performTeleport(source, entity, level, vec3.x, vec3.y, vec3.z, set, vec2.y, vec2.x, facing); } } if (targets.size() == 1) { source.sendSuccess( () -> Component.translatable( "commands.teleport.success.location.single", ((Entity)targets.iterator().next()).getDisplayName(), formatDouble(vec3.x), formatDouble(vec3.y), formatDouble(vec3.z) ), true ); } else { source.sendSuccess( () -> Component.translatable( "commands.teleport.success.location.multiple", targets.size(), formatDouble(vec3.x), formatDouble(vec3.y), formatDouble(vec3.z) ), true ); } return targets.size(); } private static String formatDouble(double value) { return String.format(Locale.ROOT, "%f", value); } private static void performTeleport( CommandSourceStack source, Entity entity, ServerLevel level, double x, double y, double z, Set relativeList, float yaw, float pitch, @Nullable TeleportCommand.LookAt facing ) throws CommandSyntaxException { BlockPos blockPos = BlockPos.containing(x, y, z); if (!Level.isInSpawnableBounds(blockPos)) { throw INVALID_POSITION.create(); } else { float f = Mth.wrapDegrees(yaw); float g = Mth.wrapDegrees(pitch); if (entity.teleportTo(level, x, y, z, relativeList, f, g)) { if (facing != null) { facing.perform(source, entity); } if (!(entity instanceof LivingEntity livingEntity && livingEntity.isFallFlying())) { entity.setDeltaMovement(entity.getDeltaMovement().multiply(1.0, 0.0, 1.0)); entity.setOnGround(true); } if (entity instanceof PathfinderMob pathfinderMob) { pathfinderMob.getNavigation().stop(); } } } } @FunctionalInterface interface LookAt { void perform(CommandSourceStack source, Entity entity); } record LookAtEntity(Entity entity, EntityAnchorArgument.Anchor anchor) implements TeleportCommand.LookAt { @Override public void perform(CommandSourceStack commandSourceStack, Entity entity) { if (entity instanceof ServerPlayer serverPlayer) { serverPlayer.lookAt(commandSourceStack.getAnchor(), this.entity, this.anchor); } else { entity.lookAt(commandSourceStack.getAnchor(), this.anchor.apply(this.entity)); } } } record LookAtPosition(Vec3 position) implements TeleportCommand.LookAt { @Override public void perform(CommandSourceStack commandSourceStack, Entity entity) { entity.lookAt(commandSourceStack.getAnchor(), this.position); } } }