Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
org.gradle.jvmargs=-Xmx4G
org.gradle.parallel=true

modVersion=3.0.0-beta.2
modVersion=3.0.0-beta.3
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please don't bump versions in PRs.

modId=controlify
modName=Controlify
modDescription=The most advanced controller mod for Minecraft.
Expand Down
18 changes: 10 additions & 8 deletions src/main/java/dev/isxander/controlify/Controlify.java
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't agree with how this is done here.

Inactive controllers should still be ticked. Move this if statement within tickInactiveController to stop the switch, not stop ticking completely.

"Ticking inactive controller",
controller
);
}
}

// Periodically save config if dirty (e.g., from gyro calibration updates)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ public record GlobalConfig(
boolean alwaysAllowKeyboardMovement,
List<String> keyboardMovementWhitelist,
List<String> seenServers,
boolean showSplitscreenAd
boolean showSplitscreenAd,
boolean autoSwitchControllers
) {
public static final Codec<GlobalConfig> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.list(Codec.STRING).fieldOf("virtual_mouse_screens").forGetter(GlobalConfig::virtualMouseScreens),
Expand All @@ -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)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DTOs should not have optional fields.

  • Defaults for GlobalSettings should exist in GlobalSettings#<init>.
  • Config migration should be done within a DataFixer, see dev.isxander.controlify.dto.dfu.
    • You will need to a new schema version, and a new fix to add this default.

).apply(instance, GlobalConfig::new));
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class GlobalSettings {
public List<String> keyboardMovementWhitelist;
public final Set<String> seenServers;
public boolean showSplitscreenAd;
public boolean autoSwitchControllers;

private static final GlobalSettings DEFAULT = new GlobalSettings();

Expand All @@ -48,6 +49,7 @@ private GlobalSettings() {
this.keyboardMovementWhitelist = new ArrayList<>();
this.seenServers = new HashSet<>();
this.showSplitscreenAd = true;
this.autoSwitchControllers = true;
}

public GlobalSettings(
Expand All @@ -63,7 +65,8 @@ public GlobalSettings(
boolean alwaysKeyboardMovement,
List<String> keyboardMovementWhitelist,
Set<String> seenServers,
boolean showSplitscreenAd
boolean showSplitscreenAd,
boolean autoSwitchControllers
) {
this.virtualMouseScreens = new HashSet<>(virtualMouseScreens);
this.mixedInput = mixedInput;
Expand All @@ -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() {
Expand Down Expand Up @@ -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()
);
}

Expand All @@ -135,7 +140,8 @@ public GlobalConfig toDTO() {
alwaysKeyboardMovement,
List.copyOf(keyboardMovementWhitelist),
List.copyOf(seenServers),
showSplitscreenAd
showSplitscreenAd,
autoSwitchControllers
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<ListOption<String>> whitelist = new AtomicReference<>();
AtomicReference<Option<String>> controllerSelector = new AtomicReference<>();

List<String> 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()
Expand Down Expand Up @@ -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.<Boolean>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.<String>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.<Boolean>createBuilder()
.name(Component.translatable("controlify.gui.use_enhanced_steam_deck_driver"))
.description(OptionDescription.createBuilder()
Expand Down Expand Up @@ -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));
}
});

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will cause a memory leak. It's not good to create throw-away event registers. result and parent will now live for the entirety of the game lifecycle

return result;
}

private static Identifier screenshot(String filename) {
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/assets/controlify/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",

Expand Down