From 4d278759551495fd443c21742aa8121b0c853529 Mon Sep 17 00:00:00 2001 From: johni0702 Date: Sun, 4 Oct 2015 19:02:11 +0200 Subject: [PATCH] Fix mouse/keys not working when replay is paused --- .../java/com/replaymod/core/ReplayMod.java | 7 +- .../replaymod/core/utils/WrappedTimer.java | 33 +++ .../replaymod/replay/InputReplayTimer.java | 200 ++++++++++++++++++ .../com/replaymod/replay/ReplayModReplay.java | 7 + .../gui/container/AbstractGuiOverlay.java | 4 + src/main/resources/META-INF/replaymod_at.cfg | 3 + 6 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/replaymod/core/utils/WrappedTimer.java create mode 100644 src/main/java/com/replaymod/replay/InputReplayTimer.java diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index 7c97eeee..570fb118 100755 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -23,7 +23,6 @@ import eu.crushedpixel.replaymod.settings.EncodingPreset; import eu.crushedpixel.replaymod.settings.RenderOptions; import eu.crushedpixel.replaymod.settings.ReplaySettings; import eu.crushedpixel.replaymod.sound.SoundHandler; -import eu.crushedpixel.replaymod.timer.ReplayTimer; import eu.crushedpixel.replaymod.utils.OpenGLUtils; import eu.crushedpixel.replaymod.utils.TooltipRenderer; import eu.crushedpixel.replaymod.video.rendering.Pipelines; @@ -177,8 +176,6 @@ public class ReplayMod { @EventHandler public void init(FMLInitializationEvent event) { - mc.timer = new ReplayTimer(); - MinecraftForge.EVENT_BUS.register(guiEventHandler = new GuiEventHandler()); FMLCommonHandler.instance().bus().register(keyInputHandler); @@ -447,4 +444,8 @@ public class ReplayMod { System.exit(-1); } } + + public Minecraft getMinecraft() { + return mc; + } } diff --git a/src/main/java/com/replaymod/core/utils/WrappedTimer.java b/src/main/java/com/replaymod/core/utils/WrappedTimer.java new file mode 100644 index 00000000..f058eb8c --- /dev/null +++ b/src/main/java/com/replaymod/core/utils/WrappedTimer.java @@ -0,0 +1,33 @@ +package com.replaymod.core.utils; + +import net.minecraft.util.Timer; + +public class WrappedTimer extends Timer { + protected final Timer wrapped; + + public WrappedTimer(Timer wrapped) { + super(0); + this.wrapped = wrapped; + copy(wrapped, this); + } + + @Override + public void updateTimer() { + copy(this, wrapped); + wrapped.updateTimer(); + copy(wrapped, this); + } + + protected void copy(Timer from, Timer to) { + to.ticksPerSecond = from.ticksPerSecond; + to.lastHRTime = from.lastHRTime; + to.elapsedTicks = from.elapsedTicks; + to.renderPartialTicks = from.renderPartialTicks; + to.timerSpeed = from.timerSpeed; + to.elapsedPartialTicks = from.elapsedPartialTicks; + to.lastSyncSysClock = from.lastSyncSysClock; + to.lastSyncHRClock = from.lastSyncHRClock; + to.field_74285_i = from.field_74285_i; + to.timeSyncAdjustment = from.timeSyncAdjustment; + } +} diff --git a/src/main/java/com/replaymod/replay/InputReplayTimer.java b/src/main/java/com/replaymod/replay/InputReplayTimer.java new file mode 100644 index 00000000..949f42f0 --- /dev/null +++ b/src/main/java/com/replaymod/replay/InputReplayTimer.java @@ -0,0 +1,200 @@ +package com.replaymod.replay; + +import com.replaymod.core.utils.WrappedTimer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.crash.CrashReport; +import net.minecraft.util.ReportedException; +import net.minecraft.util.Timer; +import net.minecraftforge.client.ForgeHooksClient; +import net.minecraftforge.fml.common.FMLCommonHandler; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.io.IOException; + +public class InputReplayTimer extends WrappedTimer { + private final ReplayModReplay mod; + private final Minecraft mc; + + public InputReplayTimer(Timer wrapped, ReplayModReplay mod) { + super(wrapped); + this.mod = mod; + this.mc = mod.getCore().getMinecraft(); + } + + @Override + public void updateTimer() { + super.updateTimer(); + + // If we are in a replay, we have to manually process key and mouse events as the + // tick speed may vary or there may not be any ticks at all (when the replay is paused) + if (mod.getReplayHandler() != null) { + if (mc.currentScreen == null || mc.currentScreen.allowUserInput) { + while (Mouse.next()) { + handleMouseEvent(); + } + + while (Keyboard.next()) { + handleKeyEvent(); + } + } else { + try { + mc.currentScreen.handleInput(); + } catch (IOException e) { // *SIGH* + e.printStackTrace(); + } + } + } + } + + protected void handleMouseEvent() { + if (ForgeHooksClient.postMouseEvent()) return; + + int button = Mouse.getEventButton() - 100; + boolean pressed = Mouse.getEventButtonState(); + + // Update key binding states + KeyBinding.setKeyBindState(button, pressed); + if (pressed) { + KeyBinding.onTick(button); + } + + int wheel = Mouse.getEventDWheel(); + if (wheel != 0) { + // TODO: Update camera movement speed + } + + if (mc.currentScreen == null) { + if (!mc.inGameHasFocus && Mouse.getEventButtonState()) { + // Regrab mouse if the user clicks into the window + mc.setIngameFocus(); + } + } else { + try { + mc.currentScreen.handleMouseInput(); + } catch (IOException e) { // WHO IS RESPONSIBLE FOR THIS MESS?!? + e.printStackTrace(); + } + } + + FMLCommonHandler.instance().fireMouseInput(); + } + + protected void handleKeyEvent() { + int key = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); + boolean pressed = Keyboard.getEventKeyState(); + + KeyBinding.setKeyBindState(key, pressed); + if (pressed) { + KeyBinding.onTick(key); + } + + // Still want to be able to create debug crashes ]:D + if (mc.debugCrashKeyPressTime > 0) { + if (Minecraft.getSystemTime() - mc.debugCrashKeyPressTime >= 6000L) { + throw new ReportedException(new CrashReport("Manually triggered debug crash", new Throwable())); + } + + if (!Keyboard.isKeyDown(Keyboard.KEY_F3) || !Keyboard.isKeyDown(Keyboard.KEY_C)) { + mc.debugCrashKeyPressTime = -1; + } + } else if (Keyboard.isKeyDown(Keyboard.KEY_F3) && Keyboard.isKeyDown(Keyboard.KEY_C)) { + mc.debugCrashKeyPressTime = Minecraft.getSystemTime(); + } + + // Twitch, screenshot, fullscreen, etc. (stuff that works everywhere) + mc.dispatchKeypresses(); + + if (pressed) { + // This might be subject to change as vanilla shaders are still kinda unused in 1.8 + if (key == Keyboard.KEY_F4 && mc.entityRenderer != null) { + mc.entityRenderer.switchUseShader(); + } + + if (mc.currentScreen != null) { + try { + mc.currentScreen.handleKeyboardInput(); + } catch (IOException e) { // AND WHO THOUGHT THIS WAS A GREAT IDEA? + e.printStackTrace(); + } + } else { + if (key == Keyboard.KEY_ESCAPE) { + mc.displayInGameMenu(); + } + + // Following are a ton of vanilla keyboard shortcuts, some are removed as they're useless in the + // replay viewer as of now + // TODO: Translate magic values to Keyboard.KEY_ constants + + if (key == 32 && Keyboard.isKeyDown(61) && mc.ingameGUI != null) { + mc.ingameGUI.getChatGUI().clearChatMessages(); + } + + if (key == 31 && Keyboard.isKeyDown(61)) { + mc.refreshResources(); + } + + if (key == 20 && Keyboard.isKeyDown(61)) { + mc.refreshResources(); + } + + if (key == 33 && Keyboard.isKeyDown(61)) { + boolean flag1 = Keyboard.isKeyDown(42) | Keyboard.isKeyDown(54); + mc.gameSettings.setOptionValue(GameSettings.Options.RENDER_DISTANCE, flag1 ? -1 : 1); + } + + if (key == 30 && Keyboard.isKeyDown(61)) { + mc.renderGlobal.loadRenderers(); + } + + if (key == 48 && Keyboard.isKeyDown(61)) { + mc.getRenderManager().setDebugBoundingBox(!mc.getRenderManager().isDebugBoundingBox()); + } + + if (key == 25 && Keyboard.isKeyDown(61)) { + mc.gameSettings.pauseOnLostFocus = !mc.gameSettings.pauseOnLostFocus; + mc.gameSettings.saveOptions(); + } + + if (key == 59) { + mc.gameSettings.hideGUI = !mc.gameSettings.hideGUI; + } + + if (key == 61) { + mc.gameSettings.showDebugInfo = !mc.gameSettings.showDebugInfo; + mc.gameSettings.showDebugProfilerChart = GuiScreen.isShiftKeyDown(); + } + + if (mc.gameSettings.keyBindTogglePerspective.isPressed()) { + mc.gameSettings.thirdPersonView = (mc.gameSettings.thirdPersonView + 1) % 3; + + if (mc.entityRenderer != null) { // Extra check, not in vanilla code + if (mc.gameSettings.thirdPersonView == 0) { + mc.entityRenderer.loadEntityShader(mc.getRenderViewEntity()); + } else if (mc.gameSettings.thirdPersonView == 1) { + mc.entityRenderer.loadEntityShader(null); + } + } + } + } + + // Navigation in the debug chart + if (mc.gameSettings.showDebugInfo && mc.gameSettings.showDebugProfilerChart) { + if (key == Keyboard.KEY_0) { + mc.updateDebugProfilerName(0); + } + + for (int i = 0; i < 9; ++i) { + if (key == 2 + i) { + mc.updateDebugProfilerName(i + 1); + } + } + } + } + + FMLCommonHandler.instance().fireKeyInput(); + } +} diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index 8595eb23..e98376cc 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -89,6 +89,9 @@ public class ReplayModReplay { @Mod.EventHandler public void init(FMLInitializationEvent event) { + Minecraft mc = core.getMinecraft(); + mc.timer = new InputReplayTimer(mc.timer, this); + new GuiHandler(this).register(); } @@ -96,4 +99,8 @@ public class ReplayModReplay { ReplayFile replayFile = new ZipReplayFile(new ReplayStudio(), file); replayHandler = new ReplayHandler(replayFile, true); } + + public ReplayMod getCore() { + return core; + } } diff --git a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java index 36130eff..32a3a9b5 100644 --- a/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java +++ b/src/main/java/de/johni0702/minecraft/gui/container/AbstractGuiOverlay.java @@ -205,6 +205,10 @@ public abstract class AbstractGuiOverlay> extend protected class UserInputGuiScreen extends net.minecraft.client.gui.GuiScreen { + { + allowUserInput = true; + } + @Override protected void keyTyped(char typedChar, int keyCode) throws IOException { forEach(Typeable.class).typeKey(MouseUtils.getMousePos(), keyCode, typedChar, isCtrlKeyDown(), isShiftKeyDown()); diff --git a/src/main/resources/META-INF/replaymod_at.cfg b/src/main/resources/META-INF/replaymod_at.cfg index a728ce6d..a9b1eb00 100644 --- a/src/main/resources/META-INF/replaymod_at.cfg +++ b/src/main/resources/META-INF/replaymod_at.cfg @@ -104,5 +104,8 @@ public net.minecraft.crash.CrashReportCategory$Entry # KeyBinding public net.minecraft.client.settings.KeyBinding field_151474_i # pressTime +# Timer +public net.minecraft.util.Timer * + # Example # public net.minecraft.package.ClassName func_some_id(Ljava/lang/Class;IZS)V # methodName