From f7cf37f201fe1295892b9cd428fd5f7f5d6488d5 Mon Sep 17 00:00:00 2001 From: isXander Date: Thu, 15 Jun 2023 18:16:59 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9E=95=20Support=20for=20analog=20boat=20mov?= =?UTF-8?q?ement.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fixes/boatfix/AnalogBoatInput.java | 5 ++ .../feature/fixes/boatfix/BoatMixin.java | 69 +++++++++++++++++++ .../fixes/boatfix/LocalPlayerMixin.java | 37 ++++++++++ .../assets/controlify/lang/en_us.json | 2 +- src/main/resources/controlify.mixins.json | 2 + 5 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 src/main/java/dev/isxander/controlify/fixes/boatfix/AnalogBoatInput.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/BoatMixin.java create mode 100644 src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/LocalPlayerMixin.java diff --git a/src/main/java/dev/isxander/controlify/fixes/boatfix/AnalogBoatInput.java b/src/main/java/dev/isxander/controlify/fixes/boatfix/AnalogBoatInput.java new file mode 100644 index 0000000..66c9834 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/fixes/boatfix/AnalogBoatInput.java @@ -0,0 +1,5 @@ +package dev.isxander.controlify.fixes.boatfix; + +public interface AnalogBoatInput { + void setAnalogInput(float forward, float right); +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/BoatMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/BoatMixin.java new file mode 100644 index 0000000..06ffb39 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/BoatMixin.java @@ -0,0 +1,69 @@ +package dev.isxander.controlify.mixins.feature.fixes.boatfix; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import dev.isxander.controlify.fixes.boatfix.AnalogBoatInput; +import net.minecraft.world.entity.vehicle.Boat; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Boat.class) +public abstract class BoatMixin implements AnalogBoatInput { + @Shadow private float deltaRotation; + @Shadow private boolean inputLeft; + @Shadow private boolean inputRight; + @Shadow private boolean inputUp; + @Shadow private boolean inputDown; + + @Unique private float analogForward; + @Unique private float analogRight; + @Unique private boolean usingAnalogInput; + + @Inject(method = "controlBoat", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;getYRot()F", ordinal = 0)) + private void rotateBoatAnalog(CallbackInfo ci) { + if (usingAnalogInput) + this.deltaRotation += analogRight; + } + + @ModifyVariable(method = "controlBoat", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;setYRot(F)V", shift = At.Shift.AFTER), ordinal = 0) + private float forwardBoatAnalog(float forwardVelocity) { + if (!usingAnalogInput) + return forwardVelocity; + + float velocity = analogForward > 0 ? analogForward * 0.04f : analogForward * 0.005f; + return forwardVelocity + velocity; + } + + @ModifyExpressionValue(method = "controlBoat", at = { + @At(value = "FIELD", target = "Lnet/minecraft/world/entity/vehicle/Boat;inputLeft:Z", opcode = Opcodes.GETFIELD, ordinal = 0), + @At(value = "FIELD", target = "Lnet/minecraft/world/entity/vehicle/Boat;inputRight:Z", opcode = Opcodes.GETFIELD, ordinal = 0), + @At(value = "FIELD", target = "Lnet/minecraft/world/entity/vehicle/Boat;inputUp:Z", opcode = Opcodes.GETFIELD, ordinal = 1), + @At(value = "FIELD", target = "Lnet/minecraft/world/entity/vehicle/Boat;inputDown:Z", opcode = Opcodes.GETFIELD, ordinal = 1) + }) + private boolean shouldDoDigitalInput(boolean original) { + return !usingAnalogInput && original; + } + + @Override + public void setAnalogInput(float forward, float right) { + this.usingAnalogInput = true; + + this.analogForward = forward; + this.analogRight = right; + + this.inputLeft = right < 0; + this.inputRight = right > 0; + this.inputUp = forward > 0; + this.inputDown = forward < 0; + } + + @Inject(method = "setInput", at = @At("HEAD")) + private void onUseDigitalInput(boolean pressingLeft, boolean pressingRight, boolean pressingForward, boolean pressingBack, CallbackInfo ci) { + this.usingAnalogInput = false; + } +} diff --git a/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/LocalPlayerMixin.java b/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/LocalPlayerMixin.java new file mode 100644 index 0000000..f669ac5 --- /dev/null +++ b/src/main/java/dev/isxander/controlify/mixins/feature/fixes/boatfix/LocalPlayerMixin.java @@ -0,0 +1,37 @@ +package dev.isxander.controlify.mixins.feature.fixes.boatfix; + +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.api.ControlifyApi; +import dev.isxander.controlify.controller.Controller; +import dev.isxander.controlify.fixes.boatfix.AnalogBoatInput; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.vehicle.Boat; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.Optional; + +@Mixin(LocalPlayer.class) +public class LocalPlayerMixin { + @WrapOperation(method = "rideTick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/vehicle/Boat;setInput(ZZZZ)V")) + private void useAnalogInput(Boat boat, boolean pressingLeft, boolean pressingRight, boolean pressingForward, boolean pressingBack, Operation original) { + if (ControlifyApi.get().currentInputMode() == InputMode.CONTROLLER && !Controlify.instance().config().globalSettings().keyboardMovement) { + Optional> controllerOpt = ControlifyApi.get().getCurrentController(); + if (controllerOpt.isPresent()) { + var controller = controllerOpt.get(); + + ((AnalogBoatInput) boat).setAnalogInput( + controller.bindings().WALK_FORWARD.state() - controller.bindings().WALK_BACKWARD.state(), + controller.bindings().WALK_RIGHT.state() - controller.bindings().WALK_LEFT.state() + ); + + return; + } + } + + original.call(boat, pressingLeft, pressingRight, pressingForward, pressingBack); + } +} diff --git a/src/main/resources/assets/controlify/lang/en_us.json b/src/main/resources/assets/controlify/lang/en_us.json index b116948..10ec24a 100644 --- a/src/main/resources/assets/controlify/lang/en_us.json +++ b/src/main/resources/assets/controlify/lang/en_us.json @@ -27,7 +27,7 @@ "controlify.gui.out_of_focus_input": "Out of Focus Input", "controlify.gui.out_of_focus_input.tooltip": "If enabled, Controlify will still receive input even if the game window is not focused.", "controlify.gui.keyboard_movement": "Keyboard-like Movement", - "controlify.gui.keyboard_movement.tooltip": "Makes movement either on or off rather than being smooth with a thumbstick, this may help in cases where server anti-cheats are harsh.", + "controlify.gui.keyboard_movement.tooltip": "Emulates keyboard WASD when using analog inputs like a thumbstick. This also applies to boat handling. This may be required on servers with harsh anti-cheats.", "controlify.gui.open_issue_tracker": "Open Issue Tracker", "controlify.gui.battery_level": "Your controller battery is currently %s.", diff --git a/src/main/resources/controlify.mixins.json b/src/main/resources/controlify.mixins.json index 55c00f5..737cf4a 100644 --- a/src/main/resources/controlify.mixins.json +++ b/src/main/resources/controlify.mixins.json @@ -12,6 +12,7 @@ "compat.sodium.SliderControlElementMixin", "compat.sodium.TickBoxControlElementMixin", "core.GLXMixin", + "feature.fixes.boatfix.BoatMixin", "feature.rumble.explosion.LightningBoltMixin", "feature.rumble.fishing.FishingHookMixin", "feature.rumble.itembreak.LivingEntityMixin", @@ -38,6 +39,7 @@ "feature.bind.ToggleKeyMappingAccessor", "feature.chatkbheight.ChatComponentMixin", "feature.chatkbheight.ChatScreenMixin", + "feature.fixes.boatfix.LocalPlayerMixin", "feature.guide.ingame.ClientPacketListenerMixin", "feature.guide.ingame.GuiMixin", "feature.guide.screen.AbstractButtonMixin",