diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java index 7fc2045..11b4fe7 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java @@ -87,9 +87,9 @@ public class MidnightControlsClient extends MidnightControls { Timer timer = new Timer(); timer.scheduleAtFixedRate(new TimerTask() { public void run() { - if (client.isRunning()) { - input.tickJoysticks(client); - input.updateCamera(client); + if (lateInitDone && client.isRunning()) { + input.tickJoysticks(); + input.updateCamera(); } } }, delay, period); @@ -171,10 +171,10 @@ public class MidnightControlsClient extends MidnightControls { */ public static void onTick(@NotNull MinecraftClient client) { initKeybindings(); - input.tick(client); - reacharound.tick(client); + input.tick(); + reacharound.tick(); if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER && (client.isWindowFocused() || MidnightControlsConfig.unfocusedInput)) - input.tickController(client); + input.tickController(); if (BINDING_RING.wasPressed()) { ring.loadFromUnbound(); @@ -200,7 +200,7 @@ public class MidnightControlsClient extends MidnightControls { client.skipGameRender = false; client.currentScreen = screen; } else if (screen != null) { - MidnightControlsClient.input.onScreenOpen(client, client.getWindow().getWidth(), client.getWindow().getHeight()); + MidnightControlsClient.input.onScreenOpen(client.getWindow().getWidth(), client.getWindow().getHeight()); } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java index a4614fa..7ed2cce 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java @@ -11,14 +11,24 @@ package eu.midnightdust.midnightcontrols.client; import com.google.common.collect.ImmutableSet; import eu.midnightdust.lib.util.PlatformFunctions; +import eu.midnightdust.midnightcontrols.client.compat.EmotecraftCompat; +import eu.midnightdust.midnightcontrols.client.compat.LibGuiCompat; +import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; +import eu.midnightdust.midnightcontrols.client.compat.YACLCompat; +import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor; +import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; +import eu.midnightdust.midnightcontrols.client.mixin.MouseAccessor; +import eu.midnightdust.midnightcontrols.client.util.InventoryUtil; import eu.midnightdust.midnightcontrols.client.util.storage.AxisStorage; +import eu.midnightdust.midnightcontrols.client.util.storage.ButtonStorage; import net.minecraft.client.gui.screen.option.KeybindsScreen; +import net.minecraft.client.gui.widget.EntryListWidget; +import net.minecraft.client.gui.widget.PressableWidget; +import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.entity.vehicle.BoatEntity; -import net.minecraft.util.Pair; import org.thinkingstudio.obsidianui.widget.AbstractSpruceWidget; import org.thinkingstudio.obsidianui.widget.container.SpruceEntryListWidget; import eu.midnightdust.midnightcontrols.MidnightControls; -import eu.midnightdust.midnightcontrols.client.compat.*; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; @@ -26,7 +36,6 @@ import eu.midnightdust.midnightcontrols.client.enums.CameraMode; import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.touch.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.gui.widget.ControllerControlsWidget; -import eu.midnightdust.midnightcontrols.client.mixin.*; import eu.midnightdust.midnightcontrols.client.ring.RingPage; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; import eu.midnightdust.midnightcontrols.client.util.MathUtil; @@ -50,16 +59,16 @@ import net.minecraft.client.gui.screen.ingame.StonecutterScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen; import net.minecraft.client.gui.screen.multiplayer.MultiplayerServerListWidget; import net.minecraft.client.gui.screen.world.WorldListWidget; -import net.minecraft.client.gui.widget.*; -import net.minecraft.screen.slot.Slot; import net.minecraft.text.TranslatableTextContent; import net.minecraft.util.math.MathHelper; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWGamepadState; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; import static org.lwjgl.glfw.GLFW.*; @@ -67,12 +76,12 @@ import static org.lwjgl.glfw.GLFW.*; /** * Represents the midnightcontrols' input handler. * - * @author LambdAurora - * @version 1.7.0 + * @author Motschen, LambdAurora + * @version 1.10.0 * @since 1.0.0 */ public class MidnightInput { - private static final Map BUTTON_COOLDOWNS = new HashMap<>(); + public static final Map BUTTON_COOLDOWNS = new HashMap<>(); // Cooldowns public int actionGuiCooldown = 0; public int joystickCooldown = 0; @@ -82,10 +91,8 @@ public class MidnightInput { private double targetPitch = 0.0; private float prevXAxis = 0.f; private float prevYAxis = 0.f; - private int targetMouseX = 0; - private int targetMouseY = 0; - private float mouseSpeedX = 0.f; - private float mouseSpeedY = 0.f; + public float mouseSpeedX = 0.f; + public float mouseSpeedY = 0.f; public int inventoryInteractionCooldown = 0; public int screenCloseCooldown = 0; @@ -95,10 +102,8 @@ public class MidnightInput { /** * This method is called every Minecraft tick. - * - * @param client the client instance */ - public void tick(@NotNull MinecraftClient client) { + public void tick() { this.targetYaw = 0.F; this.targetPitch = 0.F; @@ -114,15 +119,13 @@ public class MidnightInput { this.handleFlatLook(new AxisStorage(GLFW_GAMEPAD_AXIS_RIGHT_X, 0.8F, 1)); } - InputManager.INPUT_MANAGER.tick(client); + InputManager.INPUT_MANAGER.tick(); } /** * This method is called every Minecraft tick for controller input update. - * - * @param client the client instance */ - public void tickController(@NotNull MinecraftClient client) { + public void tickController() { BUTTON_COOLDOWNS.entrySet().stream().filter(entry -> entry.getValue() > 0) .forEach(entry -> BUTTON_COOLDOWNS.put(entry.getKey(), entry.getValue() - 1)); // Decreases the cooldown for GUI actions. @@ -139,20 +142,20 @@ public class MidnightInput { if (controller.isConnected()) { var state = controller.getState(); - this.fetchButtonInput(client, state, false); - this.fetchTriggerInput(client, state, false); + this.fetchButtonInput(state, false); + this.fetchTriggerInput(state, false); } MidnightControlsConfig.getSecondController().filter(Controller::isConnected) .ifPresent(joycon -> { var state = joycon.getState(); - this.fetchButtonInput(client, state, true); - this.fetchTriggerInput(client, state, true); + this.fetchButtonInput(state, true); + this.fetchTriggerInput(state, true); }); boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null; if (allowInput) - InputManager.updateBindings(client); + InputManager.updateBindings(); if (this.controlsInput != null) { InputManager.STATES.forEach((num, button) -> { @@ -160,7 +163,7 @@ public class MidnightInput { }); } if (this.controlsInput != null && InputManager.STATES.int2ObjectEntrySet().parallelStream().map(Map.Entry::getValue).allMatch(ButtonState::isUnpressed)) { - if (MidnightControlsConfig.debug) MidnightControls.log("Finished MidnightInput Button Edit"); + if (MidnightControlsConfig.debug) MidnightControls.log("Starting MidnightInput Button Edit"); if (this.controlsInput.focusedBinding != null && !this.controlsInput.waiting) { int[] buttons = new int[this.controlsInput.currentButtons.size()]; for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) @@ -175,28 +178,25 @@ public class MidnightInput { } /** * This method is called 1000 times a second for smooth joystick input - * - * @param client the client instance */ - public void tickJoysticks(@NotNull MinecraftClient client) { + public void tickJoysticks() { var controller = MidnightControlsConfig.getController(); if (controller.isConnected()) { - this.fetchJoystickInput(client, controller.getState(), false); + this.fetchJoystickInput(controller.getState(), false); } MidnightControlsConfig.getSecondController().filter(Controller::isConnected) .ifPresent(joycon -> { - this.fetchJoystickInput(client, joycon.getState(), true); + this.fetchJoystickInput(joycon.getState(), true); }); } /** * This method is called before the screen is rendered. * - * @param client the client instance * @param screen the screen to render */ - public void onPreRenderScreen(@NotNull MinecraftClient client, @NotNull Screen screen) { + public void onPreRenderScreen(@NotNull Screen screen) { if (!isScreenInteractive(screen)) { InputManager.INPUT_MANAGER.updateMousePosition(client); } @@ -204,10 +204,8 @@ public class MidnightInput { /** * This method is called to update the camera - * - * @param client the client instance */ - public void updateCamera(@NotNull MinecraftClient client) { + public void updateCamera() { if (!(client.currentScreen == null || client.currentScreen instanceof TouchscreenOverlay)) return; @@ -232,11 +230,10 @@ public class MidnightInput { /** * This method is called when a Screen is opened. * - * @param client the client instance * @param windowWidth the window width * @param windowHeight the window height */ - public void onScreenOpen(@NotNull MinecraftClient client, int windowWidth, int windowHeight) { + public void onScreenOpen(int windowWidth, int windowHeight) { if (client.currentScreen == null) { this.mouseSpeedX = this.mouseSpeedY = 0.0F; InputManager.INPUT_MANAGER.resetMousePosition(windowWidth, windowHeight); @@ -255,7 +252,7 @@ public class MidnightInput { } } - private void fetchButtonInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { + private void fetchButtonInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { var buffer = gamepadState.buttons(); for (int i = 0; i < buffer.limit(); i++) { int btn = leftJoycon ? ButtonBinding.controller2Button(i) : i; @@ -265,14 +262,14 @@ public class MidnightInput { if (btnState != previousState.isPressed()) { state = btnState ? ButtonState.PRESS : ButtonState.RELEASE; - this.handleButton(client, btn, btnState ? 0 : 1, btnState); + this.handleButton(new ButtonStorage(btn, btnState ? 0 : 1, btnState)); if (btnState) BUTTON_COOLDOWNS.put(btn, 5); } else if (btnState) { state = ButtonState.REPEAT; if (BUTTON_COOLDOWNS.getOrDefault(btn, 0) == 0) { BUTTON_COOLDOWNS.put(btn, 5); - this.handleButton(client, btn, 2, true); + this.handleButton(new ButtonStorage(btn, 2, true)); } } @@ -281,7 +278,7 @@ public class MidnightInput { } final MathUtil.PolarUtil polarUtil = new MathUtil.PolarUtil(); - private void fetchJoystickInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { + private void fetchJoystickInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { var buffer = gamepadState.axes(); polarUtil.calculate(buffer.get(GLFW_GAMEPAD_AXIS_LEFT_X), buffer.get(GLFW_GAMEPAD_AXIS_LEFT_Y), 1, MidnightControlsConfig.leftDeadZone); @@ -293,53 +290,37 @@ public class MidnightInput { boolean isRadialMenu = client.currentScreen instanceof RingScreen || (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)); - for (int i = 0; i < GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i++) { - int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i; - float value = buffer.get(i); + if (!isRadialMenu) { + for (int i = 0; i < GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i++) { + int axis = leftJoycon ? ButtonBinding.controller2Button(i) : i; + float value = buffer.get(i); - switch (i) { - case GLFW_GAMEPAD_AXIS_LEFT_X -> {if (MidnightControlsConfig.analogMovement) value = leftX;} - case GLFW_GAMEPAD_AXIS_LEFT_Y -> {if (MidnightControlsConfig.analogMovement) value = leftY;} - case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX; - case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY; + switch (i) { + case GLFW_GAMEPAD_AXIS_LEFT_X -> { + if (MidnightControlsConfig.analogMovement) value = leftX; + } + case GLFW_GAMEPAD_AXIS_LEFT_Y -> { + if (MidnightControlsConfig.analogMovement) value = leftY; + } + case GLFW_GAMEPAD_AXIS_RIGHT_X -> value = rightX; + case GLFW_GAMEPAD_AXIS_RIGHT_Y -> value = rightY; + } + float absValue = Math.abs(value); + + if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y) + value *= -1.0F; + + int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0); + this.handleJoystickAxis(new AxisStorage(axis, value, absValue, state)); } - float absValue = Math.abs(value); - - if (i == GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y) - value *= -1.0F; - - int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0); - if (!isRadialMenu) - this.handleJoystickAxis(client, new AxisStorage(axis, value, absValue, state)); } - if (isRadialMenu) { - float x = leftX; - float y = leftY; - - if (x == 0 && y == 0) { - x = rightX; - y = rightY; - } - int index = -1; - float border = 0.3f; - if (x < -border) { - index = 3; - if (y < -border) index = 0; - else if (y > border) index = 5; - } else if (x > border) { - index = 4; - if (y < -border) index = 2; - else if (y > border) index = 7; - } else { - if (y < -border) index = 1; - else if (y > border) index = 6; - } - if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index; - if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index); + else { + boolean leftStickActive = leftX != 0 || leftY != 0; + handleRadialMenu(leftStickActive ? leftX : rightX, leftStickActive ? leftY : rightY); } } - private void fetchTriggerInput(@NotNull MinecraftClient client, @NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { + private void fetchTriggerInput(@NotNull GLFWGamepadState gamepadState, boolean leftJoycon) { var buffer = gamepadState.axes(); for (int i = GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; i <= GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER; i++) { @@ -348,14 +329,14 @@ public class MidnightInput { float absValue = Math.abs(value); int state = value > MidnightControlsConfig.rightDeadZone ? 1 : (value < -MidnightControlsConfig.rightDeadZone ? 2 : 0); - this.handleTriggerAxis(client, new AxisStorage(axis, value, absValue, state)); + this.handleTriggerAxis(new AxisStorage(axis, value, absValue, state)); } } - public void handleButton(@NotNull MinecraftClient client, int button, int action, boolean state) { + public void handleButton(ButtonStorage storage) { if (this.controlsInput != null && this.controlsInput.focusedBinding != null) { - if (action == 0 && !this.controlsInput.currentButtons.contains(button)) { - this.controlsInput.currentButtons.add(button); + if (storage.action == 0 && !this.controlsInput.currentButtons.contains(storage.button)) { + this.controlsInput.currentButtons.add(storage.button); var buttons = new int[this.controlsInput.currentButtons.size()]; for (int i = 0; i < this.controlsInput.currentButtons.size(); i++) @@ -367,37 +348,32 @@ public class MidnightInput { return; } - if (client.currentScreen != null && (action == 0 || action == 2) && button == GLFW_GAMEPAD_BUTTON_Y && + if (client.currentScreen != null && (storage.action != 1) && storage.button == GLFW_GAMEPAD_BUTTON_Y && MidnightControlsConfig.arrowScreens.contains(client.currentScreen.getClass().getCanonicalName())) { pressKeyboardKey(client, GLFW.GLFW_KEY_ENTER); this.screenCloseCooldown = 5; } - else if (action == 0 || action == 2) { - if (client.currentScreen != null - && (button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_DOWN - || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT || button == GLFW.GLFW_GAMEPAD_BUTTON_DPAD_RIGHT)) { - if (this.actionGuiCooldown == 0) { - switch (button) { - case GLFW_GAMEPAD_BUTTON_DPAD_UP -> this.changeFocus(client.currentScreen, NavigationDirection.UP); - case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN); - case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> this.handleLeftRight(client.currentScreen, false); - case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> this.handleLeftRight(client.currentScreen, true); - } - if (MidnightControlsConfig.wasdScreens.contains(client.currentScreen.getClass().getCanonicalName())) { - switch (button) { - case GLFW_GAMEPAD_BUTTON_DPAD_UP -> pressKeyboardKey(client, GLFW.GLFW_KEY_W); - case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> pressKeyboardKey(client, GLFW.GLFW_KEY_S); - case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> pressKeyboardKey(client, GLFW.GLFW_KEY_A); - case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> pressKeyboardKey(client, GLFW.GLFW_KEY_D); - } + else if (storage.action != 1) { + if (client.currentScreen != null && storage.isDpad() && this.actionGuiCooldown == 0) { + switch (storage.button) { + case GLFW_GAMEPAD_BUTTON_DPAD_UP -> this.changeFocus(client.currentScreen, NavigationDirection.UP); + case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> this.changeFocus(client.currentScreen, NavigationDirection.DOWN); + case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> this.handleLeftRight(client.currentScreen, false); + case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> this.handleLeftRight(client.currentScreen, true); + } + if (MidnightControlsConfig.wasdScreens.contains(client.currentScreen.getClass().getCanonicalName())) { + switch (storage.button) { + case GLFW_GAMEPAD_BUTTON_DPAD_UP -> pressKeyboardKey(client, GLFW.GLFW_KEY_W); + case GLFW_GAMEPAD_BUTTON_DPAD_DOWN -> pressKeyboardKey(client, GLFW.GLFW_KEY_S); + case GLFW_GAMEPAD_BUTTON_DPAD_LEFT -> pressKeyboardKey(client, GLFW.GLFW_KEY_A); + case GLFW_GAMEPAD_BUTTON_DPAD_RIGHT -> pressKeyboardKey(client, GLFW.GLFW_KEY_D); } } return; } } - - if (action == 1) { - if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) { + else { + if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null) { if (this.actionGuiCooldown == 0) { var focused = client.currentScreen.getFocused(); if (focused != null && isScreenInteractive(client.currentScreen)) { @@ -411,7 +387,7 @@ public class MidnightInput { } } - if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) + if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) { if (client.currentScreen instanceof HandledScreen handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt( client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(), @@ -419,55 +395,50 @@ public class MidnightInput { if (!this.ignoreNextARelease && client.currentScreen != null) { var accessor = (MouseAccessor) client.mouse; accessor.midnightcontrols$onCursorPos(client.getWindow().getHandle(), client.mouse.getX(), client.mouse.getY()); - if (action == 0) { // Button pressed - accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 1, 0); - } else if (action == 1) { // Button released - accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 0, 0); - client.currentScreen.setDragging(false); - } else if (action == 2) { // Button held down / dragging - client.currentScreen.setDragging(true); + switch (storage.action) { + // Button pressed + case 0 -> accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 1, 0); + case 1 -> { // Button released + accessor.midnightcontrols$onMouseButton(client.getWindow().getHandle(), GLFW_MOUSE_BUTTON_LEFT, 0, 0); + client.currentScreen.setDragging(false); + } + case 2 -> client.currentScreen.setDragging(true); // Button held down / dragging } this.screenCloseCooldown = 5; } else { this.ignoreNextARelease = false; } } - else if (button == GLFW.GLFW_GAMEPAD_BUTTON_X && client.currentScreen != null && !isScreenInteractive(client.currentScreen) + else if (storage.button == GLFW.GLFW_GAMEPAD_BUTTON_X && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) { + double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); + double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); if (client.currentScreen instanceof HandledScreen handledScreen && ((HandledScreenAccessor) handledScreen).midnightcontrols$getSlotAt( - client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(), - client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()) != null) return; + mouseX, mouseY) != null) return; if (!this.ignoreNextXRelease && client.currentScreen != null) { - double mouseX = client.mouse.getX() * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth(); - double mouseY = client.mouse.getY() * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight(); - if (action == 0) { - Screen.wrapScreenError(() -> client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2), - "mouseClicked event handler", client.currentScreen.getClass().getCanonicalName()); - } else if (action == 1) { - Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2), - "mouseReleased event handler", client.currentScreen.getClass().getCanonicalName()); - } + if (storage.action == 0) client.currentScreen.mouseClicked(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2); + else if (storage.action == 1) client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_2); this.screenCloseCooldown = 5; } else { this.ignoreNextXRelease = false; } } } - private void handleTriggerAxis(@NotNull MinecraftClient client, AxisStorage storage) { - this.setCurrentPolarities(storage); + private void handleTriggerAxis(AxisStorage storage) { + storage.setupButtonStates(); } - private void handleJoystickAxis(@NotNull MinecraftClient client, AxisStorage storage) { - this.setCurrentPolarities(storage); + private void handleJoystickAxis(AxisStorage storage) { + storage.setupButtonStates(); - this.handleMovement(client, storage); + this.handleMovement(storage); if (this.handleScreenScrolling(client.currentScreen, storage)) return; storage.absValue = (float) MathHelper.clamp(storage.absValue / MidnightControlsConfig.getAxisMaxValue(storage.axis), 0.f, 1.f); if (client.currentScreen == null) { // Handles the look direction. - this.handleLook(client, storage); + this.handleLook(storage); } else { boolean allowMouseControl = true; @@ -521,7 +492,7 @@ public class MidnightInput { ); } - this.moveMouseToClosestSlot(client, client.currentScreen); + InventoryUtil.moveMouseToClosestSlot(client.currentScreen); } this.prevXAxis = movementX; @@ -529,44 +500,7 @@ public class MidnightInput { } } - private void setCurrentPolarities(AxisStorage storage) { - boolean currentPlusState = storage.value > storage.deadZone; - boolean currentMinusState = storage.value < -storage.deadZone; - if (storage.axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER) currentMinusState = false; - if (!MidnightControlsConfig.analogMovement && (storage.axis == GLFW_GAMEPAD_AXIS_LEFT_X || storage.axis == GLFW_GAMEPAD_AXIS_LEFT_Y)) { - currentPlusState = storage.asButtonState == 1; - currentMinusState = storage.asButtonState == 2; - } - var posButton = ButtonBinding.axisAsButton(storage.axis, true); - var negButton = ButtonBinding.axisAsButton(storage.axis, false); - var previousPlusState = InputManager.STATES.getOrDefault(posButton, ButtonState.NONE); - var previousMinusState = InputManager.STATES.getOrDefault(negButton, ButtonState.NONE); - - if (currentPlusState != previousPlusState.isPressed()) { - InputManager.STATES.put(posButton, currentPlusState ? ButtonState.PRESS : ButtonState.RELEASE); - if (currentPlusState) - BUTTON_COOLDOWNS.put(posButton, 5); - } else if (currentPlusState) { - InputManager.STATES.put(posButton, ButtonState.REPEAT); - if (BUTTON_COOLDOWNS.getOrDefault(posButton, 0) == 0) { - BUTTON_COOLDOWNS.put(posButton, 5); - } - } - - if (currentMinusState != previousMinusState.isPressed()) { - InputManager.STATES.put(negButton, currentMinusState ? ButtonState.PRESS : ButtonState.RELEASE); - if (currentMinusState) - BUTTON_COOLDOWNS.put(negButton, 5); - } else if (currentMinusState) { - InputManager.STATES.put(negButton, ButtonState.REPEAT); - if (BUTTON_COOLDOWNS.getOrDefault(negButton, 0) == 0) { - BUTTON_COOLDOWNS.put(negButton, 5); - } - } - storage.polarity = currentPlusState ? AxisStorage.Polarity.PLUS : currentMinusState ? AxisStorage.Polarity.MINUS : AxisStorage.Polarity.ZERO; - } - - private void handleMovement(@NotNull MinecraftClient client, AxisStorage storage) { + private void handleMovement(AxisStorage storage) { float axisValue = storage.absValue; if (!MidnightControlsConfig.analogMovement || (client.player != null && client.player.getVehicle() instanceof BoatEntity)) { axisValue = (float) (storage.absValue - storage.deadZone); @@ -641,6 +575,24 @@ public class MidnightInput { } return false; } + public void handleRadialMenu(float x, float y) { + int index = -1; + float border = 0.3f; + if (x < -border) { + index = 3; + if (y < -border) index = 0; + else if (y > border) index = 5; + } else if (x > border) { + index = 4; + if (y < -border) index = 2; + else if (y > border) index = 7; + } else { + if (y < -border) index = 1; + else if (y > border) index = 6; + } + if (client.currentScreen instanceof RingScreen && index > -1) RingPage.selected = index; + if (MidnightControlsCompat.isEmotecraftPresent() && EmotecraftCompat.isEmotecraftScreen(client.currentScreen)) EmotecraftCompat.handleEmoteSelector(index); + } public boolean handleListWidgetScrolling(List children, float value) { return children.stream().filter(element -> element instanceof SpruceEntryListWidget) @@ -755,10 +707,9 @@ public class MidnightInput { /** * Handles the look direction input. * - * @param client the client instance * @param storage the state of the provided axis */ - public void handleLook(@NotNull MinecraftClient client, AxisStorage storage) { + public void handleLook(AxisStorage storage) { if (client.player == null || !(storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_Y || storage.axis == GLFW_GAMEPAD_AXIS_RIGHT_X)) return; // Handles the look direction. if (MidnightControlsConfig.cameraMode == CameraMode.FLAT) handleFlatLook(storage); @@ -872,59 +823,4 @@ public class MidnightInput { public void pressKeyboardKey(Screen screen, int key) { screen.keyPressed(key, 0, 1); } - - // Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686. - private void moveMouseToClosestSlot(@NotNull MinecraftClient client, @Nullable Screen screen) { - // Makes the mouse attracted to slots. This helps with selecting items when using a controller. - if (screen instanceof HandledScreen inventoryScreen) { - var accessor = (HandledScreenAccessor) inventoryScreen; - int guiLeft = accessor.getX(); - int guiTop = accessor.getY(); - int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()); - int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()); - - // Finds the closest slot in the GUI within 14 pixels. - Optional> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream() - .map(slot -> { - int x = guiLeft + slot.x + 8; - int y = guiTop + slot.y + 8; - - // Distance between the slot and the cursor. - double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2)); - return new Pair(slot, distance); - }).filter(entry -> entry.getRight() <= 14.0) - .min(Comparator.comparingDouble(Pair::getRight)); - - if (closestSlot.isPresent() && client.player != null) { - var slot = closestSlot.get().getLeft(); - if (slot.hasStack() || !client.player.getInventory().getMainHandStack().isEmpty()) { - int slotCenterXScaled = guiLeft + slot.x + 8; - int slotCenterYScaled = guiTop + slot.y + 8; - int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth())); - int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight())); - double deltaX = slotCenterX - targetMouseX; - double deltaY = slotCenterY - targetMouseY; - - if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) { - this.targetMouseX += (int) (deltaX * 0.75); - this.targetMouseY += (int) (deltaY * 0.75); - } else { - this.mouseSpeedX *= 0.3F; - this.mouseSpeedY *= 0.3F; - } - this.mouseSpeedX *= .75F; - this.mouseSpeedY *= .75F; - } else { - this.mouseSpeedX *= .1F; - this.mouseSpeedY *= .1F; - } - } else { - this.mouseSpeedX *= .3F; - this.mouseSpeedY *= .3F; - } - } else { - this.mouseSpeedX = 0.F; - this.mouseSpeedY = 0.F; - } - } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java index 81d3378..c4360c7 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightReacharound.java @@ -28,6 +28,8 @@ import net.minecraft.world.RaycastContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; + /** * Represents the reach-around API of midnightcontrols. * @@ -39,10 +41,10 @@ public class MidnightReacharound { private boolean lastReacharoundVertical = false; private boolean onSlab = false; - public void tick(@NotNull MinecraftClient client) { - this.lastReacharoundResult = this.tryVerticalReachAround(client); + public void tick() { + this.lastReacharoundResult = this.tryVerticalReachAround(); if (this.lastReacharoundResult == null) { - this.lastReacharoundResult = this.tryHorizontalReachAround(client); + this.lastReacharoundResult = this.tryHorizontalReachAround(); this.lastReacharoundVertical = false; } else this.lastReacharoundVertical = true; } @@ -81,10 +83,9 @@ public class MidnightReacharound { /** * Returns a nullable block hit result if vertical reach-around is possible. * - * @param client the client instance * @return a block hit result if vertical reach-around is possible, else {@code null} */ - public @Nullable BlockHitResult tryVerticalReachAround(@NotNull MinecraftClient client) { + public @Nullable BlockHitResult tryVerticalReachAround() { if (!MidnightControlsFeature.VERTICAL_REACHAROUND.isAvailable()) return null; if (client.player == null || client.world == null || client.crosshairTarget == null || client.crosshairTarget.getType() != HitResult.Type.MISS @@ -113,10 +114,9 @@ public class MidnightReacharound { /** * Returns a nullable block hit result if horizontal reach-around is possible. * - * @param client the client instance * @return a block hit result if horizontal reach-around is possible */ - public @Nullable BlockHitResult tryHorizontalReachAround(@NotNull MinecraftClient client) { + public @Nullable BlockHitResult tryHorizontalReachAround() { if (!MidnightControlsFeature.HORIZONTAL_REACHAROUND.isAvailable()) return null; diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java index 5c2b335..65a063d 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java @@ -30,6 +30,8 @@ import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; +import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; + /** * Represents an input manager for controllers. * @@ -51,17 +53,17 @@ public class InputManager { protected InputManager() { } - public void tick(@NotNull MinecraftClient client) { + public void tick() { if (MidnightControlsConfig.autoSwitchMode && !MidnightControlsConfig.isEditing && MidnightControlsConfig.controlsMode != ControlsMode.TOUCHSCREEN) if (MidnightControlsConfig.getController().isConnected() && MidnightControlsConfig.getController().isGamepad()) MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER; else MidnightControlsConfig.controlsMode = ControlsMode.DEFAULT; if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) { - this.controllerTick(client); + this.controllerTick(); } } - public void controllerTick(@NotNull MinecraftClient client) { + public void controllerTick() { this.prevTargetMouseX = this.targetMouseX; this.prevTargetMouseY = this.targetMouseY; } @@ -340,7 +342,7 @@ public class InputManager { } } - public static void updateBindings(@NotNull MinecraftClient client) { + public static void updateBindings() { var skipButtons = new IntArrayList(); record ButtonStateValue(ButtonState state, float value) { } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java index cf0c4af..a6aac8a 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MappingsStringInputWidget.java @@ -41,7 +41,6 @@ public class MappingsStringInputWidget extends SpruceContainerWidget { protected MappingsStringInputWidget(Position position, int width, int height) { super(position, width, height); - //super(new TranslatableText("midnightcontrols.menu.title.mappings.string")); this.reloadMappingsOption = ReloadControllerMappingsOption.newOption(btn -> { this.writeMappings(); @@ -108,6 +107,7 @@ public class MappingsStringInputWidget extends SpruceContainerWidget { @Override public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { super.renderWidget(context, mouseX, mouseY, delta); + context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.multiple_mapping_tip"), this.textArea.getX() + this.textArea.getWidth() / 2, this.textArea.getY() + this.textArea.getHeight() - 12, 0x888888); context.drawCenteredTextWithShadow(this.client.textRenderer, Text.translatable("midnightcontrols.menu.current_controller_guid", MidnightControlsConfig.getController().getGuid()), this.textArea.getX() + this.textArea.getWidth() / 2, this.height - 21, 0xFFFFFF); } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java index bb9398e..2d47dda 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/GameRendererMixin.java @@ -33,12 +33,12 @@ public abstract class GameRendererMixin { @Shadow @Final MinecraftClient client; @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Mouse;getX()D", shift = At.Shift.BEFORE)) - private void midnigtcontrols$onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { + private void midnightcontrols$onRender(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci) { if (this.client.currentScreen != null && MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) - MidnightControlsClient.input.onPreRenderScreen(this.client, this.client.currentScreen); + MidnightControlsClient.input.onPreRenderScreen(this.client.currentScreen); } @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/DrawContext;draw()V", shift = At.Shift.BEFORE)) - private void midnigtcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) { + private void midnightcontrols$renderVirtualCursor(RenderTickCounter tickCounter, boolean tick, CallbackInfo ci, @Local DrawContext drawContext) { MidnightControlsRenderer.renderVirtualCursor(drawContext, client); if (MidnightControlsClient.isWayland) MidnightControlsRenderer.renderWaylandCursor(drawContext, client); drawContext.draw(); diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/InventoryUtil.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/InventoryUtil.java index dc55276..fee4709 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/InventoryUtil.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/InventoryUtil.java @@ -1,14 +1,17 @@ package eu.midnightdust.midnightcontrols.client.util; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.screen.slot.Slot; import org.aperlambda.lambdacommon.utils.Pair; +import org.jetbrains.annotations.Nullable; import java.util.Comparator; import java.util.Optional; import java.util.function.Predicate; import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.client; +import static eu.midnightdust.midnightcontrols.client.MidnightControlsClient.input; public class InventoryUtil { // Finds the closest slot in the GUI within 14 pixels. @@ -60,4 +63,62 @@ public class InventoryUtil { .min(Comparator.comparingDouble(p -> p.value)) .map(p -> p.key); } + + private static int targetMouseX = 0; + private static int targetMouseY = 0; + + // Inspired from https://github.com/MrCrayfish/Controllable/blob/1.14.X/src/main/java/com/mrcrayfish/controllable/client/ControllerInput.java#L686. + public static void moveMouseToClosestSlot(@Nullable Screen screen) { + // Makes the mouse attracted to slots. This helps with selecting items when using a controller. + if (screen instanceof HandledScreen inventoryScreen) { + var accessor = (HandledScreenAccessor) inventoryScreen; + int guiLeft = accessor.getX(); + int guiTop = accessor.getY(); + int mouseX = (int) (targetMouseX * (double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth()); + int mouseY = (int) (targetMouseY * (double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight()); + + // Finds the closest slot in the GUI within 14 pixels. + Optional> closestSlot = inventoryScreen.getScreenHandler().slots.parallelStream() + .map(slot -> { + int x = guiLeft + slot.x + 8; + int y = guiTop + slot.y + 8; + + // Distance between the slot and the cursor. + double distance = Math.sqrt(Math.pow(x - mouseX, 2) + Math.pow(y - mouseY, 2)); + return new net.minecraft.util.Pair<>(slot, distance); + }).filter(entry -> entry.getRight() <= 14.0) + .min(Comparator.comparingDouble(net.minecraft.util.Pair::getRight)); + + if (closestSlot.isPresent() && client.player != null) { + var slot = closestSlot.get().getLeft(); + if (slot.hasStack() || !client.player.getInventory().getMainHandStack().isEmpty()) { + int slotCenterXScaled = guiLeft + slot.x + 8; + int slotCenterYScaled = guiTop + slot.y + 8; + int slotCenterX = (int) (slotCenterXScaled / ((double) client.getWindow().getScaledWidth() / (double) client.getWindow().getWidth())); + int slotCenterY = (int) (slotCenterYScaled / ((double) client.getWindow().getScaledHeight() / (double) client.getWindow().getHeight())); + double deltaX = slotCenterX - targetMouseX; + double deltaY = slotCenterY - targetMouseY; + + if (mouseX != slotCenterXScaled || mouseY != slotCenterYScaled) { + targetMouseX += (int) (deltaX * 0.75); + targetMouseY += (int) (deltaY * 0.75); + } else { + input.mouseSpeedX *= 0.3F; + input.mouseSpeedY *= 0.3F; + } + input.mouseSpeedX *= .75F; + input.mouseSpeedY *= .75F; + } else { + input.mouseSpeedX *= .1F; + input.mouseSpeedY *= .1F; + } + } else { + input.mouseSpeedX *= .3F; + input.mouseSpeedY *= .3F; + } + } else { + input.mouseSpeedX = 0.F; + input.mouseSpeedY = 0.F; + } + } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/AxisStorage.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/AxisStorage.java index 22ea75c..4df707b 100644 --- a/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/AxisStorage.java +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/AxisStorage.java @@ -2,8 +2,11 @@ package eu.midnightdust.midnightcontrols.client.util.storage; import eu.midnightdust.midnightcontrols.client.MidnightControlsConfig; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; +import eu.midnightdust.midnightcontrols.client.enums.ButtonState; import org.lwjgl.glfw.GLFW; +import static eu.midnightdust.midnightcontrols.client.MidnightInput.BUTTON_COOLDOWNS; +import static eu.midnightdust.midnightcontrols.client.controller.InputManager.STATES; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_X; import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y; @@ -14,12 +17,17 @@ public class AxisStorage { public float value, absValue; public double deadZone; public Polarity polarity; + public boolean isTrigger; // Only used for camera handling public AxisStorage(int axis, float value, int state) { this.axis = axis; this.value = value; this.state = state; + this.deadZone = isLeftAxis() ? MidnightControlsConfig.leftDeadZone : MidnightControlsConfig.rightDeadZone; + boolean currentPlusState = value > deadZone; + boolean currentMinusState = value < -deadZone; + this.polarity = currentPlusState ? AxisStorage.Polarity.PLUS : currentMinusState ? AxisStorage.Polarity.MINUS : AxisStorage.Polarity.ZERO; } public AxisStorage(int axis, float value, float absValue, int state) { @@ -27,14 +35,14 @@ public class AxisStorage { this.value = value; this.absValue = absValue; this.state = state; - deadZone = getDeadZoneValue(axis); - asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0); + this.deadZone = isLeftAxis() ? MidnightControlsConfig.leftDeadZone : MidnightControlsConfig.rightDeadZone; + this.asButtonState = value > .5f ? 1 : (value < -.5f ? 2 : 0); if (axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER || axis == GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER - || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) - || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) { + || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER) || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) { + this.isTrigger = true; if (asButtonState == 2) { - asButtonState = 0; + this.asButtonState = 0; } else { // Fixes Triggers not working correctly on some controllers @@ -44,14 +52,60 @@ public class AxisStorage { this.state = 1; this.asButtonState = 1; } - //if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state); + } + } + boolean currentPlusState = value > deadZone; + boolean currentMinusState = value < -deadZone; + if (isTrigger) currentMinusState = false; + else if (!MidnightControlsConfig.analogMovement && isLeftAxis()) { + currentPlusState = asButtonState == 1; + currentMinusState = asButtonState == 2; + } + this.polarity = currentPlusState ? AxisStorage.Polarity.PLUS : currentMinusState ? AxisStorage.Polarity.MINUS : AxisStorage.Polarity.ZERO; + } + + public void setupButtonStates() { + var posButton = ButtonBinding.axisAsButton(axis, true); + var negButton = ButtonBinding.axisAsButton(axis, false); + var previousPlusState = STATES.getOrDefault(posButton, ButtonState.NONE); + var previousMinusState = STATES.getOrDefault(negButton, ButtonState.NONE); + + if (polarity.isPositive() != previousPlusState.isPressed()) { + STATES.put(posButton, polarity.isPositive() ? ButtonState.PRESS : ButtonState.RELEASE); + if (polarity.isPositive()) + BUTTON_COOLDOWNS.put(posButton, 5); + } else if (polarity.isPositive()) { + STATES.put(posButton, ButtonState.REPEAT); + if (BUTTON_COOLDOWNS.getOrDefault(posButton, 0) == 0) { + BUTTON_COOLDOWNS.put(posButton, 5); + } + } + + if (polarity.isNegative() != previousMinusState.isPressed()) { + STATES.put(negButton, polarity.isNegative() ? ButtonState.PRESS : ButtonState.RELEASE); + if (polarity.isNegative()) + BUTTON_COOLDOWNS.put(negButton, 5); + } else if (polarity.isNegative()) { + STATES.put(negButton, ButtonState.REPEAT); + if (BUTTON_COOLDOWNS.getOrDefault(negButton, 0) == 0) { + BUTTON_COOLDOWNS.put(negButton, 5); } } } - private static double getDeadZoneValue(int axis) { - return (axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y) ? MidnightControlsConfig.leftDeadZone : MidnightControlsConfig.rightDeadZone; + public boolean isLeftAxis() { + return axis == GLFW_GAMEPAD_AXIS_LEFT_X || axis == GLFW_GAMEPAD_AXIS_LEFT_Y || axis == GLFW_GAMEPAD_AXIS_LEFT_TRIGGER; } + public boolean isRightAxis() { + return !isLeftAxis(); + } + public enum Polarity { MINUS, ZERO, PLUS; + public boolean isPositive() { + return this == PLUS; + } + public boolean isNegative() { + return this == MINUS; + } } } diff --git a/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/ButtonStorage.java b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/ButtonStorage.java new file mode 100644 index 0000000..501f5aa --- /dev/null +++ b/common/src/main/java/eu/midnightdust/midnightcontrols/client/util/storage/ButtonStorage.java @@ -0,0 +1,18 @@ +package eu.midnightdust.midnightcontrols.client.util.storage; + +import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_LEFT; +import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_BUTTON_DPAD_UP; + +public class ButtonStorage { + public final int button, action; + public final boolean state; + + public ButtonStorage(int button, int action, boolean state) { + this.button = button; + this.action = action; + this.state = state; + } + public boolean isDpad() { + return button >= GLFW_GAMEPAD_BUTTON_DPAD_UP && button <= GLFW_GAMEPAD_BUTTON_DPAD_LEFT; + } +} diff --git a/common/src/main/resources/assets/midnightcontrols/lang/en_us.json b/common/src/main/resources/assets/midnightcontrols/lang/en_us.json index bfc2534..ea99cf7 100644 --- a/common/src/main/resources/assets/midnightcontrols/lang/en_us.json +++ b/common/src/main/resources/assets/midnightcontrols/lang/en_us.json @@ -184,6 +184,7 @@ "midnightcontrols.menu.mouse_speed.tooltip": "The controller's emulated mouse speed.", "midnightcontrols.menu.move_chat": "Move chat input box to top", "midnightcontrols.menu.move_chat.tooltip": "Moves the chat input field to the top, for better input on devices with on-screen keyboards.", + "midnightcontrols.menu.multiple_mapping_tip": "(Tip: You can also insert multiple mappings at the same time)", "midnightcontrols.menu.reacharound.horizontal": "Front Block Placing", "midnightcontrols.menu.reacharound.horizontal.tooltip": "Enables front block placing, §cmight be considered cheating on some servers§r.", "midnightcontrols.menu.reacharound.vertical": "Vertical Reacharound",