1
0
forked from Clones/Controlify

separate API from impl

This commit is contained in:
isXander
2023-02-27 18:08:40 +00:00
parent 05f863a0d7
commit 0d5307ba43
28 changed files with 250 additions and 95 deletions

View File

@ -2,13 +2,16 @@ package dev.isxander.controlify;
import com.mojang.blaze3d.Blaze3D;
import com.mojang.logging.LogUtils;
import dev.isxander.controlify.api.ControlifyApi;
import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.gui.screen.ControllerDeadzoneCalibrationScreen;
import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.config.ControlifyConfig;
import dev.isxander.controlify.controller.hid.ControllerHIDService;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.ingame.guide.InGameButtonGuide;
import dev.isxander.controlify.ingame.InGameInputHandler;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
@ -18,13 +21,14 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.toasts.SystemToast;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;
import org.lwjgl.glfw.GLFW;
import org.slf4j.Logger;
import java.util.ArrayDeque;
import java.util.Queue;
public class Controlify {
public class Controlify implements ControlifyApi {
public static final Logger LOGGER = LogUtils.getLogger();
private static Controlify instance = null;
@ -87,7 +91,7 @@ public class Controlify {
if (firstController) {
this.setCurrentController(controller);
this.setCurrentInputMode(InputMode.CONTROLLER);
this.setInputMode(InputMode.CONTROLLER);
}
if (!config().loadOrCreateControllerData(currentController)) {
@ -106,7 +110,7 @@ public class Controlify {
if (controller != null) {
setCurrentController(Controller.CONTROLLERS.values().stream().findFirst().orElse(null));
LOGGER.info("Controller disconnected: " + controller.name());
this.setCurrentInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
this.setInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
minecraft.getToasts().addToast(SystemToast.multiline(
minecraft,
@ -154,7 +158,7 @@ public class Controlify {
state = ControllerState.EMPTY;
if (state.hasAnyInput())
this.setCurrentInputMode(InputMode.CONTROLLER);
this.setInputMode(InputMode.CONTROLLER);
if (consecutiveInputSwitches > 20) {
LOGGER.warn("Controlify detected current controller to be constantly giving input and has been disabled.");
@ -169,7 +173,7 @@ public class Controlify {
}
if (currentController == null) {
this.setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
this.setInputMode(InputMode.KEYBOARD_MOUSE);
return;
}
@ -181,14 +185,15 @@ public class Controlify {
}
this.virtualMouseHandler().handleControllerInput(currentController);
ControlifyClientEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(currentController);
ControlifyEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(currentController);
}
public ControlifyConfig config() {
return config;
}
public Controller<?, ?> currentController() {
@Override
public @NotNull Controller<?, ?> currentController() {
if (currentController == null)
return Controller.DUMMY;
@ -230,11 +235,12 @@ public class Controlify {
return controllerHIDService;
}
public InputMode currentInputMode() {
public @NotNull InputMode currentInputMode() {
return currentInputMode;
}
public void setCurrentInputMode(InputMode currentInputMode) {
@Override
public void setInputMode(@NotNull InputMode currentInputMode) {
if (this.currentInputMode == currentInputMode) return;
this.currentInputMode = currentInputMode;
@ -258,7 +264,7 @@ public class Controlify {
}
lastInputSwitchTime = Blaze3D.getTime();
ControlifyClientEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode);
ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode);
}
public void hideMouse(boolean hide, boolean moveMouse) {
@ -284,4 +290,9 @@ public class Controlify {
if (instance == null) instance = new Controlify();
return instance;
}
@Override
public @NotNull ControlifyBindingsApi bindingsApi() {
return ControllerBindings.Api.INSTANCE;
}
}

View File

@ -0,0 +1,27 @@
package dev.isxander.controlify.api;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
import dev.isxander.controlify.controller.Controller;
import org.jetbrains.annotations.NotNull;
/**
* Interface with Controlify in a manner where you don't need to worry about updates
* breaking! This is the recommended way to interact with Controlify.
*/
public interface ControlifyApi {
/**
* @return the controller currently in use. If disabled, this will return {@link Controller#DUMMY}
*/
@NotNull Controller<?, ?> currentController();
@NotNull InputMode currentInputMode();
void setInputMode(@NotNull InputMode mode);
@NotNull ControlifyBindingsApi bindingsApi();
static ControlifyApi get() {
return Controlify.instance();
}
}

View File

@ -0,0 +1,32 @@
package dev.isxander.controlify.api.bind;
import dev.isxander.controlify.bindings.BindingSupplier;
import dev.isxander.controlify.bindings.GamepadBinds;
import net.minecraft.client.KeyMapping;
import net.minecraft.resources.ResourceLocation;
import java.util.function.BooleanSupplier;
public interface ControlifyBindingsApi {
/**
* Registers a custom binding for all available controllers.
* If the controller is not a gamepad, the binding with be empty by default.
*
* @param bind the default gamepad bind
* @param id the identifier for the binding, the namespace should be your modid.
* @return the binding supplier to fetch the binding for a specific controller.
*/
BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id);
/**
* Registers a custom binding for all available controllers.
* If the controller is not a gamepad, the binding with be empty by default.
*
* @param bind the default gamepad bind
* @param id the identifier for the binding, the namespace should be your modid.
* @param override the minecraft keybind to imitate.
* @param toggleOverride a supplier that returns true if the vanilla keybind should be treated as a {@link net.minecraft.client.ToggleKeyMapping}
* @return the binding supplier to fetch the binding for a specific controller.
*/
BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id, KeyMapping override, BooleanSupplier toggleOverride);
}

View File

@ -0,0 +1,8 @@
package dev.isxander.controlify.api.buttonguide;
/**
* Whether the action should be on the left or right list.
*/
public enum ActionLocation {
LEFT, RIGHT
}

View File

@ -0,0 +1,12 @@
package dev.isxander.controlify.api.buttonguide;
/**
* Defines how the action is sorted in the list. All default Controlify actions are {@link #NORMAL}.
*/
public enum ActionPriority {
LOWEST,
LOW,
NORMAL,
HIGH,
HIGHEST
}

View File

@ -0,0 +1,29 @@
package dev.isxander.controlify.api.buttonguide;
import dev.isxander.controlify.bindings.ControllerBinding;
/**
* Allows you to register your own actions to the button guide.
* This should be called through {@link dev.isxander.controlify.api.event.ControlifyEvents#BUTTON_GUIDE_REGISTRY} as
* these should be called every time the guide is initialised.
*/
public interface ButtonGuideRegistry {
/**
* Registers a new action to the button guide.
*
* @param binding the binding for the action, if unbound, the action is hidden.
* @param location the location of the action, left or right.
* @param priority the priority of the action, used to sort the list.
* @param supplier the supplier for the name of the action. can be empty to hide the action.
*/
void registerGuideAction(ControllerBinding<?> binding, ActionLocation location, ActionPriority priority, GuideActionNameSupplier supplier);
/**
* Registers a new action to the button guide.
*
* @param binding the binding for the action, if unbound, the action is hidden.
* @param location the location of the action, left or right.
* @param supplier the supplier for the name of the action. can be empty to hide the action.
*/
void registerGuideAction(ControllerBinding<?> binding, ActionLocation location, GuideActionNameSupplier supplier);
}

View File

@ -0,0 +1,25 @@
package dev.isxander.controlify.api.buttonguide;
import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.phys.HitResult;
import java.util.Optional;
/**
* Supplies the text to display for a guide action based on the current context.
* If return is empty, the action will not be displayed.
*/
@FunctionalInterface
public interface GuideActionNameSupplier {
Optional<Component> supply(
Minecraft client,
LocalPlayer player,
ClientLevel level,
HitResult hitResult,
Controller<?, ?> controller
);
}

View File

@ -1,31 +1,43 @@
package dev.isxander.controlify.event;
package dev.isxander.controlify.api.event;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.bindings.ControllerBindings;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.ingame.guide.ButtonGuideRegistry;
import dev.isxander.controlify.api.buttonguide.ButtonGuideRegistry;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
public class ControlifyClientEvents {
public final class ControlifyEvents {
/**
* Triggers when the input mode is changed from keyboard to controller or vice versa.
*/
public static final Event<InputModeChanged> INPUT_MODE_CHANGED = EventFactory.createArrayBacked(InputModeChanged.class, callbacks -> mode -> {
for (InputModeChanged callback : callbacks) {
callback.onInputModeChanged(mode);
}
});
/**
* Triggers every tick when the current controller state has been updated.
*/
public static final Event<ControllerStateUpdate> CONTROLLER_STATE_UPDATED = EventFactory.createArrayBacked(ControllerStateUpdate.class, callbacks -> controller -> {
for (ControllerStateUpdate callback : callbacks) {
callback.onControllerStateUpdate(controller);
}
});
/**
* Triggers when the button guide entries are being populated, so you can add more of your own.
*/
public static final Event<ButtonGuideRegistryEvent> BUTTON_GUIDE_REGISTRY = EventFactory.createArrayBacked(ButtonGuideRegistryEvent.class, callbacks -> (bindings, registry) -> {
for (ButtonGuideRegistryEvent callback : callbacks) {
callback.onRegisterButtonGuide(bindings, registry);
}
});
/**
* Triggers in a GUI when the virtual mouse is toggled on or off.
*/
public static final Event<VirtualMouseToggled> VIRTUAL_MOUSE_TOGGLED = EventFactory.createArrayBacked(VirtualMouseToggled.class, callbacks -> enabled -> {
for (VirtualMouseToggled callback : callbacks) {
callback.onVirtualMouseToggled(enabled);

View File

@ -0,0 +1,10 @@
package dev.isxander.controlify.api.vmousesnapping;
import java.util.Set;
/**
* An interface to implement by gui components to define snap points for virtual mouse snapping.
*/
public interface ISnapBehaviour {
Set<SnapPoint> getSnapPoints();
}

View File

@ -0,0 +1,16 @@
package dev.isxander.controlify.api.vmousesnapping;
import org.joml.Vector2i;
import org.joml.Vector2ic;
/**
* Defines a point on the screen that the virtual mouse can snap to.
*
* @param position the position on the screen where the cursor will snap to
* @param range how far away from the snap point the cursor can be and still snap to it
*/
public record SnapPoint(Vector2ic position, int range) {
public SnapPoint(int x, int y, int range) {
this(new Vector2i(x, y), range);
}
}

View File

@ -3,9 +3,10 @@ package dev.isxander.controlify.bindings;
import com.google.gson.JsonObject;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.api.bind.ControlifyBindingsApi;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.controller.ControllerState;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.bind.KeyMappingAccessor;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
@ -102,8 +103,8 @@ public class ControllerBindings<T extends ControllerState> {
register((ControllerBinding<T>) constructor.apply(this));
}
ControlifyClientEvents.CONTROLLER_STATE_UPDATED.register(this::onControllerUpdate);
ControlifyClientEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll());
ControlifyEvents.CONTROLLER_STATE_UPDATED.register(this::onControllerUpdate);
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> KeyMapping.releaseAll());
}
public ControllerBinding<T> register(ControllerBinding<T> binding) {
@ -179,13 +180,17 @@ public class ControllerBindings<T extends ControllerState> {
}
}
public static BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id) {
public static final class Api implements ControlifyBindingsApi {
public static final Api INSTANCE = new Api();
public BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id) {
CUSTOM_BINDS.put(id, bindings -> bindings.create(bind, id));
return controller -> controller.bindings().get(id);
}
public static BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id, KeyMapping override, BooleanSupplier toggleOverride) {
public BindingSupplier registerBind(GamepadBinds bind, ResourceLocation id, KeyMapping override, BooleanSupplier toggleOverride) {
CUSTOM_BINDS.put(id, bindings -> bindings.create(bind, id, override, toggleOverride));
return controller -> controller.bindings().get(id);
}
}
}

View File

@ -2,7 +2,7 @@ package dev.isxander.controlify.ingame;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.KeyboardInput;
@ -16,7 +16,7 @@ public class InGameInputHandler {
this.controller = controller;
this.minecraft = Minecraft.getInstance();
ControlifyClientEvents.INPUT_MODE_CHANGED.register(mode -> {
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> {
if (minecraft.player != null) {
minecraft.player.input = mode == InputMode.CONTROLLER
? new ControllerPlayerMovement(controller, minecraft.player)

View File

@ -1,5 +0,0 @@
package dev.isxander.controlify.ingame.guide;
public enum ActionLocation {
LEFT, RIGHT
}

View File

@ -1,9 +0,0 @@
package dev.isxander.controlify.ingame.guide;
public enum ActionPriority {
LOWEST,
LOW,
NORMAL,
HIGH,
HIGHEST
}

View File

@ -1,7 +0,0 @@
package dev.isxander.controlify.ingame.guide;
import dev.isxander.controlify.bindings.ControllerBinding;
public interface ButtonGuideRegistry {
void registerGuideAction(ControllerBinding<?> binding, ActionLocation location, GuideActionNameSupplier supplier);
}

View File

@ -1,5 +1,7 @@
package dev.isxander.controlify.ingame.guide;
import dev.isxander.controlify.api.buttonguide.ActionLocation;
import dev.isxander.controlify.api.buttonguide.ActionPriority;
import dev.isxander.controlify.bindings.ControllerBinding;
import net.minecraft.network.chat.Component;
import org.jetbrains.annotations.NotNull;

View File

@ -1,15 +0,0 @@
package dev.isxander.controlify.ingame.guide;
import dev.isxander.controlify.controller.Controller;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.chat.Component;
import net.minecraft.world.phys.HitResult;
import java.util.Optional;
@FunctionalInterface
public interface GuideActionNameSupplier {
Optional<Component> supply(Minecraft client, LocalPlayer player, ClientLevel level, HitResult hitResult, Controller<?, ?> controller);
}

View File

@ -1,9 +1,13 @@
package dev.isxander.controlify.ingame.guide;
import com.mojang.blaze3d.vertex.PoseStack;
import dev.isxander.controlify.api.buttonguide.ActionLocation;
import dev.isxander.controlify.api.buttonguide.ActionPriority;
import dev.isxander.controlify.api.buttonguide.ButtonGuideRegistry;
import dev.isxander.controlify.api.buttonguide.GuideActionNameSupplier;
import dev.isxander.controlify.bindings.ControllerBinding;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.multiplayer.ClientLevel;
@ -33,7 +37,7 @@ public class InGameButtonGuide implements ButtonGuideRegistry {
this.player = localPlayer;
registerDefaultActions();
ControlifyClientEvents.BUTTON_GUIDE_REGISTRY.invoker().onRegisterButtonGuide(controller.bindings(), this);
ControlifyEvents.BUTTON_GUIDE_REGISTRY.invoker().onRegisterButtonGuide(controller.bindings(), this);
}
public void renderHud(PoseStack poseStack, float tickDelta, int width, int height) {
@ -112,7 +116,12 @@ public class InGameButtonGuide implements ButtonGuideRegistry {
@Override
public void registerGuideAction(ControllerBinding<?> binding, ActionLocation location, GuideActionNameSupplier supplier) {
guidePredicates.add(new GuideActionSupplier(binding, location, supplier));
this.registerGuideAction(binding, location, ActionPriority.NORMAL, supplier);
}
@Override
public void registerGuideAction(ControllerBinding<?> binding, ActionLocation location, ActionPriority priority, GuideActionNameSupplier supplier) {
guidePredicates.add(new GuideActionSupplier(binding, location, priority, supplier));
}
private void registerDefaultActions() {
@ -232,10 +241,10 @@ public class InGameButtonGuide implements ButtonGuideRegistry {
}
}
private record GuideActionSupplier(ControllerBinding<?> binding, ActionLocation location, GuideActionNameSupplier nameSupplier) {
private record GuideActionSupplier(ControllerBinding<?> binding, ActionLocation location, ActionPriority priority, GuideActionNameSupplier nameSupplier) {
public Optional<GuideAction> supply(Minecraft client, LocalPlayer player, ClientLevel level, HitResult hitResult, Controller<?, ?> controller) {
return nameSupplier.supply(client, player, level, hitResult, controller)
.map(name -> new GuideAction(binding, name, location));
.map(name -> new GuideAction(binding, name, location, priority));
}
}
}

View File

@ -19,6 +19,6 @@ public class KeyboardHandlerMixin {
@Inject(method = "m_unngxkoe", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/KeyboardHandler;keyPress(JIIII)V"))
private void onKeyboardInput(long window, int i, int j, int k, int m, CallbackInfo ci) {
if (window == minecraft.getWindow().getWindow())
Controlify.instance().setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
Controlify.instance().setInputMode(InputMode.KEYBOARD_MOUSE);
}
}

View File

@ -19,20 +19,20 @@ public class MouseHandlerMixin {
@Inject(method = "m_sljgmtqm", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;onPress(JIII)V"))
private void onMouseClickInput(long window, int button, int action, int modifiers, CallbackInfo ci) {
if (window == minecraft.getWindow().getWindow())
Controlify.instance().setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
Controlify.instance().setInputMode(InputMode.KEYBOARD_MOUSE);
}
// m_swhlgdws is lambda for GLFW mouse move hook - do it outside of the `onMove` method due to fake inputs
@Inject(method = "m_swhlgdws", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;onMove(JDD)V"))
private void onMouseMoveInput(long window, double x, double y, CallbackInfo ci) {
if (window == minecraft.getWindow().getWindow())
Controlify.instance().setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
Controlify.instance().setInputMode(InputMode.KEYBOARD_MOUSE);
}
// m_qoshpwkl is lambda for GLFW mouse scroll hook - do it outside of the `onScroll` method due to fake inputs
@Inject(method = "m_qoshpwkl", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;onScroll(JDD)V"))
private void onMouseScrollInput(long window, double scrollDeltaX, double scrollDeltaY, CallbackInfo ci) {
if (window == minecraft.getWindow().getWindow())
Controlify.instance().setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
Controlify.instance().setInputMode(InputMode.KEYBOARD_MOUSE);
}
}

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.mixins.feature.virtualmouse.snapping;
import dev.isxander.controlify.virtualmouse.ISnapBehaviour;
import dev.isxander.controlify.virtualmouse.SnapPoint;
import dev.isxander.controlify.api.vmousesnapping.ISnapBehaviour;
import dev.isxander.controlify.api.vmousesnapping.SnapPoint;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;

View File

@ -1,6 +1,6 @@
package dev.isxander.controlify.mixins.feature.virtualmouse.snapping;
import dev.isxander.controlify.virtualmouse.SnapPoint;
import dev.isxander.controlify.api.vmousesnapping.SnapPoint;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.inventory.CreativeModeInventoryScreen;
import net.minecraft.network.chat.Component;

View File

@ -1,7 +1,7 @@
package dev.isxander.controlify.mixins.feature.virtualmouse.snapping;
import dev.isxander.controlify.virtualmouse.ISnapBehaviour;
import dev.isxander.controlify.virtualmouse.SnapPoint;
import dev.isxander.controlify.api.vmousesnapping.ISnapBehaviour;
import dev.isxander.controlify.api.vmousesnapping.SnapPoint;
import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.screens.Screen;

View File

@ -3,7 +3,7 @@ package dev.isxander.controlify.screenop;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.screenop.vanilla.ScreenAccessor;
import net.minecraft.client.gui.ComponentPath;
import net.minecraft.client.gui.components.events.GuiEventListener;
@ -20,7 +20,7 @@ public class ScreenProcessor<T extends Screen> {
public ScreenProcessor(T screen) {
this.screen = screen;
ControlifyClientEvents.VIRTUAL_MOUSE_TOGGLED.register(this::onVirtualMouseToggled);
ControlifyEvents.VIRTUAL_MOUSE_TOGGLED.register(this::onVirtualMouseToggled);
}
public void onControllerUpdate(Controller<?, ?> controller) {

View File

@ -4,6 +4,10 @@ import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.screenop.ComponentProcessor;
import dev.isxander.controlify.screenop.ScreenProcessor;
/**
* A component processor that handles incrementing and decrementing a slider.
* This uses {@link dev.isxander.controlify.bindings.ControllerBindings#CYCLE_OPT_FORWARD} and {@link dev.isxander.controlify.bindings.ControllerBindings#CYCLE_OPT_BACKWARD} to increment and decrement the slider.
*/
public abstract class AbstractSliderComponentProcessor implements ComponentProcessor {
private int ticksSinceIncrement = 0;
private boolean prevLeft, prevRight;

View File

@ -1,7 +0,0 @@
package dev.isxander.controlify.virtualmouse;
import java.util.Set;
public interface ISnapBehaviour {
Set<SnapPoint> getSnapPoints();
}

View File

@ -1,6 +0,0 @@
package dev.isxander.controlify.virtualmouse;
import org.joml.Vector2ic;
public record SnapPoint(Vector2ic position, int range) {
}

View File

@ -5,10 +5,12 @@ import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.datafixers.util.Pair;
import dev.isxander.controlify.Controlify;
import dev.isxander.controlify.InputMode;
import dev.isxander.controlify.api.vmousesnapping.ISnapBehaviour;
import dev.isxander.controlify.api.vmousesnapping.SnapPoint;
import dev.isxander.controlify.controller.Controller;
import dev.isxander.controlify.debug.DebugProperties;
import dev.isxander.controlify.screenop.ScreenProcessorProvider;
import dev.isxander.controlify.event.ControlifyClientEvents;
import dev.isxander.controlify.api.event.ControlifyEvents;
import dev.isxander.controlify.mixins.feature.virtualmouse.KeyboardHandlerAccessor;
import dev.isxander.controlify.mixins.feature.virtualmouse.MouseHandlerAccessor;
import net.minecraft.client.Minecraft;
@ -48,7 +50,7 @@ public class VirtualMouseHandler {
else
snapPoints = Set.of();
ControlifyClientEvents.INPUT_MODE_CHANGED.register(this::onInputModeChanged);
ControlifyEvents.INPUT_MODE_CHANGED.register(this::onInputModeChanged);
}
public void handleControllerInput(Controller<?, ?> controller) {
@ -240,7 +242,7 @@ public class VirtualMouseHandler {
}
setMousePosition();
ControlifyClientEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(true);
ControlifyEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(true);
}
public void disableVirtualMouse() {
@ -256,7 +258,7 @@ public class VirtualMouseHandler {
targetX = currentX = minecraft.mouseHandler.xpos();
targetY = currentY = minecraft.mouseHandler.ypos();
ControlifyClientEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(false);
ControlifyEvents.VIRTUAL_MOUSE_TOGGLED.invoker().onVirtualMouseToggled(false);
}
private void setMousePosition() {