From 2c442bdc4df3033c73770ff5d0ecc70953d4533b Mon Sep 17 00:00:00 2001 From: Adam Boeglin Date: Mon, 16 Feb 2026 22:08:38 -0800 Subject: [PATCH 1/3] Add global option to disable automatic controller switching The automatic controller switching behavior (where the active controller switches to whichever last provided input) makes it impossible to run multiple game instances side-by-side with different controllers. This adds a toggleable "Auto-Switch Controllers" option in global settings (default: enabled) that gates the tickInactiveController() loop. When disabled, a "Current Controller" dropdown appears allowing manual controller selection. The dropdown dynamically refreshes on controller hotplug events by rebuilding the settings screen. --- gradle.properties | 2 +- .../dev/isxander/controlify/Controlify.java | 18 +++-- .../controlify/config/dto/GlobalConfig.java | 6 +- .../config/settings/GlobalSettings.java | 12 ++- .../screen/GlobalSettingsScreenFactory.java | 77 ++++++++++++++++++- .../assets/controlify/lang/en_us.json | 4 + 6 files changed, 104 insertions(+), 15 deletions(-) diff --git a/gradle.properties b/gradle.properties index 78f592f64..e2a86a268 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true -modVersion=3.0.0-beta.2 +modVersion=3.0.0-beta.3 modId=controlify modName=Controlify modDescription=The most advanced controller mod for Minecraft. diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index a59d09185..0413067c7 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -471,14 +471,16 @@ public void tick(Minecraft client) { currentController ); }); - for (ControllerEntity controller : controllerManager.getConnectedControllers()) { - if (controller.equals(getCurrentController().orElse(null))) continue; - - wrapControllerError( - () -> tickInactiveController(controller), - "Ticking inactive controller", - controller - ); + if (config().getSettings().globalSettings().autoSwitchControllers) { + for (ControllerEntity controller : controllerManager.getConnectedControllers()) { + if (controller.equals(getCurrentController().orElse(null))) continue; + + wrapControllerError( + () -> tickInactiveController(controller), + "Ticking inactive controller", + controller + ); + } } // Periodically save config if dirty (e.g., from gyro calibration updates) diff --git a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java index 49edb6d8f..45c7acb00 100644 --- a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java +++ b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java @@ -19,7 +19,8 @@ public record GlobalConfig( boolean alwaysAllowKeyboardMovement, List keyboardMovementWhitelist, List seenServers, - boolean showSplitscreenAd + boolean showSplitscreenAd, + boolean autoSwitchControllers ) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.list(Codec.STRING).fieldOf("virtual_mouse_screens").forGetter(GlobalConfig::virtualMouseScreens), @@ -34,6 +35,7 @@ public record GlobalConfig( Codec.BOOL.fieldOf("keyboard_movement").forGetter(GlobalConfig::alwaysAllowKeyboardMovement), Codec.list(Codec.STRING).fieldOf("keyboard_movement_whitelist").forGetter(GlobalConfig::keyboardMovementWhitelist), Codec.list(Codec.STRING).fieldOf("seen_servers").forGetter(GlobalConfig::seenServers), - Codec.BOOL.fieldOf("show_splitscreen_ad").forGetter(GlobalConfig::showSplitscreenAd) + Codec.BOOL.fieldOf("show_splitscreen_ad").forGetter(GlobalConfig::showSplitscreenAd), + Codec.BOOL.optionalFieldOf("auto_switch_controllers", true).forGetter(GlobalConfig::autoSwitchControllers) ).apply(instance, GlobalConfig::new)); } diff --git a/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java b/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java index d1ac96473..bf38670c2 100644 --- a/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java +++ b/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java @@ -29,6 +29,7 @@ public class GlobalSettings { public List keyboardMovementWhitelist; public final Set seenServers; public boolean showSplitscreenAd; + public boolean autoSwitchControllers; private static final GlobalSettings DEFAULT = new GlobalSettings(); @@ -48,6 +49,7 @@ private GlobalSettings() { this.keyboardMovementWhitelist = new ArrayList<>(); this.seenServers = new HashSet<>(); this.showSplitscreenAd = true; + this.autoSwitchControllers = true; } public GlobalSettings( @@ -63,7 +65,8 @@ public GlobalSettings( boolean alwaysKeyboardMovement, List keyboardMovementWhitelist, Set seenServers, - boolean showSplitscreenAd + boolean showSplitscreenAd, + boolean autoSwitchControllers ) { this.virtualMouseScreens = new HashSet<>(virtualMouseScreens); this.mixedInput = mixedInput; @@ -78,6 +81,7 @@ public GlobalSettings( this.keyboardMovementWhitelist = new ArrayList<>(keyboardMovementWhitelist); this.seenServers = new HashSet<>(seenServers); this.showSplitscreenAd = showSplitscreenAd; + this.autoSwitchControllers = autoSwitchControllers; } public boolean shouldUseKeyboardMovement() { @@ -114,7 +118,8 @@ public static GlobalSettings fromDTO(GlobalConfig dto) { dto.alwaysAllowKeyboardMovement(), List.copyOf(dto.keyboardMovementWhitelist()), Set.copyOf(dto.seenServers()), - dto.showSplitscreenAd() + dto.showSplitscreenAd(), + dto.autoSwitchControllers() ); } @@ -135,7 +140,8 @@ public GlobalConfig toDTO() { alwaysKeyboardMovement, List.copyOf(keyboardMovementWhitelist), List.copyOf(seenServers), - showSplitscreenAd + showSplitscreenAd, + autoSwitchControllers ); } } diff --git a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java index c76d1b462..1a58e2355 100644 --- a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java +++ b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java @@ -2,6 +2,7 @@ import dev.isxander.controlify.Controlify; import dev.isxander.controlify.api.ControlifyApi; +import dev.isxander.controlify.api.event.ControlifyEvents; import dev.isxander.controlify.config.settings.GlobalSettings; import dev.isxander.controlify.controller.ControllerEntity; import dev.isxander.controlify.driver.steamdeck.SteamDeckUtil; @@ -21,16 +22,27 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.atomic.AtomicReference; public class GlobalSettingsScreenFactory { public static Screen createGlobalSettingsScreen(Screen parent) { var globalSettings = Controlify.instance().config().getSettings().globalSettings(); AtomicReference> whitelist = new AtomicReference<>(); + AtomicReference> controllerSelector = new AtomicReference<>(); + + List controllerUids = new ArrayList<>(); + controllerUids.add(""); + Controlify.instance().getControllerManager().ifPresent(cm -> { + for (ControllerEntity c : cm.getConnectedControllers()) { + controllerUids.add(c.uid()); + } + }); boolean is12106OrLater = /*? if >=1.21.6 {*/ true /*?} else {*/ /*false *//*?}*/;; - return YetAnotherConfigLib.createBuilder() + Screen result = YetAnotherConfigLib.createBuilder() .title(Component.translatable("controlify.gui.global_settings.title")) .save(() -> Controlify.instance().config().saveSafely()) .category(ConfigCategory.createBuilder() @@ -153,6 +165,56 @@ public static Screen createGlobalSettingsScreen(Screen parent) { .binding(GlobalSettings.defaults().mixedInput, () -> globalSettings.mixedInput, v -> globalSettings.mixedInput = v) .controller(TickBoxControllerBuilder::create) .build()) + .option(Option.createBuilder() + .name(Component.translatable("controlify.gui.auto_switch_controllers")) + .description(OptionDescription.createBuilder() + .text(Component.translatable("controlify.gui.auto_switch_controllers.tooltip")) + .build()) + .binding(GlobalSettings.defaults().autoSwitchControllers, () -> globalSettings.autoSwitchControllers, v -> globalSettings.autoSwitchControllers = v) + .controller(TickBoxControllerBuilder::create) + .addListener((opt, event) -> { + var selector = controllerSelector.get(); + if (selector != null) selector.setAvailable(!opt.pendingValue()); + }) + .build()) + .option(Util.make(() -> { + var opt = Option.createBuilder() + .name(Component.translatable("controlify.gui.current_controller")) + .description(OptionDescription.createBuilder() + .text(Component.translatable("controlify.gui.current_controller.tooltip")) + .build()) + .binding( + "", + () -> Controlify.instance().getCurrentController().map(ControllerEntity::uid).orElse(""), + uid -> { + if (uid.isEmpty()) { + Controlify.instance().setCurrentController(null, true); + } else { + Controlify.instance().getControllerManager().ifPresent(cm -> + cm.getConnectedControllers().stream() + .filter(c -> c.uid().equals(uid)) + .findFirst() + .ifPresent(c -> Controlify.instance().setCurrentController(c, true))); + } + } + ) + .controller(o -> CyclingListControllerBuilder.create(o) + .values(controllerUids) + .formatValue(uid -> { + if (uid.isEmpty()) return Component.translatable("controlify.gui.carousel.entry.keyboard_mouse"); + return Controlify.instance().getControllerManager() + .map(cm -> cm.getConnectedControllers().stream() + .filter(c -> c.uid().equals(uid)) + .findFirst() + .map(c -> (Component) Component.literal(c.name())) + .orElse(Component.literal(uid))) + .orElse(Component.literal(uid)); + })) + .available(!globalSettings.autoSwitchControllers) + .build(); + controllerSelector.set(opt); + return opt; + })) .optionIf(SteamDeckUtil.IS_STEAM_DECK, Option.createBuilder() .name(Component.translatable("controlify.gui.use_enhanced_steam_deck_driver")) .description(OptionDescription.createBuilder() @@ -182,6 +244,19 @@ public static Screen createGlobalSettingsScreen(Screen parent) { .build()) .build()) .build().generateScreen(parent); + + ControlifyEvents.CONTROLLER_CONNECTED.register(event -> { + if (Minecraft.getInstance().screen == result) { + Minecraft.getInstance().setScreen(createGlobalSettingsScreen(parent)); + } + }); + ControlifyEvents.CONTROLLER_DISCONNECTED.register(event -> { + if (Minecraft.getInstance().screen == result) { + Minecraft.getInstance().setScreen(createGlobalSettingsScreen(parent)); + } + }); + + return result; } private static Identifier screenshot(String filename) { diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index c4e8997fa..669a407ab 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -52,6 +52,10 @@ "controlify.gui.open_issue_tracker": "Open Issue Tracker", "controlify.gui.use_enhanced_steam_deck_driver": "Use Enhanced Steam Deck Driver", "controlify.gui.use_enhanced_steam_deck_driver.tooltip": "If enabled, Controlify will use an enhanced driver for the Steam Deck to improve compatibility and performance. This is experimental and may have bugs. This driver requires Decky Loader to be installed on your Deck.", + "controlify.gui.auto_switch_controllers": "Auto-Switch Controllers", + "controlify.gui.auto_switch_controllers.tooltip": "Automatically switches the active controller when input is detected from a different controller. Disable this if you are running multiple game instances with different controllers.", + "controlify.gui.current_controller": "Current Controller", + "controlify.gui.current_controller.tooltip": "Select which controller to use. This option is only available when auto-switching is disabled.", "controlify.gui.copy_debug_dump": "Copy Debug Dump To Clipboard", "controlify.gui.copy_debug_dump.tooltip": "Copies a Controlify debug dump to your clipboard. You may be asked to use this if you are seeking support.", From b447afdf869014e578cbe4f19b33ed5f7cd15fe9 Mon Sep 17 00:00:00 2001 From: Adam Boeglin Date: Wed, 25 Feb 2026 22:20:32 -0800 Subject: [PATCH 2/3] Persist preferred controller and restore on startup/hotplug When auto-switch is disabled, the manually selected controller is now saved as preferredControllerUid in the config. On game startup or controller hotplug, the preferred controller is automatically restored if available. The preference is only updated from the UI dropdown to avoid being overwritten by fallback selections on disconnect. --- .../dev/isxander/controlify/Controlify.java | 23 +++++++++++++++---- .../controlify/config/dto/GlobalConfig.java | 6 +++-- .../config/settings/GlobalSettings.java | 12 +++++++--- .../screen/GlobalSettingsScreenFactory.java | 1 + 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index 0413067c7..9ae58793f 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -335,12 +335,18 @@ public void discoverControllers() { CUtil.LOGGER.log("No controllers found."); } - // if no controller is currently selected, pick the first one + // if no controller is currently selected, try to restore preference or pick the first one if (this.getCurrentController().isEmpty()) { - Optional firstController = controllerManager.getConnectedControllers() - .stream() - .findAny(); - this.setCurrentController(firstController.orElse(null), false); + String preferredUid = config().getSettings().globalSettings().preferredControllerUid; + Optional preferred = Optional.empty(); + if (!config().getSettings().globalSettings().autoSwitchControllers && !preferredUid.isEmpty()) { + preferred = controllerManager.getConnectedControllers().stream() + .filter(c -> c.uid().equals(preferredUid)) + .findFirst(); + } + this.setCurrentController(preferred.orElseGet(() -> + controllerManager.getConnectedControllers().stream().findAny().orElse(null) + ), false); } config().saveIfDirty(); @@ -398,6 +404,13 @@ private void onControllerAdded(ControllerEntity controller, boolean hotplugged) config().saveIfDirty(); } + if (hotplugged && !config().getSettings().globalSettings().autoSwitchControllers) { + String preferredUid = config().getSettings().globalSettings().preferredControllerUid; + if (controller.uid().equals(preferredUid)) { + this.setCurrentController(controller, true); + } + } + setupWizards.add(wizard); } diff --git a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java index 45c7acb00..020572f0e 100644 --- a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java +++ b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java @@ -20,7 +20,8 @@ public record GlobalConfig( List keyboardMovementWhitelist, List seenServers, boolean showSplitscreenAd, - boolean autoSwitchControllers + boolean autoSwitchControllers, + String preferredControllerUid ) { public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.list(Codec.STRING).fieldOf("virtual_mouse_screens").forGetter(GlobalConfig::virtualMouseScreens), @@ -36,6 +37,7 @@ public record GlobalConfig( Codec.list(Codec.STRING).fieldOf("keyboard_movement_whitelist").forGetter(GlobalConfig::keyboardMovementWhitelist), Codec.list(Codec.STRING).fieldOf("seen_servers").forGetter(GlobalConfig::seenServers), Codec.BOOL.fieldOf("show_splitscreen_ad").forGetter(GlobalConfig::showSplitscreenAd), - Codec.BOOL.optionalFieldOf("auto_switch_controllers", true).forGetter(GlobalConfig::autoSwitchControllers) + Codec.BOOL.optionalFieldOf("auto_switch_controllers", true).forGetter(GlobalConfig::autoSwitchControllers), + Codec.STRING.optionalFieldOf("preferred_controller_uid", "").forGetter(GlobalConfig::preferredControllerUid) ).apply(instance, GlobalConfig::new)); } diff --git a/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java b/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java index bf38670c2..668f920b3 100644 --- a/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java +++ b/src/main/java/dev/isxander/controlify/config/settings/GlobalSettings.java @@ -30,6 +30,7 @@ public class GlobalSettings { public final Set seenServers; public boolean showSplitscreenAd; public boolean autoSwitchControllers; + public String preferredControllerUid; private static final GlobalSettings DEFAULT = new GlobalSettings(); @@ -50,6 +51,7 @@ private GlobalSettings() { this.seenServers = new HashSet<>(); this.showSplitscreenAd = true; this.autoSwitchControllers = true; + this.preferredControllerUid = ""; } public GlobalSettings( @@ -66,7 +68,8 @@ public GlobalSettings( List keyboardMovementWhitelist, Set seenServers, boolean showSplitscreenAd, - boolean autoSwitchControllers + boolean autoSwitchControllers, + String preferredControllerUid ) { this.virtualMouseScreens = new HashSet<>(virtualMouseScreens); this.mixedInput = mixedInput; @@ -82,6 +85,7 @@ public GlobalSettings( this.seenServers = new HashSet<>(seenServers); this.showSplitscreenAd = showSplitscreenAd; this.autoSwitchControllers = autoSwitchControllers; + this.preferredControllerUid = preferredControllerUid; } public boolean shouldUseKeyboardMovement() { @@ -119,7 +123,8 @@ public static GlobalSettings fromDTO(GlobalConfig dto) { List.copyOf(dto.keyboardMovementWhitelist()), Set.copyOf(dto.seenServers()), dto.showSplitscreenAd(), - dto.autoSwitchControllers() + dto.autoSwitchControllers(), + dto.preferredControllerUid() ); } @@ -141,7 +146,8 @@ public GlobalConfig toDTO() { List.copyOf(keyboardMovementWhitelist), List.copyOf(seenServers), showSplitscreenAd, - autoSwitchControllers + autoSwitchControllers, + preferredControllerUid ); } } diff --git a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java index 1a58e2355..5a071e014 100644 --- a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java +++ b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java @@ -196,6 +196,7 @@ public static Screen createGlobalSettingsScreen(Screen parent) { .findFirst() .ifPresent(c -> Controlify.instance().setCurrentController(c, true))); } + globalSettings.preferredControllerUid = uid; } ) .controller(o -> CyclingListControllerBuilder.create(o) From f0552c40cb0b444b33ee1d1affc83100e37444d0 Mon Sep 17 00:00:00 2001 From: Adam Boeglin Date: Wed, 25 Feb 2026 22:24:30 -0800 Subject: [PATCH 3/3] Address PR review feedback - Revert version bump in gradle.properties - Move auto-switch guard inside tickInactiveController() so inactive controllers still get ticked - Remove memory-leaking event listeners from GlobalSettingsScreenFactory - Replace optionalFieldOf with proper DataFixer migration (schema v2) that adds auto_switch_controllers and preferred_controller_uid defaults --- gradle.properties | 2 +- .../dev/isxander/controlify/Controlify.java | 21 +++++----- .../controlify/config/dto/GlobalConfig.java | 4 +- .../config/dto/dfu/ControlifyDataFixer.java | 6 ++- .../config/dto/dfu/ControlifySchemas.java | 6 +++ .../fixes/AddAutoSwitchControllersFix.java | 41 +++++++++++++++++++ .../screen/GlobalSettingsScreenFactory.java | 16 +------- 7 files changed, 66 insertions(+), 30 deletions(-) create mode 100644 src/main/java/dev/isxander/controlify/config/dto/dfu/fixes/AddAutoSwitchControllersFix.java diff --git a/gradle.properties b/gradle.properties index e2a86a268..78f592f64 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true -modVersion=3.0.0-beta.3 +modVersion=3.0.0-beta.2 modId=controlify modName=Controlify modDescription=The most advanced controller mod for Minecraft. diff --git a/src/main/java/dev/isxander/controlify/Controlify.java b/src/main/java/dev/isxander/controlify/Controlify.java index 9ae58793f..01f314168 100644 --- a/src/main/java/dev/isxander/controlify/Controlify.java +++ b/src/main/java/dev/isxander/controlify/Controlify.java @@ -484,16 +484,14 @@ public void tick(Minecraft client) { currentController ); }); - if (config().getSettings().globalSettings().autoSwitchControllers) { - for (ControllerEntity controller : controllerManager.getConnectedControllers()) { - if (controller.equals(getCurrentController().orElse(null))) continue; - - wrapControllerError( - () -> tickInactiveController(controller), - "Ticking inactive controller", - controller - ); - } + for (ControllerEntity controller : controllerManager.getConnectedControllers()) { + if (controller.equals(getCurrentController().orElse(null))) continue; + + wrapControllerError( + () -> tickInactiveController(controller), + "Ticking inactive controller", + controller + ); } // Periodically save config if dirty (e.g., from gyro calibration updates) @@ -564,7 +562,8 @@ private void tickInactiveController(ControllerEntity controller) { boolean thisControllerGivingInput = state.isGivingInput(); boolean activeControllerGivingInput = getCurrentController().map(c -> c.input().orElseThrow().stateNow().isGivingInput()).orElse(false); - if (thisControllerGivingInput && !activeControllerGivingInput) { + if (config().getSettings().globalSettings().autoSwitchControllers + && thisControllerGivingInput && !activeControllerGivingInput) { this.setCurrentController(controller, true); } } diff --git a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java index 020572f0e..84e05eac7 100644 --- a/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java +++ b/src/main/java/dev/isxander/controlify/config/dto/GlobalConfig.java @@ -37,7 +37,7 @@ public record GlobalConfig( Codec.list(Codec.STRING).fieldOf("keyboard_movement_whitelist").forGetter(GlobalConfig::keyboardMovementWhitelist), Codec.list(Codec.STRING).fieldOf("seen_servers").forGetter(GlobalConfig::seenServers), Codec.BOOL.fieldOf("show_splitscreen_ad").forGetter(GlobalConfig::showSplitscreenAd), - Codec.BOOL.optionalFieldOf("auto_switch_controllers", true).forGetter(GlobalConfig::autoSwitchControllers), - Codec.STRING.optionalFieldOf("preferred_controller_uid", "").forGetter(GlobalConfig::preferredControllerUid) + Codec.BOOL.fieldOf("auto_switch_controllers").forGetter(GlobalConfig::autoSwitchControllers), + Codec.STRING.fieldOf("preferred_controller_uid").forGetter(GlobalConfig::preferredControllerUid) ).apply(instance, GlobalConfig::new)); } diff --git a/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifyDataFixer.java b/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifyDataFixer.java index 6916f86f7..9844cba6c 100644 --- a/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifyDataFixer.java +++ b/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifyDataFixer.java @@ -2,13 +2,14 @@ import com.mojang.datafixers.DataFixer; import com.mojang.datafixers.DataFixerBuilder; +import dev.isxander.controlify.config.dto.dfu.fixes.AddAutoSwitchControllersFix; import dev.isxander.controlify.config.dto.dfu.fixes.TheHolyMigrationFix; import dev.isxander.controlify.config.settings.GlobalSettings; import dev.isxander.controlify.config.settings.profile.ProfileSettings; import dev.isxander.controlify.utils.CUtil; public final class ControlifyDataFixer { - public static final int CURRENT_VERSION = 1; + public static final int CURRENT_VERSION = 2; private static final DataFixer FIXER = createFixer(); @@ -28,6 +29,9 @@ private static DataFixer createFixer() { ProfileSettings.createDefault(CUtil.rl("generic")) )); + var v2 = builder.addSchema(2, ControlifySchemas.SchemaV2::new); + builder.addFixer(new AddAutoSwitchControllersFix(v2)); + return builder.build().fixer(); } diff --git a/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifySchemas.java b/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifySchemas.java index f9c4d7c64..87a1c56e9 100644 --- a/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifySchemas.java +++ b/src/main/java/dev/isxander/controlify/config/dto/dfu/ControlifySchemas.java @@ -47,4 +47,10 @@ public SchemaV1(int versionKey, Schema parent) { super(versionKey, parent); } } + + public static class SchemaV2 extends ControlifySchema { + public SchemaV2(int versionKey, Schema parent) { + super(versionKey, parent); + } + } } diff --git a/src/main/java/dev/isxander/controlify/config/dto/dfu/fixes/AddAutoSwitchControllersFix.java b/src/main/java/dev/isxander/controlify/config/dto/dfu/fixes/AddAutoSwitchControllersFix.java new file mode 100644 index 000000000..107bf664a --- /dev/null +++ b/src/main/java/dev/isxander/controlify/config/dto/dfu/fixes/AddAutoSwitchControllersFix.java @@ -0,0 +1,41 @@ +package dev.isxander.controlify.config.dto.dfu.fixes; + +import com.mojang.datafixers.DSL; +import com.mojang.datafixers.DataFix; +import com.mojang.datafixers.TypeRewriteRule; +import com.mojang.datafixers.schemas.Schema; +import com.mojang.serialization.Dynamic; +import dev.isxander.controlify.config.dto.dfu.ControlifyTypeReferences; + +public final class AddAutoSwitchControllersFix extends DataFix { + public AddAutoSwitchControllersFix(Schema outputSchema) { + super(outputSchema, false); + } + + @Override + protected TypeRewriteRule makeRule() { + var type = getInputSchema().getType(ControlifyTypeReferences.USER_STATE); + + return fixTypeEverywhereTyped( + "Controlify: add auto_switch_controllers and preferred_controller_uid defaults", + type, + typed -> typed.update( + DSL.remainderFinder(), + this::rewrite + ) + ); + } + + private Dynamic rewrite(Dynamic root) { + Dynamic global = root.get("global").orElseEmptyMap(); + + if (global.get("auto_switch_controllers").result().isEmpty()) { + global = global.set("auto_switch_controllers", root.createBoolean(true)); + } + if (global.get("preferred_controller_uid").result().isEmpty()) { + global = global.set("preferred_controller_uid", root.createString("")); + } + + return root.set("global", global); + } +} diff --git a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java index 5a071e014..cd25c736f 100644 --- a/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java +++ b/src/main/java/dev/isxander/controlify/gui/screen/GlobalSettingsScreenFactory.java @@ -2,7 +2,6 @@ import dev.isxander.controlify.Controlify; import dev.isxander.controlify.api.ControlifyApi; -import dev.isxander.controlify.api.event.ControlifyEvents; import dev.isxander.controlify.config.settings.GlobalSettings; import dev.isxander.controlify.controller.ControllerEntity; import dev.isxander.controlify.driver.steamdeck.SteamDeckUtil; @@ -42,7 +41,7 @@ public static Screen createGlobalSettingsScreen(Screen parent) { boolean is12106OrLater = /*? if >=1.21.6 {*/ true /*?} else {*/ /*false *//*?}*/;; - Screen result = YetAnotherConfigLib.createBuilder() + return YetAnotherConfigLib.createBuilder() .title(Component.translatable("controlify.gui.global_settings.title")) .save(() -> Controlify.instance().config().saveSafely()) .category(ConfigCategory.createBuilder() @@ -245,19 +244,6 @@ public static Screen createGlobalSettingsScreen(Screen parent) { .build()) .build()) .build().generateScreen(parent); - - ControlifyEvents.CONTROLLER_CONNECTED.register(event -> { - if (Minecraft.getInstance().screen == result) { - Minecraft.getInstance().setScreen(createGlobalSettingsScreen(parent)); - } - }); - ControlifyEvents.CONTROLLER_DISCONNECTED.register(event -> { - if (Minecraft.getInstance().screen == result) { - Minecraft.getInstance().setScreen(createGlobalSettingsScreen(parent)); - } - }); - - return result; } private static Identifier screenshot(String filename) {