mirror of
https://github.com/chylex/Better-Controls.git
synced 2025-05-31 22:34:04 +02:00
Avoid wobble sprinting when resuming sprinting after hitting an obstacle, by simulating holding sprint for multiple ticks
This commit is contained in:
parent
c0e9c92197
commit
c537e037b5
src/main
java/chylex/bettercontrols
resources
@ -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);
|
||||||
|
}
|
@ -6,11 +6,13 @@ import chylex.bettercontrols.input.ToggleTracker;
|
|||||||
import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
|
import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
|
||||||
import chylex.bettercontrols.mixin.AccessCameraFields;
|
import chylex.bettercontrols.mixin.AccessCameraFields;
|
||||||
import chylex.bettercontrols.mixin.AccessClientPlayerFields;
|
import chylex.bettercontrols.mixin.AccessClientPlayerFields;
|
||||||
|
import chylex.bettercontrols.mixin.AccessStickyKeyBindingStateGetter;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.input.KeyboardInput;
|
import net.minecraft.client.input.KeyboardInput;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
import net.minecraft.client.options.GameOptions;
|
import net.minecraft.client.options.GameOptions;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.function.BooleanSupplier;
|
||||||
|
|
||||||
public final class PlayerTicker{
|
public final class PlayerTicker{
|
||||||
private static PlayerTicker ticker = new PlayerTicker(null);
|
private static PlayerTicker ticker = new PlayerTicker(null);
|
||||||
@ -35,6 +37,7 @@ public final class PlayerTicker{
|
|||||||
|
|
||||||
private PlayerTicker(final ClientPlayerEntity player){
|
private PlayerTicker(final ClientPlayerEntity player){
|
||||||
this.ref = new WeakReference<>(player);
|
this.ref = new WeakReference<>(player);
|
||||||
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logic
|
// Logic
|
||||||
@ -46,13 +49,26 @@ public final class PlayerTicker{
|
|||||||
|
|
||||||
private boolean waitingForSprintKeyRelease = false;
|
private boolean waitingForSprintKeyRelease = false;
|
||||||
private boolean stopSprintingAfterReleasingSprintKey = false;
|
private boolean stopSprintingAfterReleasingSprintKey = false;
|
||||||
|
|
||||||
private boolean wasHittingObstacle = false;
|
private boolean wasHittingObstacle = false;
|
||||||
private boolean wasSprintingBeforeHittingObstacle = false;
|
private boolean wasSprintingBeforeHittingObstacle = false;
|
||||||
|
private int temporarySprintTimer = 0;
|
||||||
|
|
||||||
private boolean wasSneakingBeforeTouchingGround = false;
|
private boolean wasSneakingBeforeTouchingGround = false;
|
||||||
private boolean holdingSneakWhileTouchingGround = false;
|
private boolean holdingSneakWhileTouchingGround = false;
|
||||||
private int temporaryFlyOnGroundTimer = 0;
|
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){
|
public void atHead(final ClientPlayerEntity player){
|
||||||
if (FlightHelper.shouldFlyOnGround(player)){
|
if (FlightHelper.shouldFlyOnGround(player)){
|
||||||
player.setOnGround(false);
|
player.setOnGround(false);
|
||||||
@ -66,6 +82,21 @@ public final class PlayerTicker{
|
|||||||
final boolean wasSprintToggled = opts.sprintToggled;
|
final boolean wasSprintToggled = opts.sprintToggled;
|
||||||
final boolean isSprintToggled = toggleSprint.tick();
|
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){
|
if (isSprintToggled){
|
||||||
stopSprintingAfterReleasingSprintKey = false;
|
stopSprintingAfterReleasingSprintKey = false;
|
||||||
waitingForSprintKeyRelease = false;
|
waitingForSprintKeyRelease = false;
|
||||||
@ -123,7 +154,7 @@ public final class PlayerTicker{
|
|||||||
}
|
}
|
||||||
else if (wasSprintingBeforeHittingObstacle){
|
else if (wasSprintingBeforeHittingObstacle){
|
||||||
wasSprintingBeforeHittingObstacle = false;
|
wasSprintingBeforeHittingObstacle = false;
|
||||||
player.setSprinting(true);
|
temporarySprintTimer = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
// collision also stops when the player lets go of movement keys
|
// collision also stops when the player lets go of movement keys
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
"AccessControlsListKeyBinding",
|
"AccessControlsListKeyBinding",
|
||||||
"AccessKeyBindingFields",
|
"AccessKeyBindingFields",
|
||||||
"AccessScreenButtons",
|
"AccessScreenButtons",
|
||||||
|
"AccessStickyKeyBindingStateGetter",
|
||||||
"HookClientPlayerInputTick",
|
"HookClientPlayerInputTick",
|
||||||
"HookClientPlayerTick",
|
"HookClientPlayerTick",
|
||||||
"HookControlsListWidget",
|
"HookControlsListWidget",
|
||||||
|
Loading…
Reference in New Issue
Block a user