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.EntityAnchorArgument.Anchor; import net.minecraft.commands.arguments.coordinates.Coordinates; import net.minecraft.commands.arguments.coordinates.RotationArgument; import net.minecraft.commands.arguments.coordinates.Vec3Argument; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; 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.Relative; 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"), null, 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 LookAt.LookAtEntity(EntityArgument.getEntity(commandContext, "facingEntity"), 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 LookAt.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 LookAt.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(Relative.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 LookAt lookAt ) throws CommandSyntaxException { Vec3 vec3 = position.getPosition(source); Vec2 vec2 = rotation == null ? null : rotation.getRotation(source); for (Entity entity : targets) { Set set = getRelatives(position, rotation, entity.level().dimension() == level.dimension()); if (vec2 == null) { performTeleport(source, entity, level, vec3.x, vec3.y, vec3.z, set, entity.getYRot(), entity.getXRot(), lookAt); } else { performTeleport(source, entity, level, vec3.x, vec3.y, vec3.z, set, vec2.y, vec2.x, lookAt); } } 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 Set getRelatives(Coordinates position, @Nullable Coordinates rotation, boolean absolute) { Set set = EnumSet.noneOf(Relative.class); if (position.isXRelative()) { set.add(Relative.DELTA_X); if (absolute) { set.add(Relative.X); } } if (position.isYRelative()) { set.add(Relative.DELTA_Y); if (absolute) { set.add(Relative.Y); } } if (position.isZRelative()) { set.add(Relative.DELTA_Z); if (absolute) { set.add(Relative.Z); } } if (rotation == null || rotation.isXRelative()) { set.add(Relative.X_ROT); } if (rotation == null || rotation.isYRelative()) { set.add(Relative.Y_ROT); } return set; } private static String formatDouble(double value) { return String.format(Locale.ROOT, "%f", value); } private static void performTeleport( CommandSourceStack source, Entity target, ServerLevel level, double x, double y, double z, Set relatives, float yRot, float xRot, @Nullable LookAt lookAt ) throws CommandSyntaxException { BlockPos blockPos = BlockPos.containing(x, y, z); if (!Level.isInSpawnableBounds(blockPos)) { throw INVALID_POSITION.create(); } else { double d = relatives.contains(Relative.X) ? x - target.getX() : x; double e = relatives.contains(Relative.Y) ? y - target.getY() : y; double f = relatives.contains(Relative.Z) ? z - target.getZ() : z; float g = relatives.contains(Relative.Y_ROT) ? yRot - target.getYRot() : yRot; float h = relatives.contains(Relative.X_ROT) ? xRot - target.getXRot() : xRot; float i = Mth.wrapDegrees(g); float j = Mth.wrapDegrees(h); if (target.teleportTo(level, d, e, f, relatives, i, j, true)) { if (lookAt != null) { lookAt.perform(source, target); } if (!(target instanceof LivingEntity livingEntity && livingEntity.isFallFlying())) { target.setDeltaMovement(target.getDeltaMovement().multiply(1.0, 0.0, 1.0)); target.setOnGround(true); } if (target instanceof PathfinderMob pathfinderMob) { pathfinderMob.getNavigation().stop(); } } } } }