diff --git a/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java b/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java index d7bab42..05f0330 100644 --- a/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java +++ b/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java @@ -11,6 +11,7 @@ public final class BetterControlsConfig{ public boolean doubleTapForwardToSprint = true; + public boolean flyOnGroundInCreative = false; public float flightSpeedMpCreativeDefault = 1F; public float flightSpeedMpCreativeSprinting = 2F; public float flightSpeedMpSpectatorDefault = 1F; diff --git a/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java b/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java index b1a8c83..151c96b 100644 --- a/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java +++ b/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java @@ -32,6 +32,7 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js Json.setBool(obj, "Sprint.DoubleTapForward", cfg.doubleTapForwardToSprint); + Json.setBool(obj, "Flight.FlyOnGround.Creative", cfg.flyOnGroundInCreative); Json.setFloat(obj, "Flight.SpeedMp.Creative.Default", cfg.flightSpeedMpCreativeDefault); Json.setFloat(obj, "Flight.SpeedMp.Creative.Sprinting", cfg.flightSpeedMpCreativeSprinting); Json.setFloat(obj, "Flight.SpeedMp.Spectator.Default", cfg.flightSpeedMpSpectatorDefault); @@ -47,6 +48,7 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js cfg.doubleTapForwardToSprint = Json.getBool(obj, "Sprint.DoubleTapForward", cfg.doubleTapForwardToSprint); + cfg.flyOnGroundInCreative = Json.getBool(obj, "Flight.FlyOnGround.Creative", cfg.flyOnGroundInCreative); cfg.flightSpeedMpCreativeDefault = Json.getFloat(obj, "Flight.SpeedMp.Creative.Default", cfg.flightSpeedMpCreativeDefault); cfg.flightSpeedMpCreativeSprinting = Json.getFloat(obj, "Flight.SpeedMp.Creative.Sprinting", cfg.flightSpeedMpCreativeSprinting); cfg.flightSpeedMpSpectatorDefault = Json.getFloat(obj, "Flight.SpeedMp.Spectator.Default", cfg.flightSpeedMpSpectatorDefault); diff --git a/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java b/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java index a0231d9..a337c23 100644 --- a/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java +++ b/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java @@ -63,6 +63,11 @@ public class BetterControlsScreen extends GameOptionsScreen{ new Option<>(Float.valueOf(8.00F), Text.of("8x")) ); + generateLeftSideText(y, elements, Text.of("Fly On Ground (Creative Mode)")); + elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.flyOnGroundInCreative, value -> cfg.flyOnGroundInCreative = value)); + + y += ROW_HEIGHT * 4 / 3; + generateLeftSideText(y, elements, Text.of("Speed Multiplier (Creative)")); elements.add(new DiscreteValueSliderWidget<>(col2(1), y, COL2_W, flightSpeedOptions, cfg.flightSpeedMpCreativeDefault, value -> cfg.flightSpeedMpCreativeDefault = value)); diff --git a/src/main/java/chylex/bettercontrols/mixin/HookClientPlayerTick.java b/src/main/java/chylex/bettercontrols/mixin/HookClientPlayerTick.java index faf2e62..998132b 100644 --- a/src/main/java/chylex/bettercontrols/mixin/HookClientPlayerTick.java +++ b/src/main/java/chylex/bettercontrols/mixin/HookClientPlayerTick.java @@ -27,4 +27,10 @@ public abstract class HookClientPlayerTick extends AbstractClientPlayerEntity{ final ClientPlayerEntity player = (ClientPlayerEntity)(Object)this; PlayerTicker.get(player).afterInputTick(player); } + + @Inject(method = "tickMovement()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/AbstractClientPlayerEntity;tickMovement()V", ordinal = 0, shift = AFTER)) + private void afterSuperCall(final CallbackInfo info){ + final ClientPlayerEntity player = (ClientPlayerEntity)(Object)this; + PlayerTicker.get(player).afterSuperCall(player); + } } diff --git a/src/main/java/chylex/bettercontrols/player/FlightHelper.java b/src/main/java/chylex/bettercontrols/player/FlightHelper.java index d3e38d2..8324a68 100644 --- a/src/main/java/chylex/bettercontrols/player/FlightHelper.java +++ b/src/main/java/chylex/bettercontrols/player/FlightHelper.java @@ -13,6 +13,10 @@ final class FlightHelper{ return BetterControlsMod.config; } + static boolean shouldFlyOnGround(final ClientPlayerEntity player){ + return cfg().flyOnGroundInCreative && player.isCreative() && player.abilities.flying; + } + static float getFlightSpeed(final ClientPlayerEntity player){ if (player.isCreative()){ if (player.isSprinting()){ diff --git a/src/main/java/chylex/bettercontrols/player/PlayerTicker.java b/src/main/java/chylex/bettercontrols/player/PlayerTicker.java index 3556287..f17f024 100644 --- a/src/main/java/chylex/bettercontrols/player/PlayerTicker.java +++ b/src/main/java/chylex/bettercontrols/player/PlayerTicker.java @@ -33,7 +33,14 @@ public final class PlayerTicker{ // Logic + private boolean wasSneakingBeforeTouchingGround = false; + private boolean holdingSneakWhileTouchingGround = false; + public void atHead(final ClientPlayerEntity player){ + if (FlightHelper.shouldFlyOnGround(player)){ + player.setOnGround(false); + } + if (!cfg().doubleTapForwardToSprint){ ((AccessClientPlayerFields)player).setTicksLeftToDoubleTapSprint(0); } @@ -46,4 +53,44 @@ public final class PlayerTicker{ player.abilities.setFlySpeed(flightSpeed); } } + + public void afterSuperCall(final ClientPlayerEntity player){ + if (FlightHelper.shouldFlyOnGround(player)){ + final boolean isSneaking = player.isSneaking(); + final boolean isOnGround = player.isOnGround(); + + if (!isSneaking){ + wasSneakingBeforeTouchingGround = false; + } + else if (!isOnGround){ + wasSneakingBeforeTouchingGround = true; + } + + if (!isOnGround){ + holdingSneakWhileTouchingGround = false; + } + else{ + boolean cancelLanding = true; + + if (!wasSneakingBeforeTouchingGround){ + if (isSneaking){ + holdingSneakWhileTouchingGround = true; + } + else if (holdingSneakWhileTouchingGround){ + player.abilities.flying = false; + player.sendAbilitiesUpdate(); + cancelLanding = false; + } + } + + if (cancelLanding){ + player.setOnGround(false); + } + } + } + else{ + wasSneakingBeforeTouchingGround = false; + holdingSneakWhileTouchingGround = false; + } + } }