diff --git a/src/main/java/com/cleanroommc/bogosorter/ClientEventHandler.java b/src/main/java/com/cleanroommc/bogosorter/ClientEventHandler.java index 9cea457..4e71a49 100644 --- a/src/main/java/com/cleanroommc/bogosorter/ClientEventHandler.java +++ b/src/main/java/com/cleanroommc/bogosorter/ClientEventHandler.java @@ -48,9 +48,37 @@ public class ClientEventHandler { public static final KeyBinding configGuiKey = new KeyBinding("key.sort_config", KeyConflictContext.UNIVERSAL, Keyboard.KEY_K, "key.categories.bogosorter"); public static final KeyBinding sortKey = new KeyBinding("key.sort", KeyConflictContext.GUI, -98, "key.categories.bogosorter"); + public static final KeyBind moveAllSame = KeyBind.builder("move_all_same") + .lmb(true).rmb(false) + .shift(false).ctrl(false).alt(true).space(false) + .build(); + public static final KeyBind moveAll = KeyBind.builder("move_all") + .lmb(true).rmb(false) + .shift(false).ctrl(false).alt(false).space(true) + .build(); + public static final KeyBind moveSingle = KeyBind.builder("move_single") + .lmb(true).rmb(false) + .shift(false).ctrl(true).alt(false) + .build(); + public static final KeyBind moveSingleEmpty = KeyBind.builder("move_single_empty") + .lmb(false).rmb(true) + .shift(false).ctrl(true).alt(false) + .build(); + public static final KeyBind throwAllSame = KeyBind.builder("throw_all_same") + .lmb(false).rmb(false) + .shift(false).ctrl(false).alt(true).space(false) + .validator(() -> isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindDrop)) + .build(); + public static final KeyBind throwAll = KeyBind.builder("throw_all") + .lmb(false).rmb(false) + .shift(false).ctrl(false).alt(false).space(true) + .validator(() -> isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindDrop)) + .build(); + private static long timeConfigGui = 0; private static long timeSort = 0; private static long timeShortcut = 0; + private static long ticks = 0; private static GuiScreen nextGui = null; @@ -58,8 +86,15 @@ public static void openNextTick(GuiScreen screen) { ClientEventHandler.nextGui = screen; } + public static long getTicks() { + return ticks; + } + @SubscribeEvent public static void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + ticks++; + } if (ClientEventHandler.nextGui != null) { ClientGUI.open(ClientEventHandler.nextGui); ClientEventHandler.nextGui = null; @@ -105,6 +140,7 @@ public static void onKeyInput(InputEvent.MouseInputEvent event) { @SubscribeEvent(priority = EventPriority.LOW) public static void onGuiKeyInput(GuiScreenEvent.KeyboardInputEvent.Pre event) { + KeyBind.checkKeys(getTicks()); if (!(event.getGui() instanceof GuiContainer)) return; if (handleInput((GuiContainer) event.getGui())) { event.setCanceled(true); @@ -139,6 +175,7 @@ public static void onGuiKeyInput(GuiScreenEvent.KeyboardInputEvent.Pre event) { @SubscribeEvent(priority = EventPriority.LOW) public static void onMouseInput(GuiScreenEvent.MouseInputEvent.Pre event) { + KeyBind.checkKeys(getTicks()); if (event.getGui() instanceof GuiContainer && handleInput((GuiContainer) event.getGui())) { event.setCanceled(true); } @@ -150,35 +187,29 @@ public static boolean handleInput(@Nullable GuiContainer container) { return false; } if (container != null && canDoShortcutAction()) { - if (isButtonPressed(0) && !Mouse.isButtonDown(1) && !GuiScreen.isShiftKeyDown() && !GuiScreen.isCtrlKeyDown()) { - if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && !GuiScreen.isAltKeyDown() && ShortcutHandler.moveAllItems(container, false)) { - shortcutAction(); - return true; - } - if (!Keyboard.isKeyDown(Keyboard.KEY_SPACE) && GuiScreen.isAltKeyDown() && ShortcutHandler.moveAllItems(container, true)) { - shortcutAction(); - return true; - } + if (moveAll.isFirstPress() && ShortcutHandler.moveAllItems(container, false)) { + shortcutAction(); + return true; } - if (GuiScreen.isCtrlKeyDown() && !GuiScreen.isShiftKeyDown() && !GuiScreen.isAltKeyDown()) { - if (isButtonPressed(0) && !Mouse.isButtonDown(1) && ShortcutHandler.moveSingleItem(container, false)) { - shortcutAction(); - return true; - } - if (isButtonPressed(1) && !Mouse.isButtonDown(0) && ShortcutHandler.moveSingleItem(container, true)) { - shortcutAction(); - return true; - } + if (moveAllSame.isFirstPress() && ShortcutHandler.moveAllItems(container, true)) { + shortcutAction(); + return true; } - if (isKeyDown(Minecraft.getMinecraft().gameSettings.keyBindDrop) && !GuiScreen.isShiftKeyDown() && !GuiScreen.isCtrlKeyDown()) { - if (!Keyboard.isKeyDown(Keyboard.KEY_SPACE) && GuiScreen.isAltKeyDown() && ShortcutHandler.dropItems(container, true)) { - shortcutAction(); - return true; - } - if (Keyboard.isKeyDown(Keyboard.KEY_SPACE) && !GuiScreen.isAltKeyDown() && ShortcutHandler.dropItems(container, false)) { - shortcutAction(); - return true; - } + if (moveSingle.isFirstPressOrHeldLong(15) && ShortcutHandler.moveSingleItem(container, false)) { + shortcutAction(); + return true; + } + if (moveSingleEmpty.isFirstPressOrHeldLong(15) && ShortcutHandler.moveSingleItem(container, true)) { + shortcutAction(); + return true; + } + if (throwAll.isFirstPress() && ShortcutHandler.dropItems(container, false)) { + shortcutAction(); + return true; + } + if (throwAllSame.isFirstPress() && ShortcutHandler.dropItems(container, true)) { + shortcutAction(); + return true; } } boolean c = configGuiKey.isPressed(), s = sortKey.isPressed(); diff --git a/src/main/java/com/cleanroommc/bogosorter/KeyBind.java b/src/main/java/com/cleanroommc/bogosorter/KeyBind.java new file mode 100644 index 0000000..62017b6 --- /dev/null +++ b/src/main/java/com/cleanroommc/bogosorter/KeyBind.java @@ -0,0 +1,171 @@ +package com.cleanroommc.bogosorter; + +import it.unimi.dsi.fastutil.ints.IntArrayList; +import net.minecraft.client.Minecraft; +import org.lwjgl.input.Keyboard; +import org.lwjgl.input.Mouse; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BooleanSupplier; + +/** + * A key combo containing key which must be pressed and which must not be pressed in order for the key to activate. + * Works only in GUI. + */ +public class KeyBind { + + private static final List keyBinds = new ArrayList<>(); + + public static Builder builder(String name) { + return new Builder(name); + } + + private final String name; + private final int[] keys; + private final int[] notKeys; + private final BooleanSupplier additionalValidator; + + private long pressedTick = -1; + + public KeyBind(String name, int[] keys, int[] notKeys, BooleanSupplier additionalValidator) { + this.name = name; + this.keys = keys; + this.notKeys = notKeys; + this.additionalValidator = additionalValidator; + keyBinds.add(this); + } + + private static boolean isKey(int key) { + return key != Integer.MIN_VALUE; + } + + public static boolean isKeyPressed(int key) { + if (key < 0) return Mouse.isButtonDown(key + 100); + return Keyboard.isKeyDown(key); + } + + public static boolean areAllPressed(int[] keys) { + if (keys.length == 0) return true; + if (keys.length == 1) return isKeyPressed(keys[0]); + for (int key : keys) { + if (!isKeyPressed(key)) return false; + } + return true; + } + + public static boolean areAllNotPressed(int[] keys) { + if (keys.length == 0) return true; + if (keys.length == 1) return !isKeyPressed(keys[0]); + for (int key : keys) { + if (isKeyPressed(key)) return false; + } + return true; + } + + public static void checkKeys(long currentTick) { + for (KeyBind key : keyBinds) { + key.checkPressed(currentTick); + } + } + + protected void checkPressed(long currentTick) { + if (areAllPressed(this.keys) && areAllNotPressed(this.notKeys) && this.additionalValidator.getAsBoolean()) { + if (this.pressedTick < 0) { + this.pressedTick = currentTick; + } + } else { + this.pressedTick = -1; + } + } + + public boolean isPressed() { + return this.pressedTick >= 0; + } + + public int getTicksPressed() { + return this.pressedTick < 0 ? -1 : (int) (ClientEventHandler.getTicks() - this.pressedTick); + } + + public boolean isFirstPress() { + return getTicksPressed() == 0; + } + + public boolean isFirstPressOrHeldLong(int amount) { + int ticks = getTicksPressed(); + return ticks == 0 || ticks >= amount; + } + + public String getName() { + return name; + } + + public static class Builder { + + private final String name; + private final IntArrayList keys = new IntArrayList(); + private final IntArrayList notKeys = new IntArrayList(); + private BooleanSupplier validator = null; + + public Builder(String name) { + this.name = name; + } + + private Builder add(boolean press, int key) { + if (press) { + keys.add(key); + } else { + notKeys.add(key); + } + return this; + } + + public Builder mustPress(int... keys) { + for (int key : keys) this.keys.add(key); + return this; + } + + public Builder mustNotPress(int... keys) { + for (int key : keys) this.notKeys.add(key); + return this; + } + + public Builder lmb(boolean press) { + return add(press, -100); + } + + public Builder rmb(boolean press) { + return add(press, -99); + } + + public Builder ctrl(boolean press) { + if (Minecraft.IS_RUNNING_ON_MAC) { + return add(press, 219); + } + return add(press, 29); + } + + public Builder shift(boolean press) { + return add(press, 42); + } + + public Builder alt(boolean press) { + return add(press, 56); + } + + public Builder space(boolean press) { + return add(press, Keyboard.KEY_SPACE); + } + + public Builder validator(BooleanSupplier validator) { + this.validator = validator; + return this; + } + + public KeyBind build() { + keys.trim(); + notKeys.trim(); + return new KeyBind(this.name, keys.elements(), notKeys.elements(), validator != null ? validator : () -> true); + } + } +}