diff --git a/src/main/java/com/alrex/parcool/ParCool.java b/src/main/java/com/alrex/parcool/ParCool.java index a6e94f41..2454cfad 100644 --- a/src/main/java/com/alrex/parcool/ParCool.java +++ b/src/main/java/com/alrex/parcool/ParCool.java @@ -5,6 +5,7 @@ import com.alrex.parcool.api.SoundEvents; import com.alrex.parcool.client.hud.HUDRegistry; import com.alrex.parcool.client.input.KeyBindings; +import com.alrex.parcool.client.input.KeyRecorder; import com.alrex.parcool.client.renderer.Renderers; import com.alrex.parcool.common.attachment.Attachments; import com.alrex.parcool.common.attachment.ClientAttachments; @@ -24,6 +25,7 @@ import com.alrex.parcool.server.command.CommandRegistry; import com.alrex.parcool.server.limitation.Limitations; import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModLoadingContext; @@ -76,6 +78,7 @@ public ParCool(ModContainer container) { NeoForge.EVENT_BUS.addListener(this::registerCommand); NeoForge.EVENT_BUS.addListener(Limitations::init); NeoForge.EVENT_BUS.addListener(Limitations::save); + NeoForge.EVENT_BUS.addListener(EventPriority.LOW, KeyRecorder::onInputs); container.registerConfig(ModConfig.Type.SERVER, ParCoolConfig.Server.getConfigSpec()); container.registerConfig(ModConfig.Type.CLIENT, ParCoolConfig.Client.getConfigSpec()); diff --git a/src/main/java/com/alrex/parcool/client/input/KeyRecorder.java b/src/main/java/com/alrex/parcool/client/input/KeyRecorder.java index b48efcb4..ad7777a5 100644 --- a/src/main/java/com/alrex/parcool/client/input/KeyRecorder.java +++ b/src/main/java/com/alrex/parcool/client/input/KeyRecorder.java @@ -1,14 +1,21 @@ package com.alrex.parcool.client.input; import net.minecraft.client.KeyMapping; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.Input; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.phys.Vec3; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.client.event.ClientTickEvent; +import net.neoforged.neoforge.client.event.MovementInputUpdateEvent; import javax.annotation.Nullable; +import com.alrex.parcool.utilities.CameraUtil; +import com.alrex.parcool.utilities.VectorUtil; + @OnlyIn(Dist.CLIENT) public class KeyRecorder { public static final KeyState keyForward = new KeyState(); @@ -27,8 +34,9 @@ public class KeyRecorder { public static final KeyState keyWallJump = new KeyState(); public static final KeyState keyQuickTurn = new KeyState(); public static final KeyState keyFlipping = new KeyState(); - public static final KeyState keyBindGrabWall = new KeyState(); - public static Vec3 lastDirection = null; + public static final KeyState keyBindGrabWall = new KeyState(); + private static Vec3 keyboardDirection = null; + private static Vec3 lastDirection = null; @SubscribeEvent public static void onClientTick(ClientTickEvent.Post event) { @@ -49,12 +57,13 @@ public static void onClientTick(ClientTickEvent.Post event) { record(KeyBindings.getKeyQuickTurn(), keyQuickTurn); record(KeyBindings.getKeyFlipping(), keyFlipping); record(KeyBindings.getKeyGrabWall(), keyBindGrabWall); - recordMovingVector(KeyBindings.isAnyMovingKeyDown()); } @Nullable public static Vec3 getLastMoveVector() { - return lastDirection; + Vec3 vector = lastDirection; + if (vector == null) return null; + return CameraUtil.alignVectorToCamera(vector); } private static void record(Boolean isDown, KeyState state) { @@ -77,8 +86,12 @@ private static void record(KeyMapping keyBinding, KeyState state) { record(keyBinding.isDown(), state); } - private static void recordMovingVector(boolean isMoving) { - if (isMoving) lastDirection = KeyBindings.getCurrentMoveVector(); + public static void recordKeyboardMovingVector(Input moving) { + var vector = moving.getMoveVector(); + if (!VectorUtil.isZero(vector)) { + var newDirection = new Vec3(vector.x, 0, vector.y); + keyboardDirection = newDirection; + } } public static class KeyState { @@ -113,4 +126,19 @@ public int getPreviousTickNotKeyDown() { return previousTickNotKeyDown; } } + + public static void onInputs(MovementInputUpdateEvent event) { + LocalPlayer player = Minecraft.getInstance().player; + if (player == null) return; + if (keyboardDirection != null) { + lastDirection = keyboardDirection; + keyboardDirection = null; + return; + } + var vector = player.input.getMoveVector(); + if (!VectorUtil.isZero(vector)) { + var newDirection = new Vec3(vector.x, 0, vector.y); + lastDirection = newDirection; + } + } } diff --git a/src/main/java/com/alrex/parcool/common/action/impl/Dodge.java b/src/main/java/com/alrex/parcool/common/action/impl/Dodge.java index f467c4a0..36133512 100644 --- a/src/main/java/com/alrex/parcool/common/action/impl/Dodge.java +++ b/src/main/java/com/alrex/parcool/common/action/impl/Dodge.java @@ -12,6 +12,8 @@ import com.alrex.parcool.common.info.ActionInfo; import com.alrex.parcool.config.ParCoolConfig; import com.alrex.parcool.extern.AdditionalMods; +import com.alrex.parcool.utilities.CameraUtil; +import com.alrex.parcool.utilities.EntityUtil; import com.alrex.parcool.utilities.VectorUtil; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -127,7 +129,6 @@ public double getSpeedModifier(ActionInfo info) { public boolean canStart(Player player, Parkourability parkourability, ByteBuffer startInfo) { boolean enabledDoubleTap = ParCoolConfig.Client.Booleans.EnableDoubleTappingForDodge.get(); DodgeDirection direction = null; - var dodgeVec = KeyRecorder.getLastMoveVector(); if (enabledDoubleTap) { if (KeyRecorder.keyBack.isDoubleTapped()) direction = DodgeDirection.Back; if (KeyRecorder.keyLeft.isDoubleTapped()) direction = DodgeDirection.Left; @@ -138,14 +139,15 @@ public boolean canStart(Player player, Parkourability parkourability, ByteBuffer if (KeyBindings.isKeyForwardDown()) direction = DodgeDirection.Front; if (KeyBindings.isKeyLeftDown()) direction = DodgeDirection.Left; if (KeyBindings.isKeyRightDown()) direction = DodgeDirection.Right; - if (direction != null) dodgeVec = KeyBindings.getCurrentMoveVector(); } - if (direction == null || dodgeVec == null) return false; + if (direction == null) return false; + var dodgeVec = KeyRecorder.getLastMoveVector(); + if (dodgeVec == null) return false; direction = AdditionalMods.betterThirdPerson().handleCustomCameraRotationForDodge(direction); direction = AdditionalMods.shoulderSurfing().handleCustomCameraRotationForDodge(direction); startInfo.putInt(direction.ordinal()); - startInfo.putDouble(dodgeVec.x); - startInfo.putDouble(dodgeVec.z); + startInfo.putDouble(dodgeVec.x()); + startInfo.putDouble(dodgeVec.z()); return ((parkourability.getAdditionalProperties().getLandingTick() > 5 || parkourability.getAdditionalProperties().getPreviousNotLandingTick() < 2) && player.onGround() && !isInSuccessiveCoolDown(parkourability.getActionInfo()) @@ -176,8 +178,8 @@ public boolean canContinue(Player player, Parkourability parkourability) { @Override public void onStartInLocalClient(Player player, Parkourability parkourability, ByteBuffer startData) { dodgeDirection = DodgeDirection.values()[startData.getInt()]; - var dodgeVec = new Vec3(startData.getDouble(), 0, startData.getDouble()); coolTime = getMaxCoolTime(parkourability.getActionInfo()); + var dodgeVec = new Vec3(startData.getDouble(), 0, startData.getDouble()); if (successivelyCount < getMaxSuccessiveDodge(parkourability.getActionInfo())) { successivelyCount++; } @@ -187,11 +189,8 @@ public void onStartInLocalClient(Player player, Parkourability parkourability, B successivelyCoolTick = getSuccessiveCoolTime(parkourability.getActionInfo()); if (!player.onGround()) return; - var cameraEntity = Minecraft.getInstance().getCameraEntity(); - var cameraYRot = cameraEntity != null ? cameraEntity.getYRot() : 0; - dodgeVec = VectorUtil.rotateYDegrees(dodgeVec, cameraYRot); dodgeVec = dodgeVec.scale(0.9 * getSpeedModifier(parkourability.getActionInfo())); - if (AdditionalMods.isCameraDecoupled()) player.setYRot(VectorUtil.toYaw(dodgeVec)); + if (CameraUtil.isCameraDecoupled()) player.setYRot(VectorUtil.toYaw(dodgeVec)); player.setDeltaMovement(dodgeVec); Animation animation = Animation.get(player); diff --git a/src/main/java/com/alrex/parcool/extern/AdditionalMods.java b/src/main/java/com/alrex/parcool/extern/AdditionalMods.java index 4a65d661..22c8f974 100644 --- a/src/main/java/com/alrex/parcool/extern/AdditionalMods.java +++ b/src/main/java/com/alrex/parcool/extern/AdditionalMods.java @@ -2,7 +2,6 @@ import com.alrex.parcool.extern.betterthirdperson.BetterThirdPersonManager; import com.alrex.parcool.extern.shouldersurfing.ShoulderSurfingManager; - import java.util.Arrays; import java.util.function.Supplier; diff --git a/src/main/java/com/alrex/parcool/extern/betterthirdperson/BetterThirdPersonManager.java b/src/main/java/com/alrex/parcool/extern/betterthirdperson/BetterThirdPersonManager.java index 253992ff..72f8513c 100644 --- a/src/main/java/com/alrex/parcool/extern/betterthirdperson/BetterThirdPersonManager.java +++ b/src/main/java/com/alrex/parcool/extern/betterthirdperson/BetterThirdPersonManager.java @@ -19,4 +19,9 @@ public boolean isCameraDecoupled() { && !Minecraft.getInstance().options.getCameraType().isFirstPerson() && BetterThirdPerson.getCameraManager().hasCustomCamera(); } + + public Float getCameraYaw() { + if (!isCameraDecoupled()) return null; + return BetterThirdPerson.getCameraManager().getCustomCamera().getYaw(); + } } diff --git a/src/main/java/com/alrex/parcool/extern/shouldersurfing/ShoulderSurfingManager.java b/src/main/java/com/alrex/parcool/extern/shouldersurfing/ShoulderSurfingManager.java index c031257b..70e4b3da 100644 --- a/src/main/java/com/alrex/parcool/extern/shouldersurfing/ShoulderSurfingManager.java +++ b/src/main/java/com/alrex/parcool/extern/shouldersurfing/ShoulderSurfingManager.java @@ -21,4 +21,9 @@ public Boolean isCameraDecoupled() { && ShoulderSurfing.getInstance().isShoulderSurfing() && ShoulderSurfing.getInstance().isCameraDecoupled(); } + + public Float getCameraYaw() { + if (!isCameraDecoupled()) return null; + return ShoulderSurfing.getInstance().getCamera().getYRot(); + } } diff --git a/src/main/java/com/alrex/parcool/mixin/client/MovementInputMixin.java b/src/main/java/com/alrex/parcool/mixin/client/MovementInputMixin.java new file mode 100644 index 00000000..851d1873 --- /dev/null +++ b/src/main/java/com/alrex/parcool/mixin/client/MovementInputMixin.java @@ -0,0 +1,23 @@ +package com.alrex.parcool.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.At; +import com.alrex.parcool.client.input.KeyRecorder; +import net.minecraft.client.player.KeyboardInput; + +@Mixin({KeyboardInput.class}) +public class MovementInputMixin { + @Inject( + method = "tick", + at = @At( + value = "FIELD", + target = "Lnet/minecraft/client/player/KeyboardInput;shiftKeyDown:Z", + shift = At.Shift.AFTER // Execute after the field assignment + ) + ) + public void tickHook(boolean moveSlowly, float sneakingSpeedMultiplier, CallbackInfo ci) { + KeyRecorder.recordKeyboardMovingVector((KeyboardInput)(Object)this); + } +} \ No newline at end of file diff --git a/src/main/java/com/alrex/parcool/utilities/CameraUtil.java b/src/main/java/com/alrex/parcool/utilities/CameraUtil.java new file mode 100644 index 00000000..bb117c3d --- /dev/null +++ b/src/main/java/com/alrex/parcool/utilities/CameraUtil.java @@ -0,0 +1,28 @@ +package com.alrex.parcool.utilities; + +import javax.annotation.Nullable; +import com.alrex.parcool.extern.AdditionalMods; +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; + +public class CameraUtil { + public static boolean isCameraDecoupled() { + return AdditionalMods.shoulderSurfing().isCameraDecoupled() || AdditionalMods.betterThirdPerson().isCameraDecoupled(); + } + + public static float getCameraYaw() { + @Nullable Float yaw = AdditionalMods.shoulderSurfing().getCameraYaw(); + if (yaw != null) return yaw; + yaw = AdditionalMods.betterThirdPerson().getCameraYaw(); + if (yaw != null) return yaw; + return Minecraft.getInstance().cameraEntity.getYRot(); + } + + public static Vec3 alignVectorToCamera(Vec3 vector) { + if (vector == null) return null; + Minecraft mc = Minecraft.getInstance(); + if (mc.player == null) return vector; + Float cameraYaw = getCameraYaw(); + return VectorUtil.rotateYDegrees(vector, cameraYaw); + } +} diff --git a/src/main/resources/parcool.mixins.json b/src/main/resources/parcool.mixins.json index 260f7de1..052239c0 100644 --- a/src/main/resources/parcool.mixins.json +++ b/src/main/resources/parcool.mixins.json @@ -9,7 +9,8 @@ "client.LocalPlayerMixin", "client.OptionsMixin", "client.PlayerModelMixin", - "client.PlayerRendererMixin" + "client.PlayerRendererMixin", + "client.MovementInputMixin" ], "injectors": { "defaultRequire": 1