diff --git a/fabric-dimensions-v1/src/main/java/net/fabricmc/fabric/impl/dimension/FabricDimensionInternals.java b/fabric-dimensions-v1/src/main/java/net/fabricmc/fabric/impl/dimension/FabricDimensionInternals.java index df1b9b3e6..02eedb640 100644 --- a/fabric-dimensions-v1/src/main/java/net/fabricmc/fabric/impl/dimension/FabricDimensionInternals.java +++ b/fabric-dimensions-v1/src/main/java/net/fabricmc/fabric/impl/dimension/FabricDimensionInternals.java @@ -19,6 +19,7 @@ package net.fabricmc.fabric.impl.dimension; import com.google.common.base.Preconditions; import net.minecraft.entity.Entity; +import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.world.TeleportTarget; @@ -48,6 +49,21 @@ public final class FabricDimensionInternals { try { currentTarget = target; + + // Fast path for teleporting within the same dimension. + if (teleported.getWorld() == dimension) { + if (teleported instanceof ServerPlayerEntity serverPlayerEntity) { + serverPlayerEntity.networkHandler.requestTeleport(target.position.x, target.position.y, target.position.z, target.yaw, teleported.getPitch()); + } else { + teleported.refreshPositionAndAngles(target.position.x, target.position.y, target.position.z, target.yaw, teleported.getPitch()); + } + + teleported.setVelocity(target.velocity); + teleported.setHeadYaw(target.yaw); + + return teleported; + } + return (E) teleported.moveToWorld(dimension); } finally { currentTarget = null; diff --git a/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/FabricDimensionTest.java b/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/FabricDimensionTest.java index 6cd338918..5e58e3b17 100644 --- a/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/FabricDimensionTest.java +++ b/fabric-dimensions-v1/src/testmod/java/net/fabricmc/fabric/test/dimension/FabricDimensionTest.java @@ -102,6 +102,14 @@ public class FabricDimensionTest implements ModInitializer { CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(literal("fabric_dimension_test").executes(FabricDimensionTest.this::swapTargeted)) ); + + // Used to test https://github.com/FabricMC/fabric/issues/2239 + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(literal("fabric_dimension_test_desync") + .executes(FabricDimensionTest.this::testDesync))); + + // Used to test https://github.com/FabricMC/fabric/issues/2238 + CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> dispatcher.register(literal("fabric_dimension_test_entity") + .executes(FabricDimensionTest.this::testEntityTeleport))); } private int swapTargeted(CommandContext<ServerCommandSource> context) throws CommandSyntaxException { @@ -128,6 +136,50 @@ public class FabricDimensionTest implements ModInitializer { return 1; } + private int testDesync(CommandContext<ServerCommandSource> context) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + + if (player == null) { + context.getSource().sendFeedback(new LiteralText("You must be a player to execute this command."), false); + return 1; + } + + if (!context.getSource().getServer().isDedicated()) { + context.getSource().sendFeedback(new LiteralText("This command can only be executed on dedicated servers."), false); + return 1; + } + + TeleportTarget target = new TeleportTarget(player.getPos().add(5, 0, 0), player.getVelocity(), player.getYaw(), player.getPitch()); + FabricDimensions.teleport(player, (ServerWorld) player.world, target); + + return 1; + } + + private int testEntityTeleport(CommandContext<ServerCommandSource> context) throws CommandSyntaxException { + ServerPlayerEntity player = context.getSource().getPlayer(); + + if (player == null) { + context.getSource().sendFeedback(new LiteralText("You must be a player to execute this command."), false); + return 1; + } + + Entity entity = player.world + .getOtherEntities(player, player.getBoundingBox().expand(100, 100, 100)) + .stream() + .findFirst() + .orElse(null); + + if (entity == null) { + context.getSource().sendFeedback(new LiteralText("No entities found."), false); + return 1; + } + + TeleportTarget target = new TeleportTarget(player.getPos(), player.getVelocity(), player.getYaw(), player.getPitch()); + FabricDimensions.teleport(entity, (ServerWorld) entity.world, target); + + return 1; + } + private ServerWorld getModWorld(CommandContext<ServerCommandSource> context) { return getWorld(context, WORLD_KEY); }