Fix race condition between inbound and injected packets (fixes #118)

In the case of #118, this was resulting in the EntityTrackerUpdate packet (which
contains info on which skin layers should be visible) sometimes ending up before
the SpawnPlayer packet, hence the players outer skin layers being invisible at
the start of the recording.
This commit is contained in:
Jonas Herzig
2020-04-06 15:10:32 +02:00
parent ee68a63233
commit b4a2c1b266
3 changed files with 17 additions and 0 deletions

View File

@@ -394,6 +394,14 @@ public class MCVer {
//#endif //#endif
} }
public static void scheduleOnMainThread(Runnable runnable) {
//#if MC>=11400
getMinecraft().send(runnable);
//#else
//$$ getMinecraft().addScheduledTask(runnable);
//#endif
}
//#if MC>=11400 //#if MC>=11400
public static Window getWindow(MinecraftClient mc) { public static Window getWindow(MinecraftClient mc) {
//#if MC>=11500 //#if MC>=11500

View File

@@ -57,6 +57,7 @@ public abstract class MixinNetHandlerPlayClient {
//$$ @Inject(method = "handlePlayerListItem", at=@At("HEAD")) //$$ @Inject(method = "handlePlayerListItem", at=@At("HEAD"))
//#endif //#endif
public void recordOwnJoin(PlayerListS2CPacket packet, CallbackInfo ci) { public void recordOwnJoin(PlayerListS2CPacket packet, CallbackInfo ci) {
if (!MCVer.isOnMainThread()) return;
if (mcStatic.player == null) return; if (mcStatic.player == null) return;
RecordingEventHandler handler = getRecordingEventHandler(); RecordingEventHandler handler = getRecordingEventHandler();

View File

@@ -149,6 +149,14 @@ public class PacketListener extends ChannelInboundHandlerAdapter {
} }
public void save(Packet packet) { public void save(Packet packet) {
// If we're not on the main thread (i.e. we're on the netty thread), then we need to schedule the saving
// to happen on the main thread so we can guarantee correct ordering of inbound and inject packets.
// Otherwise, injected packets may end up further down the packet stream than they were supposed to and other
// inbound packets which may rely on the injected packet would behave incorrectly when played back.
if (!MCVer.isOnMainThread()) {
MCVer.scheduleOnMainThread(() -> save(packet));
return;
}
try { try {
if(packet instanceof PlayerSpawnS2CPacket) { if(packet instanceof PlayerSpawnS2CPacket) {
//#if MC>=10800 //#if MC>=10800