minecraft-src/net/minecraft/server/commands/TeleportCommand.java
2025-07-04 02:49:36 +03:00

299 lines
10 KiB
Java

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<CommandSourceStack> dispatcher) {
LiteralCommandNode<CommandSourceStack> 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<? extends Entity> 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<? extends Entity> 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<Relative> 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<Relative> getRelatives(Coordinates position, @Nullable Coordinates rotation, boolean absolute) {
Set<Relative> 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<Relative> 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();
}
}
}
}
}