1
0
forked from Clones/Controlify

scrollable vmouse, YACL compat, toggle sneak/sprint, 22w06a, custom name

This commit is contained in:
isXander
2023-02-08 21:54:01 +00:00
parent 6c5108469c
commit ab801e37b4
26 changed files with 400 additions and 91 deletions

View File

@ -13,7 +13,7 @@ plugins {
} }
group = "dev.isxander" group = "dev.isxander"
version = "1.0.0+1.19.4" version = "0.1.0+1.19.4"
repositories { repositories {
mavenCentral() mavenCentral()

View File

@ -7,12 +7,12 @@ github_release = "2.+"
machete = "1.+" machete = "1.+"
grgit = "5.0.+" grgit = "5.0.+"
minecraft = "23w05a" minecraft = "23w06a"
quilt_mappings = "1" quilt_mappings = "4"
fabric_loader = "0.14.14" fabric_loader = "0.14.14"
fabric_api = "0.73.4+1.19.4" fabric_api = "0.73.5+1.19.4"
mixin_extras = "0.2.0-beta.1" mixin_extras = "0.2.0-beta.1"
yet_another_config_lib = "2.2.0+update.1.19.4-SNAPSHOT" yet_another_config_lib = "2.3.0+beta.2+update.1.19.4-SNAPSHOT"
mod_menu = "6.0.0-beta.1" mod_menu = "6.0.0-beta.1"
hid4java = "0.7.0" hid4java = "0.7.0"

View File

@ -151,7 +151,7 @@ public class Controlify {
var minecraft = Minecraft.getInstance(); var minecraft = Minecraft.getInstance();
if (!minecraft.mouseHandler.isMouseGrabbed()) if (!minecraft.mouseHandler.isMouseGrabbed())
hideMouse(currentInputMode == InputMode.CONTROLLER); hideMouse(currentInputMode == InputMode.CONTROLLER, true);
if (minecraft.screen != null) { if (minecraft.screen != null) {
ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode); ScreenProcessorProvider.provide(minecraft.screen).onInputModeChanged(currentInputMode);
} }
@ -159,7 +159,7 @@ public class Controlify {
ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode); ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode);
} }
public void hideMouse(boolean hide) { public void hideMouse(boolean hide, boolean moveMouse) {
var minecraft = Minecraft.getInstance(); var minecraft = Minecraft.getInstance();
GLFW.glfwSetInputMode( GLFW.glfwSetInputMode(
minecraft.getWindow().getWindow(), minecraft.getWindow().getWindow(),
@ -170,7 +170,7 @@ public class Controlify {
); );
if (minecraft.screen != null) { if (minecraft.screen != null) {
var mouseHandlerAccessor = (MouseHandlerAccessor) minecraft.mouseHandler; var mouseHandlerAccessor = (MouseHandlerAccessor) minecraft.mouseHandler;
if (hide && !virtualMouseHandler().isVirtualMouseEnabled()) { if (hide && !virtualMouseHandler().isVirtualMouseEnabled() && moveMouse) {
// stop mouse hovering over last element before hiding cursor but don't actually move it // stop mouse hovering over last element before hiding cursor but don't actually move it
// so when the user switches back to mouse it will be in the same place // so when the user switches back to mouse it will be in the same place
mouseHandlerAccessor.invokeOnMove(minecraft.getWindow().getWindow(), -50, -50); mouseHandlerAccessor.invokeOnMove(minecraft.getWindow().getWindow(), -50, -50);

View File

@ -11,6 +11,7 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.BooleanSupplier;
public class ControllerBinding { public class ControllerBinding {
private final Controller controller; private final Controller controller;
@ -18,18 +19,22 @@ public class ControllerBinding {
private final IBind defaultBind; private final IBind defaultBind;
private final ResourceLocation id; private final ResourceLocation id;
private final Component name, description; private final Component name, description;
private final KeyMapping override; private final KeyMappingOverride override;
private static final Map<Controller, Set<Bind>> pressedBinds = new HashMap<>(); private static final Map<Controller, Set<Bind>> pressedBinds = new HashMap<>();
public ControllerBinding(Controller controller, IBind defaultBind, ResourceLocation id, KeyMapping override) { public ControllerBinding(Controller controller, IBind defaultBind, ResourceLocation id, KeyMapping override, BooleanSupplier toggleOverride) {
this.controller = controller; this.controller = controller;
this.bind = this.defaultBind = defaultBind; this.bind = this.defaultBind = defaultBind;
this.id = id; this.id = id;
this.name = Component.translatable("controlify.binding." + id.getNamespace() + "." + id.getPath()); this.name = Component.translatable("controlify.binding." + id.getNamespace() + "." + id.getPath());
var descKey = "controlify.binding." + id.getNamespace() + "." + id.getPath() + ".desc"; var descKey = "controlify.binding." + id.getNamespace() + "." + id.getPath() + ".desc";
this.description = Language.getInstance().has(descKey) ? Component.translatable(descKey) : Component.empty(); this.description = Language.getInstance().has(descKey) ? Component.translatable(descKey) : Component.empty();
this.override = override; this.override = override != null ? new KeyMappingOverride(override, toggleOverride) : null;
}
public ControllerBinding(Controller controller, IBind defaultBind, ResourceLocation id) {
this(controller, defaultBind, id, null, () -> false);
} }
public float state() { public float state() {
@ -86,7 +91,7 @@ public class ControllerBinding {
return description; return description;
} }
public KeyMapping override() { public KeyMappingOverride override() {
return override; return override;
} }
@ -114,4 +119,7 @@ public class ControllerBinding {
return Set.of((Bind) bind); return Set.of((Bind) bind);
} }
} }
public record KeyMappingOverride(KeyMapping keyMapping, BooleanSupplier toggleable) {
}
} }

View File

@ -26,45 +26,50 @@ public class ControllerBindings {
OPEN_CHAT, OPEN_CHAT,
GUI_PRESS, GUI_BACK, GUI_PRESS, GUI_BACK,
GUI_NEXT_TAB, GUI_PREV_TAB, GUI_NEXT_TAB, GUI_PREV_TAB,
VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE, VMOUSE_LCLICK, VMOUSE_RCLICK, VMOUSE_MCLICK, VMOUSE_SCROLL_UP, VMOUSE_SCROLL_DOWN, VMOUSE_ESCAPE, VMOUSE_SHIFT, VMOUSE_TOGGLE,
TOGGLE_DEBUG_MENU; PICK_BLOCK;
private final Map<ResourceLocation, ControllerBinding> registry = new LinkedHashMap<>(); private final Map<ResourceLocation, ControllerBinding> registry = new LinkedHashMap<>();
private final Controller controller;
public ControllerBindings(Controller controller) { public ControllerBindings(Controller controller) {
this.controller = controller;
var options = Minecraft.getInstance().options; var options = Minecraft.getInstance().options;
register(WALK_FORWARD = new ControllerBinding(controller, Bind.LEFT_STICK_FORWARD, new ResourceLocation("controlify", "walk_forward"), null)); register(WALK_FORWARD = new ControllerBinding(controller, Bind.LEFT_STICK_FORWARD, new ResourceLocation("controlify", "walk_forward")));
register(WALK_BACKWARD = new ControllerBinding(controller, Bind.LEFT_STICK_BACKWARD, new ResourceLocation("controlify", "walk_backward"), null)); register(WALK_BACKWARD = new ControllerBinding(controller, Bind.LEFT_STICK_BACKWARD, new ResourceLocation("controlify", "walk_backward")));
register(WALK_LEFT = new ControllerBinding(controller, Bind.LEFT_STICK_LEFT, new ResourceLocation("controlify", "strafe_left"), null)); register(WALK_LEFT = new ControllerBinding(controller, Bind.LEFT_STICK_LEFT, new ResourceLocation("controlify", "strafe_left")));
register(WALK_RIGHT = new ControllerBinding(controller, Bind.LEFT_STICK_RIGHT, new ResourceLocation("controlify", "strafe_right"), null)); register(WALK_RIGHT = new ControllerBinding(controller, Bind.LEFT_STICK_RIGHT, new ResourceLocation("controlify", "strafe_right")));
register(JUMP = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "jump"), options.keyJump)); register(JUMP = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "jump"), options.keyJump, () -> false));
register(SNEAK = new ControllerBinding(controller, Bind.RIGHT_STICK_PRESS, new ResourceLocation("controlify", "sneak"), options.keyShift)); register(SNEAK = new ControllerBinding(controller, Bind.RIGHT_STICK_PRESS, new ResourceLocation("controlify", "sneak"), options.keyShift, () -> controller.config().toggleSneak));
register(ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, new ResourceLocation("controlify", "attack"), options.keyAttack)); register(ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, new ResourceLocation("controlify", "attack"), options.keyAttack, () -> false));
register(USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, new ResourceLocation("controlify", "use"), options.keyUse)); register(USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, new ResourceLocation("controlify", "use"), options.keyUse, () -> false));
register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "sprint"), options.keySprint)); register(SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "sprint"), options.keySprint, () -> controller.config().toggleSprint));
register(DROP = new ControllerBinding(controller, Bind.DPAD_DOWN, new ResourceLocation("controlify", "drop"), options.keyDrop)); register(DROP = new ControllerBinding(controller, Bind.DPAD_DOWN, new ResourceLocation("controlify", "drop"), options.keyDrop, () -> false));
register(NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "next_slot"), null)); register(NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "next_slot")));
register(PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "prev_slot"), null)); register(PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "prev_slot")));
register(PAUSE = new ControllerBinding(controller, Bind.START, new ResourceLocation("controlify", "pause"), null)); register(PAUSE = new ControllerBinding(controller, Bind.START, new ResourceLocation("controlify", "pause")));
register(INVENTORY = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "inventory"), options.keyInventory)); register(INVENTORY = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "inventory"), options.keyInventory, () -> false));
register(CHANGE_PERSPECTIVE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "change_perspective"), options.keyTogglePerspective)); register(CHANGE_PERSPECTIVE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "change_perspective"), options.keyTogglePerspective, () -> false));
register(OPEN_CHAT = new ControllerBinding(controller, Bind.DPAD_UP, new ResourceLocation("controlify", "open_chat"), options.keyChat)); register(OPEN_CHAT = new ControllerBinding(controller, Bind.DPAD_UP, new ResourceLocation("controlify", "open_chat"), options.keyChat, () -> false));
register(GUI_PRESS = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "gui_press"), null)); register(GUI_PRESS = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "gui_press")));
register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back"), null)); register(GUI_BACK = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "gui_back")));
register(GUI_NEXT_TAB = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "gui_next_tab"), null)); register(GUI_NEXT_TAB = new ControllerBinding(controller, Bind.RIGHT_BUMPER, new ResourceLocation("controlify", "gui_next_tab")));
register(GUI_PREV_TAB = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "gui_prev_tab"), null)); register(GUI_PREV_TAB = new ControllerBinding(controller, Bind.LEFT_BUMPER, new ResourceLocation("controlify", "gui_prev_tab")));
register(VMOUSE_LCLICK = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "vmouse_lclick"), null)); register(VMOUSE_LCLICK = new ControllerBinding(controller, Bind.A_BUTTON, new ResourceLocation("controlify", "vmouse_lclick")));
register(VMOUSE_RCLICK = new ControllerBinding(controller, Bind.X_BUTTON, new ResourceLocation("controlify", "vmouse_rclick"), null)); register(VMOUSE_RCLICK = new ControllerBinding(controller, Bind.X_BUTTON, new ResourceLocation("controlify", "vmouse_rclick")));
register(VMOUSE_MCLICK = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "vmouse_mclick"), null)); register(VMOUSE_MCLICK = new ControllerBinding(controller, Bind.Y_BUTTON, new ResourceLocation("controlify", "vmouse_mclick")));
register(VMOUSE_ESCAPE = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "vmouse_escape"), null)); register(VMOUSE_SCROLL_UP = new ControllerBinding(controller, Bind.RIGHT_STICK_FORWARD, new ResourceLocation("controlify", "vmouse_scroll_up")));
register(VMOUSE_SHIFT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "vmouse_shift"), null)); register(VMOUSE_SCROLL_DOWN = new ControllerBinding(controller, Bind.RIGHT_STICK_BACKWARD, new ResourceLocation("controlify", "vmouse_scroll_down")));
register(VMOUSE_TOGGLE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "vmouse_toggle"), null)); register(VMOUSE_ESCAPE = new ControllerBinding(controller, Bind.B_BUTTON, new ResourceLocation("controlify", "vmouse_escape")));
register(TOGGLE_DEBUG_MENU = new ControllerBinding(controller, new CompoundBind(Bind.BACK, Bind.START), new ResourceLocation("controlify", "toggle_debug_menu"), null)); register(VMOUSE_SHIFT = new ControllerBinding(controller, Bind.LEFT_STICK_PRESS, new ResourceLocation("controlify", "vmouse_shift")));
register(VMOUSE_TOGGLE = new ControllerBinding(controller, Bind.BACK, new ResourceLocation("controlify", "vmouse_toggle")));
register(PICK_BLOCK = new ControllerBinding(controller, Bind.DPAD_LEFT, new ResourceLocation("controlify", "pick_block"), options.keyPickItem, () -> false));
ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller); ControlifyEvents.CONTROLLER_BIND_REGISTRY.invoker().onRegisterControllerBinds(this, controller);
ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::imitateVanillaClick); ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::onControllerUpdate);
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll()); ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll());
} }
@ -97,7 +102,13 @@ public class ControllerBindings {
} }
} }
private void imitateVanillaClick(Controller controller) { public void onControllerUpdate(Controller controller) {
if (controller != this.controller) return;
imitateVanillaClick();
}
private void imitateVanillaClick() {
ControllerBinding.clearPressedBinds(controller); ControllerBinding.clearPressedBinds(controller);
if (Controlify.instance().currentInputMode() != InputMode.CONTROLLER) if (Controlify.instance().currentInputMode() != InputMode.CONTROLLER)
@ -106,12 +117,20 @@ public class ControllerBindings {
return; return;
for (var binding : registry().values()) { for (var binding : registry().values()) {
KeyMapping vanillaKey = binding.override(); var override = binding.override();
if (vanillaKey == null) continue; if (override == null) continue;
var vanillaKeyCode = ((KeyMappingAccessor) vanillaKey).getKey(); var accessor = (KeyMappingAccessor) override.keyMapping();
var vanillaKeyCode = accessor.getKey();
KeyMapping.set(vanillaKeyCode, binding.held()); if (override.toggleable().getAsBoolean()) {
if (binding.justPressed()) {
// must set field directly to avoid ToggleKeyMapping breaking things
accessor.setIsDown(!accessor.getIsDown());
}
} else {
KeyMapping.set(vanillaKeyCode, binding.held());
}
if (binding.justPressed()) KeyMapping.click(vanillaKeyCode); if (binding.justPressed()) KeyMapping.click(vanillaKeyCode);
} }
} }

View File

@ -19,7 +19,7 @@ import java.util.*;
public class ScreenProcessor<T extends Screen> { public class ScreenProcessor<T extends Screen> {
public final T screen; public final T screen;
private int lastMoved = 0; protected int lastMoved = 0;
public ScreenProcessor(T screen) { public ScreenProcessor(T screen) {
this.screen = screen; this.screen = screen;
@ -51,6 +51,7 @@ public class ScreenProcessor<T extends Screen> {
setInitialFocus(); setInitialFocus();
var focusTree = getFocusTree(); var focusTree = getFocusTree();
var focuses = List.copyOf(focusTree);
while (!focusTree.isEmpty()) { while (!focusTree.isEmpty()) {
var focused = focusTree.poll(); var focused = focusTree.poll();
var processor = ComponentProcessorProvider.provide(focused); var processor = ComponentProcessorProvider.provide(focused);
@ -89,8 +90,12 @@ public class ScreenProcessor<T extends Screen> {
ComponentPath path = screen.nextFocusPath(event); ComponentPath path = screen.nextFocusPath(event);
if (path != null) { if (path != null) {
accessor.invokeChangeFocus(path); accessor.invokeChangeFocus(path);
ComponentProcessorProvider.provide(path.component()).onNavigateTo(this, controller);
lastMoved = 0; lastMoved = 0;
var newFocusTree = getFocusTree();
while (!newFocusTree.isEmpty() && !focuses.contains(newFocusTree.peek())) {
ComponentProcessorProvider.provide(newFocusTree.poll()).onFocusGained(this, controller);
}
} }
} }
} }

View File

@ -1,11 +1,7 @@
package dev.isxander.controlify.compatibility.screen.component; package dev.isxander.controlify.compatibility.screen.component;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor; import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.controller.AxesState;
import dev.isxander.controlify.controller.ButtonState;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState;
import net.minecraft.client.gui.components.events.GuiEventListener;
public interface ComponentProcessor { public interface ComponentProcessor {
ComponentProcessor EMPTY = new ComponentProcessor(){}; ComponentProcessor EMPTY = new ComponentProcessor(){};
@ -18,6 +14,6 @@ public interface ComponentProcessor {
return false; return false;
} }
default void onNavigateTo(ScreenProcessor<?> screen, Controller controller) { default void onFocusGained(ScreenProcessor<?> screen, Controller controller) {
} }
} }

View File

@ -0,0 +1,26 @@
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 net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.AbstractButton;
public class AbstractButtonComponentProcessor implements ComponentProcessor {
private final AbstractButton button;
public AbstractButtonComponentProcessor(AbstractButton button) {
this.button = button;
}
@Override
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller controller) {
if (controller.bindings().GUI_PRESS.justPressed()) {
button.playDownSound(Minecraft.getInstance().getSoundManager());
button.onPress();
return true;
}
return false;
}
}

View File

@ -64,7 +64,7 @@ public class SliderComponentProcessor implements ComponentProcessor {
} }
@Override @Override
public void onNavigateTo(ScreenProcessor<?> screen, Controller controller) { public void onFocusGained(ScreenProcessor<?> screen, Controller controller) {
System.out.println("navigated!"); System.out.println("navigated!");
this.canChangeValueSetter.accept(false); this.canChangeValueSetter.accept(false);
} }

View File

@ -0,0 +1,33 @@
package dev.isxander.controlify.compatibility.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement;
public class CyclingControllerElementComponentProcessor implements ComponentProcessor {
private final CyclingControllerElement cyclingController;
private int lastInput = 0;
public CyclingControllerElementComponentProcessor(CyclingControllerElement cyclingController) {
this.cyclingController = cyclingController;
}
@Override
public boolean overrideControllerNavigation(ScreenProcessor<?> screen, Controller controller) {
var rightStickX = controller.state().axes().rightStickX();
var rightStickY = controller.state().axes().rightStickY();
var input = Math.abs(rightStickX) > Math.abs(rightStickY) ? rightStickX : rightStickY;
var inputI = Math.abs(input) < controller.config().buttonActivationThreshold ? 0 : input > 0 ? 1 : -1;
if (inputI != 0 && inputI != lastInput) {
cyclingController.cycleValue(input > 0 ? 1 : -1);
lastInput = inputI;
return true;
}
lastInput = inputI;
return false;
}
}

View File

@ -0,0 +1,37 @@
package dev.isxander.controlify.compatibility.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
public class SliderControllerElementComponentProcessor implements ComponentProcessor {
private final SliderControllerElement slider;
private int ticksSinceIncrement = 0;
private int lastInput = 0;
public SliderControllerElementComponentProcessor(SliderControllerElement element) {
this.slider = element;
}
@Override
public boolean overrideControllerButtons(ScreenProcessor<?> screen, Controller controller) {
ticksSinceIncrement++;
var rightStickX = controller.state().axes().rightStickX();
var rightStickY = controller.state().axes().rightStickY();
var input = Math.abs(rightStickX) > Math.abs(rightStickY) ? rightStickX : rightStickY;
if (Math.abs(input) > controller.config().buttonActivationThreshold) {
if (ticksSinceIncrement > controller.config().screenRepeatNavigationDelay || input != lastInput) {
slider.incrementValue(lastInput = input > 0 ? 1 : -1);
ticksSinceIncrement = 0;
return true;
}
} else {
this.lastInput = 0;
}
return false;
}
}

View File

@ -0,0 +1,32 @@
package dev.isxander.controlify.compatibility.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.gui.YACLScreen;
public class YACLScreenProcessor extends ScreenProcessor<YACLScreen> {
public YACLScreenProcessor(YACLScreen screen) {
super(screen);
}
@Override
protected void handleComponentNavigation(Controller controller) {
if (controller.bindings().GUI_NEXT_TAB.justPressed()) {
var idx = screen.getCurrentCategoryIdx() + 1;
if (idx >= screen.config.categories().size()) idx = 0;
screen.changeCategory(idx);
}
if (controller.bindings().GUI_PREV_TAB.justPressed()) {
var idx = screen.getCurrentCategoryIdx() - 1;
if (idx < 0) idx = screen.config.categories().size() - 1;
screen.changeCategory(idx);
}
super.handleComponentNavigation(controller);
}
@Override
protected void setInitialFocus() {
screen.setFocused(screen.optionList);
}
}

View File

@ -47,7 +47,7 @@ public class BindButtonController implements Controller<IBind> {
} }
public static class BindButtonWidget extends ControllerWidget<BindButtonController> implements ComponentProcessorProvider, ComponentProcessor { public static class BindButtonWidget extends ControllerWidget<BindButtonController> implements ComponentProcessorProvider, ComponentProcessor {
private boolean awaitingControllerInput = false, skipFirstTickInput = false; private boolean awaitingControllerInput = false;
private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC); private final Component awaitingText = Component.translatable("controlify.gui.bind_input_awaiting").withStyle(ChatFormatting.ITALIC);
private final Set<Bind> pressedBinds = new LinkedHashSet<>(); private final Set<Bind> pressedBinds = new LinkedHashSet<>();

View File

@ -7,11 +7,13 @@ import dev.isxander.controlify.controller.ControllerTheme;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import dev.isxander.yacl.api.*; import dev.isxander.yacl.api.*;
import dev.isxander.yacl.gui.controllers.ActionController; import dev.isxander.yacl.gui.controllers.ActionController;
import dev.isxander.yacl.gui.controllers.BooleanController;
import dev.isxander.yacl.gui.controllers.TickBoxController; import dev.isxander.yacl.gui.controllers.TickBoxController;
import dev.isxander.yacl.gui.controllers.cycling.CyclingListController; import dev.isxander.yacl.gui.controllers.cycling.CyclingListController;
import dev.isxander.yacl.gui.controllers.cycling.EnumController; import dev.isxander.yacl.gui.controllers.cycling.EnumController;
import dev.isxander.yacl.gui.controllers.slider.FloatSliderController; import dev.isxander.yacl.gui.controllers.slider.FloatSliderController;
import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController; import dev.isxander.yacl.gui.controllers.slider.IntegerSliderController;
import dev.isxander.yacl.gui.controllers.string.StringController;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.Util; import net.minecraft.Util;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -62,14 +64,14 @@ public class YACLHelper {
for (var controller : Controller.CONTROLLERS.values()) { for (var controller : Controller.CONTROLLERS.values()) {
var category = ConfigCategory.createBuilder(); var category = ConfigCategory.createBuilder();
var customName = controller.config().customName; category.name(Component.literal(controller.name()));
category.name(Component.literal(customName == null ? controller.name() : customName));
var config = controller.config(); var config = controller.config();
var def = controller.defaultConfig(); var def = controller.defaultConfig();
var configGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.config")) var basicGroup = OptionGroup.createBuilder()
.tooltip(Component.translatable("controlify.gui.group.config.tooltip")) .name(Component.translatable("controlify.gui.group.basic"))
.tooltip(Component.translatable("controlify.gui.group.basic.tooltip"))
.option(Option.createBuilder(float.class) .option(Option.createBuilder(float.class)
.name(Component.translatable("controlify.gui.horizontal_look_sensitivity")) .name(Component.translatable("controlify.gui.horizontal_look_sensitivity"))
.tooltip(Component.translatable("controlify.gui.horizontal_look_sensitivity.tooltip")) .tooltip(Component.translatable("controlify.gui.horizontal_look_sensitivity.tooltip"))
@ -82,12 +84,43 @@ public class YACLHelper {
.binding(def.verticalLookSensitivity, () -> config.verticalLookSensitivity, v -> config.verticalLookSensitivity = v) .binding(def.verticalLookSensitivity, () -> config.verticalLookSensitivity, v -> config.verticalLookSensitivity = v)
.controller(opt -> new FloatSliderController(opt, 0.1f, 2f, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100)))) .controller(opt -> new FloatSliderController(opt, 0.1f, 2f, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build()) .build())
.option(Option.createBuilder(boolean.class)
.name(Component.translatable("controlify.gui.toggle_sprint"))
.tooltip(Component.translatable("controlify.gui.toggle_sprint.tooltip"))
.binding(def.toggleSprint, () -> config.toggleSprint, v -> config.toggleSprint = v)
.controller(opt -> new BooleanController(opt, v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold")), false))
.build())
.option(Option.createBuilder(boolean.class)
.name(Component.translatable("controlify.gui.toggle_sneak"))
.tooltip(Component.translatable("controlify.gui.toggle_sneak.tooltip"))
.binding(def.toggleSneak, () -> config.toggleSneak, v -> config.toggleSneak = v)
.controller(opt -> new BooleanController(opt, v -> Component.translatable("controlify.gui.format.hold_toggle." + (v ? "toggle" : "hold")), false))
.build())
.option(Option.createBuilder(float.class) .option(Option.createBuilder(float.class)
.name(Component.translatable("controlify.gui.vmouse_sensitivity")) .name(Component.translatable("controlify.gui.vmouse_sensitivity"))
.tooltip(Component.translatable("controlify.gui.vmouse_sensitivity.tooltip")) .tooltip(Component.translatable("controlify.gui.vmouse_sensitivity.tooltip"))
.binding(def.virtualMouseSensitivity, () -> config.virtualMouseSensitivity, v -> config.virtualMouseSensitivity = v) .binding(def.virtualMouseSensitivity, () -> config.virtualMouseSensitivity, v -> config.virtualMouseSensitivity = v)
.controller(opt -> new FloatSliderController(opt, 0.1f, 2f, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100)))) .controller(opt -> new FloatSliderController(opt, 0.1f, 2f, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build()) .build())
.option(Option.createBuilder(ControllerTheme.class)
.name(Component.translatable("controlify.gui.controller_theme"))
.tooltip(Component.translatable("controlify.gui.controller_theme.tooltip"))
.binding(controller.type().theme(), () -> config.theme, v -> config.theme = v)
.controller(EnumController::new)
.instant(true)
.build())
.option(Option.createBuilder(String.class)
.name(Component.translatable("controlify.gui.custom_name"))
.tooltip(Component.translatable("controlify.gui.custom_name.tooltip"))
.binding(def.customName == null ? "" : def.customName, () -> config.customName == null ? "" : config.customName, v -> config.customName = (v.equals("") ? null : v))
.controller(StringController::new)
.build());
category.group(basicGroup.build());
var advancedGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.advanced"))
.tooltip(Component.translatable("controlify.gui.group.advanced.tooltip"))
.collapsed(true)
.option(Option.createBuilder(int.class) .option(Option.createBuilder(int.class)
.name(Component.translatable("controlify.gui.screen_repeat_navi_delay")) .name(Component.translatable("controlify.gui.screen_repeat_navi_delay"))
.tooltip(Component.translatable("controlify.gui.screen_repeat_navi_delay.tooltip")) .tooltip(Component.translatable("controlify.gui.screen_repeat_navi_delay.tooltip"))
@ -113,15 +146,8 @@ public class YACLHelper {
.tooltip(Component.translatable("controlify.gui.button_activation_threshold.tooltip")) .tooltip(Component.translatable("controlify.gui.button_activation_threshold.tooltip"))
.binding(def.buttonActivationThreshold, () -> config.buttonActivationThreshold, v -> config.buttonActivationThreshold = v) .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)))) .controller(opt -> new FloatSliderController(opt, 0, 1, 0.05f, v -> Component.literal(String.format("%.0f%%", v*100))))
.build())
.option(Option.createBuilder(ControllerTheme.class)
.name(Component.translatable("controlify.gui.controller_theme"))
.tooltip(Component.translatable("controlify.gui.controller_theme.tooltip"))
.binding(controller.type().theme(), () -> config.theme, v -> config.theme = v)
.controller(EnumController::new)
.instant(true)
.build()); .build());
category.group(configGroup.build()); category.group(advancedGroup.build());
var controlsGroup = OptionGroup.createBuilder() var controlsGroup = OptionGroup.createBuilder()
.name(Component.translatable("controlify.gui.group.controls")); .name(Component.translatable("controlify.gui.group.controls"));

View File

@ -178,6 +178,9 @@ public final class Controller {
public ControllerTheme theme = type().theme(); public ControllerTheme theme = type().theme();
public boolean toggleSprint = true;
public boolean toggleSneak = true;
public String customName = null; public String customName = null;
} }
} }

View File

@ -3,12 +3,15 @@ package dev.isxander.controlify.ingame;
import dev.isxander.controlify.controller.Controller; import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.player.Input; import net.minecraft.client.player.Input;
import net.minecraft.client.player.LocalPlayer;
public class ControllerPlayerMovement extends Input { public class ControllerPlayerMovement extends Input {
private final Controller controller; private final Controller controller;
private final LocalPlayer player;
public ControllerPlayerMovement(Controller controller) { public ControllerPlayerMovement(Controller controller, LocalPlayer player) {
this.controller = controller; this.controller = controller;
this.player = player;
} }
@Override @Override
@ -42,6 +45,13 @@ public class ControllerPlayerMovement extends Input {
} }
this.jumping = bindings.JUMP.held(); this.jumping = bindings.JUMP.held();
this.shiftKeyDown = bindings.SNEAK.held();
if (player.getAbilities().flying || !controller.config().toggleSneak) {
this.shiftKeyDown = bindings.SNEAK.held();
} else {
if (bindings.SNEAK.justPressed()) {
this.shiftKeyDown = !this.shiftKeyDown;
}
}
} }
} }

View File

@ -21,7 +21,7 @@ public class InGameInputHandler {
this.controller = controller; this.controller = controller;
this.minecraft = Minecraft.getInstance(); this.minecraft = Minecraft.getInstance();
this.controllerInput = new ControllerPlayerMovement(controller); this.controllerInput = new ControllerPlayerMovement(controller, minecraft.player);
this.keyboardInput = new KeyboardInput(minecraft.options); this.keyboardInput = new KeyboardInput(minecraft.options);
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> { ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> {
@ -45,9 +45,6 @@ public class InGameInputHandler {
if (controller.bindings().PAUSE.justPressed()) { if (controller.bindings().PAUSE.justPressed()) {
minecraft.pauseGame(false); minecraft.pauseGame(false);
} }
if (controller.bindings().TOGGLE_DEBUG_MENU.justPressed()) {
minecraft.options.renderDebug = !minecraft.options.renderDebug;
}
if (minecraft.player != null) { if (minecraft.player != null) {
if (controller.bindings().NEXT_SLOT.justPressed()) { if (controller.bindings().NEXT_SLOT.justPressed()) {
minecraft.player.getInventory().swapPaint(-1); minecraft.player.getInventory().swapPaint(-1);
@ -73,9 +70,9 @@ public class InGameInputHandler {
var delta = time - deltaTime; var delta = time - deltaTime;
deltaTime = time; deltaTime = time;
var hsensitivity = controller.config().horizontalLookSensitivity * 8.0 + 2.0; var hsensitivity = controller.config().horizontalLookSensitivity * 9.6 + 2.0;
var hsensCubed = hsensitivity * hsensitivity * hsensitivity; var hsensCubed = hsensitivity * hsensitivity * hsensitivity;
var vsensitivity = controller.config().verticalLookSensitivity * 8.0 + 2.0; var vsensitivity = controller.config().verticalLookSensitivity * 9.6 + 2.0;
var vsensCubed = vsensitivity * vsensitivity * vsensitivity; var vsensCubed = vsensitivity * vsensitivity * vsensitivity;
var dx = accumulatedDX * delta; var dx = accumulatedDX * delta;
@ -93,7 +90,6 @@ public class InGameInputHandler {
accumulatedDY -= Math.max(dy * 20, accumulatedDY); accumulatedDY -= Math.max(dy * 20, accumulatedDY);
} }
if (minecraft.player != null) if (minecraft.player != null)
minecraft.player.turn(dx * hsensCubed, dy * vsensCubed); minecraft.player.turn(dx * hsensCubed, dy * vsensCubed);
} }

View File

@ -0,0 +1,19 @@
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.AbstractButtonComponentProcessor;
import net.minecraft.client.gui.components.AbstractButton;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(AbstractButton.class)
public class AbstractButtonMixin implements ComponentProcessorProvider {
@Unique private final AbstractButtonComponentProcessor controlify$processor
= new AbstractButtonComponentProcessor((AbstractButton) (Object) this);
@Override
public ComponentProcessor componentProcessor() {
return controlify$processor;
}
}

View File

@ -0,0 +1,19 @@
package dev.isxander.controlify.mixins.compat.screen.yacl;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.CyclingControllerElementComponentProcessor;
import dev.isxander.yacl.gui.controllers.cycling.CyclingControllerElement;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(CyclingControllerElement.class)
public class CyclingControllerElementMixin implements ComponentProcessorProvider {
@Unique private final CyclingControllerElementComponentProcessor controlify$processor
= new CyclingControllerElementComponentProcessor((CyclingControllerElement) (Object) this);
@Override
public ComponentProcessor componentProcessor() {
return controlify$processor;
}
}

View File

@ -0,0 +1,19 @@
package dev.isxander.controlify.mixins.compat.screen.yacl;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessor;
import dev.isxander.controlify.compatibility.screen.component.ComponentProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.SliderControllerElementComponentProcessor;
import dev.isxander.yacl.gui.controllers.slider.SliderControllerElement;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(SliderControllerElement.class)
public class SliderControllerElementMixin implements ComponentProcessorProvider {
@Unique private final SliderControllerElementComponentProcessor controlify$processor
= new SliderControllerElementComponentProcessor((SliderControllerElement) (Object) this);
@Override
public ComponentProcessor componentProcessor() {
return controlify$processor;
}
}

View File

@ -0,0 +1,18 @@
package dev.isxander.controlify.mixins.compat.screen.yacl;
import dev.isxander.controlify.compatibility.screen.ScreenProcessor;
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
import dev.isxander.controlify.compatibility.yacl.YACLScreenProcessor;
import dev.isxander.yacl.gui.YACLScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
@Mixin(YACLScreen.class)
public class YACLScreenMixin implements ScreenProcessorProvider {
@Unique private final YACLScreenProcessor controlify$processor = new YACLScreenProcessor((YACLScreen) (Object) this);
@Override
public ScreenProcessor<?> screenProcessor() {
return controlify$processor;
}
}

View File

@ -24,6 +24,6 @@ public class ClientPacketListenerMixin {
@Inject(method = "handleLogin", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER)) @Inject(method = "handleLogin", at = @At(value = "FIELD", target = "Lnet/minecraft/client/player/LocalPlayer;input:Lnet/minecraft/client/player/Input;", opcode = Opcodes.ASTORE, shift = At.Shift.AFTER))
private void useControllerInput(ClientboundLoginPacket packet, CallbackInfo ci) { private void useControllerInput(ClientboundLoginPacket packet, CallbackInfo ci) {
if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER && minecraft.player != null) if (Controlify.instance().currentInputMode() == InputMode.CONTROLLER && minecraft.player != null)
minecraft.player.input = new ControllerPlayerMovement(Controlify.instance().currentController()); minecraft.player.input = new ControllerPlayerMovement(Controlify.instance().currentController(), minecraft.player);
} }
} }

View File

@ -9,4 +9,10 @@ import org.spongepowered.asm.mixin.gen.Accessor;
public interface KeyMappingAccessor { public interface KeyMappingAccessor {
@Accessor @Accessor
InputConstants.Key getKey(); InputConstants.Key getKey();
@Accessor
void setIsDown(boolean down);
@Accessor
boolean getIsDown();
} }

View File

@ -22,6 +22,9 @@ public class VirtualMouseHandler {
private double targetX, targetY; private double targetX, targetY;
private double currentX, currentY; private double currentX, currentY;
private double scrollX, scrollY;
private final Minecraft minecraft; private final Minecraft minecraft;
private boolean virtualMouseEnabled; private boolean virtualMouseEnabled;
@ -51,6 +54,8 @@ public class VirtualMouseHandler {
targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth()); targetX = Mth.clamp(targetX, 0, minecraft.getWindow().getWidth());
targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight()); targetY = Mth.clamp(targetY, 0, minecraft.getWindow().getHeight());
scrollY += controller.bindings().VMOUSE_SCROLL_UP.state() - controller.bindings().VMOUSE_SCROLL_DOWN.state();
var mouseHandler = (MouseHandlerAccessor) minecraft.mouseHandler; var mouseHandler = (MouseHandlerAccessor) minecraft.mouseHandler;
var keyboardHandler = (KeyboardHandlerAccessor) minecraft.keyboardHandler; var keyboardHandler = (KeyboardHandlerAccessor) minecraft.keyboardHandler;
@ -83,12 +88,27 @@ public class VirtualMouseHandler {
public void updateMouse() { public void updateMouse() {
if (!virtualMouseEnabled) return; if (!virtualMouseEnabled) return;
if (targetX == currentX && targetY == currentY) return; // don't need to needlessly update mouse position
currentX = Mth.lerp(minecraft.getDeltaFrameTime(), currentX, targetX); if (Math.round(targetX * 100) / 100.0 != Math.round(currentX * 100) / 100.0 || Math.round(targetY * 100) / 100.0 != Math.round(currentY * 100) / 100.0) {
currentY = Mth.lerp(minecraft.getDeltaFrameTime(), currentY, targetY); currentX = Mth.lerp(minecraft.getDeltaFrameTime(), currentX, targetX);
currentY = Mth.lerp(minecraft.getDeltaFrameTime(), currentY, targetY);
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY); ((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnMove(minecraft.getWindow().getWindow(), currentX, currentY);
} else {
currentX = targetX;
currentY = targetY;
}
if (Math.abs(scrollX) >= 0.01 || Math.abs(scrollY) >= 0.01) {
var currentScrollY = scrollY * Minecraft.getInstance().getDeltaFrameTime();
scrollY -= currentScrollY;
var currentScrollX = scrollX * Minecraft.getInstance().getDeltaFrameTime();
scrollX -= currentScrollX;
((MouseHandlerAccessor) minecraft.mouseHandler).invokeOnScroll(minecraft.getWindow().getWindow(), currentScrollX, currentScrollY);
} else {
scrollX = scrollY = 0;
}
} }
public void onScreenChanged() { public void onScreenChanged() {
@ -141,7 +161,6 @@ public class VirtualMouseHandler {
public void enableVirtualMouse() { public void enableVirtualMouse() {
if (virtualMouseEnabled) return; if (virtualMouseEnabled) return;
setMousePosition();
GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED); GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_DISABLED);
virtualMouseEnabled = true; virtualMouseEnabled = true;
@ -152,6 +171,7 @@ public class VirtualMouseHandler {
targetX = currentX = minecraft.mouseHandler.xpos(); targetX = currentX = minecraft.mouseHandler.xpos();
targetY = currentY = minecraft.mouseHandler.ypos(); targetY = currentY = minecraft.mouseHandler.ypos();
} }
setMousePosition();
ControlifyEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(true); ControlifyEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(true);
} }
@ -162,6 +182,7 @@ public class VirtualMouseHandler {
// make sure minecraft doesn't think the mouse is grabbed when it isn't // make sure minecraft doesn't think the mouse is grabbed when it isn't
((MouseHandlerAccessor) minecraft.mouseHandler).setMouseGrabbed(false); ((MouseHandlerAccessor) minecraft.mouseHandler).setMouseGrabbed(false);
Controlify.instance().hideMouse(true, true);
GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL); GLFW.glfwSetInputMode(minecraft.getWindow().getWindow(), GLFW.GLFW_CURSOR, GLFW.GLFW_CURSOR_NORMAL);
setMousePosition(); setMousePosition();
virtualMouseEnabled = false; virtualMouseEnabled = false;
@ -196,7 +217,7 @@ public class VirtualMouseHandler {
if (screens.contains(screenClass)) { if (screens.contains(screenClass)) {
screens.remove(screenClass); screens.remove(screenClass);
disableVirtualMouse(); disableVirtualMouse();
Controlify.instance().hideMouse(true); Controlify.instance().hideMouse(true, false);
minecraft.getToasts().addToast(SystemToast.multiline( minecraft.getToasts().addToast(SystemToast.multiline(
minecraft, minecraft,

View File

@ -6,14 +6,24 @@
"controlify.gui.out_of_focus_input.tooltip": "If enabled, Controlify will still receive input even if the game window is not focused.", "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.open_issue_tracker": "Open Issue Tracker",
"controlify.gui.group.config": "Config", "controlify.gui.group.basic": "Basic",
"controlify.gui.group.config.tooltip": "Adjust the controller configuration.", "controlify.gui.group.basic.tooltip": "Adjust how your controller behaves.",
"controlify.gui.horizontal_look_sensitivity": "Horizontal Look Sensitivity", "controlify.gui.horizontal_look_sensitivity": "Horizontal Look Sensitivity",
"controlify.gui.horizontal_look_sensitivity.tooltip": "How fast the camera moves horizontally when looking around.", "controlify.gui.horizontal_look_sensitivity.tooltip": "How fast the camera moves horizontally when looking around.",
"controlify.gui.vertical_look_sensitivity": "Vertical Look Sensitivity", "controlify.gui.vertical_look_sensitivity": "Vertical Look Sensitivity",
"controlify.gui.vertical_look_sensitivity.tooltip": "How fast the camera moves vertically when looking around.", "controlify.gui.vertical_look_sensitivity.tooltip": "How fast the camera moves vertically when looking around.",
"controlify.gui.toggle_sneak": "Sneak",
"controlify.gui.toggle_sneak.tooltip": "How the state of the sneak button behaves.",
"controlify.gui.toggle_sprint": "Sprint",
"controlify.gui.toggle_sprint.tooltip": "How the state of the sprint button behaves.",
"controlify.gui.vmouse_sensitivity": "Virtual Mouse Sensitivity", "controlify.gui.vmouse_sensitivity": "Virtual Mouse Sensitivity",
"controlify.gui.vmouse_sensitivity.tooltip": "How fast the virtual mouse moves.", "controlify.gui.vmouse_sensitivity.tooltip": "How fast the virtual mouse moves.",
"controlify.gui.controller_theme": "Controller Theme",
"controlify.gui.controller_theme.tooltip": "The theme to use for rendering controller buttons.",
"controlify.gui.custom_name": "Display Name",
"controlify.gui.custom_name.tooltip": "Name to display for this controller throughout Minecraft.",
"controlify.gui.group.advanced": "Advanced",
"controlify.gui.group.advanced.tooltip": "Settings you probably shouldn't touch!.",
"controlify.gui.screen_repeat_navi_delay": "Screen Repeat Navigation Delay", "controlify.gui.screen_repeat_navi_delay": "Screen Repeat Navigation Delay",
"controlify.gui.screen_repeat_navi_delay.tooltip": "How the delay is for navigation to start repeating if you hold the stick.", "controlify.gui.screen_repeat_navi_delay.tooltip": "How the delay is for navigation to start repeating if you hold the stick.",
"controlify.gui.left_stick_deadzone": "Left Stick Deadzone", "controlify.gui.left_stick_deadzone": "Left Stick Deadzone",
@ -23,14 +33,14 @@
"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.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.button_activation_threshold": "Button Activation Threshold", "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.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.",
"controlify.gui.group.controls": "Controls", "controlify.gui.group.controls": "Controls",
"controlify.gui.group.controls.tooltip": "Adjust the controller controls.", "controlify.gui.group.controls.tooltip": "Adjust the controller controls.",
"controlify.gui.bind_input_awaiting": "Press any button", "controlify.gui.bind_input_awaiting": "Press any button",
"controlify.gui.format.ticks": "%s ticks", "controlify.gui.format.ticks": "%s ticks",
"controlify.gui.format.hold_toggle.hold": "Hold",
"controlify.gui.format.hold_toggle.toggle": "Toggle",
"controlify.gui.format.open": "OPEN URL", "controlify.gui.format.open": "OPEN URL",
"controlify.gui.error.title": "Could not open Controlify settings", "controlify.gui.error.title": "Could not open Controlify settings",
@ -43,7 +53,7 @@
"controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled", "controlify.toast.vmouse_disabled.title": "Virtual Mouse Disabled",
"controlify.toast.vmouse_disabled.description": "Controlify virtual mouse is now disabled for this screen.", "controlify.toast.vmouse_disabled.description": "Controlify virtual mouse is now disabled for this screen.",
"controlify.toast.controller_connected.title": "Controller Connected", "controlify.toast.controller_connected.title": "Controller Connected",
"controlify.toast.controller_connected.description": "A new '%s' controller named has just been connected. You can switch to your other controller in Controlify settings.", "controlify.toast.controller_connected.description": "A controller named '%s' has just been connected. You can switch to your other controller in Controlify settings.",
"controlify.toast.controller_disconnected.title": "Controller Disconnected", "controlify.toast.controller_disconnected.title": "Controller Disconnected",
"controlify.toast.controller_disconnected.description": "'%s' was disconnected.", "controlify.toast.controller_disconnected.description": "'%s' was disconnected.",
@ -73,10 +83,12 @@
"controlify.binding.controlify.vmouse_lclick": "Virtual Mouse LClick", "controlify.binding.controlify.vmouse_lclick": "Virtual Mouse LClick",
"controlify.binding.controlify.vmouse_rclick": "Virtual Mouse RClick", "controlify.binding.controlify.vmouse_rclick": "Virtual Mouse RClick",
"controlify.binding.controlify.vmouse_mclick": "Virtual Mouse MClick", "controlify.binding.controlify.vmouse_mclick": "Virtual Mouse MClick",
"controlify.binding.controlify.vmouse_scroll_up": "Virtual Mouse Scroll Up",
"controlify.binding.controlify.vmouse_scroll_down": "Virtual Mouse Scroll Down",
"controlify.binding.controlify.vmouse_escape": "Virtual Mouse Key Escape", "controlify.binding.controlify.vmouse_escape": "Virtual Mouse Key Escape",
"controlify.binding.controlify.vmouse_shift": "Virtual Mouse Key Shift", "controlify.binding.controlify.vmouse_shift": "Virtual Mouse Key Shift",
"controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse", "controlify.binding.controlify.vmouse_toggle": "Toggle Virtual Mouse",
"controlify.binding.controlify.toggle_debug_menu": "Toggle F3 Menu", "controlify.binding.controlify.pick_block": "Pick Block",
"controlify.beta.title": "Controlify Beta Notice", "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": "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.",

View File

@ -6,6 +6,7 @@
"mixins": [ "mixins": [
], ],
"client": [ "client": [
"compat.screen.vanilla.AbstractButtonMixin",
"compat.screen.vanilla.AbstractContainerEventHandlerMixin", "compat.screen.vanilla.AbstractContainerEventHandlerMixin",
"compat.screen.vanilla.AbstractSelectionListMixin", "compat.screen.vanilla.AbstractSelectionListMixin",
"compat.screen.vanilla.AbstractSliderButtonMixin", "compat.screen.vanilla.AbstractSliderButtonMixin",
@ -22,6 +23,9 @@
"compat.screen.vanilla.SelectWorldScreenMixin", "compat.screen.vanilla.SelectWorldScreenMixin",
"compat.screen.vanilla.ServerSelectionListEntryMixin", "compat.screen.vanilla.ServerSelectionListEntryMixin",
"compat.screen.vanilla.WorldSelectionListEntryMixin", "compat.screen.vanilla.WorldSelectionListEntryMixin",
"compat.screen.yacl.CyclingControllerElementMixin",
"compat.screen.yacl.SliderControllerElementMixin",
"compat.screen.yacl.YACLScreenMixin",
"core.ClientPacketListenerMixin", "core.ClientPacketListenerMixin",
"core.KeyboardHandlerMixin", "core.KeyboardHandlerMixin",
"core.MinecraftMixin", "core.MinecraftMixin",