diff --git a/.github/README.md b/.github/README.md index d61150c..f8e61c3 100644 --- a/.github/README.md +++ b/.github/README.md @@ -19,14 +19,6 @@ Another fabric mod to add controller support to Minecraft Java - with a focus on -## Work In Progress - -This mod is still in development (so is this readme!) and is not ready for use. If you want to help contribute, -there are a few things you can do: - -- Find/create controller diagrams & buttons for each major controller brand. -- Add built-in support for common mod GUIs (contact me for a how-to). - ## Why another? Yes, mods like [Midnight Controls](https://modrinth.com/mod/midnight-controls) already exist. However due to the fact it @@ -35,6 +27,18 @@ create this mod! ## Features +### Controller vibration + +Controlify supports controller vibration, which has not been seen before for PC versions of Minecraft, +including Bedrock Windows 10 Edition. Configure the intensity of each vibration source, with +complex vibration patterns for lots of aspects of the game (e.g. when you take damage). + +### Built-in gyro support + +Controlify has built-in support for controller gyroscopes, allowing you to make fine movements in-game +with your controller. This can be combined with [flick stick](https://www.reddit.com/r/gamedev/comments/bw5xct/flick_stick_is_a_new_way_to_control_3d_games_with/) to be able to use a controller without +the compromise. + ### Controller identification Controlify has the ability to identify the make and model of your controller automatically, diff --git a/changelogs/1.1.0-beta.3+1.19.4.md b/changelogs/1.1.0-beta.3+1.19.4.md new file mode 100644 index 0000000..b00afaa --- /dev/null +++ b/changelogs/1.1.0-beta.3+1.19.4.md @@ -0,0 +1,83 @@ +# Controlify 1.1 (Beta 3) + +## New Features + +### Gyro support + +Controlify now has built-in support for controller gyroscopes, allowing you to make fine movements in-game. +This can be combined with [flick stick](https://www.reddit.com/r/gamedev/comments/bw5xct/flick_stick_is_a_new_way_to_control_3d_games_with/) to be able to use a controller without +the compromise of using the thumbsticks. + +This requires use of a compatible controller, such as a Dualsense controller. + +Currently, the Steam Deck is not supported, as it does not expose the gyro data to the OS, however, explicit +support for this device is planned in the future. + +## UI sounds + +A toggleable setting enables playing the legacy console edition UI sound when changing the selected component +in GUIs. In the future, this will be expanded to have more sounds. + +### Under-the-hood drivers + +Controlify now uses a new driver system, which allows me to combine multiple libraries to create a more +powerful controller interface, with a modular system to mix and match drivers. + +This means in the future, I can add more advanced features per-controller, such as Steam Deck touchpad and +back buttons explicitly supported in-game. + +### Improved joystick mapping + +Allows the mapping of joysticks to be more flexible, allowing for more complex mappings. This has been +battle-tested with a Thrustmaster TM.16000M FCS HOTAS joystick. + +### Built-in resource pack for extra mappings + +Controlify now has a built-in resource pack, which contains mappings and language files for the +aforementioned joystick. + +The split was done to not modify the default language file, which would become huge in size and potentially cause merge +conflicts. + +### Improved crash handling + +Where possible, Controlify now generates Minecraft crash reports with details of the controller which +caused the crash. + +## Changes + +### Screen navigation improvements + +Moving between components in GUIs feel more like most other games, where when holding the stick in a direction, +it moves once, waits a bit, and then moves through components quickly. Think holding down a key while you type. + +### More controller identifications + +More controllers are now identified out-of-box, particularly the PS3 and Dualsense controllers. + +Along with that, Dualsense, PS3 and Steam Deck now have textures. + +### Vibration natives downloading changes + +The vibration natives are now downloaded from my maven repository, allowing for better version control +and syncing with the mod version. + +## Bug Fixes + +- Fixed a bug where closing the pause menu or similar menu would cause you to trigger in-game inputs if + bound to the same button +- Fixed YetAnotherConfigLib not being declared as a fabric dependency, causing crashes if not present. + +## API Changes + +### Sources JAR now published + +The sources JAR is now published to the maven repository, allowing you to debug Controlify and view documentation in your IDE. + +### Controller binding API refactor + +Controller binding API has had a minor refactor that will cause incompatibilities with mods. + +### YACL option binding generator + +Bindings now allow you to create a YACL option, to add to your own config GUIs. diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index 42db320..fddeb89 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -228,8 +228,9 @@ public class Controlify implements ControlifyApi { controller.rumbleManager().tick(); } - if (state.hasAnyInput()) + if (state.hasAnyInput()) { this.setInputMode(InputMode.CONTROLLER); + } if (consecutiveInputSwitches > 100) { LOGGER.warn("Controlify detected current controller to be constantly giving input and has been disabled."); @@ -408,8 +409,8 @@ public class Controlify implements ControlifyApi { } @Override - public void setInputMode(@NotNull InputMode currentInputMode) { - if (this.currentInputMode == currentInputMode) return; + public boolean setInputMode(@NotNull InputMode currentInputMode) { + if (this.currentInputMode == currentInputMode) return false; this.currentInputMode = currentInputMode; var minecraft = Minecraft.getInstance(); @@ -432,7 +433,12 @@ public class Controlify implements ControlifyApi { } lastInputSwitchTime = Blaze3D.getTime(); + if (currentInputMode == InputMode.CONTROLLER) + getCurrentController().ifPresent(Controller::clearState); + ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode); + + return true; } public void hideMouse(boolean hide, boolean moveMouse) { diff --git a/src/main/java/dev/isxander/controlify/api/ControlifyApi.java b/src/main/java/dev/isxander/controlify/api/ControlifyApi.java index b79756b..ac599ba 100644 --- a/src/main/java/dev/isxander/controlify/api/ControlifyApi.java +++ b/src/main/java/dev/isxander/controlify/api/ControlifyApi.java @@ -30,7 +30,7 @@ public interface ControlifyApi { * Get the current input mode for the game. */ @NotNull InputMode currentInputMode(); - void setInputMode(@NotNull InputMode mode); + boolean setInputMode(@NotNull InputMode mode); static ControlifyApi get() { return Controlify.instance(); diff --git a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java index 448000a..38fba8e 100644 --- a/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java +++ b/src/main/java/dev/isxander/controlify/bindings/ControllerBindings.java @@ -137,7 +137,6 @@ public class ControllerBindings { .identifier("controlify", "sneak") .defaultBind(GamepadBinds.RIGHT_STICK_PRESS) .category(MOVEMENT_CATEGORY) - .vanillaOverride(options.keyShift, () -> controller.config().toggleSneak) .build()); register(ATTACK = ControllerBindingBuilder.create(controller) .identifier("controlify", "attack") 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 26199d9..be131cb 100644 --- a/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java +++ b/src/main/java/dev/isxander/controlify/config/gui/YACLHelper.java @@ -220,9 +220,7 @@ public class YACLHelper { category.group(makeVibrationGroup(globalVibrationOption, config, def)); } - if (controller instanceof GamepadController gamepad && gamepad.hasGyro()) { - category.group(makeGyroGroup(gamepad)); - } + category.group(makeGyroGroup(controller)); var advancedGroup = OptionGroup.createBuilder() .name(Component.translatable("controlify.gui.group.advanced")) @@ -309,19 +307,27 @@ public class YACLHelper { return vibrationGroup.build(); } - private static OptionGroup makeGyroGroup(GamepadController gamepad) { - var gpCfg = gamepad.config(); - var gpCfgDef = gamepad.defaultConfig(); + private static OptionGroup makeGyroGroup(Controller controller) { + GamepadController gamepad = (controller instanceof GamepadController) ? (GamepadController) controller : null; + boolean hasGyro = gamepad != null && gamepad.hasGyro(); + + var gpCfg = gamepad != null ? gamepad.config() : null; + var gpCfgDef = gamepad != null ? gamepad.defaultConfig() : null; + + Component noGyroTooltip = Component.translatable("controlify.gui.group.gyro.no_gyro.tooltip").withStyle(ChatFormatting.RED); Option gyroSensitivity; List> gyroOptions = new ArrayList<>(); var gyroGroup = OptionGroup.createBuilder() .name(Component.translatable("controlify.gui.group.gyro")) .tooltip(Component.translatable("controlify.gui.group.gyro.tooltip")) + .collapsed(!hasGyro) .option(gyroSensitivity = Option.createBuilder(float.class) .name(Component.translatable("controlify.gui.gyro_look_sensitivity")) .tooltip(Component.translatable("controlify.gui.gyro_look_sensitivity.tooltip")) - .binding(gpCfgDef.gyroLookSensitivity, () -> gpCfg.gyroLookSensitivity, v -> gpCfg.gyroLookSensitivity = v) + .tooltip(hasGyro ? Component.empty() : noGyroTooltip) + .available(hasGyro) + .binding(hasGyro ? gpCfgDef.gyroLookSensitivity : 0, () -> hasGyro ? gpCfg.gyroLookSensitivity : 0, v -> gpCfg.gyroLookSensitivity = v) .controller(opt -> new FloatSliderController(opt, 0f, 1f, 0.05f, percentOrOffFormatter)) .listener((opt, sensitivity) -> gyroOptions.forEach(o -> { o.setAvailable(sensitivity > 0); @@ -332,7 +338,9 @@ public class YACLHelper { var opt = Option.createBuilder(boolean.class) .name(Component.translatable("controlify.gui.gyro_requires_button")) .tooltip(Component.translatable("controlify.gui.gyro_requires_button.tooltip")) - .binding(gpCfgDef.gyroRequiresButton, () -> gpCfg.gyroRequiresButton, v -> gpCfg.gyroRequiresButton = v) + .tooltip(hasGyro ? Component.empty() : noGyroTooltip) + .available(hasGyro) + .binding(hasGyro ? gpCfgDef.gyroRequiresButton : false, () -> hasGyro ? gpCfg.gyroRequiresButton : false, v -> gpCfg.gyroRequiresButton = v) .controller(TickBoxController::new) .available(gyroSensitivity.pendingValue() > 0) .build(); @@ -343,7 +351,9 @@ public class YACLHelper { var opt = Option.createBuilder(boolean.class) .name(Component.translatable("controlify.gui.flick_stick")) .tooltip(Component.translatable("controlify.gui.flick_stick.tooltip")) - .binding(gpCfgDef.flickStick, () -> gpCfg.flickStick, v -> gpCfg.flickStick = v) + .tooltip(hasGyro ? Component.empty() : noGyroTooltip) + .available(hasGyro) + .binding(hasGyro ? gpCfgDef.flickStick : false, () -> hasGyro ? gpCfg.flickStick : false, v -> gpCfg.flickStick = v) .controller(TickBoxController::new) .available(gyroSensitivity.pendingValue() > 0) .build(); diff --git a/src/main/java/dev/isxander/controlify/controller/gamepad/BuiltinGamepadTheme.java b/src/main/java/dev/isxander/controlify/controller/gamepad/BuiltinGamepadTheme.java index 7b9c84c..14005e9 100644 --- a/src/main/java/dev/isxander/controlify/controller/gamepad/BuiltinGamepadTheme.java +++ b/src/main/java/dev/isxander/controlify/controller/gamepad/BuiltinGamepadTheme.java @@ -9,7 +9,8 @@ public enum BuiltinGamepadTheme implements NameableEnum { XBOX_ONE("Xbox One", "xbox_one"), DUALSHOCK4("Dualshock 4", "dualshock4"), DUALSHOCK3("Dualshock 3", "dualshock3"), - DUALSENSE("Dualsense", "dualsense"); + DUALSENSE("Dualsense", "dualsense"), + STEAM_DECK("Steam Deck", "steam_deck"); private final String name, id; diff --git a/src/main/java/dev/isxander/controlify/controller/gamepad/GamepadController.java b/src/main/java/dev/isxander/controlify/controller/gamepad/GamepadController.java index 47ebe85..e5a1d06 100644 --- a/src/main/java/dev/isxander/controlify/controller/gamepad/GamepadController.java +++ b/src/main/java/dev/isxander/controlify/controller/gamepad/GamepadController.java @@ -81,16 +81,6 @@ public class GamepadController extends AbstractController