Эх сурвалжийг харах

Avoid wobble sprinting when resuming sprinting after hitting an obstacle, by simulating holding sprint for multiple ticks

chylex 4 жил өмнө
parent
commit
c537e037b5

+ 16 - 0
src/main/java/chylex/bettercontrols/mixin/AccessStickyKeyBindingStateGetter.java

@@ -0,0 +1,16 @@
+package chylex.bettercontrols.mixin;
+import net.minecraft.client.options.StickyKeyBinding;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Mutable;
+import org.spongepowered.asm.mixin.gen.Accessor;
+import java.util.function.BooleanSupplier;
+
+@Mixin(StickyKeyBinding.class)
+public interface AccessStickyKeyBindingStateGetter{
+	@Accessor
+	BooleanSupplier getToggleGetter();
+	
+	@Accessor
+	@Mutable
+	void setToggleGetter(final BooleanSupplier toggleGetter);
+}

+ 32 - 1
src/main/java/chylex/bettercontrols/player/PlayerTicker.java

@@ -6,11 +6,13 @@ import chylex.bettercontrols.input.ToggleTracker;
 import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
 import chylex.bettercontrols.mixin.AccessCameraFields;
 import chylex.bettercontrols.mixin.AccessClientPlayerFields;
+import chylex.bettercontrols.mixin.AccessStickyKeyBindingStateGetter;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.input.KeyboardInput;
 import net.minecraft.client.network.ClientPlayerEntity;
 import net.minecraft.client.options.GameOptions;
 import java.lang.ref.WeakReference;
+import java.util.function.BooleanSupplier;
 
 public final class PlayerTicker{
 	private static PlayerTicker ticker = new PlayerTicker(null);
@@ -35,6 +37,7 @@ public final class PlayerTicker{
 	
 	private PlayerTicker(final ClientPlayerEntity player){
 		this.ref = new WeakReference<>(player);
+		setup();
 	}
 	
 	// Logic
@@ -46,13 +49,26 @@ public final class PlayerTicker{
 	
 	private boolean waitingForSprintKeyRelease = false;
 	private boolean stopSprintingAfterReleasingSprintKey = false;
+	
 	private boolean wasHittingObstacle = false;
 	private boolean wasSprintingBeforeHittingObstacle = false;
+	private int temporarySprintTimer = 0;
 	
 	private boolean wasSneakingBeforeTouchingGround = false;
 	private boolean holdingSneakWhileTouchingGround = false;
 	private int temporaryFlyOnGroundTimer = 0;
 	
+	private void setup(){
+		final AccessStickyKeyBindingStateGetter sprint = (AccessStickyKeyBindingStateGetter)mc().options.keySprint;
+		BooleanSupplier getter = sprint.getToggleGetter();
+		
+		if (getter instanceof SprintPressGetter){
+			getter = ((SprintPressGetter)getter).getWrapped();
+		}
+		
+		sprint.setToggleGetter(new SprintPressGetter(getter, () -> temporarySprintTimer > 0));
+	}
+	
 	public void atHead(final ClientPlayerEntity player){
 		if (FlightHelper.shouldFlyOnGround(player)){
 			player.setOnGround(false);
@@ -66,6 +82,21 @@ public final class PlayerTicker{
 		final boolean wasSprintToggled = opts.sprintToggled;
 		final boolean isSprintToggled = toggleSprint.tick();
 		
+		if (temporarySprintTimer > 0){
+			stopSprintingAfterReleasingSprintKey = false;
+			waitingForSprintKeyRelease = false;
+			
+			final int nextTemporarySprintTimer = temporarySprintTimer - 1;
+			temporarySprintTimer = 0;
+			
+			if (!opts.keySprint.isPressed() && opts.keyForward.isPressed()){
+				temporarySprintTimer = nextTemporarySprintTimer;
+			}
+			else if (cfg().tapSprintKeyAgainToStopSprinting){
+				stopSprintingAfterReleasingSprintKey = true;
+			}
+		}
+		
 		if (isSprintToggled){
 			stopSprintingAfterReleasingSprintKey = false;
 			waitingForSprintKeyRelease = false;
@@ -123,7 +154,7 @@ public final class PlayerTicker{
 				}
 				else if (wasSprintingBeforeHittingObstacle){
 					wasSprintingBeforeHittingObstacle = false;
-					player.setSprinting(true);
+					temporarySprintTimer = 10;
 				}
 				
 				// collision also stops when the player lets go of movement keys

+ 21 - 0
src/main/java/chylex/bettercontrols/player/SprintPressGetter.java

@@ -0,0 +1,21 @@
+package chylex.bettercontrols.player;
+import java.util.function.BooleanSupplier;
+
+final class SprintPressGetter implements BooleanSupplier{
+	private final BooleanSupplier wrapped;
+	private final BooleanSupplier or;
+	
+	public SprintPressGetter(final BooleanSupplier wrapped, final BooleanSupplier or){
+		this.wrapped = wrapped;
+		this.or = or;
+	}
+	
+	public BooleanSupplier getWrapped(){
+		return wrapped;
+	}
+	
+	@Override
+	public boolean getAsBoolean(){
+		return wrapped.getAsBoolean() || or.getAsBoolean();
+	}
+}

+ 1 - 0
src/main/resources/bettercontrols.mixins.json

@@ -10,6 +10,7 @@
     "AccessControlsListKeyBinding",
     "AccessKeyBindingFields",
     "AccessScreenButtons",
+    "AccessStickyKeyBindingStateGetter",
     "HookClientPlayerInputTick",
     "HookClientPlayerTick",
     "HookControlsListWidget",