diff --git a/src/main/java/com/replaymod/replay/FullReplaySender.java b/src/main/java/com/replaymod/replay/FullReplaySender.java index a6e8ae7d..fd41e6e2 100644 --- a/src/main/java/com/replaymod/replay/FullReplaySender.java +++ b/src/main/java/com/replaymod/replay/FullReplaySender.java @@ -267,6 +267,8 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend /** * Whether to allow (process) the next player movement packet. + * + * Must only be accessed from the main thread. */ protected boolean allowMovement; @@ -639,7 +641,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend if(p instanceof GameJoinS2CPacket) { GameJoinS2CPacket packet = (GameJoinS2CPacket) p; int entId = packet.getEntityId(); - allowMovement = true; + schedulePacketHandler(() -> allowMovement = true); actualID = entId; entId = -1789435; // Camera entity id should be negative which is an invalid id and can't be used by servers //#if MC>=11400 @@ -773,7 +775,7 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend //#endif //#endif - allowMovement = true; + schedulePacketHandler(() -> allowMovement = true); } if(p instanceof PlayerPositionLookS2CPacket) { @@ -789,8 +791,6 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend if(replayHandler.shouldSuppressCameraMovements()) return null; - CameraEntity cent = replayHandler.getCameraEntity(); - //#if MC>=10800 //#if MC>=11400 for (PlayerPositionLookS2CPacket.Flag relative : ppl.getFlags()) { @@ -812,29 +812,28 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend } //#endif - if(cent != null) { - if(!allowMovement && !((Math.abs(cent.getX() - ppl.getX()) > TP_DISTANCE_LIMIT) || - (Math.abs(cent.getZ() - ppl.getZ()) > TP_DISTANCE_LIMIT))) { - return null; - } else { - allowMovement = false; - } - } - - new Runnable() { + schedulePacketHandler(new Runnable() { @Override @SuppressWarnings("unchecked") public void run() { + // FIXME: world shouldn't ever be null at this point, now that we use the packet queue + // probably fine to remove on the next non-patch version (don't want to break stuff now) if (mc.world == null || !mc.isOnThread()) { ReplayMod.instance.runLater(this); return; } CameraEntity cent = replayHandler.getCameraEntity(); + if (!allowMovement && !((Math.abs(cent.getX() - ppl.getX()) > TP_DISTANCE_LIMIT) || + (Math.abs(cent.getZ() - ppl.getZ()) > TP_DISTANCE_LIMIT))) { + return; + } else { + allowMovement = false; + } cent.setCameraPosition(ppl.getX(), ppl.getY(), ppl.getZ()); cent.setCameraRotation(ppl.getYaw(), ppl.getPitch(), cent.roll); } - }.run(); + }); return null; } @@ -1273,6 +1272,22 @@ public class FullReplaySender extends ChannelDuplexHandler implements ReplaySend ReplayMod.instance.runTasks(); } + /** + * Runs the given runnable on the main thread as if it was a packet handler. + * Note that the packet handler queue has different behavior than the standard ReplayMod queue. + */ + private void schedulePacketHandler(Runnable runnable) { + if (mc.isOnThread()) { + runnable.run(); + } else { + //#if MC>=11400 + mc.execute(runnable); + //#else + //$$ mc.addScheduledTask(runnable); + //#endif + } + } + protected void processPacketSync(Packet p) { //#if MC>=10904 if (p instanceof UnloadChunkS2CPacket) {