From c72392fb62f831e77257193fb8d05931a098a083 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Fri, 14 Jun 2019 14:49:54 +0200 Subject: [PATCH] Fix various NPE while in replay on 1.8.9 or below Nulling the world and calling runTick proved to be too volatile, so instead let's try performing an early return from runTick via mixin. --- .../replaymod/core/mixin/MixinMinecraft.java | 16 +++++++- .../com/replaymod/core/versions/MCVer.java | 4 ++ .../replaymod/replay/InputReplayTimer.java | 37 +++++++++---------- 3 files changed, 35 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java b/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java index 9f2b22bb..2a7f9b51 100644 --- a/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java +++ b/src/main/java/com/replaymod/core/mixin/MixinMinecraft.java @@ -5,12 +5,12 @@ import net.minecraft.client.MinecraftClient; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //#if MC>=11300 import com.replaymod.core.events.PostRenderCallback; import com.replaymod.core.events.PreRenderCallback; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; //#else //$$ import org.spongepowered.asm.mixin.injection.Redirect; //$$ import com.replaymod.replay.InputReplayTimer; @@ -84,6 +84,18 @@ public abstract class MixinMinecraft //$$ e.printStackTrace(); //$$ } //$$ } + //#else + //$$ private boolean earlyReturn; + //$$ + //$$ @Override + //$$ public void replayModSetEarlyReturnFromRunTick(boolean earlyReturn) { + //$$ this.earlyReturn = earlyReturn; + //$$ } + //$$ + //$$ @Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;sendClickBlockToController(Z)V"), cancellable = true) + //$$ private void doEarlyReturnFromRunTick(CallbackInfo ci) { + //$$ if (earlyReturn) ci.cancel(); + //$$ } //#endif //$$ @Redirect( //#if MC>=10904 diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index e720aa87..3cccfd68 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -477,8 +477,12 @@ public class MCVer { //#if MC>=11300 void replayModProcessKeyBinds(); //#else + //#if MC>=10904 //$$ void replayModRunTickMouse(); //$$ void replayModRunTickKeyboard(); + //#else + //$$ void replayModSetEarlyReturnFromRunTick(boolean earlyReturn); + //#endif //#endif //#if MC>=11400 void replayModExecuteTaskQueue(); diff --git a/src/main/java/com/replaymod/replay/InputReplayTimer.java b/src/main/java/com/replaymod/replay/InputReplayTimer.java index b1f1cc1b..862c449f 100644 --- a/src/main/java/com/replaymod/replay/InputReplayTimer.java +++ b/src/main/java/com/replaymod/replay/InputReplayTimer.java @@ -67,7 +67,6 @@ public class InputReplayTimer extends WrappedTimer { } mc.keyboard.pollDebugCrash(); //#else - //#if MC>=10904 //$$ if (mc.currentScreen != null) { //#if MC>=10800 //$$ try { @@ -80,26 +79,24 @@ public class InputReplayTimer extends WrappedTimer { //#endif //$$ } //$$ if (mc.currentScreen == null || mc.currentScreen.allowUserInput) { - //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModRunTickMouse(); - //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModRunTickKeyboard(); + //#if MC>=10904 + //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModRunTickMouse(); + //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModRunTickKeyboard(); + //#else + //$$ // 1.8.9 and below has one giant tick function, so we try to only do keyboard & mouse as far as possible + //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModSetEarlyReturnFromRunTick(true); + //#if MC>=10800 + //$$ try { + //$$ mc.runTick(); + //$$ } catch (IOException e) { // *SIGH* + //$$ e.printStackTrace(); + //$$ } + //#else + //$$ mc.runTick(); + //#endif + //$$ ((MCVer.MinecraftMethodAccessor) mc).replayModSetEarlyReturnFromRunTick(false); + //#endif //$$ } - //#else - //$$ // 1.8.9 and below has one giant tick function, so we try to only do keyboard & mouse as far as possible - //$$ WorldClient world = mc.theWorld; - //$$ mc.theWorld = null; - //#if MC>=10800 - //$$ try { - //$$ mc.runTick(); - //$$ } catch (IOException e) { // *SIGH* - //$$ e.printStackTrace(); - //$$ } - //#else - //$$ mc.runTick(); - //#endif - //$$ if (mc.theWorld == null) { - //$$ mc.theWorld = world; - //$$ } - //#endif //#endif } }