From 6c5108469cd431688c18734a8912b74f66905524 Mon Sep 17 00:00:00 2001 From: isXander Date: Sun, 5 Feb 2023 14:55:20 +0000 Subject: [PATCH] compound binds, complete vanilla compat, better vmouse screen handling, controller uuid, beta notice screen, configurable movement keys, vmouse shift key, icon, optimize controller save/load --- .github/README.md | 2 +- assets/icon.psd | Bin 0 -> 258747 bytes build.gradle.kts | 8 +- gradle/libs.versions.toml | 4 +- .../dev/isxander/controlify/Controlify.java | 24 +++--- .../isxander/controlify/bindings/Bind.java | 48 ++++++++--- .../controlify/bindings/CompoundBind.java | 77 ++++++++++++++++++ .../bindings/ControllerBinding.java | 77 ++++++++++++++---- .../bindings/ControllerBindings.java | 25 ++++-- .../isxander/controlify/bindings/IBind.java | 38 +++++++++ .../compatibility/screen/ScreenProcessor.java | 15 +++- .../CreativeModeInventoryScreenProcessor.java | 31 +++++++ .../JoinMultiplayerScreenProcessor.java | 25 ++++++ ...nguageSelectionListComponentProcessor.java | 35 ++++++++ ...rSelectionListEntryComponentProcessor.java | 18 ++++ .../controlify/config/ClassTypeAdapter.java | 22 +++++ .../controlify/config/ControlifyConfig.java | 25 ++++-- .../controlify/config/GlobalSettings.java | 7 +- .../config/gui/BindButtonController.java | 66 ++++++++++----- .../controlify/config/gui/YACLHelper.java | 42 +++++++--- .../controlify/controller/Controller.java | 19 +++-- .../controller/hid/ControllerHIDService.java | 5 +- .../controlify/gui/ButtonRenderer.java | 6 +- .../gui/screen/BetaNoticeScreen.java | 63 ++++++++++++++ .../ingame/ControllerPlayerMovement.java | 22 +++-- .../controlify/ingame/InGameInputHandler.java | 25 ++++-- .../vanilla/AbstractSliderButtonMixin.java | 12 +++ .../CreativeModeInventoryScreenAccessor.java | 16 ++++ .../CreativeModeInventoryScreenMixin.java | 19 +++++ .../JoinMultiplayerScreenAccessor.java | 12 +++ .../vanilla/JoinMultiplayerScreenMixin.java | 23 ++++++ .../LanguageSelectionListEntryMixin.java | 26 ++++++ .../vanilla/OptionsSubScreenAccessor.java | 12 +++ .../ServerSelectionListEntryMixin.java | 21 +++++ .../mixins/core/MinecraftMixin.java | 15 +++- .../virtualmouse/InputConstantsMixin.java | 21 +++++ .../virtualmouse/VirtualMouseHandler.java | 19 +++-- .../assets/controlify/lang/en_us.json | 31 +++++-- .../buttons/dualshock4/left_stick_down.png | Bin 0 -> 2008 bytes .../buttons/dualshock4/left_stick_left.png | Bin 0 -> 2073 bytes .../{left_stick.png => left_stick_press.png} | Bin .../buttons/dualshock4/left_stick_right.png | Bin 0 -> 2064 bytes .../gui/buttons/dualshock4/left_stick_up.png | Bin 0 -> 2002 bytes .../buttons/dualshock4/right_stick_down.png | Bin 0 -> 2012 bytes .../buttons/dualshock4/right_stick_left.png | Bin 0 -> 2082 bytes ...{right_stick.png => right_stick_press.png} | Bin .../buttons/dualshock4/right_stick_right.png | Bin 0 -> 2073 bytes .../gui/buttons/dualshock4/right_stick_up.png | Bin 0 -> 2008 bytes .../gui/buttons/xbox/left_stick_down.png | Bin 0 -> 1872 bytes .../gui/buttons/xbox/left_stick_left.png | Bin 0 -> 1874 bytes .../{left_stick.png => left_stick_press.png} | Bin .../gui/buttons/xbox/left_stick_right.png | Bin 0 -> 1865 bytes .../gui/buttons/xbox/left_stick_up.png | Bin 0 -> 1866 bytes .../gui/buttons/xbox/right_stick_down.png | Bin 0 -> 1880 bytes .../gui/buttons/xbox/right_stick_left.png | Bin 0 -> 2034 bytes ...{right_stick.png => right_stick_press.png} | Bin .../gui/buttons/xbox/right_stick_right.png | Bin 0 -> 2023 bytes .../gui/buttons/xbox/right_stick_up.png | Bin 0 -> 1874 bytes src/main/resources/controlify.accessWidener | 3 + src/main/resources/controlify.mixins.json | 8 ++ src/main/resources/fabric.mod.json | 1 + src/main/resources/icon.png | Bin 0 -> 32357 bytes 62 files changed, 831 insertions(+), 137 deletions(-) create mode 100644 assets/icon.psd create mode 100644 src/main/java/dev/isxander/controlify/bindings/CompoundBind.java create mode 100644 src/main/java/dev/isxander/controlify/bindings/IBind.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/vanilla/CreativeModeInventoryScreenProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/vanilla/JoinMultiplayerScreenProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/vanilla/LanguageSelectionListComponentProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/compatibility/vanilla/ServerSelectionListEntryComponentProcessor.java create mode 100644 src/main/java/dev/isxander/controlify/config/ClassTypeAdapter.java create mode 100644 src/main/java/dev/isxander/controlify/gui/screen/BetaNoticeScreen.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenAccessor.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenAccessor.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/LanguageSelectionListEntryMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/OptionsSubScreenAccessor.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/ServerSelectionListEntryMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/InputConstantsMixin.java create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_down.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_left.png rename src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/{left_stick.png => left_stick_press.png} (100%) create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_right.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_up.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_down.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_left.png rename src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/{right_stick.png => right_stick_press.png} (100%) create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_right.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_up.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_down.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_left.png rename src/main/resources/assets/controlify/textures/gui/buttons/xbox/{left_stick.png => left_stick_press.png} (100%) create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_right.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_up.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_down.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_left.png rename src/main/resources/assets/controlify/textures/gui/buttons/xbox/{right_stick.png => right_stick_press.png} (100%) create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_right.png create mode 100644 src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_up.png create mode 100644 src/main/resources/controlify.accessWidener create mode 100644 src/main/resources/icon.png diff --git a/.github/README.md b/.github/README.md index b1353e3..54ed604 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,6 +1,6 @@
-Icon +Icon # Control-ify diff --git a/assets/icon.psd b/assets/icon.psd new file mode 100644 index 0000000000000000000000000000000000000000..329b7950a59c721c0d49f921b1d20c007ce29f6f GIT binary patch literal 258747 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

Es+r6+_VL9zjVXAv_P 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 literal 0 HcmV?d00001 diff --git a/build.gradle.kts b/build.gradle.kts index eaf5d85..2582080 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -30,6 +30,10 @@ repositories { maven("https://jitpack.io") } +loom { + accessWidenerPath.set(file("src/main/resources/controlify.accesswidener")) +} + val minecraftVersion = libs.versions.minecraft.get() dependencies { @@ -52,10 +56,6 @@ dependencies { include(libs.hid4java) } -machete { - -} - tasks { processResources { val modId: String by project diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0c13b2..f462a88 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,8 +9,8 @@ grgit = "5.0.+" minecraft = "23w05a" quilt_mappings = "1" -fabric_loader = "0.14.13" -fabric_api = "0.73.3+1.19.4" +fabric_loader = "0.14.14" +fabric_api = "0.73.4+1.19.4" mixin_extras = "0.2.0-beta.1" yet_another_config_lib = "2.2.0+update.1.19.4-SNAPSHOT" mod_menu = "6.0.0-beta.1" diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index b10f756..55ae038 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -36,37 +36,36 @@ public class Controlify { controllerHIDService = new ControllerHIDService(); // find already connected controllers - for (int i = 0; i < GLFW.GLFW_JOYSTICK_LAST; i++) { + for (int i = 0; i <= GLFW.GLFW_JOYSTICK_LAST; i++) { if (GLFW.glfwJoystickPresent(i)) { int jid = i; - controllerHIDService.awaitNextDevice(device -> { + controllerHIDService.awaitNextController(device -> { setCurrentController(Controller.create(jid, device)); LOGGER.info("Controller found: " + currentController.name()); + config().loadOrCreateControllerData(currentController); }); } } controllerHIDService.start(); - config().load(); // load after initial controller discovery - config().save(); // save new controller configs if they don't exist + config().load(); // listen for new controllers GLFW.glfwSetJoystickCallback((jid, event) -> { if (event == GLFW.GLFW_CONNECTED) { - controllerHIDService.awaitNextDevice(device -> { + controllerHIDService.awaitNextController(device -> { setCurrentController(Controller.create(jid, device)); - LOGGER.info("Controller connected: " + currentController.name() + " (" + device.getPath() + ")"); + LOGGER.info("Controller connected: " + currentController.name()); this.setCurrentInputMode(InputMode.CONTROLLER); - config().load(); // load config again if a configuration already exists for this controller - config().save(); // save config if it doesn't exist + config().loadOrCreateControllerData(currentController); minecraft.getToasts().addToast(SystemToast.multiline( minecraft, SystemToast.SystemToastIds.PERIODIC_NOTIFICATION, Component.translatable("controlify.toast.controller_connected.title"), - Component.translatable("controlify.toast.controller_connected.description") + Component.translatable("controlify.toast.controller_connected.description", currentController.name()) )); }); @@ -98,6 +97,8 @@ public class Controlify { } ControllerState state = currentController == null ? ControllerState.EMPTY : currentController.state(); + if (!config().globalSettings().outOfFocusInput && !client.isWindowActive()) + state = ControllerState.EMPTY; if (state.hasAnyInput()) this.setCurrentInputMode(InputMode.CONTROLLER); @@ -108,12 +109,13 @@ public class Controlify { } if (client.screen != null) { - if (!this.virtualMouseHandler().isVirtualMouseEnabled()) - ScreenProcessorProvider.provide(client.screen).onControllerUpdate(currentController); + ScreenProcessorProvider.provide(client.screen).onControllerUpdate(currentController); } else { this.inGameInputHandler().inputTick(); } this.virtualMouseHandler().handleControllerInput(currentController); + + ControlifyEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(currentController); } public ControlifyConfig config() { diff --git a/src/main/java/dev/isxander/controlify/bindings/Bind.java b/src/main/java/dev/isxander/controlify/bindings/Bind.java index d1b7b53..b8ca800 100644 --- a/src/main/java/dev/isxander/controlify/bindings/Bind.java +++ b/src/main/java/dev/isxander/controlify/bindings/Bind.java @@ -1,21 +1,25 @@ package dev.isxander.controlify.bindings; +import com.google.gson.JsonElement; +import com.google.gson.JsonPrimitive; +import com.mojang.blaze3d.vertex.PoseStack; import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.ControllerState; +import dev.isxander.controlify.gui.ButtonRenderer; import net.minecraft.resources.ResourceLocation; import java.util.function.BiFunction; import java.util.function.Function; -public enum Bind { +public enum Bind implements IBind { A_BUTTON(state -> state.buttons().a(), "a_button"), B_BUTTON(state -> state.buttons().b(), "b_button"), X_BUTTON(state -> state.buttons().x(), "x_button"), Y_BUTTON(state -> state.buttons().y(), "y_button"), LEFT_BUMPER(state -> state.buttons().leftBumper(), "left_bumper"), RIGHT_BUMPER(state -> state.buttons().rightBumper(), "right_bumper"), - LEFT_STICK(state -> state.buttons().leftStick(), "left_stick"), - RIGHT_STICK(state -> state.buttons().rightStick(), "right_stick"), + LEFT_STICK_PRESS(state -> state.buttons().leftStick(), "left_stick_press"), + RIGHT_STICK_PRESS(state -> state.buttons().rightStick(), "right_stick_press"), START(state -> state.buttons().start(), "start"), BACK(state -> state.buttons().back(), "back"), GUIDE(state -> state.buttons().guide(), "guide"), // the middle button @@ -23,23 +27,42 @@ public enum Bind { DPAD_DOWN(state -> state.buttons().dpadDown(), "dpad_down"), DPAD_LEFT(state -> state.buttons().dpadLeft(), "dpad_left"), DPAD_RIGHT(state -> state.buttons().dpadRight(), "dpad_right"), - LEFT_TRIGGER((state, controller) -> state.axes().leftTrigger() >= controller.config().leftTriggerActivationThreshold, "left_trigger"), - RIGHT_TRIGGER((state, controller) -> state.axes().rightTrigger() >= controller.config().rightTriggerActivationThreshold, "right_trigger"); + LEFT_TRIGGER((state, controller) -> state.axes().leftTrigger(), "left_trigger"), + RIGHT_TRIGGER((state, controller) -> state.axes().rightTrigger(), "right_trigger"), + LEFT_STICK_FORWARD((state, controller) -> -Math.min(0, state.axes().leftStickY()), "left_stick_up"), + LEFT_STICK_BACKWARD((state, controller) -> Math.max(0, state.axes().leftStickY()), "left_stick_down"), + LEFT_STICK_LEFT((state, controller) -> -Math.min(0, state.axes().leftStickX()), "left_stick_left"), + LEFT_STICK_RIGHT((state, controller) -> Math.max(0, state.axes().leftStickX()), "left_stick_right"), + RIGHT_STICK_FORWARD((state, controller) -> -Math.min(0, state.axes().rightStickY()), "right_stick_up"), + RIGHT_STICK_BACKWARD((state, controller) -> Math.max(0, state.axes().rightStickY()), "right_stick_down"), + RIGHT_STICK_LEFT((state, controller) -> -Math.min(0, state.axes().rightStickX()), "right_stick_left"), + RIGHT_STICK_RIGHT((state, controller) -> Math.max(0, state.axes().rightStickX()), "right_stick_right"); - private final BiFunction state; + private final BiFunction state; private final String identifier; - Bind(BiFunction state, String identifier) { + Bind(BiFunction state, String identifier) { this.state = state; this.identifier = identifier; } Bind(Function state, String identifier) { - this((state1, controller) -> state.apply(state1), identifier); + this((state1, controller) -> state.apply(state1) ? 1f : 0f, identifier); } - public boolean state(ControllerState controllerState, Controller controller) { - return state.apply(controllerState, controller); + @Override + public float state(ControllerState state, Controller controller) { + return this.state.apply(state, controller); + } + + @Override + public void draw(PoseStack matrices, int x, int centerY, Controller controller) { + ButtonRenderer.drawButton(this, controller, matrices, x, centerY); + } + + @Override + public ButtonRenderer.DrawSize drawSize() { + return new ButtonRenderer.DrawSize(22, 22); } public String identifier() { @@ -50,6 +73,11 @@ public enum Bind { return new ResourceLocation("controlify", "textures/gui/buttons/" + controller.config().theme.id() + "/" + identifier + ".png"); } + @Override + public JsonElement toJson() { + return new JsonPrimitive(identifier); + } + public static Bind fromIdentifier(String identifier) { for (Bind bind : values()) { if (bind.identifier.equals(identifier)) return bind; diff --git a/src/main/java/dev/isxander/controlify/bindings/CompoundBind.java b/src/main/java/dev/isxander/controlify/bindings/CompoundBind.java new file mode 100644 index 0000000..3c7e0ba --- /dev/null +++ b/src/main/java/dev/isxander/controlify/bindings/CompoundBind.java @@ -0,0 +1,77 @@ +package dev.isxander.controlify.bindings; + +import com.google.common.collect.ImmutableSet; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.controller.ControllerState; +import dev.isxander.controlify.gui.ButtonRenderer; +import net.minecraft.client.Minecraft; + +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.Set; + +public class CompoundBind implements IBind { + private final Set binds; + + CompoundBind(Bind... binds) { + this.binds = new LinkedHashSet<>(Arrays.asList(binds)); + } + + public Set binds() { + return ImmutableSet.copyOf(binds); + } + + @Override + public float state(ControllerState state, Controller controller) { + return held(state, controller) ? 1f : 0f; + } + + @Override + public boolean held(ControllerState state, Controller controller) { + return binds.stream().allMatch(bind -> bind.held(state, controller)); + } + + @Override + public void draw(PoseStack matrices, int x, int centerY, Controller controller) { + var font = Minecraft.getInstance().font; + + var iterator = binds.iterator(); + while (iterator.hasNext()) { + var bind = iterator.next(); + + bind.draw(matrices, x, centerY, controller); + x += bind.drawSize().width(); + + if (iterator.hasNext()) { + font.drawShadow(matrices, "+", x + 1, centerY - font.lineHeight / 2f, 0xFFFFFF); + x += font.width("+") + 2; + } + } + } + + @Override + public ButtonRenderer.DrawSize drawSize() { + return new ButtonRenderer.DrawSize( + binds.stream().map(IBind::drawSize).mapToInt(ButtonRenderer.DrawSize::width).sum() + (binds.size() - 1) * (2 + Minecraft.getInstance().font.width("+")), + binds.stream().map(IBind::drawSize).mapToInt(ButtonRenderer.DrawSize::height).max().orElse(0) + ); + } + + @Override + public JsonElement toJson() { + var list = new JsonArray(); + for (IBind bind : binds) { + list.add(bind.toJson()); + } + return list; + } + + @Override + public boolean equals(Object obj) { + return obj instanceof CompoundBind compoundBind && compoundBind.binds.equals(binds) + || obj instanceof Bind bind && Set.of(bind).equals(binds); + } +} diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBinding.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBinding.java index bb4bdd7..9c0d085 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBinding.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBinding.java @@ -1,52 +1,76 @@ package dev.isxander.controlify.bindings; import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.controller.ControllerState; import net.minecraft.client.KeyMapping; +import net.minecraft.locale.Language; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + public class ControllerBinding { private final Controller controller; - private Bind bind; - private final Bind defaultBind; + private IBind bind; + private final IBind defaultBind; private final ResourceLocation id; private final Component name, description; private final KeyMapping override; - public ControllerBinding(Controller controller, Bind defaultBind, ResourceLocation id, Component description, KeyMapping override) { + private static final Map> pressedBinds = new HashMap<>(); + + public ControllerBinding(Controller controller, IBind defaultBind, ResourceLocation id, KeyMapping override) { this.controller = controller; this.bind = this.defaultBind = defaultBind; this.id = id; this.name = Component.translatable("controlify.binding." + id.getNamespace() + "." + id.getPath()); - this.description = description; + var descKey = "controlify.binding." + id.getNamespace() + "." + id.getPath() + ".desc"; + this.description = Language.getInstance().has(descKey) ? Component.translatable(descKey) : Component.empty(); this.override = override; } - public ControllerBinding(Controller controller, Bind defaultBind, ResourceLocation id, KeyMapping override) { - this(controller, defaultBind, id, Component.empty(), override); - } - - public boolean held() { + public float state() { return bind.state(controller.state(), controller); } + public boolean held() { + return bind.held(controller.state(), controller); + } + public boolean justPressed() { - return held() && !bind.state(controller.prevState(), controller); + if (hasBindPressed(this)) return false; + + if (held() && !bind.held(controller.prevState(), controller)) { + addPressedBind(this); + return true; + } else { + return false; + } } public boolean justReleased() { - return !held() && bind.state(controller.prevState(), controller); + if (hasBindPressed(this)) return false; + + if (!held() && bind.held(controller.prevState(), controller)) { + addPressedBind(this); + return true; + } else { + return false; + } } - public Bind currentBind() { + public IBind currentBind() { return bind; } - public void setCurrentBind(Bind bind) { + public void setCurrentBind(IBind bind) { this.bind = bind; } - public Bind defaultBind() { + public IBind defaultBind() { return defaultBind; } @@ -65,4 +89,29 @@ public class ControllerBinding { public KeyMapping override() { return override; } + + // FIXME: very hack solution please remove me + + public static void clearPressedBinds(Controller controller) { + if (pressedBinds.containsKey(controller)) { + pressedBinds.get(controller).clear(); + } + } + + private static boolean hasBindPressed(ControllerBinding binding) { + var pressed = pressedBinds.getOrDefault(binding.controller, Set.of()); + return pressed.containsAll(getBinds(binding.bind)); + } + + private static void addPressedBind(ControllerBinding binding) { + pressedBinds.computeIfAbsent(binding.controller, c -> new HashSet<>()).addAll(getBinds(binding.bind)); + } + + private static Set getBinds(IBind bind) { + if (bind instanceof CompoundBind compoundBind) { + return compoundBind.binds(); + } else { + return Set.of((Bind) bind); + } + } } diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java index a8b9c95..97771f3 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java @@ -14,6 +14,7 @@ import java.util.*; public class ControllerBindings { public final ControllerBinding + WALK_FORWARD, WALK_BACKWARD, WALK_LEFT, WALK_RIGHT, JUMP, SNEAK, ATTACK, USE, SPRINT, @@ -24,18 +25,24 @@ public class ControllerBindings { CHANGE_PERSPECTIVE, OPEN_CHAT, GUI_PRESS, GUI_BACK, - VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_ESCAPE, VMOUSE_TOGGLE; + GUI_NEXT_TAB, GUI_PREV_TAB, + VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE, + TOGGLE_DEBUG_MENU; private final Map registry = new LinkedHashMap<>(); public ControllerBindings(Controller controller) { var options = Minecraft.getInstance().options; + register(WALK_FORWARD = new ControllerBinding(controller, Bind.LEFT_STICK_FORWARD, new ResourceLocation("controlify", "walk_forward"), null)); + register(WALK_BACKWARD = new ControllerBinding(controller, Bind.LEFT_STICK_BACKWARD, new ResourceLocation("controlify", "walk_backward"), null)); + register(WALK_LEFT = new ControllerBinding(controller, Bind.LEFT_STICK_LEFT, new ResourceLocation("controlify", "strafe_left"), null)); + register(WALK_RIGHT = new ControllerBinding(controller, Bind.LEFT_STICK_RIGHT, new ResourceLocation("controlify", "strafe_right"), null)); register(JUMP = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "jump"), options.keyJump)); - register(SNEAK = new ControllerBinding(controller, Bind.RIGHT_STICK, new ResourceLocation("controlify", "sneak"), options.keyShift)); + register(SNEAK = new ControllerBinding(controller, Bind.RIGHT_STICK_PRESS, new ResourceLocation("controlify", "sneak"), options.keyShift)); register(ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, new ResourceLocation("controlify", "attack"), options.keyAttack)); register(USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, new ResourceLocation("controlify", "use"), options.keyUse)); - register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK, new ResourceLocation("controlify", "sprint"), options.keySprint)); + register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "sprint"), options.keySprint)); register(DROP = new ControllerBinding(controller, Bind.DPAD_DOWN, new ResourceLocation("controlify", "drop"), options.keyDrop)); register(NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "next_slot"), null)); register(PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "prev_slot"), null)); @@ -45,11 +52,15 @@ public class ControllerBindings { register(OPEN_CHAT = new ControllerBinding(controller, Bind.DPAD_UP, new ResourceLocation("controlify", "open_chat"), options.keyChat)); register(GUI_PRESS = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "gui_press"), null)); register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back"), null)); + register(GUI_NEXT_TAB = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "gui_next_tab"), null)); + register(GUI_PREV_TAB = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "gui_prev_tab"), null)); register(VMOUSE_LCLICK = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "vmouse_lclick"), null)); register(VMOUSE_RCLICK = new ControllerBinding(controller, Bind.X_BUTTON, new ResourceLocation("controlify", "vmouse_rclick"), null)); register(VMOUSE_MCLICK = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "vmouse_mclick"), null)); register(VMOUSE_ESCAPE = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "vmouse_escape"), null)); + register(VMOUSE_SHIFT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "vmouse_shift"), null)); register(VMOUSE_TOGGLE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "vmouse_toggle"), null)); + register(TOGGLE_DEBUG_MENU = new ControllerBinding(controller, new CompoundBind(Bind.BACK, Bind.START), new ResourceLocation("controlify", "toggle_debug_menu"), null)); ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller); @@ -73,7 +84,7 @@ public class ControllerBindings { public JsonObject toJson() { JsonObject json = new JsonObject(); for (var binding : registry().values()) { - json.addProperty(binding.id().toString(), binding.currentBind().identifier()); + json.add(binding.id().toString(), binding.currentBind().toJson()); } return json; } @@ -82,13 +93,17 @@ public class ControllerBindings { for (var binding : registry().values()) { var bind = json.get(binding.id().toString()); if (bind == null) continue; - binding.setCurrentBind(Bind.fromIdentifier(bind.getAsString())); + binding.setCurrentBind(IBind.fromJson(bind)); } } private void imitateVanillaClick(Controller controller) { + ControllerBinding.clearPressedBinds(controller); + if (Controlify.instance().currentInputMode() != InputMode.CONTROLLER) return; + if (Minecraft.getInstance().screen != null && !Minecraft.getInstance().screen.passEvents) + return; for (var binding : registry().values()) { KeyMapping vanillaKey = binding.override(); diff --git a/src/main/java/dev/isxander/controlify/bindings/IBind.java b/src/main/java/dev/isxander/controlify/bindings/IBind.java new file mode 100644 index 0000000..8dd3326 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/bindings/IBind.java @@ -0,0 +1,38 @@ +package dev.isxander.controlify.bindings; + +import com.google.gson.JsonElement; +import com.mojang.blaze3d.vertex.PoseStack; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.controller.ControllerState; +import dev.isxander.controlify.gui.ButtonRenderer; + +import java.util.Collection; + +public interface IBind { + float state(ControllerState state, Controller controller); + default boolean held(ControllerState state, Controller controller) { + return state(state, controller) > controller.config().buttonActivationThreshold; + } + + void draw(PoseStack matrices, int x, int centerY, Controller controller); + ButtonRenderer.DrawSize drawSize(); + + JsonElement toJson(); + + static IBind fromJson(JsonElement json) { + if (json.isJsonArray()) { + return new CompoundBind(json.getAsJsonArray().asList().stream().map(element -> Bind.fromIdentifier(element.getAsString())).toArray(Bind[]::new)); + } else { + return Bind.fromIdentifier(json.getAsString()); + } + } + + static IBind create(Collection binds) { + if (binds.size() == 1) return binds.stream().findAny().orElseThrow(); + return new CompoundBind(binds.toArray(new Bind[0])); + } + static IBind create(Bind... binds) { + if (binds.length == 1) return binds[0]; + return new CompoundBind(binds); + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/screen/ScreenProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/screen/ScreenProcessor.java index 129e4a9..247594b 100644 --- a/src/main/java/dev/isxander/controlify/compatibility/screen/ScreenProcessor.java +++ b/src/main/java/dev/isxander/controlify/compatibility/screen/ScreenProcessor.java @@ -27,8 +27,12 @@ public class ScreenProcessor { } public void onControllerUpdate(Controller controller) { - handleComponentNavigation(controller); - handleButtons(controller); + if (!Controlify.instance().virtualMouseHandler().isVirtualMouseEnabled()) { + handleComponentNavigation(controller); + handleButtons(controller); + } else { + handleVMouseNavigation(controller); + } } public void onInputModeChanged(InputMode mode) { @@ -43,6 +47,9 @@ public class ScreenProcessor { } protected void handleComponentNavigation(Controller controller) { + if (screen.getFocused() == null) + setInitialFocus(); + var focusTree = getFocusTree(); while (!focusTree.isEmpty()) { var focused = focusTree.poll(); @@ -102,6 +109,10 @@ public class ScreenProcessor { screen.onClose(); } + protected void handleVMouseNavigation(Controller controller) { + + } + public void onWidgetRebuild() { setInitialFocus(); } diff --git a/src/main/java/dev/isxander/controlify/compatibility/vanilla/CreativeModeInventoryScreenProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/vanilla/CreativeModeInventoryScreenProcessor.java new file mode 100644 index 0000000..aff76b4 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/vanilla/CreativeModeInventoryScreenProcessor.java @@ -0,0 +1,31 @@ +package dev.isxander.controlify.compatibility.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.mixins.compat.screen.vanilla.CreativeModeInventoryScreenAccessor; +import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import net.minecraft.world.item.CreativeModeTabs; + +public class CreativeModeInventoryScreenProcessor extends ScreenProcessor { + public CreativeModeInventoryScreenProcessor(CreativeModeInventoryScreen screen) { + super(screen); + } + + @Override + protected void handleVMouseNavigation(Controller controller) { + var accessor = (CreativeModeInventoryScreenAccessor) screen; + + if (controller.bindings().GUI_NEXT_TAB.justPressed()) { + var tabs = CreativeModeTabs.tabs(); + int newIndex = tabs.indexOf(accessor.getSelectedTab()) + 1; + if (newIndex >= tabs.size()) newIndex = 0; + accessor.invokeSelectTab(tabs.get(newIndex)); + } + if (controller.bindings().GUI_PREV_TAB.justPressed()) { + var tabs = CreativeModeTabs.tabs(); + int newIndex = tabs.indexOf(accessor.getSelectedTab()) - 1; + if (newIndex < 0) newIndex = tabs.size() - 1; + accessor.invokeSelectTab(tabs.get(newIndex)); + } + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/vanilla/JoinMultiplayerScreenProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/vanilla/JoinMultiplayerScreenProcessor.java new file mode 100644 index 0000000..03f80f1 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/vanilla/JoinMultiplayerScreenProcessor.java @@ -0,0 +1,25 @@ +package dev.isxander.controlify.compatibility.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.controller.Controller; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; + +public class JoinMultiplayerScreenProcessor extends ScreenProcessor { + private final ServerSelectionList list; + + public JoinMultiplayerScreenProcessor(JoinMultiplayerScreen screen, ServerSelectionList list) { + super(screen); + this.list = list; + } + + @Override + protected void handleButtons(Controller controller) { + if (screen.getFocused() instanceof Button && controller.bindings().GUI_BACK.justPressed()) { + screen.setFocused(list); + } + + super.handleButtons(controller); + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/vanilla/LanguageSelectionListComponentProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/vanilla/LanguageSelectionListComponentProcessor.java new file mode 100644 index 0000000..896cb46 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/vanilla/LanguageSelectionListComponentProcessor.java @@ -0,0 +1,35 @@ +package dev.isxander.controlify.compatibility.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.mixins.compat.screen.vanilla.OptionsSubScreenAccessor; +import net.minecraft.client.Minecraft; + +public class LanguageSelectionListComponentProcessor implements ComponentProcessor { + private final String code; + + public LanguageSelectionListComponentProcessor(String code) { + this.code = code; + } + + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + if (controller.bindings().GUI_PRESS.justPressed()) { + var minecraft = Minecraft.getInstance(); + var languageManager = minecraft.getLanguageManager(); + if (!code.equals(languageManager.getSelected())) { + languageManager.setSelected(code); + minecraft.options.languageCode = code; + minecraft.reloadResourcePacks(); + minecraft.options.save(); + } + + minecraft.setScreen(((OptionsSubScreenAccessor) screen.screen).getLastScreen()); + + return true; + } + + return false; + } +} diff --git a/src/main/java/dev/isxander/controlify/compatibility/vanilla/ServerSelectionListEntryComponentProcessor.java b/src/main/java/dev/isxander/controlify/compatibility/vanilla/ServerSelectionListEntryComponentProcessor.java new file mode 100644 index 0000000..2c6d956 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/compatibility/vanilla/ServerSelectionListEntryComponentProcessor.java @@ -0,0 +1,18 @@ +package dev.isxander.controlify.compatibility.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.mixins.compat.screen.vanilla.JoinMultiplayerScreenAccessor; + +public class ServerSelectionListEntryComponentProcessor implements ComponentProcessor { + @Override + public boolean overrideControllerButtons(ScreenProcessor screen, Controller controller) { + if (controller.bindings().GUI_PRESS.justPressed()) { + screen.screen.setFocused(((JoinMultiplayerScreenAccessor) screen.screen).getSelectButton()); + return true; + } + + return true; + } +} diff --git a/src/main/java/dev/isxander/controlify/config/ClassTypeAdapter.java b/src/main/java/dev/isxander/controlify/config/ClassTypeAdapter.java new file mode 100644 index 0000000..1df5115 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/config/ClassTypeAdapter.java @@ -0,0 +1,22 @@ +package dev.isxander.controlify.config; + +import com.google.gson.*; + +import java.lang.reflect.Type; + +public class ClassTypeAdapter implements JsonSerializer>, JsonDeserializer> { + + @Override + public Class deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + return Class.forName(json.getAsString()); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @Override + public JsonElement serialize(Class src, Type typeOfSrc, JsonSerializationContext context) { + return new JsonPrimitive(src.getName()); + } +} diff --git a/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java b/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java index 1d83b45..dedf469 100644 --- a/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java +++ b/src/main/java/dev/isxander/controlify/config/ControlifyConfig.java @@ -17,10 +17,12 @@ public class ControlifyConfig { .serializeNulls() .setPrettyPrinting() .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) + .registerTypeHierarchyAdapter(Class.class, new ClassTypeAdapter()) .create(); private JsonObject controllerData = new JsonObject(); private GlobalSettings globalSettings = new GlobalSettings(); + private boolean firstLaunch; public void save() { Controlify.LOGGER.info("Saving Controlify config..."); @@ -37,6 +39,7 @@ public class ControlifyConfig { Controlify.LOGGER.info("Loading Controlify config..."); if (!Files.exists(CONFIG_PATH)) { + firstLaunch = true; save(); return; } @@ -55,8 +58,7 @@ public class ControlifyConfig { for (var controller : Controller.CONTROLLERS.values()) { // `add` replaces if already existing - // TODO: find a better way to identify controllers, GUID will report the same for multiple controllers of the same model - newControllerData.add(controller.uid(), generateControllerConfig(controller)); + newControllerData.add(controller.uid().toString(), generateControllerConfig(controller)); } controllerData = newControllerData; @@ -82,15 +84,22 @@ public class ControlifyConfig { JsonObject controllers = object.getAsJsonObject("controllers"); if (controllers != null) { + this.controllerData = controllers; for (var controller : Controller.CONTROLLERS.values()) { - var settings = controllers.getAsJsonObject(controller.uid()); - if (settings != null) { - applyControllerConfig(controller, settings); - } + loadOrCreateControllerData(controller); } } } + public void loadOrCreateControllerData(Controller controller) { + var uid = controller.uid().toString(); + if (controllerData.has(uid)) { + applyControllerConfig(controller, controllerData.getAsJsonObject(uid)); + } else { + save(); + } + } + private void applyControllerConfig(Controller controller, JsonObject object) { controller.setConfig(GSON.fromJson(object.getAsJsonObject("config"), Controller.ControllerConfig.class)); controller.bindings().fromJson(object.getAsJsonObject("bindings")); @@ -99,4 +108,8 @@ public class ControlifyConfig { public GlobalSettings globalSettings() { return globalSettings; } + + public boolean isFirstLaunch() { + return firstLaunch; + } } diff --git a/src/main/java/dev/isxander/controlify/config/GlobalSettings.java b/src/main/java/dev/isxander/controlify/config/GlobalSettings.java index f40887d..693fbfd 100644 --- a/src/main/java/dev/isxander/controlify/config/GlobalSettings.java +++ b/src/main/java/dev/isxander/controlify/config/GlobalSettings.java @@ -1,13 +1,16 @@ package dev.isxander.controlify.config; import com.google.common.collect.Lists; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import java.util.List; public class GlobalSettings { public static final GlobalSettings DEFAULT = new GlobalSettings(); - public List virtualMouseScreens = Lists.newArrayList( - + public List> virtualMouseScreens = Lists.newArrayList( + AbstractContainerScreen.class ); + + public boolean outOfFocusInput = false; } diff --git a/src/main/java/dev/isxander/controlify/config/gui/BindButtonController.java b/src/main/java/dev/isxander/controlify/config/gui/BindButtonController.java index 74066a0..be8e4cd 100644 --- a/src/main/java/dev/isxander/controlify/config/gui/BindButtonController.java +++ b/src/main/java/dev/isxander/controlify/config/gui/BindButtonController.java @@ -2,6 +2,7 @@ package dev.isxander.controlify.config.gui; import com.mojang.blaze3d.vertex.PoseStack; import dev.isxander.controlify.bindings.Bind; +import dev.isxander.controlify.bindings.IBind; import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; @@ -17,23 +18,27 @@ import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; -public class BindButtonController implements Controller { - private final Option option; +import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Set; + +public class BindButtonController implements Controller { + private final Option option; private final dev.isxander.controlify.controller.Controller controller; - public BindButtonController(Option option, dev.isxander.controlify.controller.Controller controller) { + public BindButtonController(Option option, dev.isxander.controlify.controller.Controller controller) { this.option = option; this.controller = controller; } @Override - public Option option() { + public Option option() { return this.option; } @Override public Component formatValue() { - return Component.literal(option().pendingValue().identifier()); + return Component.empty(); } @Override @@ -42,8 +47,9 @@ public class BindButtonController implements Controller { } public static class BindButtonWidget extends ControllerWidget implements ComponentProcessorProvider, ComponentProcessor { - private boolean awaitingControllerInput = false; + private boolean awaitingControllerInput = false, skipFirstTickInput = false; private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC); + private final Set pressedBinds = new LinkedHashSet<>(); public BindButtonWidget(BindButtonController control, YACLScreen screen, Dimension dim) { super(control, screen, dim); @@ -52,9 +58,17 @@ public class BindButtonController implements Controller { @Override protected void drawValueText(PoseStack matrices, int mouseX, int mouseY, float delta) { if (awaitingControllerInput) { - textRenderer.drawShadow(matrices, awaitingText, getDimension().xLimit() - textRenderer.width(awaitingText) - getXPadding(), getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF); + if (pressedBinds.isEmpty()) { + textRenderer.drawShadow(matrices, awaitingText, getDimension().xLimit() - textRenderer.width(awaitingText) - getXPadding(), getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF); + } else { + var bind = IBind.create(pressedBinds); + var plusSize = 2 + textRenderer.width("+"); + bind.draw(matrices, getDimension().xLimit() - bind.drawSize().width() - getXPadding() - plusSize, getDimension().centerY(), control.controller); + textRenderer.drawShadow(matrices, "+", getDimension().xLimit() - getXPadding() - plusSize, getDimension().centerY() - textRenderer.lineHeight / 2f, 0xFFFFFF); + } } else { - ButtonRenderer.drawButton(control.option().pendingValue(), control.controller, matrices, getDimension().xLimit() - ButtonRenderer.BUTTON_SIZE / 2, getDimension().centerY(), ButtonRenderer.BUTTON_SIZE); + var bind = control.option().pendingValue(); + bind.draw(matrices, getDimension().xLimit() - bind.drawSize().width(), getDimension().centerY(), control.controller); } } @@ -84,24 +98,32 @@ public class BindButtonController implements Controller { } @Override - public boolean overrideControllerButtons(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) { - if (!awaitingControllerInput || !isFocused()) return false; - - for (var bind : Bind.values()) { - boolean stateNow = bind.state(controller.state(), controller); - boolean stateBefore = bind.state(controller.prevState(), controller); - if (stateNow && !stateBefore) { - control.option().requestSet(bind); - awaitingControllerInput = false; - return true; - } + public boolean overrideControllerButtons(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) { + if (controller.bindings().GUI_PRESS.justPressed()) { + return awaitingControllerInput = true; } - return false; + if (!awaitingControllerInput) return false; + + if (pressedBinds.stream().anyMatch(bind -> !bind.held(controller.state(), controller))) { + // finished + awaitingControllerInput = false; + control.option().requestSet(IBind.create(pressedBinds)); + pressedBinds.clear(); + } else { + for (var bind : Bind.values()) { + if (bind.held(controller.state(), controller) && !bind.held(controller.prevState(), controller)) { + pressedBinds.add(bind); + } + } + control.controller.consumeButtonState(); + } + + return true; } @Override - public boolean overrideControllerNavigation(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) { + public boolean overrideControllerNavigation(ScreenProcessor screen, dev.isxander.controlify.controller.Controller controller) { return awaitingControllerInput; } @@ -115,7 +137,7 @@ public class BindButtonController implements Controller { if (awaitingControllerInput) return textRenderer.width(awaitingText); - return ButtonRenderer.BUTTON_SIZE; + return control.option().pendingValue().drawSize().width(); } } } diff --git a/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java b/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java index ff04bc7..a7a42db 100644 --- a/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java +++ b/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java @@ -1,28 +1,41 @@ package dev.isxander.controlify.config.gui; import dev.isxander.controlify.Controlify; -import dev.isxander.controlify.bindings.Bind; +import dev.isxander.controlify.bindings.IBind; import dev.isxander.controlify.config.GlobalSettings; import dev.isxander.controlify.controller.ControllerTheme; import dev.isxander.controlify.controller.Controller; import dev.isxander.yacl.api.*; +import dev.isxander.yacl.gui.controllers.ActionController; import dev.isxander.yacl.gui.controllers.TickBoxController; import dev.isxander.yacl.gui.controllers.cycling.CyclingListController; import dev.isxander.yacl.gui.controllers.cycling.EnumController; import dev.isxander.yacl.gui.controllers.slider.FloatSliderController; import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController; import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.AlertScreen; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; public class YACLHelper { public static Screen generateConfigScreen(Screen parent) { + if (Controlify.instance().currentController() == null) { + return new AlertScreen( + () -> Minecraft.getInstance().setScreen(parent), + Component.translatable("controlify.gui.error.title").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), + Component.translatable("controlify.gui.error.message").withStyle(ChatFormatting.RED) + ); + } + var controlify = Controlify.instance(); var yacl = YetAnotherConfigLib.createBuilder() .title(Component.literal("Controlify")) .save(() -> controlify.config().save()); + var globalSettings = Controlify.instance().config().globalSettings(); var globalCategory = ConfigCategory.createBuilder() .name(Component.translatable("controlify.gui.category.global")) .option(Option.createBuilder(Controller.class) @@ -31,6 +44,17 @@ public class YACLHelper { .binding(Controlify.instance().currentController(), () -> Controlify.instance().currentController(), v -> Controlify.instance().setCurrentController(v)) .controller(opt -> new CyclingListController<>(opt, Controller.CONTROLLERS.values().stream().filter(Controller::connected).toList(), c -> Component.literal(c.name()))) .instant(true) + .build()) + .option(Option.createBuilder(boolean.class) + .name(Component.translatable("controlify.gui.out_of_focus_input")) + .tooltip(Component.translatable("controlify.gui.out_of_focus_input.tooltip")) + .binding(GlobalSettings.DEFAULT.outOfFocusInput, () -> globalSettings.outOfFocusInput, v -> globalSettings.outOfFocusInput = v) + .controller(TickBoxController::new) + .build()) + .option(ButtonOption.createBuilder() + .name(Component.translatable("controlify.gui.open_issue_tracker")) + .action((screen, button) -> Util.getPlatform().openUri("https://github.com/isxander/controlify/issues")) + .controller(opt -> new ActionController(opt, Component.translatable("controlify.gui.format.open"))) .build()); yacl.category(globalCategory.build()); @@ -85,15 +109,9 @@ public class YACLHelper { .controller(opt -> new FloatSliderController(opt, 0, 1, 0.01f, v -> Component.literal(String.format("%.0f%%", v*100)))) .build()) .option(Option.createBuilder(float.class) - .name(Component.translatable("controlify.gui.left_trigger_threshold")) - .tooltip(Component.translatable("controlify.gui.left_trigger_threshold.tooltip")) - .binding(def.leftTriggerActivationThreshold, () -> config.leftTriggerActivationThreshold, v -> config.leftTriggerActivationThreshold = v) - .controller(opt -> new FloatSliderController(opt, 0, 1, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100)))) - .build()) - .option(Option.createBuilder(float.class) - .name(Component.translatable("controlify.gui.right_trigger_threshold")) - .tooltip(Component.translatable("controlify.gui.right_trigger_threshold.tooltip")) - .binding(def.rightTriggerActivationThreshold, () -> config.rightTriggerActivationThreshold, v -> config.rightTriggerActivationThreshold = v) + .name(Component.translatable("controlify.gui.button_activation_threshold")) + .tooltip(Component.translatable("controlify.gui.button_activation_threshold.tooltip")) + .binding(def.buttonActivationThreshold, () -> config.buttonActivationThreshold, v -> config.buttonActivationThreshold = v) .controller(opt -> new FloatSliderController(opt, 0, 1, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100)))) .build()) .option(Option.createBuilder(ControllerTheme.class) @@ -108,10 +126,12 @@ public class YACLHelper { var controlsGroup = OptionGroup.createBuilder() .name(Component.translatable("controlify.gui.group.controls")); for (var control : controller.bindings().registry().values()) { - controlsGroup.option(Option.createBuilder(Bind.class) + controlsGroup.option(Option.createBuilder(IBind.class) .name(control.name()) .binding(control.defaultBind(), control::currentBind, control::setCurrentBind) .controller(opt -> new BindButtonController(opt, controller)) + .tooltip(control.description()) + .instant(true) .build()); } category.group(controlsGroup.build()); diff --git a/src/main/java/dev/isxander/controlify/controller/Controller.java b/src/main/java/dev/isxander/controlify/controller/Controller.java index db449af..32dbc95 100644 --- a/src/main/java/dev/isxander/controlify/controller/Controller.java +++ b/src/main/java/dev/isxander/controlify/controller/Controller.java @@ -7,19 +7,21 @@ import org.hid4java.HidDevice; import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFWGamepadState; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.UUID; public final class Controller { public static final Map CONTROLLERS = new HashMap<>(); - public static final Controller DUMMY = new Controller(-1, "DUMMY", "DUMMY", false, "DUMMY", ControllerType.UNKNOWN); + public static final Controller DUMMY = new Controller(-1, "DUMMY", "DUMMY", false, UUID.randomUUID(), ControllerType.UNKNOWN); private final int joystickId; private final String guid; private final String name; private final boolean gamepad; - private final String uid; + private final UUID uid; private final ControllerType type; private ControllerState state = ControllerState.EMPTY; @@ -28,7 +30,7 @@ public final class Controller { private final ControllerBindings bindings = new ControllerBindings(this); private ControllerConfig config, defaultConfig; - public Controller(int joystickId, String guid, String name, boolean gamepad, String uid, ControllerType type) { + public Controller(int joystickId, String guid, String name, boolean gamepad, UUID uid, ControllerType type) { this.joystickId = joystickId; this.guid = guid; this.name = name; @@ -62,8 +64,10 @@ public final class Controller { .rightTriggerDeadZone(config().rightTriggerDeadzone); ButtonState buttonState = ButtonState.fromController(this); state = new ControllerState(axesState, buttonState); + } - ControlifyEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(this); + public void consumeButtonState() { + this.state = new ControllerState(state().axes(), ButtonState.EMPTY); } public ControllerBindings bindings() { @@ -89,7 +93,7 @@ public final class Controller { return guid; } - public String uid() { + public UUID uid() { return uid; } @@ -141,7 +145,7 @@ public final class Controller { String guid = GLFW.glfwGetJoystickGUID(id); boolean gamepad = GLFW.glfwJoystickIsGamepad(id); String fallbackName = gamepad ? GLFW.glfwGetGamepadName(id) : GLFW.glfwGetJoystickName(id); - String uid = device.getPath(); + UUID uid = UUID.nameUUIDFromBytes(device.getPath().getBytes(StandardCharsets.UTF_8)); ControllerType type = ControllerType.getTypeForHID(new HIDIdentifier(device.getVendorId(), device.getProductId())); String name = type != ControllerType.UNKNOWN || fallbackName == null ? type.friendlyName() : fallbackName; int tries = 1; @@ -166,8 +170,7 @@ public final class Controller { public float leftTriggerDeadzone = 0.0f; public float rightTriggerDeadzone = 0.0f; - public float leftTriggerActivationThreshold = 0.5f; - public float rightTriggerActivationThreshold = 0.5f; + public float buttonActivationThreshold = 0.5f; public int screenRepeatNavigationDelay = 4; diff --git a/src/main/java/dev/isxander/controlify/controller/hid/ControllerHIDService.java b/src/main/java/dev/isxander/controlify/controller/hid/ControllerHIDService.java index 64f5b75..c5844bb 100644 --- a/src/main/java/dev/isxander/controlify/controller/hid/ControllerHIDService.java +++ b/src/main/java/dev/isxander/controlify/controller/hid/ControllerHIDService.java @@ -1,6 +1,7 @@ package dev.isxander.controlify.controller.hid; import dev.isxander.controlify.Controlify; +import dev.isxander.controlify.controller.ControllerType; import org.hid4java.*; import org.hid4java.event.HidServicesEvent; @@ -35,7 +36,7 @@ public class ControllerHIDService implements HidServicesListener { services.start(); } - public void awaitNextDevice(Consumer consumer) { + public void awaitNextController(Consumer consumer) { deviceQueue.add(consumer); } @@ -46,6 +47,8 @@ public class ControllerHIDService implements HidServicesListener { if (isController(device)) { if (deviceQueue.peek() != null) { deviceQueue.poll().accept(event.getHidDevice()); + } else { + Controlify.LOGGER.error("Unhandled controller: " + ControllerType.getTypeForHID(new HIDIdentifier(device.getVendorId(), device.getProductId())).friendlyName()); } } } diff --git a/src/main/java/dev/isxander/controlify/gui/ButtonRenderer.java b/src/main/java/dev/isxander/controlify/gui/ButtonRenderer.java index 4f27501..c4e6f5c 100644 --- a/src/main/java/dev/isxander/controlify/gui/ButtonRenderer.java +++ b/src/main/java/dev/isxander/controlify/gui/ButtonRenderer.java @@ -9,10 +9,12 @@ import net.minecraft.client.gui.GuiComponent; public class ButtonRenderer { public static final int BUTTON_SIZE = 22; - public static void drawButton(Bind button, Controller controller, PoseStack poseStack, int x, int y, int size) { + public static void drawButton(Bind button, Controller controller, PoseStack poseStack, int x, int centerY) { RenderSystem.setShaderTexture(0, button.textureLocation(controller)); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); - GuiComponent.blit(poseStack, x - size / 2, y - size / 2, 0, 0, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE); + GuiComponent.blit(poseStack, x, centerY - BUTTON_SIZE / 2, 0, 0, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE); } + + public record DrawSize(int width, int height) { } } diff --git a/src/main/java/dev/isxander/controlify/gui/screen/BetaNoticeScreen.java b/src/main/java/dev/isxander/controlify/gui/screen/BetaNoticeScreen.java new file mode 100644 index 0000000..2783783 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/gui/screen/BetaNoticeScreen.java @@ -0,0 +1,63 @@ +package dev.isxander.controlify.gui.screen; + +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.ChatFormatting; +import net.minecraft.Util; +import net.minecraft.client.gui.components.AccessibilityOnboardingTextWidget; +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.components.MultiLineTextWidget; +import net.minecraft.client.gui.layouts.FrameLayout; +import net.minecraft.client.gui.layouts.GridLayout; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.gui.screens.TitleScreen; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.CommonComponents; +import net.minecraft.network.chat.Component; + +public class BetaNoticeScreen extends Screen { + private MultiLineTextWidget textWidget; + + public BetaNoticeScreen() { + super(Component.translatable("controlify.beta.title")); + } + + @Override + protected void init() { + textWidget = new AccessibilityOnboardingTextWidget( + font, + Component.translatable("controlify.beta.message", + Component.translatable("controlify.beta.message.link") + .withStyle(ChatFormatting.AQUA) + ), + this.width - 10 + ); + textWidget.setX(this.width / 2 - textWidget.getWidth() / 2); + textWidget.setY(30); + addRenderableWidget(textWidget); + + addRenderableWidget( + Button.builder( + Component.translatable("controlify.beta.button"), + btn -> Util.getPlatform().openUri("https://github.com/isXander/controlify/issues") + ) + .pos(this.width / 2 - 75, this.height - 8 - 20 - 20 - 4) + .width(150) + .build() + ); + addRenderableWidget( + Button.builder( + CommonComponents.GUI_CONTINUE, + btn -> minecraft.setScreen(new TitleScreen()) + ) + .pos(this.width / 2 - 75, this.height - 8 - 20) + .width(150) + .build() + ); + } + + @Override + public void render(PoseStack matrices, int mouseX, int mouseY, float delta) { + renderBackground(matrices); + super.render(matrices, mouseX, mouseY, delta); + } +} diff --git a/src/main/java/dev/isxander/controlify/ingame/ControllerPlayerMovement.java b/src/main/java/dev/isxander/controlify/ingame/ControllerPlayerMovement.java index b4ddfc0..1d87458 100644 --- a/src/main/java/dev/isxander/controlify/ingame/ControllerPlayerMovement.java +++ b/src/main/java/dev/isxander/controlify/ingame/ControllerPlayerMovement.java @@ -25,25 +25,23 @@ public class ControllerPlayerMovement extends Input { return; } - var axes = controller.state().axes(); + var bindings = controller.bindings(); - this.up = axes.leftStickY() < 0; - this.down = axes.leftStickY() > 0; - this.left = axes.leftStickX() < 0; - this.right = axes.leftStickX() > 0; - this.leftImpulse = -axes.leftStickX(); - this.forwardImpulse = -axes.leftStickY(); + this.forwardImpulse = bindings.WALK_FORWARD.state() - bindings.WALK_BACKWARD.state(); + this.leftImpulse = bindings.WALK_LEFT.state() - bindings.WALK_RIGHT.state(); + + // .1 to prevent using boat turning absolute hell with left/right left/right + this.up = bindings.WALK_FORWARD.state() > 0.1; + this.down = bindings.WALK_BACKWARD.state() > 0.1; + this.left = bindings.WALK_LEFT.state() > 0.1; + this.right = bindings.WALK_RIGHT.state() > 0.1; if (slowDown) { this.leftImpulse *= f; this.forwardImpulse *= f; } - var bindings = controller.bindings(); - this.jumping = bindings.JUMP.held(); - if (bindings.SNEAK.justPressed()) { - this.shiftKeyDown = !this.shiftKeyDown; - } + this.shiftKeyDown = bindings.SNEAK.held(); } } diff --git a/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java b/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java index ce81f6b..6e8a677 100644 --- a/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java +++ b/src/main/java/dev/isxander/controlify/ingame/InGameInputHandler.java @@ -34,17 +34,20 @@ public class InGameInputHandler { } public void inputTick() { - var axes = controller.state().axes(); - if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) { - accumulatedDX += axes.rightStickX(); - accumulatedDY += axes.rightStickY(); - } + handlePlayerLookInput(); + handleKeybinds(); + } - processPlayerLook(); + protected void handleKeybinds() { + if (Minecraft.getInstance().screen != null && !Minecraft.getInstance().screen.passEvents) + return; if (controller.bindings().PAUSE.justPressed()) { minecraft.pauseGame(false); } + if (controller.bindings().TOGGLE_DEBUG_MENU.justPressed()) { + minecraft.options.renderDebug = !minecraft.options.renderDebug; + } if (minecraft.player != null) { if (controller.bindings().NEXT_SLOT.justPressed()) { minecraft.player.getInventory().swapPaint(-1); @@ -55,6 +58,16 @@ public class InGameInputHandler { } } + protected void handlePlayerLookInput() { + var axes = controller.state().axes(); + if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) { + accumulatedDX += axes.rightStickX(); + accumulatedDY += axes.rightStickY(); + } + + processPlayerLook(); + } + public void processPlayerLook() { var time = Blaze3D.getTime(); var delta = time - deltaTime; diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/AbstractSliderButtonMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/AbstractSliderButtonMixin.java index 0e3575d..4ff1127 100644 --- a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/AbstractSliderButtonMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/AbstractSliderButtonMixin.java @@ -1,12 +1,17 @@ package dev.isxander.controlify.mixins.compat.screen.vanilla; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import dev.isxander.controlify.Controlify; +import dev.isxander.controlify.InputMode; import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; import dev.isxander.controlify.compatibility.vanilla.SliderComponentProcessor; +import net.minecraft.client.InputType; import net.minecraft.client.gui.components.AbstractSliderButton; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; /** * Mixin to insert a custom {@link ComponentProcessor} into slider to support left/right movement without navigating to next component. @@ -22,6 +27,13 @@ public class AbstractSliderButtonMixin implements ComponentProcessorProvider { val -> this.canChangeValue = val ); + @ModifyExpressionValue(method = "setFocused", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;getLastInputType()Lnet/minecraft/client/InputType;")) + private InputType shouldChangeValue(InputType type) { + if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER) + return InputType.NONE; // none doesn't pass condition + return type; + } + @Override public ComponentProcessor componentProcessor() { return controlify$processor; diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenAccessor.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenAccessor.java new file mode 100644 index 0000000..3fe873e --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenAccessor.java @@ -0,0 +1,16 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import net.minecraft.world.item.CreativeModeTab; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(CreativeModeInventoryScreen.class) +public interface CreativeModeInventoryScreenAccessor { + @Accessor + CreativeModeTab getSelectedTab(); + + @Invoker + void invokeSelectTab(CreativeModeTab tab); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenMixin.java new file mode 100644 index 0000000..d795b7b --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/CreativeModeInventoryScreenMixin.java @@ -0,0 +1,19 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; +import dev.isxander.controlify.compatibility.vanilla.CreativeModeInventoryScreenProcessor; +import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(CreativeModeInventoryScreen.class) +public class CreativeModeInventoryScreenMixin implements ScreenProcessorProvider { + @Unique private final CreativeModeInventoryScreenProcessor controlify$screenProcessor + = new CreativeModeInventoryScreenProcessor((CreativeModeInventoryScreen) (Object) this); + + @Override + public ScreenProcessor screenProcessor() { + return controlify$screenProcessor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenAccessor.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenAccessor.java new file mode 100644 index 0000000..9b953a4 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenAccessor.java @@ -0,0 +1,12 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import net.minecraft.client.gui.components.Button; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(JoinMultiplayerScreen.class) +public interface JoinMultiplayerScreenAccessor { + @Accessor + Button getSelectButton(); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenMixin.java new file mode 100644 index 0000000..910b62f --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/JoinMultiplayerScreenMixin.java @@ -0,0 +1,23 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import dev.isxander.controlify.compatibility.screen.ScreenProcessor; +import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider; +import dev.isxander.controlify.compatibility.vanilla.JoinMultiplayerScreenProcessor; +import net.minecraft.client.gui.screens.multiplayer.JoinMultiplayerScreen; +import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(JoinMultiplayerScreen.class) +public class JoinMultiplayerScreenMixin implements ScreenProcessorProvider { + @Shadow protected ServerSelectionList serverSelectionList; + + @Unique private final JoinMultiplayerScreenProcessor controlify$processor + = new JoinMultiplayerScreenProcessor((JoinMultiplayerScreen) (Object) this, serverSelectionList); + + @Override + public ScreenProcessor screenProcessor() { + return controlify$processor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/LanguageSelectionListEntryMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/LanguageSelectionListEntryMixin.java new file mode 100644 index 0000000..6c184ad --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/LanguageSelectionListEntryMixin.java @@ -0,0 +1,26 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; +import dev.isxander.controlify.compatibility.vanilla.LanguageSelectionListComponentProcessor; +import net.minecraft.client.gui.screens.LanguageSelectScreen; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(LanguageSelectScreen.LanguageSelectionList.Entry.class) +public class LanguageSelectionListEntryMixin implements ComponentProcessorProvider { + @Shadow @Final String code; + + @Unique private LanguageSelectionListComponentProcessor controlify$componentProcessor = null; + + @Override + public ComponentProcessor componentProcessor() { + // lazily create the component processor so `code` is defined + if (controlify$componentProcessor == null) + controlify$componentProcessor = new LanguageSelectionListComponentProcessor(code); + + return controlify$componentProcessor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/OptionsSubScreenAccessor.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/OptionsSubScreenAccessor.java new file mode 100644 index 0000000..61437fb --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/OptionsSubScreenAccessor.java @@ -0,0 +1,12 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import net.minecraft.client.gui.screens.OptionsSubScreen; +import net.minecraft.client.gui.screens.Screen; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(OptionsSubScreen.class) +public interface OptionsSubScreenAccessor { + @Accessor + Screen getLastScreen(); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/ServerSelectionListEntryMixin.java b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/ServerSelectionListEntryMixin.java new file mode 100644 index 0000000..8ab2ca3 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/compat/screen/vanilla/ServerSelectionListEntryMixin.java @@ -0,0 +1,21 @@ +package dev.isxander.controlify.mixins.compat.screen.vanilla; + +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor; +import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider; +import dev.isxander.controlify.compatibility.vanilla.ServerSelectionListEntryComponentProcessor; +import net.minecraft.client.gui.screens.multiplayer.ServerSelectionList; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(ServerSelectionList.Entry.class) +public class ServerSelectionListEntryMixin implements ComponentProcessorProvider { + @Unique private final ServerSelectionListEntryComponentProcessor controlify$componentProcessor + = new ServerSelectionListEntryComponentProcessor(); + + @Override + public ComponentProcessor componentProcessor() { + return ((ServerSelectionList.Entry) (Object) this) instanceof ServerSelectionList.LANHeader + ? ComponentProcessor.EMPTY + : controlify$componentProcessor; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/core/MinecraftMixin.java b/src/main/java/dev/isxander/controlify/mixins/core/MinecraftMixin.java index 38cc7a5..990d7d5 100644 --- a/src/main/java/dev/isxander/controlify/mixins/core/MinecraftMixin.java +++ b/src/main/java/dev/isxander/controlify/mixins/core/MinecraftMixin.java @@ -1,14 +1,21 @@ package dev.isxander.controlify.mixins.core; import dev.isxander.controlify.Controlify; +import dev.isxander.controlify.gui.screen.BetaNoticeScreen; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.client.main.GameConfig; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Minecraft.class) -public class MinecraftMixin { +public abstract class MinecraftMixin { + @Shadow public abstract void setScreen(@Nullable Screen screen); + @Inject(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyboardHandler;setup(J)V", shift = At.Shift.AFTER)) private void onInputInitialized(CallbackInfo ci) { Controlify.instance().onInitializeInput(); @@ -18,4 +25,10 @@ public class MinecraftMixin { private void doPlayerLook(boolean tick, CallbackInfo ci) { Controlify.instance().inGameInputHandler().processPlayerLook(); } + + @Inject(method = "", at = @At("TAIL")) + private void showBetaScreen(GameConfig args, CallbackInfo ci) { + if (Controlify.instance().config().isFirstLaunch()) + setScreen(new BetaNoticeScreen()); + } } diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/InputConstantsMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/InputConstantsMixin.java new file mode 100644 index 0000000..ac01da4 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/virtualmouse/InputConstantsMixin.java @@ -0,0 +1,21 @@ +package dev.isxander.controlify.mixins.feature.virtualmouse; + +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.mojang.blaze3d.platform.InputConstants; +import dev.isxander.controlify.Controlify; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(InputConstants.class) +public class InputConstantsMixin { + // must modify isKeyDown here because Screen.hasShiftDown has some instances that ask for this directly. + @ModifyReturnValue(method = "isKeyDown", at = @At("RETURN")) + private static boolean modifyIsKeyDown(boolean keyDown, long window, int key) { + if (key == GLFW.GLFW_KEY_LEFT_SHIFT) { + return keyDown || Controlify.instance().currentController().bindings().VMOUSE_SHIFT.held(); + } + + return keyDown; + } +} diff --git a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java index 748681e..3203edd 100644 --- a/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java +++ b/src/main/java/dev/isxander/controlify/virtualmouse/VirtualMouseHandler.java @@ -180,20 +180,21 @@ public class VirtualMouseHandler { } public boolean requiresVirtualMouse() { - return Controlify.instance().currentInputMode() == InputMode.CONTROLLER - && minecraft.screen != null - && (ScreenProcessorProvider.provide(minecraft.screen).forceVirtualMouse() - || Controlify.instance().config().globalSettings().virtualMouseScreens.contains(minecraft.screen.getClass().getName()) - ); + var isController = Controlify.instance().currentInputMode() == InputMode.CONTROLLER; + var hasScreen = minecraft.screen != null; + var forceVirtualMouse = hasScreen && ScreenProcessorProvider.provide(minecraft.screen).forceVirtualMouse(); + var screenIsVMouseScreen = hasScreen && Controlify.instance().config().globalSettings().virtualMouseScreens.stream().anyMatch(s -> s.isAssignableFrom(minecraft.screen.getClass())); + + return isController && hasScreen && (forceVirtualMouse || screenIsVMouseScreen); } public void toggleVirtualMouse() { if (minecraft.screen == null) return; var screens = Controlify.instance().config().globalSettings().virtualMouseScreens; - var screenName = minecraft.screen.getClass().getName(); - if (screens.contains(screenName)) { - screens.remove(screenName); + var screenClass = minecraft.screen.getClass(); + if (screens.contains(screenClass)) { + screens.remove(screenClass); disableVirtualMouse(); Controlify.instance().hideMouse(true); @@ -204,7 +205,7 @@ public class VirtualMouseHandler { Component.translatable("controlify.toast.vmouse_disabled.description") )); } else { - screens.add(screenName); + screens.add(screenClass); enableVirtualMouse(); minecraft.getToasts().addToast(SystemToast.multiline( diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index 412d119..d00c16e 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -2,9 +2,9 @@ "controlify.gui.category.global": "Global", "controlify.gui.current_controller": "Current Controller", "controlify.gui.current_controller.tooltip": "In Controlify's infancy, only one controller can be used at a time, this selects which one you want to use.", - "controlify.gui.vmouse_screens": "Virtual Mouse Screens", - "controlify.gui.vmouse_screens.tooltip": "A list of Screen class names that require virtual mouse to operate, this is usually due to the screen not being compatible with controller input.", - "controlify.gui.vmouse_screens.placeholder": "Screen class name here...", + "controlify.gui.out_of_focus_input": "Out of Focus Input", + "controlify.gui.out_of_focus_input.tooltip": "If enabled, Controlify will still receive input even if the game window is not focused.", + "controlify.gui.open_issue_tracker": "Open Issue Tracker", "controlify.gui.group.config": "Config", "controlify.gui.group.config.tooltip": "Adjust the controller configuration.", @@ -21,10 +21,8 @@ "controlify.gui.right_stick_deadzone": "Right Stick Deadzone", "controlify.gui.right_stick_deadzone.tooltip": "How far the right joystick needs to be pushed before registering input.", "controlify.gui.stickdrift_warning": "Warning: Setting this too low will cause stickdrift! This is where the internals of your controller become mis-calibrated and register small amounts of input when there shouldn't be.", - "controlify.gui.left_trigger_threshold": "Left Trigger Threshold", - "controlify.gui.left_trigger_threshold.tooltip": "How far the left trigger needs to be pushed before registering as pressed.", - "controlify.gui.right_trigger_threshold": "Right Trigger Threshold", - "controlify.gui.right_trigger_threshold.tooltip": "How far the right trigger needs to be pushed before registering as pressed.", + "controlify.gui.button_activation_threshold": "Button Activation Threshold", + "controlify.gui.button_activation_threshold.tooltip": "How far a button needs to be pushed before registering as pressed.", "controlify.gui.controller_theme": "Controller Theme", "controlify.gui.controller_theme.tooltip": "The theme to use for rendering controller buttons.", @@ -33,6 +31,10 @@ "controlify.gui.bind_input_awaiting": "Press any button", "controlify.gui.format.ticks": "%s ticks", + "controlify.gui.format.open": "OPEN URL", + + "controlify.gui.error.title": "Could not open Controlify settings", + "controlify.gui.error.message": "You cannot change Controlify setttings when you have no controllers connected. Please connect a controller first.", "controlify.gui.button": "Controller Settings...", @@ -48,6 +50,10 @@ "controlify.controller_theme.xbox_one": "Xbox", "controlify.controller_theme.dualshock4": "PS4", + "controlify.binding.controlify.walk_forward": "Walk Forward", + "controlify.binding.controlify.walk_backward": "Walk Backward", + "controlify.binding.controlify.strafe_left": "Strafe Left", + "controlify.binding.controlify.strafe_right": "Strafe Right", "controlify.binding.controlify.jump": "Jump", "controlify.binding.controlify.sneak": "Sneak", "controlify.binding.controlify.attack": "Attack", @@ -61,10 +67,19 @@ "controlify.binding.controlify.open_chat": "Open Chat", "controlify.binding.controlify.gui_press": "GUI Press", "controlify.binding.controlify.gui_back": "GUI Back", + "controlify.binding.controlify.gui_next_tab": "GUI Next Tab", + "controlify.binding.controlify.gui_prev_tab": "GUI Previous Tab", "controlify.binding.controlify.drop": "Drop Item", "controlify.binding.controlify.vmouse_lclick": "Virtual Mouse LClick", "controlify.binding.controlify.vmouse_rclick": "Virtual Mouse RClick", "controlify.binding.controlify.vmouse_mclick": "Virtual Mouse MClick", "controlify.binding.controlify.vmouse_escape": "Virtual Mouse Key Escape", - "controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse" + "controlify.binding.controlify.vmouse_shift": "Virtual Mouse Key Shift", + "controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse", + "controlify.binding.controlify.toggle_debug_menu": "Toggle F3 Menu", + + "controlify.beta.title": "Controlify Beta Notice", + "controlify.beta.message": "You are currently using Controlify Beta.\n\nThis mod is a work in progress and will contain many bugs. Please, if you spot a bug in this mod or have a suggestion to make it even better, please create an issue on the %s!\n\nYou can always find the link to the issue tracker in Controlify's settings menu.", + "controlify.beta.message.link": "issue tracker", + "controlify.beta.button": "Open Issue Tracker..." } diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_down.png b/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_down.png new file mode 100644 index 0000000000000000000000000000000000000000..e300c0545c7edf61cb6aa57b84b2fda5723ee419 GIT binary patch literal 2008 zcmbVNeQeZZ81GcZ#+ZpwmWc#w_lIEY_3J*n-R8C%ZbIi62aGur-?eY=%I?~(?d@(0 zBe3Zd!!)48u;@sH7~>x^LBYT@OAHbdqi&jwEK_%c?GK{?l8Iko>f8Gg$oL4CYx}nS zJ-_Goe7sNhH8nn6ykhkV48w{W>I2Q_T4Ems`RIJ+<48HW6zcUmObjb}&_438p|?vh zET2J;5?uc^^%?MG9&*!6PmSR~FAxN`ZwLpSY&9W>*0Ggtq=$4|XxXlRKwV356 zkk)h%Q9VbinwdnQlu-$wQ;dVQgGvDvS;qy6uW8X>oJ?H3l#MEa)dt)i{!7Nty}LUfzYOMz^L>f+i_)_YEj# zkmY#V#dFRq3bl#^EO0BFB=WLmL;;FWiGmQMbTvfaxxDeUT0}FDJ0yoo`4$AeK{YL) zim)NzCs2?MMUi-sbF%Jsk4XBwEKPDwr;qf}3{AQvNn#;z(=v2r?E{(^vrCz^mu!29 zfsjV_jMpiVKF;YS0pn&!&h3RB#^pn_a@PJ?LqVGfMDCggwfz4PW?8CHL?)`0nb{CE zAe31}luA2HTP7>Z4EnoCNJEYkJx-bgG6zXkh8ztz0KAe^LD}7pjPUd-O+?+=W2z_l zdc{`Io$`j8 zof+x-V{Uq1!9qnDk>~!PX6wTPdw;ody7bY3$7au&CtjnPFk|(_Pq!5=4A$MZr+avz zsLeZae)y;1ipBQcsds-!j?M+7$y3_4Zw@tm`06C54#}P5{A3w%?9JmBT1SukHnn5y z=+?_WTlehVR=xOZr`F$lzFd6n@0OXXqr2Ot%;~C~gBM!P{(JvOpXZUqlJQml{8)9V ZX!*Aj2fxF@zuVv5hPuYUNX-j<{{aK~u($vK literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_left.png b/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/left_stick_left.png new file mode 100644 index 0000000000000000000000000000000000000000..da7516fdf80d64fbd0bfda9e627a4db038c44aef GIT binary patch literal 2073 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 VT&&)9W|#HVt*dVIPHfq}^Ivf%q+I|2 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_down.png b/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_down.png new file mode 100644 index 0000000000000000000000000000000000000000..43010e0cbdbb52bbbd9485060eb1815e7c442014 GIT binary patch literal 2012 zcmbVNeQeZZ81GbI&hdw+NYqFz3Bsh;uj}rv?1tNJU*e6io$Mx}yw|>W>vq?cw%gqn zB06K3M4cK5kpU6|G8ZE*3_n;hhvFuJ3A*_QlQ487`-2cB6BdGtzP&Gj3?y8x?c4VE z{GQ+Q@jiW{vZ8cu)+1RMhRrQ6^HibheCx=Zjm}4U!pqU+UahRwz_9xsu#OCD`;G+| zHk*@ue$(%LRuI*Q4M=JL+F}t6p)o9PMN9)?12pjf49SX{xX}9zfyb za#@QGt6M63VoQVQl86=gcwS6E1QBQgJQfKnh7fZTab5wft;ZCB$025en<%gx;(l)> zUZm;}ciCuCq-h#wIEPIFcHn^gGMuGZmSPx+b&#}6;CO-N@Z^s`{&XoQRC!90-q4+! zs54DXpr~jxYKw9Uww)=XJdaElQH)JD@y zAgzfYB3hbOF_MWwDWhUQqZk`)1r-NMVj8D4>fyL^Nu*#HMxbIE2+O3gTAgaDMxA;S z>h$aD9H8WSy=fmaYKcVBE)27{35AhN$c$*i*Q`OR3L0voF2dp_By*7!jV2W75SXg& zQ`K;)RFx^oIBT~t_>vk~k<_TM^cn-`0VZ@4sA?QZvn0*^_zgP(P_s9SrC z_oPrJTMC+!eyibzv;sWdh5`_+?d2v!tFNF$Bp=H&ROI$DnxKu=K}0%pzaSnqP&~$6nx7SBAs=luO??iPnnPMGKLJ-Ypim>8{S2Ixx>c%R?-(55J zQgAd(tz~+Sqnq@X04j)DM|1v@T_+A;SjMVyPl3<*)~{Qc_g0^UqtI2)m z4t>7Tc90n8WJ-39*RI??UQ6yfQvFyl+h1x=?eDqVz2m??FaKPB>P+Zt-VZqw8x~Ghc5Df>cYK`D7advu#p!|L zf3E2*9qGMzZnQHqe`m$_XV3eFFYf+D+_Yy(Dm^qj*1oP|Q*`0g=F3xqYliGs{+>GH l)h~UtKg0X`==5YCHobiOnHRSn_F3QG^5P25XNBuq{{_i;y1oDa literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_left.png b/src/main/resources/assets/controlify/textures/gui/buttons/dualshock4/right_stick_left.png new file mode 100644 index 0000000000000000000000000000000000000000..3be5fede79132d8f58a54aeb4675807e9606a117 GIT binary patch literal 2082 zcmbVN3vAS69Pa>!z_EmfNQg@5LIkzf*WG$8+{m~)*noq1J7i2__}YHGHM?uOw#VJZ zfQ7^dae&b%h#1jCw_t#f2ok1DBAGFUVKfqDiGh%iz(NKFP%%Ef-pfG-5-!*G@BjP% z{;%)bTEBAXUNaT1$bnm{V2s{UIT7pE4>kw~@*5e_= zg1F$NNtvc;oZ)z{0(^jn{%3HOW?711D3&K_LFD`*&EbU~f&5vDD#pS~3f|CDkZ5)s zQ>3U&CgaU;Uc*XIj35XU%~C8&A_Qr-=?=(}x?Ndh2t!-8G}F-x9d{XlWTc%Sfwbm> zNSP&C-7X{wrHsk~lVZHI8&nRc$R(VawvsvLicG;IOhMhT5tb=o&1S}KOG)TPh2 zIY7ycMoT_M)sjk;T-Z)zJqn|ckWtZgyv>AE4BAH8l3`>$l3D3SV~QaQ0>`l8hLJ3m zs=g>0XMJ7hIz0E$pcfdr&XJwf25yon(rX;{b|lEdYEN26k$ZaYAiVO=;# zpdh`PrienIien`nl0LyNkUZ^U$N4*&~&Mf+8jhK30wAD9QV{C^P^S!z&3Hma3f7>LCnQMgNL z)oz%sOjcDH^sgcz4LMTgeKZMF4w9@2IT~;P1QcZ<<#s>>AiKjEBxJWM zp+Xd1YopZj{_2sZ%``(qI(oO}5w@W^8DPPh1SowU2f7esLQ>nr7PP<|_I3PR}+3~}o0XJUwz{6iiY0E>Z^Zr94Oz}&^mqm_+Ulf^{21= zIdI`x&&{Kk&UP%FJ@%i=t>WoRe?5D7Q(yPBgC`u~AOe$$OQYK7gc_n=By=Evf3vt`RRITTbY>}JEI@3mE z$OmWz06?;Qz^6h129WqN$pMaISeD@eGzdw&C;^_#|0wLwRyApMH5Ww6 zD$*KGK2bPjOa@vE>jPd;S)i&EaaOyX%sN*U1|?An8Loq|Y!Pd%+n3kOgmMB3{V8RC`{q1@igFQz{WsO5^>eQf*eXVRbA`62PMQfUcx{w zSU}-cQK1VTgi{qsGwl?_5$Y+JK#XN1D6*J0sm@HAHg<>Q@LAuoEHxUA3k?M|M#2;h z(x>aH#PY!q2U(8xYXLxOqM*{yFF;yUkm6U_AVP7mU>`A+cCVBLdllP@ARbhp!eLWU zpcPSI={Oe>X*Cdlp-=!q4haSO*KHjS6HGob4{rJYA}p}f;)onvD8sbu;an1AFd0BRDIX~{WfUTEWq(n?A;c30sK(hN05Q3ZM;itSaaPZh?1tp zNNp_m-u{pFd~g(ut>02HzO><)k5`vn9RB;N<)5uwQ5K!Lo|@DzJ)Ocj&<_ zXD&}F|7rfGohP2(cm0%1kCVo2{Y}y@Ogz<7wrImH-?8YcYb&nQ9wi!qbQmBkB)>*hp1B*U;%gvPLs7t30xB0M7`Zd`_wWR zmMYpbSl3qN7uuQyP9!!K<3$M`5k#Q@@I*8s>wLmZBzbwXHXl<2o`e|9Zlc6=h&T9Z z@G?b%IA@_rfu?EP$~r9~umLBuKa4Xp!%$W$#W+ct<5@dTvv~SPAb*+|#$H7B zb~@k^fWVMJyWK_#cAJ$9Fr1wfold}UP5>Ba%h*?I65324a@Rbl<^PK?!%~7G(owDS z^oA$}q4X*u6`Nt2GMQk|ivA7~(vT$ur;R2-kcA`@ge(nM09>M2M48=>jPTSdMMT}+ zW3ngt3dvN^n)X`0}CFAcr8D(G+3Ek*sE_6x7XCO1`^p z?q%R;n3~J%97i|VF9DPhwT9;WZvW)t7&h-QucyTCdTHdf-d9fI`Q_`JRcl=5@b&Vh ztzEgRrY!#FbL{UdSWT=tvHmG};7fjS=UX!?#=hTq^>6{Gt$e1mY2CZWa$1JgUmX8n zU@<0aS#fl{~Ki)QOwyV11t9>)a zs-OJsf!X1O?f2$Pv@#Ge7iR~^(%JZi~~EO=N)|SP>1)M_Ioz% z?R{ha&waZF|7>htyT^Lz>fyln51|XTinBeZVq41g9O@d0t=)gzHZjxRBmCI6ZRNPu z_;#P$K5*uz-UClmpWb$VI5#t*5}ZSuP7O2b_2ce#YvqJ(H`&NK=XP$##E(}s0+ zt;Db;du5;B^a~Zds7CBSQUlN)i)aXqVQbdLG$1xY6A!=!S@95aUk(zuEP04Jmp}_z z2@J_)Z91%JtMrL&jUp!zYoEo}#CSvyfhNFXk+5R$F%J>v<6b!=%R7?Y5nG{wFsita# z)LT%eKHuN~6;}{aJ{FB75=pr*%+eN=Mxr2#q77fG2B~UjsLi?vOIuKwxmGqBU!p@` zs=7~A!%3;Ck|E=))6U?l>tsbzqek8W1Ly@N^bklj2T8Le&G_g--i1`7>*rB|D#^jt zn@~<4Q^>RQ0u*W$37Ft^I7#G#svZF-LpcH(Af+h{1fHrJU!sOp9l1l{IO4tqfiG7K z6DT4q_j(AFq+OOJJ}9~+z_Aj^xVRu$AUcC2Ck6{hwt#lS0L!=>OkvXAtBTE*lu3ID z*-MfWNCj?|ETn@D(hZ$%GEe}5q&wi`xWa(b$--dL{&`(Sn+b&Pn#bB=RuAxHvVqiT zO>BW0*pyg>WjroB4@9e-J%niK2qhx%T3)0Acb36CZ8QWC>Eim%BMdcYMu85C8c?DB zw{@sn#chC=+edw8x-A;@4gGdEQ74KihJexl(M+TWD-X(=9rIF9H>(u?wqVXA;b?eS z%hcRN52?uu6-2G0xtdnI>;#6{YRbJuzQSFj9X(CQ=#0|G4P{gR$P3C>*r$^#vPWJD zrIVAzM0>~5b=hxy_|SJv=`;4h_bRuJZ`qo4#@7)&H%4}GqW{rSfDyNBwh z2I}SphA$r=f4F>L&&ku>PglO!H2g6B^;vz&W9a**C_U!h{BJf0e7N z=2o2>nw-AmU$<{1A|Lhn$3M%N<2H|8`t|4ECVro8`(XB;o>8aJeEr8s;g1U+P2AHt eHu(3*-h;)jZTk;?bB?yNvmcOAD2yF(%F7_viP8yUU!ySs+FwzNI& z08NIP1r=HL$5>=UU8W8-!%QVEvIu5O{!qx`9}+viEL2@d}J=O63sBv!D46mbKhIhl;R;9dNLy+t| ziW`K)@-`J5Xsh(`ZB4vGz+8LKk~j+qB0%TRcqA-oY}|<@cv(0$UK1Fafapz5tke)h z>%3K{TUG(;Fq1e>k|au57_-1xIR@Bvp)^U;1Vs@vgOd){Vq-}QnmjP5rwReK+Vfme z4L&)skgh8%LBwJ)bIf9v)gVDR91en{37W9XpR<#5WXs#M4*Z8cNqv$dim$T4l_Efau;(}5F%u32!B#!1RY+F2WPjXb!H^2&l3 zXuShv^-*?~a3I&&n!0Ft*a01T;WHrLU48;f+1cV|5F*IE_)-8u+70SVIED3F| zm#vUAos)P_;c;RxNwX*ltd$0!xR?PrV`F%nW2_Wzx6>TXGXaZ@VQdx$m7edB`KV!K zYQ6yH3xbssiWwTWlK~6P04sz0i@5;K_^l3y-EW2bft3D!RfL;~3qLTAvBiuvz?O>| zbf-1B1rC7bsAnVx|H~KOP@)> zVe>ME>Andc(w!GbkXnU(wQF?qZwQi6Q{gG~+20;KdEvxmG`H+YrgBHFSon-|bOi4- z`#u<|%6a(kYcIL4nJ!-I$>^H+Jh+-CHnzUp5*r!K|M@Jaw_fe5Ja=lz)qbYEQSNYc zn06pt)Ro4W8{1}EhF)|Nr(QTQ6m59xO7E0AJHF?=3qR4`yvc>Zqr2yS{C92%={%oP zU9|Ge@d?Lw&7%iTn?4f#^*z5gpC9a+>(tEe6pdt!7w<$4{aG?_>~wy?WpZ?2A^+H! zt!w)izBZxQ>$$nxGHbe*XItN0ns$wkFF$m(@B8S@%*WQ=L<;Bee$!t^Jjj-(wr|?k z-E{GZ&w9E=@7^u{tQ6+)yH@J5QOrA^H8HP-zBpdfF!{*L;XiyHW#Z|v!QRH2>+w(D zANqD|j_UADw_mzZRvY@|Q1@4T*Q1vfrdB;iGF=~Hi}R~%{n6o><(reUMe*fdr%a#x gFwHDByn>Gne{4Iq{qKJNg7Md@D68}g>}`DYKPe@JumAu6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_press.png similarity index 100% rename from src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick.png rename to src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_press.png diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_right.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_right.png new file mode 100644 index 0000000000000000000000000000000000000000..5b3590320959fbee2ccf63e94a5faf6751e62599 GIT binary patch literal 1865 zcmbVNeQeZZ81LL%=46IoGIcE2m1H_XuU~h&YvI_}4R-8q&h3&7WVrX*_wKs8Yirx> z?v|J(#u#Q|qEmV0y52Km*F(jJJWEgyVySo4xNNCdb zZTowE&&Th1pANRRY$_=(E5=f;-;)EKW~bjLh-%yhBsB+gvg9T@9Ddrb zHNc46)UU(#{+58)9~F6tsM&z8PYQ@24o!e3<1xh$l5Qf+E12JjwR2|~HjV48!rg4UI+9Y5HPUu*Rvoy<63`4O_lI8`@A-zd;6SR;TNhD&Rgy!g z+feoZ;}RHNaJaH4)G87%!QF6@D1=l!4p4@29E2gIDPaQ7)lFznW2%nap>VjgZ@*vg zDuxLZ5qdpt0wrmaWl7*!juUwoOEPx5lawSoN4i3^i*!m7WJRZga|G$Ey+;*$Eh)41 z60%1YK&p1Kq>B!5q!S{NU^NJl&Y+#=T|v8@g`uqdGrEj66Nue6kF~|D9uS&j1F4hB zY=L(8LS_|{@wDs$5UqB06QZRfl!(l0d5H?#TLz1?i3mibOY6IcFw~Hl06MG-qeA^} z>ri)!+W>uckNVzpTQcff`t5$A&J+Lsp|kX|%k%D0#qsAmKmE3&sG?x`8xOo% zwm&peesKKB=vO@U!QruM0O?zHJAJOLq=VmG!T@JP|J#JUD*jQmDP+ zm2UUlU6 T&!sN~>u2X}Z1Ehf?|$h&I^A|+ literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_up.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/left_stick_up.png new file mode 100644 index 0000000000000000000000000000000000000000..15329f458e66667a68bfa7abfa1c7866e469f660 GIT binary patch literal 1866 zcmbVNeQeZZ81FRd*c=%#adX+UDM1;b*Iw_lWw#G@(@nX#Y-cux8sBT*yKC;QEp2ai z8)_yofOGN@BN7~4E4RJ-fZ{Ym4@d=y=O{5rf0-R3FPD>V$ue!@62u z81~36(c7dqc~)?|95Dew_CZrTq98Pem6XL5z=xoY`(QwnT*T#X2MJshTtuVILwl4; z7!<49RM^l~>*d=*JSz}orFco4Lj)1113VrHOBxq<5eZ%nt&P_dfhQn($VF5b4)G>W z9bPG`5NAy^$6W*EwBrWglFvz*1o(H1;;5Xhe@__=!b^GR>$ z$wdTpUEwGy7K@o;7L%+7C^O5l6wOc!Lm~vJwMsgOlajVD#o&e-uZoH;$`Woc0-qe! zT?C4CHi?Lmrj@j0p-{=FI8Z3Fi8hi-00lmcQ=)1(;auP;7={rj=^DbC(^w@a>#`P< z??Rpae47JQT#qO1W6oG2k+cgsl_~_f zta@cRoRX?86*A6PO=f&?qbLb-Oe?;{0J?z=T?A6iLedOLo4vG?vmw>!=2?_S7DRvR z9Vn~U?BvWWXLF=bs8s}@ga5+`Jm;6y2tXN%5fFfsA_WLMT{o^$4$CTXhr+QWe0w}x zjil*7;$e;3MW7^2q9||z?GyaKN|S=$ERc-PY9m>z-A~%=7Miy+K!8?|vUkgT)Q~b| zFBtZM6$o|*Lpo`{g>*oxgY?;fpLF=FEbH`Htqk<1>|a(zw3$Hofq9HAX7m78Eow-e z*5npwfUA?Mu!tvQ=KycCvy0#j9ic!ZUyE~9;Jz}LrHut4BAr{`S%fD0^%ziLMF17* zo~=XOEp838+#~Ay(rwPDZ|k=Qi8@(KJ_w`$L^F{hj65h~cFama-KkRI+bwe@1xLfn zSf=MDdPq-RC?RSU&DBef?dij?3{Q=_!t4BC+G+c3gxdmzv`tO9hpCU^LyXelBSVmXSkCe ze}C=9ckSLYYYzY8X$=0lYU81za~xct(n3ymEeG apmjn7gDp1)9@=L7?P{uO-M!1-SorZ@Xi?kKNtY zZVD=47(S+nGEA0z;Kz(&SR}e&WQGLiKVZNwCNV(g5Y^9?roqY=PhB4WfIVd1c>?euuw|J%w)fsJ=BihUGqBURhXI zcRq&A`%nzk8nuDvI9`#gKv2Tanvhh4#;~Q!5-Q*up@D~CRFpl$#Qp;WE(#uEwIe_W z)C$-j`r0(OvaLGAw>9!^fml|GFHLaBfdmbJC#0CHa|sWT^vj{O`I;i|B*bX+5M^dS zyf#pSS1209-Bz09X`04utkWt0J8(irG0xBoL)mN;<0NS}$2vHg#Zw1?;%P#J3wobP zMMF;>qQNj!j-ul6xHZmN6)j5H+-^5TGZe#+2tn$tvH=pLtQVv`c%jZ~qH2hWjGG=o zSZOvq1mZfIgrsKN%6h6$sANmg8*R#6l9s4o2nAroIPt=h* zt*I@r5;mn)F%eJ7&H>(RXAi-fIzq%?_O&=i1#T~cS^IbcL{8_{cNU>55hD&XSQbTv z`rp=}ZpK>&Ew^TUd%DfZ`nrC*6V|C>@(nI@ir4jD z_Cfu7H9ZpdFH)W#v{!qxAM^d% zyy@Pq;pIP^4_566`Yi6_XSa5;#!Nd483sDH4i%Q617-2Y^M=&wC17AZ}x zqVnujYqHp0aKzaSf{{UUSjMe}E literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_left.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_left.png new file mode 100644 index 0000000000000000000000000000000000000000..dcda058863a58bd91c0c0f8eaf20e7adbaf45822 GIT binary patch literal 2034 zcmbVNeQeZZ81KwB8H$mh3z^F(MF~WE{k*TbV;sA|1|BZsl5GqE@3n7l-L46N?mQJ0bNU-V^T3Xe|;$aJi3$^wapfWJu=NX3b4Js(=n`= zQzA`vQ}_iz)KwRd^eA*CRRf_htggE2Y^WNov-t9770NqNy0RqHDOr2%>t29Uzd_ zOc1J(r`4=%qEO1HBrqt(MLR*Ifs&ZV869Rk?OYNm7>6pYQiYDm^Ywj%uFa&HEAW+pfl4ePoiO@d5jjBd3&!ED(q{yi|P<({t zP+U zuFP}7bYw~r4D8wx;lwpV}UJ;~R)DrqFyia!+r@mc5r4FM{h7EJJU{&@YUr6iODm4I zB)iFhA%nZ`Q+siK9_yIe1{fqruZtj2e+PYP{=DYuz zHU}HUhIZSDl_Lx`I-dBso><(LC||@jFJAj>!6vYwuk>oA*!+6o<=$=AQv0x>_lu%) zKR+N|C_lPpW1pvZ`0Dm`W7|&mos5<*@?D5Flr+8FwzJSE8d>8XrMbGccoAeaSA6_y0;BQ-%z2`nycV;a% zf6`24^{{W#_t(spg}>HK3jVl*9q#QFl?~nBJ$7i-4gOH_wHo#G?B>+?yKmlj`ll7t zdWG1!XX?~`b;(NyBg3C6d!rxo^%p<%oqgx%l_i5GQu~sX72lLKu6*OIU)s-Bxldkb z9-Hx5zk1@2@gvQ@pFiAD^u(T1-tob|m-nnM__Au?*u|ai+0IwFu4ZZIz=G8;{|k`b Bz9#?x literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_press.png similarity index 100% rename from src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick.png rename to src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_press.png diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_right.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_right.png new file mode 100644 index 0000000000000000000000000000000000000000..452c230066b7d64a019ea6f170c5b35e500856cc GIT binary patch literal 2023 zcmbVNZEVzJ9Ph+zb4UVW<^l$4(FF{>zTNG1Ww$YQV>_|i+%9a)knmjl^sel#t!5y@t70x~kQ@De{T*f5caF~%==pj#FabbcUF;)s|mW+)#}F~O(zCXj)I%e8&l z{{H{p@Bi}r`)*59!=jR9B^ZV+@;CZg(Y4e*iVM;C{HKw1=<<}_xW&Yd5LzHKnr>u z3@eR04cNA`DIo6b5Z9=?5 zXu<0=1L7VBO^P&4;|%9^NWcl)(6tt4X_loJhGN|$?cq5WPjh(oM<6~!lKEEO#w;7U z^Acgp(s_!C$K#GT=g^E0#dtg(ie@R6B@u!&ld1(0q-w6pdGJ9~G!)%ZG!?f!f}j?& zyadvk2_mZJ-Ku6bQ7C0p0_YUupzWa2KuOHw^q3JzlS?86BQOe8%S2cvkJZDPrI}&v z0j~3}?;$|R6@)y;yjr5sJcVi1??7Q>6EZK_3?y|(wL(*i86vFTfn=_-qtW>~0|HAk z0-6@dm8vBt8E2gi24CH-sFD^p*W6_QeZYcV0#%J8X_lm!0A0zuP}S(p3`)=>MNZy_ zat2rq6_)4RITUIY30UA^I7#GX&4>aNp%MilNa<>b!1H$HewAUY(6OLGeX?^jI= zs3P?HyaWo;p(qkhyJWUPWId$Fxm=_ZI9W0n3^F8L;R!;wn}Mt=Z|~E@m|e=8y@c#p zS!U3`f`l~WNYU-2Ng#8OWM#@j&wt(n+#R}nREx89#3V^>13f?McLhtjPT4Vgw+VJUT=k>%(Y&hf>Ho)3olT|~25JbR8BGy(9O-IiNG&vA5<{}MnIxi-+8pZMVWF$^o{^!sW9mHlTAG6TK%;`*Al^1_X!hZ6WN0ed3R8jn5YC{-MEv7407~ z?=0L^GKQ^RbMVQt)Bc`cl1*2qJZuWX#-p1`O=aYnGjrWep>6WK=bc-(`$5^6xpi2J zvZr{u^D_PPrB3n6_@>n(%Cf$hi@OGHeAv5BP>+5-*ZA_GmL*I2nD55PbLvYs2LH5v z?CxEB^~?74n?+@OI(1z+^7GIPySX*C``P!(vAu&ggI(mu%D&@$$+-gTh29fyF*DCk zU6{CDWi)RnHhK;a$F8j~7rc0&8J}UxkAB@fx&2DTH{W)zyq@girec4+vRn+xsj{^b z1LsErljlZfj}0!rc#~VHx6X{TcW(bFermS!)bGc~t}N|Y^v_7@kLroJhEcfX#GMsG pgUxqd53N7+_qE|$&-I*6)kNP+{Wf-K&#e6^_SZN0MmKDG`(HDfw;=!k literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_up.png b/src/main/resources/assets/controlify/textures/gui/buttons/xbox/right_stick_up.png new file mode 100644 index 0000000000000000000000000000000000000000..7aa84d73522e081647c38807760b09f9cd1a0c84 GIT binary patch literal 1874 zcmbVN4NMzl7(Sw)+a$7>Opp;Thug$?y`Q$UJysW>Y!KIupCZU4@^SZ-Ug-UBchG{G zEd)u1(YQr0nH!mNQHf#6aLY(g`3c!XVMHBdCX2|XiAEDdrZ|m1-<7u67B-h%?t0(d zJ@5NI@B6&p+x?}!ovCXdS&LyIAH5lKa84BNInq5{4V8hAZy5M?*9Ff>fyqTnW~>|WZd z7Q&!d+@`^bHlLqwYvf%5vHdB0TZBUnBxnFUB86m~i@1rXUk0R1Hy)anmEH zSDFnsfw- z8MhaZJsSux=*%S{4Xq^au+bz4SRu&(RXE(u{Izq%?<+Zp<1@0_^75i`yBB!hCyMoY_fDr~7%x^%2 z`rp=}ZpB*%Ew^WVXS%J*`i6eH8`iO6@Z)XgeIzg;(H;&3#) z%w=M3qKCxfg)(xjp}E?a^Q#BLk}69)`F`iCGnFR~bkGkx_wVazX-w{#)Y9bI((jt{ zQ}31cjsNaEhV5;?Ixwy79i5t1+AkjHDe95B%g46-^4t2EaK{mS!nNEupMt$np3!&u z{GT66nVn#tZpq*WE~OPbv#Y-{XVZqwqfHyXXwJgEU5wPFr~J6_^8pNd?aIg}3t!*Y z+i`kUJhVC3zrNu8uG#UNxtdqf+KKtj!@jQ`+cSDO{L)N~{^INwtSc*%FP~dJ`p-mr z6@Je*FN~+pe_ZwRV9!StTG?35)}`myJv{N| h@@zMr|MyVdLT29BO!&fkQ={g;UP+P9bE2TG{XhJwit7LX literal 0 HcmV?d00001 diff --git a/src/main/resources/controlify.accessWidener b/src/main/resources/controlify.accessWidener new file mode 100644 index 0000000..d60b1d8 --- /dev/null +++ b/src/main/resources/controlify.accessWidener @@ -0,0 +1,3 @@ +accessWidener v2 named + +accessible class net/minecraft/client/gui/screens/LanguageSelectScreen$LanguageSelectionList diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index fc83df1..0a7b619 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -10,10 +10,17 @@ "compat.screen.vanilla.AbstractSelectionListMixin", "compat.screen.vanilla.AbstractSliderButtonMixin", "compat.screen.vanilla.ContainerObjectSelectionListEntryMixin", + "compat.screen.vanilla.CreativeModeInventoryScreenAccessor", + "compat.screen.vanilla.CreativeModeInventoryScreenMixin", + "compat.screen.vanilla.JoinMultiplayerScreenAccessor", + "compat.screen.vanilla.JoinMultiplayerScreenMixin", + "compat.screen.vanilla.LanguageSelectionListEntryMixin", + "compat.screen.vanilla.OptionsSubScreenAccessor", "compat.screen.vanilla.ScreenAccessor", "compat.screen.vanilla.ScreenMixin", "compat.screen.vanilla.SelectWorldScreenAccessor", "compat.screen.vanilla.SelectWorldScreenMixin", + "compat.screen.vanilla.ServerSelectionListEntryMixin", "compat.screen.vanilla.WorldSelectionListEntryMixin", "core.ClientPacketListenerMixin", "core.KeyboardHandlerMixin", @@ -22,6 +29,7 @@ "feature.bind.KeyMappingAccessor", "feature.settingsbutton.ControlsScreenMixin", "feature.virtualmouse.GameRendererMixin", + "feature.virtualmouse.InputConstantsMixin", "feature.virtualmouse.KeyboardHandlerAccessor", "feature.virtualmouse.MinecraftMixin", "feature.virtualmouse.MouseHandlerAccessor", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ed0c907..0e61efa 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -25,6 +25,7 @@ "mixins": [ "controlify.mixins.json" ], + "accessWidener": "controlify.accesswidener", "depends": { "fabricloader": ">=0.14.0", "minecraft": "~1.19.4-", diff --git a/src/main/resources/icon.png b/src/main/resources/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..da98edcd4a31f5c7f019132a3dbebffa59ad60b2 GIT binary patch literal 32357 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