forked from Clones/Controlify
in-game input and start of keybind system
This commit is contained in:
@ -26,6 +26,7 @@ repositories {
|
|||||||
includeGroup("maven.modrinth")
|
includeGroup("maven.modrinth")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maven("https://jitpack.io")
|
||||||
}
|
}
|
||||||
|
|
||||||
val minecraftVersion = libs.versions.minecraft.get()
|
val minecraftVersion = libs.versions.minecraft.get()
|
||||||
@ -39,6 +40,10 @@ dependencies {
|
|||||||
modImplementation(libs.fabric.loader)
|
modImplementation(libs.fabric.loader)
|
||||||
|
|
||||||
modImplementation(libs.fabric.api)
|
modImplementation(libs.fabric.api)
|
||||||
|
|
||||||
|
implementation(libs.mixin.extras)
|
||||||
|
annotationProcessor(libs.mixin.extras)
|
||||||
|
include(libs.mixin.extras)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
@ -11,12 +11,14 @@ minecraft = "23w04a"
|
|||||||
quilt_mappings = "10"
|
quilt_mappings = "10"
|
||||||
fabric_loader = "0.14.13"
|
fabric_loader = "0.14.13"
|
||||||
fabric_api = "0.73.1+1.19.4"
|
fabric_api = "0.73.1+1.19.4"
|
||||||
|
mixin_extras = "0.2.0-beta.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
|
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
|
||||||
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
|
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
|
||||||
|
|
||||||
fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
|
fabric_api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
|
||||||
|
mixin_extras = { module = "com.github.llamalad7:mixinextras", version.ref = "mixin_extras" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
loom = { id = "fabric-loom", version.ref = "loom" }
|
loom = { id = "fabric-loom", version.ref = "loom" }
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package dev.isxander.controlify;
|
package dev.isxander.controlify;
|
||||||
|
|
||||||
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
|
import dev.isxander.controlify.compatibility.screen.ScreenProcessorProvider;
|
||||||
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 dev.isxander.controlify.controller.ControllerState;
|
||||||
|
import dev.isxander.controlify.event.ControlifyEvents;
|
||||||
|
import dev.isxander.controlify.ingame.InGameInputHandler;
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
@ -13,13 +13,14 @@ public class Controlify {
|
|||||||
private static Controlify instance = null;
|
private static Controlify instance = null;
|
||||||
|
|
||||||
private Controller currentController;
|
private Controller currentController;
|
||||||
|
private InGameInputHandler inGameInputHandler;
|
||||||
private InputMode currentInputMode;
|
private InputMode currentInputMode;
|
||||||
|
|
||||||
public void onInitializeInput() {
|
public void onInitializeInput() {
|
||||||
// find already connected controllers
|
// find already connected controllers
|
||||||
for (int i = 0; i < GLFW.GLFW_JOYSTICK_LAST; i++) {
|
for (int i = 0; i < GLFW.GLFW_JOYSTICK_LAST; i++) {
|
||||||
if (GLFW.glfwJoystickPresent(i)) {
|
if (GLFW.glfwJoystickPresent(i)) {
|
||||||
currentController = Controller.byId(i);
|
setCurrentController(Controller.byId(i));
|
||||||
System.out.println("Connected: " + currentController.name());
|
System.out.println("Connected: " + currentController.name());
|
||||||
this.setCurrentInputMode(InputMode.CONTROLLER);
|
this.setCurrentInputMode(InputMode.CONTROLLER);
|
||||||
}
|
}
|
||||||
@ -29,23 +30,21 @@ public class Controlify {
|
|||||||
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
GLFW.glfwSetJoystickCallback((jid, event) -> {
|
||||||
System.out.println("Event: " + event);
|
System.out.println("Event: " + event);
|
||||||
if (event == GLFW.GLFW_CONNECTED) {
|
if (event == GLFW.GLFW_CONNECTED) {
|
||||||
currentController = Controller.byId(jid);
|
setCurrentController(Controller.byId(jid));
|
||||||
System.out.println("Connected: " + currentController.name());
|
System.out.println("Connected: " + currentController.name());
|
||||||
this.setCurrentInputMode(InputMode.CONTROLLER);
|
this.setCurrentInputMode(InputMode.CONTROLLER);
|
||||||
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
} else if (event == GLFW.GLFW_DISCONNECTED) {
|
||||||
Controller.CONTROLLERS.remove(jid);
|
Controller.CONTROLLERS.remove(jid);
|
||||||
currentController = Controller.CONTROLLERS.values().stream().filter(Controller::connected).findFirst().orElse(null);
|
setCurrentController(Controller.CONTROLLERS.values().stream().filter(Controller::connected).findFirst().orElse(null));
|
||||||
System.out.println("Disconnected: " + jid);
|
System.out.println("Disconnected: " + jid);
|
||||||
this.setCurrentInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
|
this.setCurrentInputMode(currentController == null ? InputMode.KEYBOARD_MOUSE : InputMode.CONTROLLER);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ClientTickEvents.START_CLIENT_TICK.register(client -> {
|
ClientTickEvents.START_CLIENT_TICK.register(this::updateControllers);
|
||||||
updateControllers();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateControllers() {
|
public void updateControllers(Minecraft client) {
|
||||||
for (Controller controller : Controller.CONTROLLERS.values()) {
|
for (Controller controller : Controller.CONTROLLERS.values()) {
|
||||||
controller.updateState();
|
controller.updateState();
|
||||||
}
|
}
|
||||||
@ -55,8 +54,31 @@ public class Controlify {
|
|||||||
if (state.hasAnyInput())
|
if (state.hasAnyInput())
|
||||||
this.setCurrentInputMode(InputMode.CONTROLLER);
|
this.setCurrentInputMode(InputMode.CONTROLLER);
|
||||||
|
|
||||||
Minecraft client = Minecraft.getInstance();
|
if (currentController == null) {
|
||||||
if (client.screen != null && currentController != null) ScreenProcessorProvider.provide(client.screen).onControllerUpdate(currentController);
|
this.setCurrentInputMode(InputMode.KEYBOARD_MOUSE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client.screen != null) {
|
||||||
|
ScreenProcessorProvider.provide(client.screen).onControllerUpdate(currentController);
|
||||||
|
} else {
|
||||||
|
this.getInGameInputHandler().inputTick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Controller getCurrentController() {
|
||||||
|
return currentController;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentController(Controller controller) {
|
||||||
|
if (this.currentController == controller) return;
|
||||||
|
|
||||||
|
this.currentController = controller;
|
||||||
|
this.inGameInputHandler = new InGameInputHandler(controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
public InGameInputHandler getInGameInputHandler() {
|
||||||
|
return inGameInputHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputMode getCurrentInputMode() {
|
public InputMode getCurrentInputMode() {
|
||||||
@ -64,7 +86,10 @@ public class Controlify {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setCurrentInputMode(InputMode currentInputMode) {
|
public void setCurrentInputMode(InputMode currentInputMode) {
|
||||||
|
if (this.currentInputMode == currentInputMode) return;
|
||||||
|
|
||||||
this.currentInputMode = currentInputMode;
|
this.currentInputMode = currentInputMode;
|
||||||
|
ControlifyEvents.INPUT_MODE_CHANGED.invoker().onInputModeChanged(currentInputMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Controlify getInstance() {
|
public static Controlify getInstance() {
|
||||||
|
37
src/main/java/dev/isxander/controlify/bindings/Bind.java
Normal file
37
src/main/java/dev/isxander/controlify/bindings/Bind.java
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package dev.isxander.controlify.bindings;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.controller.ControllerState;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Bind {
|
||||||
|
boolean state(ControllerState controllerState);
|
||||||
|
|
||||||
|
Bind A_BUTTON = state -> state.buttons().a();
|
||||||
|
Bind B_BUTTON = state -> state.buttons().b();
|
||||||
|
Bind X_BUTTON = state -> state.buttons().x();
|
||||||
|
Bind Y_BUTTON = state -> state.buttons().y();
|
||||||
|
Bind LEFT_BUMPER = state -> state.buttons().leftBumper();
|
||||||
|
Bind RIGHT_BUMPER = state -> state.buttons().rightBumper();
|
||||||
|
Bind LEFT_STICK = state -> state.buttons().leftStick();
|
||||||
|
Bind RIGHT_STICK = state -> state.buttons().rightStick();
|
||||||
|
Bind START = state -> state.buttons().start();
|
||||||
|
Bind BACK = state -> state.buttons().back();
|
||||||
|
Bind LEFT_TRIGGER = leftTrigger(0.5f);
|
||||||
|
Bind RIGHT_TRIGGER = rightTrigger(0.5f);
|
||||||
|
|
||||||
|
Bind[] ALL = {
|
||||||
|
A_BUTTON, B_BUTTON, X_BUTTON, Y_BUTTON,
|
||||||
|
LEFT_BUMPER, RIGHT_BUMPER,
|
||||||
|
LEFT_STICK, RIGHT_STICK,
|
||||||
|
START, BACK,
|
||||||
|
LEFT_TRIGGER, RIGHT_TRIGGER
|
||||||
|
};
|
||||||
|
|
||||||
|
static Bind leftTrigger(float threshold) {
|
||||||
|
return state -> state.axes().leftTrigger() > threshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Bind rightTrigger(float threshold) {
|
||||||
|
return state -> state.axes().rightTrigger() > threshold;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package dev.isxander.controlify.bindings;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
public class ControllerBinding {
|
||||||
|
private final Controller controller;
|
||||||
|
private final Bind bind;
|
||||||
|
private final Component name, description;
|
||||||
|
|
||||||
|
public ControllerBinding(Controller controller, Bind defaultBind, String id, Component description) {
|
||||||
|
this.controller = controller;
|
||||||
|
this.bind = defaultBind;
|
||||||
|
this.name = Component.translatable("controlify.binding." + id);
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ControllerBinding(Controller controller, Bind defaultBind, String id) {
|
||||||
|
this(controller, defaultBind, id, Component.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean held() {
|
||||||
|
return bind.state(controller.state());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean justPressed() {
|
||||||
|
return held() && !bind.state(controller.prevState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean justReleased() {
|
||||||
|
return !held() && bind.state(controller.prevState());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component description() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package dev.isxander.controlify.bindings;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
|
||||||
|
public class ControllerBindings {
|
||||||
|
public final ControllerBinding JUMP, SNEAK, ATTACK, USE, SPRINT, NEXT_SLOT, PREV_SLOT;
|
||||||
|
public final ControllerBinding[] ALL;
|
||||||
|
|
||||||
|
public ControllerBindings(Controller controller) {
|
||||||
|
JUMP = new ControllerBinding(controller, Bind.A_BUTTON, "jump");
|
||||||
|
SNEAK = new ControllerBinding(controller, Bind.RIGHT_STICK, "sneak");
|
||||||
|
ATTACK = new ControllerBinding(controller, Bind.RIGHT_TRIGGER, "attack");
|
||||||
|
USE = new ControllerBinding(controller, Bind.LEFT_TRIGGER, "use");
|
||||||
|
SPRINT = new ControllerBinding(controller, Bind.LEFT_STICK, "sprint");
|
||||||
|
NEXT_SLOT = new ControllerBinding(controller, Bind.RIGHT_BUMPER, "next_slot");
|
||||||
|
PREV_SLOT = new ControllerBinding(controller, Bind.LEFT_BUMPER, "prev_slot");
|
||||||
|
|
||||||
|
ALL = new ControllerBinding[] {
|
||||||
|
JUMP, SNEAK, ATTACK, USE, SPRINT, NEXT_SLOT, PREV_SLOT
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
package dev.isxander.controlify.controller;
|
package dev.isxander.controlify.controller;
|
||||||
|
|
||||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
import dev.isxander.controlify.bindings.ControllerBindings;
|
||||||
|
import dev.isxander.controlify.event.ControlifyEvents;
|
||||||
import org.lwjgl.glfw.GLFW;
|
import org.lwjgl.glfw.GLFW;
|
||||||
import org.lwjgl.glfw.GLFWGamepadState;
|
import org.lwjgl.glfw.GLFWGamepadState;
|
||||||
|
|
||||||
@ -10,13 +11,17 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public final class Controller {
|
public final class Controller {
|
||||||
public static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
public static final Map<Integer, Controller> CONTROLLERS = new HashMap<>();
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
private final String guid;
|
private final String guid;
|
||||||
private final String name;
|
private final String name;
|
||||||
private final boolean gamepad;
|
private final boolean gamepad;
|
||||||
|
|
||||||
private ControllerState state = ControllerState.EMPTY;
|
private ControllerState state = ControllerState.EMPTY;
|
||||||
private ControllerState prevState = ControllerState.EMPTY;
|
private ControllerState prevState = ControllerState.EMPTY;
|
||||||
|
|
||||||
|
private final ControllerBindings bindings = new ControllerBindings(this);
|
||||||
|
|
||||||
public Controller(int id, String guid, String name, boolean gamepad) {
|
public Controller(int id, String guid, String name, boolean gamepad) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.guid = guid;
|
this.guid = guid;
|
||||||
@ -47,6 +52,12 @@ public final class Controller {
|
|||||||
.rightTriggerDeadZone(0.1f);
|
.rightTriggerDeadZone(0.1f);
|
||||||
ButtonState buttonState = ButtonState.fromController(this);
|
ButtonState buttonState = ButtonState.fromController(this);
|
||||||
state = new ControllerState(axesState, buttonState);
|
state = new ControllerState(axesState, buttonState);
|
||||||
|
|
||||||
|
ControlifyEvents.CONTROLLER_STATE_UPDATED.invoker().onControllerStateUpdate(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ControllerBindings bindings() {
|
||||||
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean connected() {
|
public boolean connected() {
|
||||||
@ -89,7 +100,7 @@ public final class Controller {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(id);
|
return Objects.hash(guid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package dev.isxander.controlify.event;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.InputMode;
|
||||||
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
import net.fabricmc.fabric.api.event.Event;
|
||||||
|
import net.fabricmc.fabric.api.event.EventFactory;
|
||||||
|
|
||||||
|
public class ControlifyEvents {
|
||||||
|
public static final Event<InputModeChanged> INPUT_MODE_CHANGED = EventFactory.createArrayBacked(InputModeChanged.class, callbacks -> mode -> {
|
||||||
|
for (InputModeChanged callback : callbacks) {
|
||||||
|
callback.onInputModeChanged(mode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static final Event<ControllerStateUpdate> CONTROLLER_STATE_UPDATED = EventFactory.createArrayBacked(ControllerStateUpdate.class, callbacks -> controller -> {
|
||||||
|
for (ControllerStateUpdate callback : callbacks) {
|
||||||
|
callback.onControllerStateUpdate(controller);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface InputModeChanged {
|
||||||
|
void onInputModeChanged(InputMode mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ControllerStateUpdate {
|
||||||
|
void onControllerStateUpdate(Controller controller);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
package dev.isxander.controlify.ingame;
|
||||||
|
|
||||||
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
import net.minecraft.client.player.Input;
|
||||||
|
|
||||||
|
public class ControllerPlayerMovement extends Input {
|
||||||
|
private final Controller controller;
|
||||||
|
|
||||||
|
public ControllerPlayerMovement(Controller controller) {
|
||||||
|
this.controller = controller;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick(boolean slowDown, float f) {
|
||||||
|
var axes = controller.state().axes();
|
||||||
|
|
||||||
|
this.up = axes.leftStickY() < 0;
|
||||||
|
this.down = axes.leftStickY() > 0;
|
||||||
|
this.left = axes.leftStickX() < 0;
|
||||||
|
this.right = axes.leftStickX() > 0;
|
||||||
|
this.leftImpulse = -axes.leftStickX();
|
||||||
|
this.forwardImpulse = -axes.leftStickY();
|
||||||
|
|
||||||
|
if (slowDown) {
|
||||||
|
this.leftImpulse *= f;
|
||||||
|
this.forwardImpulse *= f;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bindings = controller.bindings();
|
||||||
|
|
||||||
|
this.jumping = bindings.JUMP.held();
|
||||||
|
if (bindings.SNEAK.justPressed()) {
|
||||||
|
this.shiftKeyDown = !this.shiftKeyDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package dev.isxander.controlify.ingame;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.Blaze3D;
|
||||||
|
import dev.isxander.controlify.InputMode;
|
||||||
|
import dev.isxander.controlify.controller.Controller;
|
||||||
|
import dev.isxander.controlify.event.ControlifyEvents;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.player.KeyboardInput;
|
||||||
|
|
||||||
|
public class InGameInputHandler {
|
||||||
|
private final Controller controller;
|
||||||
|
private final Minecraft minecraft;
|
||||||
|
|
||||||
|
private double accumulatedDX, accumulatedDY;
|
||||||
|
private double deltaTime;
|
||||||
|
|
||||||
|
public InGameInputHandler(Controller controller) {
|
||||||
|
this.controller = controller;
|
||||||
|
this.minecraft = Minecraft.getInstance();
|
||||||
|
|
||||||
|
ControlifyEvents.INPUT_MODE_CHANGED.register(mode -> {
|
||||||
|
if (minecraft.player != null) {
|
||||||
|
minecraft.player.input = mode == InputMode.CONTROLLER
|
||||||
|
? new ControllerPlayerMovement(controller)
|
||||||
|
: new KeyboardInput(minecraft.options);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void inputTick() {
|
||||||
|
var axes = controller.state().axes();
|
||||||
|
if (minecraft.mouseHandler.isMouseGrabbed() && minecraft.isWindowActive()) {
|
||||||
|
accumulatedDX += axes.rightStickX();
|
||||||
|
accumulatedDY += axes.rightStickY();
|
||||||
|
}
|
||||||
|
|
||||||
|
processPlayerLook();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processPlayerLook() {
|
||||||
|
var time = Blaze3D.getTime();
|
||||||
|
var delta = time - deltaTime;
|
||||||
|
deltaTime = time;
|
||||||
|
|
||||||
|
var sensitivity = 1f * 8f + 2f;
|
||||||
|
var sensCubed = sensitivity * sensitivity * sensitivity;
|
||||||
|
|
||||||
|
var dx = accumulatedDX * delta;
|
||||||
|
var dy = accumulatedDY * delta;
|
||||||
|
accumulatedDX -= dx * 20; // 20 is how quickly the camera will slow down
|
||||||
|
accumulatedDY -= dy * 20;
|
||||||
|
|
||||||
|
if (minecraft.player != null)
|
||||||
|
minecraft.player.turn(dx * sensCubed, dy * sensCubed);
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,9 @@ import org.spongepowered.asm.mixin.Mixin;
|
|||||||
import org.spongepowered.asm.mixin.Shadow;
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
import org.spongepowered.asm.mixin.Unique;
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin to insert a custom {@link ComponentProcessor} into slider to support left/right movement without navigating to next component.
|
||||||
|
*/
|
||||||
@Mixin(AbstractSliderButton.class)
|
@Mixin(AbstractSliderButton.class)
|
||||||
public class AbstractSliderButtonMixin implements ComponentProcessorProvider {
|
public class AbstractSliderButtonMixin implements ComponentProcessorProvider {
|
||||||
@Shadow private boolean canChangeValue;
|
@Shadow private boolean canChangeValue;
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package dev.isxander.controlify.mixins;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||||
|
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||||
|
import dev.isxander.controlify.Controlify;
|
||||||
|
import dev.isxander.controlify.InputMode;
|
||||||
|
import dev.isxander.controlify.ingame.ControllerPlayerMovement;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.Options;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.client.player.Input;
|
||||||
|
import net.minecraft.client.player.KeyboardInput;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundLoginPacket;
|
||||||
|
import org.objectweb.asm.Opcodes;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Override input handling for main player.
|
||||||
|
*/
|
||||||
|
@Mixin(ClientPacketListener.class)
|
||||||
|
public class ClientPacketListenerMixin {
|
||||||
|
@Shadow @Final private Minecraft minecraft;
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
if (Controlify.getInstance().getCurrentInputMode() == InputMode.CONTROLLER && minecraft.player != null)
|
||||||
|
minecraft.player.input = new ControllerPlayerMovement(Controlify.getInstance().getCurrentController());
|
||||||
|
}
|
||||||
|
}
|
@ -13,4 +13,9 @@ public class MinecraftMixin {
|
|||||||
private void onInputInitialized(CallbackInfo ci) {
|
private void onInputInitialized(CallbackInfo ci) {
|
||||||
Controlify.getInstance().onInitializeInput();
|
Controlify.getInstance().onInitializeInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "runTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MouseHandler;turnPlayer()V"))
|
||||||
|
private void doPlayerLook(boolean tick, CallbackInfo ci) {
|
||||||
|
Controlify.getInstance().getInGameInputHandler().processPlayerLook();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"AbstractSliderButtonMixin",
|
"AbstractSliderButtonMixin",
|
||||||
|
"ClientPacketListenerMixin",
|
||||||
"KeyboardHandlerMixin",
|
"KeyboardHandlerMixin",
|
||||||
"MinecraftMixin",
|
"MinecraftMixin",
|
||||||
"MouseHandlerMixin",
|
"MouseHandlerMixin",
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
"license": "LGPL-3.0-or-later",
|
"license": "LGPL-3.0-or-later",
|
||||||
"environment": "client",
|
"environment": "client",
|
||||||
"entrypoints": {
|
"entrypoints": {
|
||||||
|
"preLaunch": [
|
||||||
|
"com.llamalad7.mixinextras.MixinExtrasBootstrap::init"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"controlify.mixins.json"
|
"controlify.mixins.json"
|
||||||
|
Reference in New Issue
Block a user