Fabric API

Fabric API

106M Downloads

Fabric Dimensions slight desync on teleportation on multiplayer

LordDeatHunter opened this issue ยท 4 comments

commented

When teleporting a player with FabricDimensions#teleport on multiplayer, there's a slight desync on the client side.
For the player, they initially "teleport" to spawn with no items, xp, buffs, etc (basically a "fresh" new player instance), and then get teleported to the specified location a second later with all the items/xp/etc. they originally had.

My guess is that the teleport code runs both on client and server side for some reason, and that on the client side, there's a new player instance with default, non-copied data, and after teleporting client-side, the server syncs the player with a proper teleportation packet.

Tested with the following versions:
Minecraft: 1.18.2
Fabric API: 0.53.0
Fabric Dimensions: 2.1.17

commented

Thats perfect, thanks a lot ๐Ÿ‘

commented

I made a PoC test mod for both this and #2238, but I figured making a whole repo for it would be overkill. Here's a single file containing all you need to replicate both issues.

package wraith.fabricdimpoc;

import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.dimension.v1.FabricDimensions;
import net.minecraft.entity.Entity;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.LiteralText;
import net.minecraft.world.TeleportTarget;

public class FDPEvents {

    public static void initialize() {
        CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) ->
            dispatcher.register(CommandManager.literal("fdp")
                .then(CommandManager.literal("2238")
                    .executes(context -> {
                            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(entity.getPos(), entity.getVelocity(), entity.getYaw(), entity.getPitch());
                            FabricDimensions.teleport(entity, (ServerWorld) entity.world, target);
                            return 1;
                        }
                    )
                )
                .then(CommandManager.literal("2239")
                    .executes(context -> {
                            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(), player.getVelocity(), player.getYaw(), player.getPitch());
                            FabricDimensions.teleport(player, (ServerWorld) player.world, target);
                            return 1;
                        }
                    )
                )
            )
        );
    }

}

Call FDPEvents.initialize() on mod init, then /fdp 2239 for this issue and /fdp 2238 for the other.
(I think this issue doesn't happen 100% of the time. It might be dependent on the server's performance or distance from spawn, but so far I've been able to replicate it more than 90% of the time)

commented

Have you got a mod or snippet of code that can be used to help reproduce this?

commented

Both issues seem to be happen when teleporting between the same dimension. The API was only really designed to teleport between diffrent dimensions, however I think it would be wise to correcatlly handle teleporting within the same dimension.