From fc1ae0e10919b01be991dca3ddf2197912db8f40 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 16:24:33 +0200 Subject: [PATCH 1/7] Hide unsupported render methods in settings gui (fixes #284) --- .../com/replaymod/render/RenderSettings.java | 27 +++++++++++++++++++ .../render/gui/GuiRenderSettings.java | 17 ++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/replaymod/render/RenderSettings.java b/src/main/java/com/replaymod/render/RenderSettings.java index 2a972888..529732d3 100644 --- a/src/main/java/com/replaymod/render/RenderSettings.java +++ b/src/main/java/com/replaymod/render/RenderSettings.java @@ -47,6 +47,21 @@ public class RenderSettings { public boolean hasFixedAspectRatio() { return this == EQUIRECTANGULAR || this == ODS || this == CUBIC; } + + @SuppressWarnings("RedundantIfStatement") + public boolean isSupported() { + //#if MC<10800 || MC>=11500 + if (this == BLEND) { + return false; + } + //#endif + + return true; + } + + public static RenderMethod[] getSupported() { + return Arrays.stream(values()).filter(RenderMethod::isSupported).toArray(RenderMethod[]::new); + } } public enum EncodingPreset { @@ -90,6 +105,18 @@ public class RenderSettings { public String toString() { return I18n.translate("replaymod.gui.rendersettings.presets." + name().replace('_', '.').toLowerCase()); } + + public boolean isSupported() { + if (this == BLEND) { + return RenderMethod.BLEND.isSupported(); + } else { + return true; + } + } + + public static EncodingPreset[] getSupported() { + return Arrays.stream(values()).filter(EncodingPreset::isSupported).toArray(EncodingPreset[]::new); + } } @AllArgsConstructor diff --git a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java index 46ff2570..75d60f95 100644 --- a/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java +++ b/src/main/java/com/replaymod/render/gui/GuiRenderSettings.java @@ -75,7 +75,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { } updateInputs(); } - }).setMinSize(new Dimension(0, 20)).setValues(RenderSettings.RenderMethod.values()); + }).setMinSize(new Dimension(0, 20)).setValues(RenderSettings.RenderMethod.getSupported()); { for (Map.Entry entry : @@ -102,7 +102,7 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { } updateInputs(); } - }).setMinSize(new Dimension(0, 20)).setValues(RenderSettings.EncodingPreset.values()); + }).setMinSize(new Dimension(0, 20)).setValues(RenderSettings.EncodingPreset.getSupported()); public final GuiNumberField videoWidth = new GuiNumberField().setSize(50, 20).setMinValue(1).setValidateOnFocusChange(true); public final GuiNumberField videoHeight = new GuiNumberField().setSize(50, 20).setMinValue(1).setValidateOnFocusChange(true); @@ -450,12 +450,6 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { } } - //#if MC<10800 || MC>=11500 - if (method == RenderSettings.RenderMethod.BLEND) { - return "replaymod.gui.rendersettings.no_blend_on_1_7_10"; - } - //#endif - return null; } @@ -489,8 +483,13 @@ public class GuiRenderSettings extends GuiScreen implements Closeable { } public void load(RenderSettings settings) { - renderMethodDropdown.setSelected(settings.getRenderMethod()); + if (settings.getRenderMethod().isSupported()) { + renderMethodDropdown.setSelected(settings.getRenderMethod()); + } RenderSettings.EncodingPreset encodingPreset = settings.getEncodingPreset(); + if (!encodingPreset.isSupported()) { + encodingPreset = null; + } if (encodingPreset == null) { encodingPreset = getDefaultRenderSettings().getEncodingPreset(); } From 5983d99354ef11db973f748a80eea335a8a25191 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 16:57:36 +0200 Subject: [PATCH 2/7] Fix jittering once a tick during rendering pre-1.16 (fixes #264) The fetching of the ticks variable was accidentally moved to before the timer update while updating to 1.16, this caused the interpolation to be off by one tick each frame in which the timer advances to the next tick. --- .../java/com/replaymod/render/rendering/VideoRenderer.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java index de488519..34799f86 100644 --- a/src/main/java/com/replaymod/render/rendering/VideoRenderer.java +++ b/src/main/java/com/replaymod/render/rendering/VideoRenderer.java @@ -236,14 +236,15 @@ public class VideoRenderer implements RenderInfo { RenderTickCounter timer = ((MinecraftAccessor) mc).getTimer(); //#if MC>=11600 //$$ int elapsedTicks = - //#else - int elapsedTicks = timer.ticksThisFrame; //#endif timer.beginRenderTick( //#if MC>=11400 MCVer.milliTime() //#endif ); + //#if MC<11600 + int elapsedTicks = timer.ticksThisFrame; + //#endif executeTaskQueue(); From 35cc78c70c83c9004092a5b14744f277fa437eb5 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 17:19:38 +0200 Subject: [PATCH 3/7] Fix crash due to invalid characters in video file name (fixes #265) 037d54f Prevent FileChooserPopup from selecting invalid file names --- jGui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jGui b/jGui index 20e11e08..037d54f8 160000 --- a/jGui +++ b/jGui @@ -1 +1 @@ -Subproject commit 20e11e080336cf7da2de2d2546d1013589131507 +Subproject commit 037d54f83a736123a7b834f2485b0adc08744033 From a4b6e9262741ad04e41c9cc595ee52512171ba6c Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 18:43:33 +0200 Subject: [PATCH 4/7] Position recording control buttons relative to Exit (fixes #281) --- .../com/replaymod/core/versions/MCVer.java | 32 +++++++++++ .../recording/gui/GuiRecordingControls.java | 55 ++++++++++++------- 2 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/main/java/com/replaymod/core/versions/MCVer.java b/src/main/java/com/replaymod/core/versions/MCVer.java index de5ae5c5..0df685db 100644 --- a/src/main/java/com/replaymod/core/versions/MCVer.java +++ b/src/main/java/com/replaymod/core/versions/MCVer.java @@ -42,6 +42,12 @@ import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.gui.widget.AbstractButtonWidget; import java.util.concurrent.CompletableFuture; + +//#if MC>=11600 +//$$ import net.minecraft.text.TranslatableText; +//#else +import net.minecraft.client.resource.language.I18n; +//#endif //#else //$$ import com.google.common.util.concurrent.FutureCallback; //$$ import com.google.common.util.concurrent.Futures; @@ -119,6 +125,7 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.Callable; import java.util.function.Consumer; +import java.util.Optional; /** * Abstraction over things that have changed between different MC versions. @@ -603,6 +610,31 @@ public class MCVer { //#endif } + //#if MC>=11400 + public static Optional findButton(List buttonList, @SuppressWarnings("unused") String text, @SuppressWarnings("unused") int id) { + //#if MC>=11600 + //$$ final TranslatableText message = new TranslatableText(text); + //#else + final String message = I18n.translate(text); + //#endif + for (AbstractButtonWidget b : buttonList) { + if (message.equals(b.getMessage())) { + return Optional.of(b); + } + } + return Optional.empty(); + } + //#else + //$$ public static Optional findButton(List buttonList, @SuppressWarnings("unused") String text, int id) { + //$$ for (GuiButton b : buttonList) { + //$$ if (b.id == id) { + //$$ return Optional.of(b); + //$$ } + //$$ } + //$$ return Optional.empty(); + //$$ } + //#endif + //#if MC>=11400 public static void processKeyBinds() { ((MinecraftMethodAccessor) getMinecraft()).replayModProcessKeyBinds(); diff --git a/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java b/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java index d4b2d5de..c34c21e2 100644 --- a/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java +++ b/src/main/java/com/replaymod/recording/gui/GuiRecordingControls.java @@ -7,13 +7,13 @@ import com.replaymod.editor.gui.MarkerProcessor; import com.replaymod.recording.Setting; import com.replaymod.recording.packet.PacketListener; import de.johni0702.minecraft.gui.container.GuiPanel; -import de.johni0702.minecraft.gui.container.GuiScreen; import de.johni0702.minecraft.gui.container.VanillaGuiScreen; import de.johni0702.minecraft.gui.element.GuiButton; import de.johni0702.minecraft.gui.layout.CustomLayout; import de.johni0702.minecraft.gui.layout.HorizontalLayout; import de.johni0702.minecraft.gui.utils.EventRegistrations; import net.minecraft.client.gui.screen.GameMenuScreen; +import net.minecraft.client.gui.screen.Screen; //#if FABRIC>=1 import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback; @@ -25,6 +25,14 @@ import de.johni0702.minecraft.gui.versions.callbacks.InitScreenCallback; //$$ import static com.replaymod.core.versions.MCVer.getGui; //#endif +//#if MC>=11400 +import net.minecraft.client.gui.widget.AbstractButtonWidget; +//#endif + +import java.util.List; +import java.util.Optional; +import java.util.function.Function; + public class GuiRecordingControls extends EventRegistrations { private ReplayMod core; private PacketListener packetListener; @@ -70,21 +78,6 @@ public class GuiRecordingControls extends EventRegistrations { updateState(); } - //#if FABRIC>=1 - { on(InitScreenCallback.EVENT, (screen, buttons) -> { - if (screen instanceof GameMenuScreen) { - show((GameMenuScreen) screen); - } - }); } - //#else - //$$ @SubscribeEvent - //$$ public void onGuiInit(GuiScreenEvent.InitGuiEvent.Post event) { - //$$ if (getGui(event) instanceof IngameMenuScreen) { - //$$ show((IngameMenuScreen) getGui(event)); - //$$ } - //$$ } - //#endif - private void updateState() { buttonPauseResume.setI18nLabel("replaymod.gui.recording." + (paused ? "resume" : "pause")); buttonStartStop.setI18nLabel("replaymod.gui.recording." + (stopped ? "start" : "stop")); @@ -92,12 +85,32 @@ public class GuiRecordingControls extends EventRegistrations { buttonPauseResume.setEnabled(!stopped); } - public void show(GameMenuScreen gui) { - int modMenuOffset = MCVer.isModLoaded("modmenu") ? 12 : 0; - VanillaGuiScreen.setup(gui).setLayout(new CustomLayout() { + //#if FABRIC>=1 + { on(InitScreenCallback.EVENT, this::injectIntoIngameMenu); } + private void injectIntoIngameMenu(Screen guiScreen, List buttonList) { + //#else + //$$ @SubscribeEvent + //$$ public void injectIntoIngameMenu(GuiScreenEvent.InitGuiEvent.Post event) { + //$$ Screen guiScreen = getGui(event); + //#if MC>=11400 + //$$ List buttonList = MCVer.getButtonList(event); + //#else + //$$ List buttonList = MCVer.getButtonList(event); + //#endif + //#endif + if (!(guiScreen instanceof GameMenuScreen)) { + return; + } + Function yPos = + MCVer.findButton(buttonList, "menu.returnToMenu", 1) + .map(Optional::of) + .orElse(MCVer.findButton(buttonList, "menu.disconnect", 1)) + .>map(it -> (height) -> it.y) + .orElse((height) -> height / 4 + 120 - 16); + VanillaGuiScreen.setup(guiScreen).setLayout(new CustomLayout() { @Override - protected void layout(GuiScreen container, int width, int height) { - pos(panel, width / 2 - 100, height / 4 + 128 + modMenuOffset); + protected void layout(de.johni0702.minecraft.gui.container.GuiScreen container, int width, int height) { + pos(panel, width / 2 - 100, yPos.apply(height) + 16 + 8); } }).addElements(null, panel); } From 8d82953c0b9bdaa5a4b5c4fa197bc32064f7e0e1 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 19:30:09 +0200 Subject: [PATCH 5/7] Fix hands always rendering with 1.16 OF shaders (fixes #280) --- .../shaders/mixin/MixinShadersRender.java | 19 +++++++++++++++++-- .../render/hooks/EntityRendererHandler.java | 10 +++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/replaymod/compat/shaders/mixin/MixinShadersRender.java b/src/main/java/com/replaymod/compat/shaders/mixin/MixinShadersRender.java index 9e06dd27..58f59ec1 100644 --- a/src/main/java/com/replaymod/compat/shaders/mixin/MixinShadersRender.java +++ b/src/main/java/com/replaymod/compat/shaders/mixin/MixinShadersRender.java @@ -7,6 +7,11 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +//#if MC>=11600 +//$$ import net.minecraft.client.render.Camera; +//$$ import net.minecraft.client.util.math.MatrixStack; +//#endif + //#if MC>=11400 import com.replaymod.core.events.PreRenderHandCallback; //#else @@ -21,8 +26,18 @@ import com.replaymod.core.events.PreRenderHandCallback; }, remap = false) public abstract class MixinShadersRender { - @Inject(method = "renderHand0", at = @At("HEAD"), cancellable = true, remap = false) - private static void replayModCompat_disableRenderHand0(GameRenderer er, float partialTicks, int renderPass, CallbackInfo ci) { + @Inject(method = { "renderHand0", "renderHand1" }, at = @At("HEAD"), cancellable = true, remap = false) + private static void replayModCompat_disableRenderHand0( + GameRenderer er, + //#if MC>=11600 + //$$ MatrixStack stack, + //$$ Camera camera, + //#endif + float partialTicks, + //#if MC<11600 + int renderPass, + //#endif + CallbackInfo ci) { //#if MC>=11400 if (PreRenderHandCallback.EVENT.invoker().preRenderHand()) { //#else diff --git a/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java b/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java index 9d335a74..de08ec2c 100644 --- a/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java +++ b/src/main/java/com/replaymod/render/hooks/EntityRendererHandler.java @@ -5,6 +5,7 @@ import com.replaymod.render.RenderSettings; import com.replaymod.render.capturer.CaptureData; import com.replaymod.render.capturer.RenderInfo; import com.replaymod.render.capturer.WorldRenderer; +import de.johni0702.minecraft.gui.utils.EventRegistrations; import lombok.Getter; import net.minecraft.client.MinecraftClient; @@ -15,6 +16,7 @@ import net.minecraft.client.util.math.MatrixStack; //#if MC>=11400 import com.replaymod.core.events.PostRenderCallback; import com.replaymod.core.events.PreRenderCallback; +import com.replaymod.core.events.PreRenderHandCallback; //#else //#if MC>=11400 //$$ import net.minecraftforge.fml.hooks.BasicEventHooks; @@ -25,7 +27,7 @@ import com.replaymod.core.events.PreRenderCallback; import java.io.IOException; -public class EntityRendererHandler implements WorldRenderer { +public class EntityRendererHandler extends EventRegistrations implements WorldRenderer { public final MinecraftClient mc = MCVer.getMinecraft(); @Getter @@ -42,7 +44,12 @@ public class EntityRendererHandler implements WorldRenderer { this.settings = settings; this.renderInfo = renderInfo; + //#if MC>=11400 + on(PreRenderHandCallback.EVENT, () -> omnidirectional); + //#endif + ((IEntityRenderer) mc.gameRenderer).replayModRender_setHandler(this); + register(); } @Override @@ -84,6 +91,7 @@ public class EntityRendererHandler implements WorldRenderer { @Override public void close() throws IOException { ((IEntityRenderer) mc.gameRenderer).replayModRender_setHandler(null); + unregister(); } @Override From 063657af4ca4ac647da6c49b361ead8ce971e5b1 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 19:51:09 +0200 Subject: [PATCH 6/7] Fix DELETE keybinding on 1.14+ (fixes #270) --- src/main/java/com/replaymod/core/KeyBindingRegistry.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/replaymod/core/KeyBindingRegistry.java b/src/main/java/com/replaymod/core/KeyBindingRegistry.java index 35a2163d..efbe38bc 100644 --- a/src/main/java/com/replaymod/core/KeyBindingRegistry.java +++ b/src/main/java/com/replaymod/core/KeyBindingRegistry.java @@ -23,6 +23,7 @@ import static com.replaymod.core.ReplayMod.MOD_ID; import com.replaymod.core.events.KeyBindingEventCallback; import com.replaymod.core.events.KeyEventCallback; import com.replaymod.core.events.PreRenderCallback; +import org.lwjgl.glfw.GLFW; //#else //$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; //$$ import net.minecraftforge.fml.common.gameevent.InputEvent; @@ -133,7 +134,7 @@ public class KeyBindingRegistry extends EventRegistrations { //#if MC>=11400 private void handleRaw(int keyCode, int action) { - if (action != 0) return; + if (action != GLFW.GLFW_PRESS) return; //#else //$$ private void handleRaw() { //$$ int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey(); From fd7b6030f9f34197fbd7a8ff8061c336cb8b8775 Mon Sep 17 00:00:00 2001 From: Jonas Herzig Date: Sat, 25 Jul 2020 21:34:30 +0200 Subject: [PATCH 7/7] Fix keybinding conflicts on 1.14+ (fixes #268) This fixes both, replay-exclusive keybindings blocking vanilla ones as well as vanilla keybindings blocking replay-exclusive ones. The magic happens in Mixin_ContextualKeyBindings. --- .../replaymod/core/KeyBindingRegistry.java | 22 +++++-- .../java/com/replaymod/core/ReplayMod.java | 2 +- .../mixin/Mixin_ContextualKeyBindings.java | 63 +++++++++++++++++++ .../com/replaymod/extras/FullBrightness.java | 2 +- .../extras/playeroverview/PlayerOverview.java | 2 +- .../recording/ReplayModRecording.java | 2 +- .../com/replaymod/replay/ReplayHandler.java | 2 +- .../com/replaymod/replay/ReplayModReplay.java | 23 ++++--- .../simplepathing/ReplayModSimplePathing.java | 6 +- .../simplepathing/preview/PathPreview.java | 2 +- src/main/resources/mixins.core.replaymod.json | 1 + 11 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 src/main/java/com/replaymod/core/mixin/Mixin_ContextualKeyBindings.java diff --git a/src/main/java/com/replaymod/core/KeyBindingRegistry.java b/src/main/java/com/replaymod/core/KeyBindingRegistry.java index efbe38bc..addb407e 100644 --- a/src/main/java/com/replaymod/core/KeyBindingRegistry.java +++ b/src/main/java/com/replaymod/core/KeyBindingRegistry.java @@ -35,7 +35,9 @@ import org.lwjgl.glfw.GLFW; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; public class KeyBindingRegistry extends EventRegistrations { private static final String CATEGORY = "replaymod.title"; @@ -44,19 +46,20 @@ public class KeyBindingRegistry extends EventRegistrations { //#endif private Map keyBindings = new HashMap(); + private Set onlyInReplay = new HashSet<>(); private Multimap keyBindingHandlers = ArrayListMultimap.create(); private Multimap repeatedKeyBindingHandlers = ArrayListMultimap.create(); private Multimap rawHandlers = ArrayListMultimap.create(); - public void registerKeyBinding(String name, int keyCode, Runnable whenPressed) { - keyBindingHandlers.put(registerKeyBinding(name, keyCode), whenPressed); + public void registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) { + keyBindingHandlers.put(registerKeyBinding(name, keyCode, onlyInRepay), whenPressed); } - public void registerRepeatedKeyBinding(String name, int keyCode, Runnable whenPressed) { - repeatedKeyBindingHandlers.put(registerKeyBinding(name, keyCode), whenPressed); + public void registerRepeatedKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) { + repeatedKeyBindingHandlers.put(registerKeyBinding(name, keyCode, onlyInRepay), whenPressed); } - private KeyBinding registerKeyBinding(String name, int keyCode) { + private KeyBinding registerKeyBinding(String name, int keyCode, boolean onlyInRepay) { KeyBinding keyBinding = keyBindings.get(name); if (keyBinding == null) { //#if FABRIC>=1 @@ -72,6 +75,11 @@ public class KeyBindingRegistry extends EventRegistrations { //$$ ClientRegistry.registerKeyBinding(keyBinding); //#endif keyBindings.put(name, keyBinding); + if (onlyInRepay) { + this.onlyInReplay.add(keyBinding); + } + } else if (!onlyInRepay) { + this.onlyInReplay.remove(keyBinding); } return keyBinding; } @@ -84,6 +92,10 @@ public class KeyBindingRegistry extends EventRegistrations { return Collections.unmodifiableMap(keyBindings); } + public Set getOnlyInReplay() { + return Collections.unmodifiableSet(onlyInReplay); + } + //#if MC>=11400 { on(KeyBindingEventCallback.EVENT, this::handleKeyBindings); } { on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); } diff --git a/src/main/java/com/replaymod/core/ReplayMod.java b/src/main/java/com/replaymod/core/ReplayMod.java index 0fb75540..48388e23 100644 --- a/src/main/java/com/replaymod/core/ReplayMod.java +++ b/src/main/java/com/replaymod/core/ReplayMod.java @@ -318,7 +318,7 @@ public class ReplayMod implements public void registerKeyBindings(KeyBindingRegistry registry) { registry.registerKeyBinding("replaymod.input.settings", 0, () -> { new GuiReplaySettings(null, settingsRegistry).display(); - }); + }, false); } @Override diff --git a/src/main/java/com/replaymod/core/mixin/Mixin_ContextualKeyBindings.java b/src/main/java/com/replaymod/core/mixin/Mixin_ContextualKeyBindings.java new file mode 100644 index 00000000..18e1ec58 --- /dev/null +++ b/src/main/java/com/replaymod/core/mixin/Mixin_ContextualKeyBindings.java @@ -0,0 +1,63 @@ +//#if MC>=11400 +package com.replaymod.core.mixin; + +import com.replaymod.core.ReplayMod; +import com.replaymod.replay.ReplayModReplay; +import net.minecraft.client.options.KeyBinding; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * We have bunch of keybindings which only have an effect while in a replay but heavily conflict with vanilla ones + * otherwise. To work around this, we prevent our keybindings (or conflicting ones) from making it into the keysByCode + * map, depending on the current context. + */ +@Mixin(KeyBinding.class) +public class Mixin_ContextualKeyBindings { + @Shadow @Final private static Map keysById; + + @Unique private static final List temporarilyRemoved = new ArrayList<>(); + + @Inject(method = "updateKeysByCode", at = @At("HEAD")) + private static void preContextualKeyBindings(CallbackInfo ci) { + Set onlyInReplay = ReplayMod.instance.getKeyBindingRegistry().getOnlyInReplay(); + if (ReplayModReplay.instance.getReplayHandler() != null) { + // In replay, remove any conflicting key bindings, so that ours are guaranteed in + Mixin_ContextualKeyBindings.keysById.values().removeIf(keyBinding -> { + for (KeyBinding exclusiveBinding : onlyInReplay) { + if (keyBinding.equals(exclusiveBinding) && keyBinding != exclusiveBinding) { + temporarilyRemoved.add(keyBinding); + return true; + } + } + return false; + }); + } else { + // Not in a replay, remove all replay-exclusive keybindings + for (KeyBinding keyBinding : onlyInReplay) { + if (Mixin_ContextualKeyBindings.keysById.remove(keyBinding.getId()) != null) { + temporarilyRemoved.add(keyBinding); + } + } + } + } + + @Inject(method = "updateKeysByCode", at = @At("RETURN")) + private static void postContextualKeyBindings(CallbackInfo ci) { + for (KeyBinding keyBinding : temporarilyRemoved) { + Mixin_ContextualKeyBindings.keysById.put(keyBinding.getId(), keyBinding); + } + temporarilyRemoved.clear(); + } +} +//#endif diff --git a/src/main/java/com/replaymod/extras/FullBrightness.java b/src/main/java/com/replaymod/extras/FullBrightness.java index 5587e3f8..2459af5b 100644 --- a/src/main/java/com/replaymod/extras/FullBrightness.java +++ b/src/main/java/com/replaymod/extras/FullBrightness.java @@ -53,7 +53,7 @@ public class FullBrightness extends EventRegistrations implements Extra { updateIndicator(replayHandler.getOverlay()); } } - }); + }, true); register(); } diff --git a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java index 65fa6a3b..0cbbbf8c 100644 --- a/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java +++ b/src/main/java/com/replaymod/extras/playeroverview/PlayerOverview.java @@ -93,7 +93,7 @@ public class PlayerOverview extends EventRegistrations implements Extra { new PlayerOverviewGui(PlayerOverview.this, players).display(); } } - }); + }, true); register(); } diff --git a/src/main/java/com/replaymod/recording/ReplayModRecording.java b/src/main/java/com/replaymod/recording/ReplayModRecording.java index b37a416d..94ae0902 100644 --- a/src/main/java/com/replaymod/recording/ReplayModRecording.java +++ b/src/main/java/com/replaymod/recording/ReplayModRecording.java @@ -58,7 +58,7 @@ public class ReplayModRecording implements Module { core.printInfoToChat("replaymod.chat.addedmarker"); } } - }); + }, false); } @Override diff --git a/src/main/java/com/replaymod/replay/ReplayHandler.java b/src/main/java/com/replaymod/replay/ReplayHandler.java index 18769e4d..5c88dfc0 100644 --- a/src/main/java/com/replaymod/replay/ReplayHandler.java +++ b/src/main/java/com/replaymod/replay/ReplayHandler.java @@ -237,7 +237,7 @@ public class ReplayHandler { //#endif overlay.setVisible(false); - ReplayModReplay.instance.replayHandler = null; + ReplayModReplay.instance.forcefullyStopReplay(); mc.openScreen(null); diff --git a/src/main/java/com/replaymod/replay/ReplayModReplay.java b/src/main/java/com/replaymod/replay/ReplayModReplay.java index da416ae3..cd484740 100644 --- a/src/main/java/com/replaymod/replay/ReplayModReplay.java +++ b/src/main/java/com/replaymod/replay/ReplayModReplay.java @@ -23,6 +23,7 @@ import com.replaymod.replaystudio.replay.ReplayFile; import com.replaymod.replaystudio.replay.ZipReplayFile; import com.replaymod.replaystudio.studio.ReplayStudio; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.options.KeyBinding; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -46,7 +47,7 @@ public class ReplayModReplay implements Module { public static Logger LOGGER = LogManager.getLogger(); - protected ReplayHandler replayHandler; + private ReplayHandler replayHandler; public ReplayHandler getReplayHandler() { return replayHandler; @@ -78,7 +79,7 @@ public class ReplayModReplay implements Module { } } } - }); + }, true); registry.registerKeyBinding("replaymod.input.thumbnail", Keyboard.KEY_N, new Runnable() { @Override @@ -113,7 +114,7 @@ public class ReplayModReplay implements Module { }); } } - }); + }, true); registry.registerKeyBinding("replaymod.input.playpause", Keyboard.KEY_P, new Runnable() { @Override @@ -122,7 +123,7 @@ public class ReplayModReplay implements Module { replayHandler.getOverlay().playPauseButton.onClick(); } } - }); + }, true); registry.registerKeyBinding("replaymod.input.quickmode", Keyboard.KEY_Q, () -> { if (replayHandler != null) { @@ -133,19 +134,19 @@ public class ReplayModReplay implements Module { replayHandler.getReplaySender().setAsyncMode(true); })); } - }); + }, true); core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.rollclockwise", Keyboard.KEY_L, () -> { // Noop, actual handling logic in CameraEntity#update - }); + }, true); core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.rollcounterclockwise", Keyboard.KEY_J, () -> { // Noop, actual handling logic in CameraEntity#update - }); + }, true); core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.resettilt", Keyboard.KEY_K, () -> { Optional.ofNullable(replayHandler).map(ReplayHandler::getCameraEntity).ifPresent(c -> c.roll = 0); - }); + }, true); } @Override @@ -191,10 +192,16 @@ public class ReplayModReplay implements Module { } } replayHandler = new ReplayHandler(replayFile, true); + //#if MC>=11400 + KeyBinding.updateKeysByCode(); // see Mixin_ContextualKeyBindings + //#endif } public void forcefullyStopReplay() { replayHandler = null; + //#if MC>=11400 + KeyBinding.updateKeysByCode(); // see Mixin_ContextualKeyBindings + //#endif } public ReplayMod getCore() { diff --git a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java index 6dd3c208..72409aeb 100644 --- a/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java +++ b/src/main/java/com/replaymod/simplepathing/ReplayModSimplePathing.java @@ -82,13 +82,13 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module pathPreview.registerKeyBindings(registry); core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.keyframerepository", Keyboard.KEY_X, () -> { if (guiPathing != null) guiPathing.keyframeRepoButtonPressed(); - }); + }, true); core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.clearkeyframes", Keyboard.KEY_C, () -> { if (guiPathing != null) guiPathing.clearKeyframesButtonPressed(); - }); + }, true); core.getKeyBindingRegistry().registerRepeatedKeyBinding("replaymod.input.synctimeline", Keyboard.KEY_V, () -> { if (guiPathing != null) guiPathing.syncTimeButtonPressed(); - }); + }, true); core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () -> { if (guiPathing != null) guiPathing.deleteButtonPressed(); }); diff --git a/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java b/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java index fb11f524..4c3be797 100644 --- a/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java +++ b/src/main/java/com/replaymod/simplepathing/preview/PathPreview.java @@ -42,7 +42,7 @@ public class PathPreview extends EventRegistrations { SettingsRegistry settings = mod.getCore().getSettingsRegistry(); settings.set(Setting.PATH_PREVIEW, !settings.get(Setting.PATH_PREVIEW)); settings.save(); - }); + }, true); } private void update() { diff --git a/src/main/resources/mixins.core.replaymod.json b/src/main/resources/mixins.core.replaymod.json index 6d4fcac1..c403dc01 100644 --- a/src/main/resources/mixins.core.replaymod.json +++ b/src/main/resources/mixins.core.replaymod.json @@ -6,6 +6,7 @@ "client": [ //#if MC>=11400 "AbstractButtonWidgetAccessor", + "Mixin_ContextualKeyBindings", "MixinGameRenderer", "MixinModResourcePackUtil", //#endif