diff --git a/build.gradle b/build.gradle index 3c9dcb2..49aeede 100644 --- a/build.gradle +++ b/build.gradle @@ -110,8 +110,8 @@ dependencies { // modImplementation "io.github.ennuil:LibZoomer:${project.libzoomer_version}" modImplementation "org.quiltmc:quilt-json5:1.0.0" - modApi "maven.modrinth:sodium:${project.sodium_version}" - //modImplementation("maven.modrinth:emi:${project.emi_version}") + modCompileOnly "maven.modrinth:sodium:${project.sodium_version}" + modImplementation("maven.modrinth:emi:${project.emi_version}") modImplementation "maven.modrinth:emotecraft:${project.emotecraft_version}" modImplementation "io.github.kosmx:bendy-lib:${project.bendylib_version}" diff --git a/gradle.properties b/gradle.properties index ce1255f..cad3cf6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ yarn_mappings=1.19+build.1 loader_version=0.14.7 # Mod Properties -mod_version = 1.3.0 +mod_version = 1.4.0 maven_group = eu.midnightdust archives_base_name = midnightcontrols modrinth_id=bXX9h73M @@ -22,7 +22,7 @@ midnightlib_version=0.5.2 modmenu_version=4.0.0 emotecraft_version=2.1.3-SNAPSHOT-build.29-MC1.19-fabric bendylib_version=2.0.+ -emi_version=0.1.1+1.18.2 +emi_version=0.2.0+1.19 # Ok Zoomer and LibZoomer are temporarily disabled for the time being, as we are currently using Reflection at runtime instead in OkZoomerCompat due to there being two major, completely incompatible API versions. # ok_zoomer_version=5.0.0-beta.3+1.17.1 diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java b/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java index a3b388e..20aecd0 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/ControllerType.java @@ -24,15 +24,15 @@ import java.util.Optional; * @since 1.0.0 */ public enum ControllerType implements Nameable { - DEFAULT(0, Text.of("Default")), - DUALSHOCK(1, Text.of("Dualshock")), - DUALSENSE(2, Text.of("Dualsense")), - SWITCH(3, Text.of("Switch")), - XBOX_360(4, Text.of("Xbox 360")), - XBOX(5, Text.of("Xbox")), - STEAM_DECK(6, Text.of("Steam Deck")), - STEAM_CONTROLLER(7, Text.of("Steam Controller")), - OUYA(8, Text.of("Ouya")); + DEFAULT(0), + DUALSHOCK(1), + DUALSENSE(2), + SWITCH(3), + XBOX_360(4), + XBOX(5), + STEAM_DECK(6), + STEAM_CONTROLLER(7), + OUYA(8); private final int id; private final Text text; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java index 1d0ead5..3c344bb 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsClient.java @@ -20,7 +20,6 @@ import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsHud; -import eu.midnightdust.midnightcontrols.client.gui.RingScreen; import eu.midnightdust.midnightcontrols.client.gui.TouchscreenOverlay; import eu.midnightdust.midnightcontrols.client.mixin.KeyBindingRegistryImplAccessor; import eu.midnightdust.midnightcontrols.client.ring.KeyBindingRingAction; diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java index bb2aae5..5cfd05d 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightControlsConfig.java @@ -16,6 +16,7 @@ import eu.midnightdust.midnightcontrols.MidnightControlsFeature; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; import eu.midnightdust.midnightcontrols.client.controller.Controller; import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import net.minecraft.client.MinecraftClient; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.lwjgl.glfw.GLFW; @@ -23,13 +24,13 @@ import org.lwjgl.glfw.GLFW; import java.util.*; import java.util.regex.Pattern; -import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_X; -import static org.lwjgl.glfw.GLFW.GLFW_GAMEPAD_AXIS_LEFT_Y; +import static org.lwjgl.glfw.GLFW.*; /** * Represents MidnightControls configuration. */ public class MidnightControlsConfig extends MidnightConfig { + public static boolean isEditing = false; // General @Entry(name = "midnightcontrols.menu.controls_mode") public static ControlsMode controlsMode = ControlsMode.DEFAULT; @Entry(name = "midnightcontrols.menu.auto_switch_mode") public static boolean autoSwitchMode = true; @@ -60,11 +61,12 @@ public class MidnightControlsConfig extends MidnightConfig { @Entry(name = "Controller ID") public static Object controllerID = 0; @Entry(name = "2nd Controller ID") public static Object secondControllerID = -1; @Entry(name = "midnightcontrols.menu.controller_type") public static ControllerType controllerType = ControllerType.DEFAULT; - @Entry(name = "Mouse screens") public static List mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui", "net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375", "net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen"); + @Entry(name = "Mouse screens") public static List mouseScreens = Lists.newArrayList("me.jellysquid.mods.sodium.client.gui", "net.coderbot.iris.gui", "net.minecraft.client.gui.screen.advancement", "net.minecraft.client.gui.screen.pack.PackScreen", "net.minecraft.class_5375", "net.minecraft.class_457", "net.minecraft.class_408", "me.flashyreese.mods.reeses_sodium_options.client.gui", "dev.emi.emi.screen", "hardcorequesting.client.interfaces.GuiQuestBook", "hardcorequesting.client.interfaces.GuiReward", "hardcorequesting.client.interfaces.EditTrackerScreen"); @Entry(name = "Keybindings") public static Map BINDINGS = new HashMap<>(); private static final Pattern BUTTON_BINDING_PATTERN = Pattern.compile("(-?\\d+)\\+?"); @Entry(name = "Max analog values") public static double[] maxAnalogValues = new double[]{1, 1, 1, 1}; + @Entry public static boolean triggerFix = true; /** * Loads the configuration @@ -92,12 +94,23 @@ public class MidnightControlsConfig extends MidnightConfig { */ public static Controller getController() { var raw = MidnightControlsConfig.controllerID; + Controller controller = Controller.byId(GLFW.GLFW_JOYSTICK_1); if (raw instanceof Number) { - return Controller.byId(((Number) raw).intValue()); + controller = Controller.byId(((Number) raw).intValue()); } else if (raw instanceof String) { - return Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1)); + controller = Controller.byGuid((String) raw).orElse(Controller.byId(GLFW.GLFW_JOYSTICK_1)); } - return Controller.byId(GLFW.GLFW_JOYSTICK_1); + if ((!controller.isConnected() || !controller.isGamepad()) && MidnightControlsConfig.autoSwitchMode && !isEditing) { + for (int i = 0; i < GLFW.GLFW_JOYSTICK_LAST; ++i) { + Controller gamepad = Controller.byId(i); + if (gamepad.isConnected() && gamepad.isGamepad()) { + controller = gamepad; + i = GLFW_JOYSTICK_LAST; + } + } + } + if (controller.isConnected() && controller.isGamepad() && MidnightControlsConfig.autoSwitchMode && !isEditing) MidnightControlsConfig.controlsMode = ControlsMode.CONTROLLER; + return controller; } /** diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java index 947627a..093dcb0 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/MidnightInput.java @@ -11,8 +11,8 @@ package eu.midnightdust.midnightcontrols.client; import com.google.common.collect.ImmutableSet; import dev.lambdaurora.spruceui.widget.container.SpruceEntryListWidget; -import dev.lambdaurora.spruceui.widget.container.SpruceOptionListWidget; import eu.midnightdust.midnightcontrols.MidnightControls; +import eu.midnightdust.midnightcontrols.client.compat.EMICompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat; import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; @@ -31,7 +31,6 @@ import dev.lambdaurora.spruceui.widget.AbstractSprucePressableButtonWidget; import dev.lambdaurora.spruceui.widget.SpruceElement; import dev.lambdaurora.spruceui.widget.SpruceLabelWidget; import dev.lambdaurora.spruceui.widget.container.SpruceParentWidget; -import net.fabricmc.fabric.impl.item.group.CreativeGuiExtensions; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.Element; @@ -51,8 +50,6 @@ import net.minecraft.client.gui.widget.EntryListWidget; import net.minecraft.client.gui.widget.PressableWidget; import net.minecraft.client.gui.widget.SliderWidget; import net.minecraft.screen.slot.Slot; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.text.Text; import net.minecraft.util.math.MathHelper; import org.aperlambda.lambdacommon.utils.Pair; import org.jetbrains.annotations.NotNull; @@ -129,6 +126,7 @@ public class MidnightInput { InputManager.updateStates(); var controller = MidnightControlsConfig.getController(); + if (controller.isConnected()) { var state = controller.getState(); this.fetchButtonInput(client, state, false); @@ -141,10 +139,7 @@ public class MidnightInput { this.fetchAxeInput(client, state, true); }); - boolean allowInput = true; - - if (this.controlsInput != null && this.controlsInput.focusedBinding != null) - allowInput = false; + boolean allowInput = this.controlsInput == null || this.controlsInput.focusedBinding == null; if (allowInput) InputManager.updateBindings(client); @@ -194,7 +189,7 @@ public class MidnightInput { float rotationPitch = (float) (player.prevPitch + (this.targetPitch / 0.10) * tickDelta); client.player.setYaw(rotationYaw); client.player.setPitch(MathHelper.clamp(rotationPitch, -90.f, 90.f)); - if (client.player.isRiding()) { + if (client.player.isRiding() && client.player.getVehicle() != null) { client.player.getVehicle().onPassengerLookAround(client.player); } client.getTutorialManager().onUpdateMouse(this.targetPitch, this.targetYaw); @@ -322,7 +317,7 @@ public class MidnightInput { if (button == GLFW.GLFW_GAMEPAD_BUTTON_A && client.currentScreen != null && !isScreenInteractive(client.currentScreen) && this.actionGuiCooldown == 0) { - if (client.currentScreen instanceof CreativeInventoryScreen creativeScreen && ((HandledScreenAccessor) creativeScreen).midnightcontrols$getSlotAt( + 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; if (!this.ignoreNextARelease) { @@ -335,7 +330,7 @@ public class MidnightInput { Screen.wrapScreenError(() -> client.currentScreen.mouseReleased(mouseX, mouseY, GLFW.GLFW_MOUSE_BUTTON_1), "mouseReleased event handler", client.currentScreen.getClass().getCanonicalName()); } - this.actionGuiCooldown = 5; + //this.actionGuiCooldown = 5; } else { this.ignoreNextARelease = false; } @@ -371,11 +366,24 @@ public class MidnightInput { private void handleAxe(@NotNull MinecraftClient client, int axis, float value, float absValue, int state) { int 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)) - if (asButtonState == 2) + || axis == ButtonBinding.controller2Button(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER)) { + if (asButtonState == 2) { asButtonState = 0; + } + else { + // Fixes Triggers not working correctly on some controllers + if (MidnightControlsConfig.triggerFix) { + value = 1.0f; + absValue = 1.0f; + state = 1; + asButtonState = 1; + } + if (MidnightControlsConfig.debug) System.out.println(axis + " "+ value + " " + absValue + " " + state); + } + } { boolean currentPlusState = asButtonState == 1; @@ -463,19 +471,20 @@ public class MidnightInput { } } else if (client.currentScreen != null) { if (axis == GLFW_GAMEPAD_AXIS_RIGHT_Y && absValue >= deadZone) { + float finalValue = value; client.currentScreen.children().stream().filter(element -> element instanceof EntryListWidget) .map(element -> (EntryListWidget) element) .filter(element -> element.getType().isFocused()) .anyMatch(element -> { - element.mouseScrolled(0.0, 0.0, -value); + element.mouseScrolled(0.0, 0.0, -finalValue); return true; }); client.currentScreen.children().stream().filter(element -> element instanceof SpruceEntryListWidget) .map(element -> (SpruceEntryListWidget) element) .filter(element -> element.getType().isFocused()) .anyMatch(element -> { - MidnightControls.get().log(String.valueOf(value)); - element.mouseScrolled(0.0, 0.0, -value); + MidnightControls.get().log(String.valueOf(finalValue)); + element.mouseScrolled(0.0, 0.0, -finalValue); return true; }); return; @@ -653,23 +662,28 @@ public class MidnightInput { } private boolean changeFocus(@NotNull Screen screen, NavigationDirection direction) { - if (screen instanceof SpruceScreen spruceScreen) { - if (spruceScreen.onNavigation(direction, false)) { - this.actionGuiCooldown = 5; + if (!isScreenInteractive(screen) && !screen.getClass().getCanonicalName().contains("me.jellysquid.mods.sodium.client.gui")) return false; + try { + if (screen instanceof SpruceScreen spruceScreen) { + if (spruceScreen.onNavigation(direction, false)) { + this.actionGuiCooldown = 5; + } + return false; } - return false; - } - if (FabricLoader.getInstance().isModLoaded("sodium")) SodiumCompat.handleInput(screen, direction.isLookingForward()); - if (!screen.changeFocus(direction.isLookingForward())) { - if (screen.changeFocus(direction.isLookingForward())) { + if (FabricLoader.getInstance().isModLoaded("sodium")) + SodiumCompat.handleInput(screen, direction.isLookingForward()); + if (!screen.changeFocus(direction.isLookingForward())) { + if (screen.changeFocus(direction.isLookingForward())) { + this.actionGuiCooldown = 5; + return false; + } + return true; + } else { this.actionGuiCooldown = 5; return false; } - return true; - } else { - this.actionGuiCooldown = 5; - return false; - } + } catch (Exception exception) {MidnightControls.get().warn("Unknown exception encountered while trying to change focus: "+exception);} + return false; } public static boolean isScreenInteractive(@NotNull Screen screen) { diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java new file mode 100644 index 0000000..cf9706f --- /dev/null +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/EMICompat.java @@ -0,0 +1,41 @@ +package eu.midnightdust.midnightcontrols.client.compat; + +import dev.emi.emi.screen.EmiScreen; +import dev.emi.emi.screen.EmiScreenManager; +import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; +import eu.midnightdust.midnightcontrols.client.controller.ButtonBinding; +import eu.midnightdust.midnightcontrols.client.controller.ButtonCategory; +import eu.midnightdust.midnightcontrols.client.controller.InputManager; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import org.aperlambda.lambdacommon.Identifier; +import org.jetbrains.annotations.NotNull; +import org.lwjgl.glfw.GLFW; + +public class EMICompat implements CompatHandler { + public static boolean handleTabs(boolean direction) { + if (MidnightControlsClient.get().input.actionGuiCooldown == 0 &&EmiScreenManager.searchLeft != null && EmiScreenManager.searchRight != null) { + if (direction) EmiScreenManager.searchRight.onPress(); + else EmiScreenManager.searchLeft.onPress(); + MidnightControlsClient.get().input.actionGuiCooldown = 5; + return true; + } + return false; + } + @Override + public void handle(@NotNull MidnightControlsClient mod) { + ButtonCategory category = new ButtonCategory(new Identifier("midnightcontrols","category.emi")); + InputManager.registerCategory(category); + new ButtonBinding.Builder("emi_page_left") + .buttons(GLFW.GLFW_GAMEPAD_BUTTON_LEFT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)) + .category(category) + .action((client,action,value,buttonState)->handleTabs(false)).cooldown() + .filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen || client.currentScreen instanceof EmiScreen)) + .register(); + new ButtonBinding.Builder("emi_page_right") + .buttons(GLFW.GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER, ButtonBinding.axisAsButton(GLFW.GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER, true)) + .category(category) + .action((client,action,value,buttonState)->handleTabs(true)).cooldown() + .filter(((client, buttonBinding) -> client.currentScreen instanceof HandledScreen || client.currentScreen instanceof EmiScreen)) + .register(); + } +} diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java index f646a86..caf70a8 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/MidnightControlsCompat.java @@ -45,10 +45,10 @@ public class MidnightControlsCompat { mod.log("Adding Ok Zoomer compatibility..."); HANDLERS.add(new OkZoomerCompat()); } - /*if (isReiPresent()) { - mod.log("Adding REI compatiblity..."); - HANDLERS.add(new ReiCompat()); - }*/ + if (isEMIPresent()) { + mod.log("Adding EMI compatibility..."); + HANDLERS.add(new EMICompat()); + } if (FabricLoader.getInstance().isModLoaded("hardcorequesting") && LambdaReflection.doesClassExist(HQMCompat.GUI_BASE_CLASS_PATH)) { mod.log("Adding HQM compatibility..."); HANDLERS.add(new HQMCompat()); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java index c082ed4..7964921 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/compat/SodiumCompat.java @@ -22,8 +22,10 @@ public class SodiumCompat { i = (direction ? ((max > i) ? ++i : 0) : (i > 0 ? --i : max)); var dimensions = accessor.getControls().get(i).getDimensions(); - InputManager.INPUT_MANAGER.targetMouseX = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterX()); - InputManager.INPUT_MANAGER.targetMouseY = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterY()); + int x = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterX()); + int y = (int) (client.getWindow().getScaleFactor() * dimensions.getCenterY()); + InputManager.queueMousePosition(x,y); + InputManager.INPUT_MANAGER.updateMousePosition(client); MidnightControlsClient.get().input.actionGuiCooldown = 5; if (MidnightControlsConfig.debug) MidnightControls.get().log(i+" "+accessor.getControls().size()+" | " + dimensions.getCenterX() + " " + dimensions.getCenterY()); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java index 0c8e59f..9dfe509 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/ButtonBinding.java @@ -62,6 +62,9 @@ public class ButtonBinding { .action(MovementHandler.HANDLER).onlyInGame().register(); public static final ButtonBinding SCREENSHOT = new Builder("screenshot").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_A) .action(InputHandlers::handleScreenshot).cooldown().register(); + + public static final ButtonBinding DEBUG_SCREEN = new Builder("debug_screen").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_B) + .action((client,binding,value,action) -> {if (action == ButtonState.PRESS) client.options.debugEnabled = !client.options.debugEnabled; return true;}).cooldown().register(); public static final ButtonBinding SLOT_DOWN = new Builder("slot_down").buttons(GLFW_GAMEPAD_BUTTON_DPAD_DOWN) .action(InputHandlers.handleInventorySlotPad(1)).onlyInInventory().cooldown().register(); public static final ButtonBinding SLOT_LEFT = new Builder("slot_left").buttons(GLFW_GAMEPAD_BUTTON_DPAD_LEFT) @@ -89,7 +92,7 @@ public class ButtonBinding { .action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register(); public static final ButtonBinding QUICK_MOVE = new Builder("quick_move").buttons(GLFW_GAMEPAD_BUTTON_Y) .action(InputHandlers.handleActions()).filter(InputHandlers::inInventory).cooldown().register(); - public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register(); + public static final ButtonBinding TOGGLE_PERSPECTIVE = new Builder("toggle_perspective").filter(InputHandlers::inGame).buttons(GLFW_GAMEPAD_BUTTON_DPAD_UP, GLFW_GAMEPAD_BUTTON_Y).cooldown().register(); public static final ButtonBinding USE = new Builder("use").buttons(axisAsButton(GLFW_GAMEPAD_AXIS_LEFT_TRIGGER, true)).register(); private int[] button; @@ -387,18 +390,26 @@ public class ButtonBinding { ButtonBinding.HOTBAR_RIGHT, ButtonBinding.INVENTORY, ButtonBinding.SWAP_HANDS, + ButtonBinding.TAB_LEFT, + ButtonBinding.TAB_RIGHT, ButtonBinding.PAGE_LEFT, ButtonBinding.PAGE_RIGHT, ButtonBinding.TAKE, ButtonBinding.TAKE_ALL, - ButtonBinding.QUICK_MOVE + ButtonBinding.QUICK_MOVE, + ButtonBinding.SLOT_UP, + ButtonBinding.SLOT_DOWN, + ButtonBinding.SLOT_LEFT, + ButtonBinding.SLOT_RIGHT )); MULTIPLAYER_CATEGORY = InputManager.registerDefaultCategory("key.categories.multiplayer", category -> category.registerAllBindings(ButtonBinding.CHAT, ButtonBinding.PLAYER_LIST)); MISC_CATEGORY = InputManager.registerDefaultCategory("key.categories.misc", category -> category.registerAllBindings( ButtonBinding.SCREENSHOT, + ButtonBinding.TOGGLE_PERSPECTIVE, + ButtonBinding.PAUSE_GAME, //SMOOTH_CAMERA, - ButtonBinding.TOGGLE_PERSPECTIVE + ButtonBinding.DEBUG_SCREEN )); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java index 8e6e881..4885c4e 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputHandlers.java @@ -9,23 +9,28 @@ package eu.midnightdust.midnightcontrols.client.controller; +import com.google.common.collect.ImmutableSet; import eu.midnightdust.midnightcontrols.client.ButtonState; import eu.midnightdust.midnightcontrols.client.MidnightControlsClient; import eu.midnightdust.midnightcontrols.client.MidnightInput; +import eu.midnightdust.midnightcontrols.client.compat.EMICompat; import eu.midnightdust.midnightcontrols.client.compat.MidnightControlsCompat; import eu.midnightdust.midnightcontrols.client.compat.SodiumCompat; import eu.midnightdust.midnightcontrols.client.mixin.AdvancementsScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.CreativeInventoryScreenAccessor; import eu.midnightdust.midnightcontrols.client.mixin.RecipeBookWidgetAccessor; import eu.midnightdust.midnightcontrols.client.util.HandledScreenAccessor; +import eu.midnightdust.midnightcontrols.client.util.MouseAccessor; import net.fabricmc.fabric.impl.item.group.CreativeGuiExtensions; import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gl.Framebuffer; +import net.minecraft.client.gui.hud.DebugHud; import net.minecraft.client.gui.screen.advancement.AdvancementsScreen; import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.gui.screen.ingame.InventoryScreen; +import net.minecraft.client.gui.widget.PressableWidget; import net.minecraft.client.util.ScreenshotRecorder; import net.minecraft.item.ItemGroup; import net.minecraft.item.Items; @@ -118,9 +123,27 @@ public class InputHandlers { var screen = (HandledScreenAccessor) client.currentScreen; try { if (next) { - ((CreativeGuiExtensions) screen).fabric_nextPage(); + return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget) + .map(element -> (PressableWidget) element) + .filter(element -> element.getMessage() != null && element.getMessage().getContent() != null) + .anyMatch(element -> { + if (element.getMessage().getString().equals(">")) { + element.onPress(); + return true; + } + return false; + }); } else { - ((CreativeGuiExtensions) screen).fabric_previousPage(); + return client.currentScreen.children().stream().filter(element -> element instanceof PressableWidget) + .map(element -> (PressableWidget) element) + .filter(element -> element.getMessage() != null && element.getMessage().getContent() != null) + .anyMatch(element -> { + if (element.getMessage().getString().equals("<")) { + element.onPress(); + return true; + } + return false; + }); } } catch (Exception ignored) {} } @@ -144,6 +167,7 @@ public class InputHandlers { int slotId; if (slot == null) { if (button.getName().equals("take_all")) { + ((MouseAccessor) client.mouse).setLeftButtonClicked(true); return false; } slotId = accessor.midnightcontrols$isClickOutsideBounds(x, y, accessor.getX(), accessor.getY(), GLFW_MOUSE_BUTTON_1) ? -999 : -1; @@ -155,24 +179,21 @@ public class InputHandlers { MidnightControlsClient.get().input.inventoryInteractionCooldown = 5; switch (button.getName()) { - case "take_all": - if (accessor instanceof CreativeInventoryScreen) { - if (((CreativeInventoryScreenAccessor) accessor).midnightcontrols$isCreativeInventorySlot(slot)) + case "take_all": { + if (screen instanceof CreativeInventoryScreen) { + if (slot != null && (((CreativeInventoryScreenAccessor) accessor).midnightcontrols$isCreativeInventorySlot(slot) || MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot)))) actionType = SlotActionType.CLONE; - if (slot != null && MidnightControlsCompat.streamCompatHandlers().anyMatch(handler -> handler.isCreativeSlot(screen, slot))) - actionType = SlotActionType.CLONE; - } else { - if (slot != null && screen.getScreenHandler().getCursorStack() != null) { - return screen.mouseReleased(x, y, GLFW.GLFW_MOUSE_BUTTON_1); - } else actionType = SlotActionType.PICKUP_ALL; } break; - case "take": + } + case "take": { clickData = GLFW_MOUSE_BUTTON_2; break; - case "quick_move": + } + case "quick_move": { actionType = SlotActionType.QUICK_MOVE; break; + } default: return false; } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java index 9b8ce30..0acfbbc 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/controller/InputManager.java @@ -51,6 +51,10 @@ public class InputManager { } public void tick(@NotNull MinecraftClient client) { + 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); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java index 1263049..d27bbbc 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsHud.java @@ -72,8 +72,8 @@ public class MidnightControlsHud extends Hud { this.dropItemButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.DROP_ITEM); this.attackButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.ATTACK); this.useButtonWidth = MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.USE); - if (client.getWindow().getScaleFactor() >= 4) { - scale = (float) (0.75f * (client.getWindow().getScaleFactor()-3)); + if (client.options.getGuiScale().getValue() >= 4) { + scale = 0.75f; } else scale = 1f; } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java index 4b3b8d5..22ef957 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/gui/MidnightControlsSettingsScreen.java @@ -154,6 +154,7 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { public MidnightControlsSettingsScreen(Screen parent, boolean hideControls) { super(Text.translatable("midnightcontrols.title.settings")); + MidnightControlsConfig.isEditing = true; this.parent = parent; // General options this.inputModeOption = new SpruceCyclingOption("midnightcontrols.menu.controls_mode", @@ -248,12 +249,14 @@ public class MidnightControlsSettingsScreen extends SpruceScreen { @Override public void removed() { + MidnightControlsConfig.isEditing = false; MidnightControlsConfig.save(); super.removed(); } @Override public void close() { + MidnightControlsConfig.isEditing = false; MidnightControlsConfig.save(); super.close(); } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java index c8e50e0..1a8daa5 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/ControlsOptionsScreenMixin.java @@ -9,14 +9,18 @@ package eu.midnightdust.midnightcontrols.client.mixin; +import eu.midnightdust.lib.util.screen.TexturedOverlayButtonWidget; import eu.midnightdust.midnightcontrols.client.gui.MidnightControlsSettingsScreen; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.option.ControlsOptionsScreen; import net.minecraft.client.gui.screen.option.GameOptionsScreen; import net.minecraft.client.gui.widget.ButtonWidget; import net.minecraft.client.option.GameOptions; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; +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; @@ -26,16 +30,27 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; */ @Mixin(ControlsOptionsScreen.class) public abstract class ControlsOptionsScreenMixin extends GameOptionsScreen { + @Unique private final boolean showAlternativeButton = FabricLoader.getInstance().isModLoaded("crawl"); public ControlsOptionsScreenMixin(Screen parent, GameOptions gameOptions, Text text) { super(parent, gameOptions, text); } + @Inject(method = "init", at = @At(value = "INVOKE", ordinal = 1, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;")) + private void addAlternativeControllerButton(CallbackInfo ci) { + if (showAlternativeButton) { + this.addDrawableChild(new TexturedOverlayButtonWidget(this.width / 2 + 158, this.height / 6 - 12, 20, 20,0,0,20, new Identifier("midnightcontrols", "textures/gui/midnightcontrols_button.png"), 32, 64, (button) -> { + this.client.setScreen(new MidnightControlsSettingsScreen(this, false)); + }, Text.translatable("midnightcontrols.menu.title.controller"))); + } + } @Inject(method = "init", at = @At(value = "INVOKE", ordinal = 4, shift = At.Shift.AFTER, target = "Lnet/minecraft/client/gui/screen/option/ControlsOptionsScreen;addDrawableChild(Lnet/minecraft/client/gui/Element;)Lnet/minecraft/client/gui/Element;")) private void addControllerButton(CallbackInfo ci) { - int i = this.width / 2 - 155; - int j = i + 160; - int k = this.height / 6 - 12 + 48;; - this.addDrawableChild(new ButtonWidget(j, k, 150, 20, Text.translatable("midnightcontrols.menu.title.controller").append("..."), (button) -> { - this.client.setScreen(new MidnightControlsSettingsScreen(this, false)); - })); + if (!showAlternativeButton) { + int i = this.width / 2 - 155; + int j = i + 160; + int k = this.height / 6 - 12 + 48; + this.addDrawableChild(new ButtonWidget(j, k, 150, 20, Text.translatable("midnightcontrols.menu.title.controller").append("..."), (button) -> { + this.client.setScreen(new MidnightControlsSettingsScreen(this, false)); + })); + } } } diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java index eea2062..619233a 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/HandledScreenMixin.java @@ -59,8 +59,8 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor { public void onRender(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo ci) { if (MidnightControlsConfig.controlsMode == ControlsMode.CONTROLLER) { var client = MinecraftClient.getInstance(); - if (client.getWindow().getScaleFactor() >= 4) { - scale = (float) (0.75f * (client.getWindow().getScaleFactor()-3)); + if (client.options.getGuiScale().getValue() >= 4) { + scale = 0.75f; } else scale = 1f; if (scale != 1f) matrices.scale(scale,scale,scale); int x = 2, y = (int) (client.getWindow().getScaledHeight() * (1 / scale) - 2 - MidnightControlsRenderer.ICON_SIZE); @@ -74,7 +74,9 @@ public abstract class HandledScreenMixin implements HandledScreenAccessor { y -= 24; } if (MidnightControlsCompat.isEMIPresent()) { - x = (int) (client.getWindow().getScaledWidth() * (1 / scale) - 55 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup")) * (1 / scale) - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move")) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE)); + x = (int) (client.getWindow().getScaledWidth() * (1 / scale) - 55 - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.pickup")) + * (1 / scale) - client.textRenderer.getWidth(Text.translatable("midnightcontrols.action.quick_move")) + - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.TAKE) - MidnightControlsRenderer.getBindingIconWidth(ButtonBinding.QUICK_MOVE)); } x = MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_X}, "midnightcontrols.action.pickup", true, client); MidnightControlsRenderer.drawButtonTip(matrices, x, y, new int[]{GLFW.GLFW_GAMEPAD_BUTTON_Y}, "midnightcontrols.action.quick_move", true, client); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java index b541eb4..068d199 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MinecraftClientMixin.java @@ -109,7 +109,11 @@ public abstract class MinecraftClientMixin { } this.midnightcontrols$lastPos = this.player.getPos(); } - // Applied three times for smooth camera turning even on low FPS + // Applied multiple times for smooth camera turning even on low FPS + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;startTick()V", shift = At.Shift.BEFORE)) + private void onPrePreRender(CallbackInfo ci) { + MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); + } @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Recorder;startTick()V", shift = At.Shift.AFTER)) private void onPreRender(CallbackInfo ci) { MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); @@ -122,6 +126,10 @@ public abstract class MinecraftClientMixin { private void onPostRender(CallbackInfo ci) { MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); } + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;endTick()V", shift = At.Shift.AFTER)) + private void onPostPostRender(CallbackInfo ci) { + MidnightControlsClient.get().onRender((MinecraftClient) (Object) (this)); + } @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/GameRenderer;render(FJZ)V", shift = At.Shift.AFTER)) private void renderVirtualCursor(boolean fullRender, CallbackInfo ci) { diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java index 3e014d6..211f002 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/mixin/MouseMixin.java @@ -20,6 +20,7 @@ import org.lwjgl.glfw.GLFW; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.gen.Invoker; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -35,6 +36,9 @@ public abstract class MouseMixin implements MouseAccessor { @Final private MinecraftClient client; + @Accessor + public abstract void setLeftButtonClicked(boolean value); + @Invoker("onCursorPos") public abstract void midnightcontrols$onCursorPos(long window, double x, double y); diff --git a/src/main/java/eu/midnightdust/midnightcontrols/client/util/MouseAccessor.java b/src/main/java/eu/midnightdust/midnightcontrols/client/util/MouseAccessor.java index 9b97031..0b6e004 100644 --- a/src/main/java/eu/midnightdust/midnightcontrols/client/util/MouseAccessor.java +++ b/src/main/java/eu/midnightdust/midnightcontrols/client/util/MouseAccessor.java @@ -14,4 +14,5 @@ package eu.midnightdust.midnightcontrols.client.util; */ public interface MouseAccessor { void midnightcontrols$onCursorPos(long window, double x, double y); + void setLeftButtonClicked(boolean value); } diff --git a/src/main/resources/assets/midnightcontrols/lang/de_de.json b/src/main/resources/assets/midnightcontrols/lang/de_de.json index 2899547..39622d0 100644 --- a/src/main/resources/assets/midnightcontrols/lang/de_de.json +++ b/src/main/resources/assets/midnightcontrols/lang/de_de.json @@ -83,7 +83,7 @@ "midnightcontrols.controller_type.ouya": "OUYA", "midnightcontrols.controls_mode.default": "Tastatur/Maus", "midnightcontrols.controls_mode.controller": "Controller", - "midnightcontrols.controls_mode.touchscreen": "Touchscreen", + "midnightcontrols.controls_mode.touchscreen": "Touchscreen (In Arbeit)", "midnightcontrols.hud_side.left": "links", "midnightcontrols.hud_side.right": "rechts", "midnightcontrols.menu.analog_movement": "Analoge Bewegung", diff --git a/src/main/resources/assets/midnightcontrols/lang/en_us.json b/src/main/resources/assets/midnightcontrols/lang/en_us.json index bba5d1c..b9ca512 100644 --- a/src/main/resources/assets/midnightcontrols/lang/en_us.json +++ b/src/main/resources/assets/midnightcontrols/lang/en_us.json @@ -8,6 +8,7 @@ "midnightcontrols.action.attack": "Attack", "midnightcontrols.action.back": "Back", "midnightcontrols.action.chat": "Open Chat", + "midnightcontrols.action.debug_screen": "Open Debug HUD (F3)", "midnightcontrols.action.drop_item": "Drop Item", "midnightcontrols.action.exit": "Exit", "midnightcontrols.action.forward": "Forward", @@ -26,6 +27,10 @@ "midnightcontrols.action.quick_move": "Quick move", "midnightcontrols.action.right": "Right", "midnightcontrols.action.screenshot": "Take Screenshot", + "midnightcontrols.action.slot_up": "Move Slot up", + "midnightcontrols.action.slot_down": "Move Slot down", + "midnightcontrols.action.slot_left": "Move Slot left", + "midnightcontrols.action.slot_right": "Move Slot right", "midnightcontrols.action.sneak": "Sneak", "midnightcontrols.action.sprint": "Sprint", "midnightcontrols.action.swap_hands": "Swap Hands", @@ -33,6 +38,8 @@ "midnightcontrols.action.toggle_smooth_camera": "Toggle Cinematic Camera", "midnightcontrols.action.page_back": "Previous Page", "midnightcontrols.action.page_next": "Next Page", + "midnightcontrols.action.tab_back": "Previous Tab", + "midnightcontrols.action.tab_next": "Next Tab", "midnightcontrols.action.take": "Take Item", "midnightcontrols.action.take_all": "Take Stack", "midnightcontrols.action.use": "Use", @@ -40,8 +47,9 @@ "midnightcontrols.action.zoom_in": "Increase Zoom", "midnightcontrols.action.zoom_out": "Decrease Zoom", "midnightcontrols.action.zoom_reset": "Reset Zoom", - "midnightcontrols.action.key.emotecraft.fastchoose": "Fast Choose Emote", - "midnightcontrols.action.key.emotecraft.stop": "Stop Emote", + "midnightcontrols.action.emi_page_left": "Previous Page", + "midnightcontrols.action.emi_page_right": "Next Page", + "midnightcontrols.category.emi": "EMI", "midnightcontrols.button.a": "A", "midnightcontrols.button.b": "B", "midnightcontrols.button.x": "X", @@ -79,15 +87,18 @@ "midnightcontrols.controller.mappings.error": "Error while loading mappings.", "midnightcontrols.controller.mappings.error.write": "Error while writing mappings to file.", "midnightcontrols.controller.mappings.updated": "Updated mappings!", - "midnightcontrols.controller_type.default": "default", + "midnightcontrols.controller_type.default": "Default", "midnightcontrols.controller_type.dualshock": "DualShock", + "midnightcontrols.controller_type.dualsense": "DualSense", "midnightcontrols.controller_type.switch": "Switch", "midnightcontrols.controller_type.xbox": "Xbox", - "midnightcontrols.controller_type.steam": "Steam", + "midnightcontrols.controller_type.xbox_360": "Xbox 360", + "midnightcontrols.controller_type.steam_controller": "Steam Controller", + "midnightcontrols.controller_type.steam_deck": "Steam Deck", "midnightcontrols.controller_type.ouya": "OUYA", "midnightcontrols.controls_mode.default": "Keyboard/Mouse", "midnightcontrols.controls_mode.controller": "Controller", - "midnightcontrols.controls_mode.touchscreen": "Touchscreen", + "midnightcontrols.controls_mode.touchscreen": "Touchscreen (WIP)", "midnightcontrols.hud_side.left": "left", "midnightcontrols.hud_side.right": "right", "midnightcontrols.menu.analog_movement": "Analog Movement", diff --git a/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png b/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png new file mode 100644 index 0000000..4d35fd2 Binary files /dev/null and b/src/main/resources/assets/midnightcontrols/textures/gui/midnightcontrols_button.png differ