Allow raw key handlers to cancel keybindings (required for #305)
So that when you press e.g. Ctrl+Z, it doesn't trigger the keybinding bound to Z (currently full brightness).
This commit is contained in:
@@ -4,6 +4,8 @@ import com.google.common.collect.ArrayListMultimap;
|
|||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.replaymod.core.mixin.KeyBindingAccessor;
|
import com.replaymod.core.mixin.KeyBindingAccessor;
|
||||||
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
import de.johni0702.minecraft.gui.utils.EventRegistrations;
|
||||||
|
import com.replaymod.core.events.KeyBindingEventCallback;
|
||||||
|
import com.replaymod.core.events.KeyEventCallback;
|
||||||
import com.replaymod.core.versions.MCVer;
|
import com.replaymod.core.versions.MCVer;
|
||||||
import net.minecraft.client.options.KeyBinding;
|
import net.minecraft.client.options.KeyBinding;
|
||||||
import net.minecraft.util.crash.CrashReport;
|
import net.minecraft.util.crash.CrashReport;
|
||||||
@@ -21,13 +23,9 @@ import static com.replaymod.core.ReplayMod.MOD_ID;
|
|||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
import com.replaymod.core.events.KeyBindingEventCallback;
|
|
||||||
import com.replaymod.core.events.KeyEventCallback;
|
|
||||||
import com.replaymod.core.events.PreRenderCallback;
|
import com.replaymod.core.events.PreRenderCallback;
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
//#else
|
//#else
|
||||||
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||||
//$$ import net.minecraftforge.fml.common.gameevent.InputEvent;
|
|
||||||
//$$ import net.minecraftforge.fml.common.gameevent.TickEvent;
|
//$$ import net.minecraftforge.fml.common.gameevent.TickEvent;
|
||||||
//$$ import org.lwjgl.input.Keyboard;
|
//$$ import org.lwjgl.input.Keyboard;
|
||||||
//$$ import static com.replaymod.core.versions.MCVer.FML_BUS;
|
//$$ import static com.replaymod.core.versions.MCVer.FML_BUS;
|
||||||
@@ -42,6 +40,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class KeyBindingRegistry extends EventRegistrations {
|
public class KeyBindingRegistry extends EventRegistrations {
|
||||||
private static final String CATEGORY = "replaymod.title";
|
private static final String CATEGORY = "replaymod.title";
|
||||||
@@ -51,7 +50,7 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
|
|
||||||
private final Map<String, Binding> bindings = new HashMap<>();
|
private final Map<String, Binding> bindings = new HashMap<>();
|
||||||
private Set<KeyBinding> onlyInReplay = new HashSet<>();
|
private Set<KeyBinding> onlyInReplay = new HashSet<>();
|
||||||
private Multimap<Integer, Runnable> rawHandlers = ArrayListMultimap.create();
|
private Multimap<Integer, Supplier<Boolean>> rawHandlers = ArrayListMultimap.create();
|
||||||
|
|
||||||
public Binding registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) {
|
public Binding registerKeyBinding(String name, int keyCode, Runnable whenPressed, boolean onlyInRepay) {
|
||||||
Binding binding = registerKeyBinding(name, keyCode, onlyInRepay);
|
Binding binding = registerKeyBinding(name, keyCode, onlyInRepay);
|
||||||
@@ -91,7 +90,7 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerRaw(int keyCode, Runnable whenPressed) {
|
public void registerRaw(int keyCode, Supplier<Boolean> whenPressed) {
|
||||||
rawHandlers.put(keyCode, whenPressed);
|
rawHandlers.put(keyCode, whenPressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,17 +103,9 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
{ on(KeyBindingEventCallback.EVENT, this::handleKeyBindings); }
|
|
||||||
{ on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); }
|
|
||||||
{ on(PreRenderCallback.EVENT, this::handleRepeatedKeyBindings); }
|
{ on(PreRenderCallback.EVENT, this::handleRepeatedKeyBindings); }
|
||||||
//#else
|
//#else
|
||||||
//$$ @SubscribeEvent
|
//$$ @SubscribeEvent
|
||||||
//$$ public void onKeyInput(InputEvent.KeyInputEvent event) {
|
|
||||||
//$$ handleKeyBindings();
|
|
||||||
//$$ handleRaw();
|
|
||||||
//$$ }
|
|
||||||
//$$
|
|
||||||
//$$ @SubscribeEvent
|
|
||||||
//$$ public void onTick(TickEvent.RenderTickEvent event) {
|
//$$ public void onTick(TickEvent.RenderTickEvent event) {
|
||||||
//$$ if (event.phase != TickEvent.Phase.START) return;
|
//$$ if (event.phase != TickEvent.Phase.START) return;
|
||||||
//$$ handleRepeatedKeyBindings();
|
//$$ handleRepeatedKeyBindings();
|
||||||
@@ -129,6 +120,7 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ on(KeyBindingEventCallback.EVENT, this::handleKeyBindings); }
|
||||||
private void handleKeyBindings() {
|
private void handleKeyBindings() {
|
||||||
for (Binding binding : bindings.values()) {
|
for (Binding binding : bindings.values()) {
|
||||||
while (binding.keyBinding.wasPressed()) {
|
while (binding.keyBinding.wasPressed()) {
|
||||||
@@ -152,24 +144,23 @@ public class KeyBindingRegistry extends EventRegistrations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=11400
|
{ on(KeyEventCallback.EVENT, (keyCode, scanCode, action, modifiers) -> handleRaw(keyCode, action)); }
|
||||||
private void handleRaw(int keyCode, int action) {
|
private boolean handleRaw(int keyCode, int action) {
|
||||||
if (action != GLFW.GLFW_PRESS) return;
|
if (action != KeyEventCallback.ACTION_PRESS) return false;
|
||||||
//#else
|
for (final Supplier<Boolean> handler : rawHandlers.get(keyCode)) {
|
||||||
//$$ private void handleRaw() {
|
|
||||||
//$$ int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
|
|
||||||
//#endif
|
|
||||||
for (final Runnable runnable : rawHandlers.get(keyCode)) {
|
|
||||||
try {
|
try {
|
||||||
runnable.run();
|
if (handler.get()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
CrashReport crashReport = CrashReport.create(cause, "Handling Raw Key Binding");
|
CrashReport crashReport = CrashReport.create(cause, "Handling Raw Key Binding");
|
||||||
CrashReportSection category = crashReport.addElement("Key Binding");
|
CrashReportSection category = crashReport.addElement("Key Binding");
|
||||||
MCVer.addDetail(category, "Key Code", () -> "" + keyCode);
|
MCVer.addDetail(category, "Key Code", () -> "" + keyCode);
|
||||||
MCVer.addDetail(category, "Handler", runnable::toString);
|
MCVer.addDetail(category, "Handler", handler::toString);
|
||||||
throw new CrashException(crashReport);
|
throw new CrashException(crashReport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Binding {
|
public class Binding {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
//#if MC>=11400
|
|
||||||
package com.replaymod.core.events;
|
package com.replaymod.core.events;
|
||||||
|
|
||||||
import de.johni0702.minecraft.gui.utils.Event;
|
import de.johni0702.minecraft.gui.utils.Event;
|
||||||
@@ -14,4 +13,3 @@ public interface KeyBindingEventCallback {
|
|||||||
|
|
||||||
void onKeybindingEvent();
|
void onKeybindingEvent();
|
||||||
}
|
}
|
||||||
//#endif
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
//#if MC>=11400
|
|
||||||
package com.replaymod.core.events;
|
package com.replaymod.core.events;
|
||||||
|
|
||||||
import de.johni0702.minecraft.gui.utils.Event;
|
import de.johni0702.minecraft.gui.utils.Event;
|
||||||
@@ -7,11 +6,21 @@ public interface KeyEventCallback {
|
|||||||
Event<KeyEventCallback> EVENT = Event.create((listeners) ->
|
Event<KeyEventCallback> EVENT = Event.create((listeners) ->
|
||||||
(key, scanCode, action, modifiers) -> {
|
(key, scanCode, action, modifiers) -> {
|
||||||
for (KeyEventCallback listener : listeners) {
|
for (KeyEventCallback listener : listeners) {
|
||||||
listener.onKeyEvent(key, scanCode, action, modifiers);
|
if (listener.onKeyEvent(key, scanCode, action, modifiers)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
void onKeyEvent(int key, int scanCode, int action, int modifiers);
|
//#if MC>=11400
|
||||||
|
int ACTION_RELEASE = org.lwjgl.glfw.GLFW.GLFW_RELEASE;
|
||||||
|
int ACTION_PRESS = org.lwjgl.glfw.GLFW.GLFW_PRESS;
|
||||||
|
//#else
|
||||||
|
//$$ int ACTION_RELEASE = 0;
|
||||||
|
//$$ int ACTION_PRESS = 1;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
boolean onKeyEvent(int key, int scanCode, int action, int modifiers);
|
||||||
}
|
}
|
||||||
//#endif
|
|
||||||
|
|||||||
@@ -1,20 +1,51 @@
|
|||||||
//#if MC>=11400
|
|
||||||
package com.replaymod.core.mixin;
|
package com.replaymod.core.mixin;
|
||||||
|
|
||||||
import com.replaymod.core.events.KeyBindingEventCallback;
|
import com.replaymod.core.events.KeyBindingEventCallback;
|
||||||
import com.replaymod.core.events.KeyEventCallback;
|
import com.replaymod.core.events.KeyEventCallback;
|
||||||
import net.minecraft.client.Keyboard;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
//#if MC>=11400
|
||||||
|
import net.minecraft.client.Keyboard;
|
||||||
|
//#else
|
||||||
|
//$$ import net.minecraft.client.settings.KeyBinding;
|
||||||
|
//$$ import org.lwjgl.input.Keyboard;
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
//#if MC>=11400
|
||||||
@Mixin(Keyboard.class)
|
@Mixin(Keyboard.class)
|
||||||
public class MixinKeyboardListener {
|
public class MixinKeyboardListener {
|
||||||
@Inject(method = "onKey", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/options/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V", shift = At.Shift.AFTER))
|
private static final String ON_KEY_PRESSED = "Lnet/minecraft/client/options/KeyBinding;onKeyPressed(Lnet/minecraft/client/util/InputUtil$Key;)V";
|
||||||
|
|
||||||
|
@Inject(method = "onKey", at = @At(value = "INVOKE", target = ON_KEY_PRESSED), cancellable = true)
|
||||||
|
private void beforeKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
|
||||||
|
if (KeyEventCallback.EVENT.invoker().onKeyEvent(key, scanCode, action, modifiers)) {
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "onKey", at = @At(value = "INVOKE", target = ON_KEY_PRESSED, shift = At.Shift.AFTER))
|
||||||
private void afterKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
|
private void afterKeyBindingTick(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) {
|
||||||
KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
|
KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
|
||||||
KeyEventCallback.EVENT.invoker().onKeyEvent(key, scanCode, action, modifiers);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//#else
|
||||||
|
//$$ @Mixin(KeyBinding.class)
|
||||||
|
//$$ public class MixinKeyboardListener {
|
||||||
|
//$$ @Inject(method = "onTick", at = @At("HEAD"), cancellable = true)
|
||||||
|
//$$ private static void beforeKeyBindingTick(CallbackInfo ci) {
|
||||||
|
//$$ int keyCode = Keyboard.getEventKey() == 0 ? Keyboard.getEventCharacter() + 256 : Keyboard.getEventKey();
|
||||||
|
//$$ int action = Keyboard.getEventKeyState() ? KeyEventCallback.ACTION_PRESS : KeyEventCallback.ACTION_RELEASE;
|
||||||
|
//$$ if (KeyEventCallback.EVENT.invoker().onKeyEvent(keyCode, 0, action, 0)) {
|
||||||
|
//$$ ci.cancel();
|
||||||
|
//$$ }
|
||||||
|
//$$ }
|
||||||
|
//$$
|
||||||
|
//$$ @Inject(method = "onTick", at = @At("RETURN"))
|
||||||
|
//$$ private static void afterKeyBindingTick(CallbackInfo ci) {
|
||||||
|
//$$ KeyBindingEventCallback.EVENT.invoker().onKeybindingEvent();
|
||||||
|
//$$ }
|
||||||
|
//$$ }
|
||||||
//#endif
|
//#endif
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.replaymod.replay.gui.overlay;
|
package com.replaymod.replay.gui.overlay;
|
||||||
|
|
||||||
import com.replaymod.core.ReplayMod;
|
import com.replaymod.core.ReplayMod;
|
||||||
|
import com.replaymod.core.events.KeyBindingEventCallback;
|
||||||
|
import com.replaymod.core.events.KeyEventCallback;
|
||||||
import com.replaymod.core.versions.MCVer.Keyboard;
|
import com.replaymod.core.versions.MCVer.Keyboard;
|
||||||
import com.replaymod.replay.ReplayHandler;
|
import com.replaymod.replay.ReplayHandler;
|
||||||
import com.replaymod.replay.ReplayModReplay;
|
import com.replaymod.replay.ReplayModReplay;
|
||||||
@@ -23,15 +25,6 @@ import de.johni0702.minecraft.gui.utils.lwjgl.WritablePoint;
|
|||||||
import net.minecraft.client.options.GameOptions;
|
import net.minecraft.client.options.GameOptions;
|
||||||
import net.minecraft.client.resource.language.I18n;
|
import net.minecraft.client.resource.language.I18n;
|
||||||
|
|
||||||
//#if MC>=11400
|
|
||||||
import com.replaymod.core.events.KeyBindingEventCallback;
|
|
||||||
import com.replaymod.core.events.KeyEventCallback;
|
|
||||||
import org.lwjgl.glfw.GLFW;
|
|
||||||
//#else
|
|
||||||
//$$ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
|
||||||
//$$ import net.minecraftforge.fml.common.gameevent.InputEvent;
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
import static com.replaymod.core.ReplayMod.TEXTURE_SIZE;
|
||||||
|
|
||||||
public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
|
public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
|
||||||
@@ -183,13 +176,8 @@ public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
|
|||||||
//$$ public // All event handlers need to be public in 1.7.10
|
//$$ public // All event handlers need to be public in 1.7.10
|
||||||
//#endif
|
//#endif
|
||||||
class EventHandler extends EventRegistrations {
|
class EventHandler extends EventRegistrations {
|
||||||
//#if MC>=11400
|
|
||||||
{ on(KeyBindingEventCallback.EVENT, this::onKeyBindingEvent); }
|
{ on(KeyBindingEventCallback.EVENT, this::onKeyBindingEvent); }
|
||||||
private void onKeyBindingEvent() {
|
private void onKeyBindingEvent() {
|
||||||
//#else
|
|
||||||
//$$ @SubscribeEvent
|
|
||||||
//$$ public void onKeyBindingEvent(InputEvent.KeyInputEvent event) {
|
|
||||||
//#endif
|
|
||||||
GameOptions gameSettings = getMinecraft().options;
|
GameOptions gameSettings = getMinecraft().options;
|
||||||
while (gameSettings.keyChat.wasPressed() || gameSettings.keyCommand.wasPressed()) {
|
while (gameSettings.keyChat.wasPressed() || gameSettings.keyCommand.wasPressed()) {
|
||||||
if (!isMouseVisible()) {
|
if (!isMouseVisible()) {
|
||||||
@@ -198,16 +186,9 @@ public class GuiReplayOverlay extends AbstractGuiOverlay<GuiReplayOverlay> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#if MC>=11400
|
{ on(KeyEventCallback.EVENT, (int key, int scanCode, int action, int modifiers) -> { onKeyInput(key, action); return false; }); }
|
||||||
{ on(KeyEventCallback.EVENT, (int key, int scanCode, int action, int modifiers) -> onKeyInput(key, action)); }
|
|
||||||
private void onKeyInput(int key, int action) {
|
private void onKeyInput(int key, int action) {
|
||||||
if (action != GLFW.GLFW_PRESS) return;
|
if (action != KeyEventCallback.ACTION_PRESS) return;
|
||||||
//#else
|
|
||||||
//$$ @SubscribeEvent
|
|
||||||
//$$ public void onKeyInput(InputEvent.KeyInputEvent event) {
|
|
||||||
//$$ if (!Keyboard.getEventKeyState()) return;
|
|
||||||
//$$ int key = Keyboard.getEventKey();
|
|
||||||
//#endif
|
|
||||||
// Allow F1 to be used to hide the replay gui (e.g. for recording with OBS)
|
// Allow F1 to be used to hide the replay gui (e.g. for recording with OBS)
|
||||||
if (isMouseVisible() && key == Keyboard.KEY_F1) {
|
if (isMouseVisible() && key == Keyboard.KEY_F1) {
|
||||||
hidden = !hidden;
|
hidden = !hidden;
|
||||||
|
|||||||
@@ -97,9 +97,8 @@ public class ReplayModSimplePathing extends EventRegistrations implements Module
|
|||||||
settingsRegistry.set(Setting.AUTO_SYNC, active);
|
settingsRegistry.set(Setting.AUTO_SYNC, active);
|
||||||
settingsRegistry.save();
|
settingsRegistry.save();
|
||||||
});
|
});
|
||||||
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () -> {
|
core.getKeyBindingRegistry().registerRaw(Keyboard.KEY_DELETE, () ->
|
||||||
if (guiPathing != null) guiPathing.deleteButtonPressed();
|
guiPathing != null && guiPathing.deleteButtonPressed());
|
||||||
});
|
|
||||||
keyPositionKeyframe = core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.positionkeyframe", Keyboard.KEY_I, () -> {
|
keyPositionKeyframe = core.getKeyBindingRegistry().registerKeyBinding("replaymod.input.positionkeyframe", Keyboard.KEY_I, () -> {
|
||||||
if (guiPathing != null) guiPathing.toggleKeyframe(SPPath.POSITION, false);
|
if (guiPathing != null) guiPathing.toggleKeyframe(SPPath.POSITION, false);
|
||||||
}, true);
|
}, true);
|
||||||
|
|||||||
@@ -468,10 +468,12 @@ public class GuiPathing {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteButtonPressed() {
|
public boolean deleteButtonPressed() {
|
||||||
if (mod.getSelectedPath() != null) {
|
if (mod.getSelectedPath() != null) {
|
||||||
toggleKeyframe(mod.getSelectedPath(), false);
|
toggleKeyframe(mod.getSelectedPath(), false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startLoadingEntityTracker() {
|
private void startLoadingEntityTracker() {
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
"Mixin_RegisterDynamicResourcePacks",
|
"Mixin_RegisterDynamicResourcePacks",
|
||||||
//#endif
|
//#endif
|
||||||
//#if MC>=11400
|
//#if MC>=11400
|
||||||
"MixinKeyboardListener",
|
|
||||||
"MixinMouse",
|
"MixinMouse",
|
||||||
//#endif
|
//#endif
|
||||||
//#if MC<10800
|
//#if MC<10800
|
||||||
//$$ "ResourcePackRepositoryAccessor",
|
//$$ "ResourcePackRepositoryAccessor",
|
||||||
//#endif
|
//#endif
|
||||||
|
"MixinKeyboardListener",
|
||||||
"MixinMinecraft",
|
"MixinMinecraft",
|
||||||
"GuiMainMenuAccessor",
|
"GuiMainMenuAccessor",
|
||||||
"GuiScreenAccessor",
|
"GuiScreenAccessor",
|
||||||
|
|||||||
Reference in New Issue
Block a user