mirror of
				https://github.com/chylex/Better-Controls.git
				synced 2025-11-04 03:40:14 +01:00 
			
		
		
		
	Compare commits
	
		
			4 Commits
		
	
	
		
			767ab9cb7d
			...
			5111ac5f7e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						
						
							
						
						5111ac5f7e
	
				 | 
					
					
						|||
| 
						
						
							
						
						ee3db91f0c
	
				 | 
					
					
						|||
| 
						
						
							
						
						9da758937e
	
				 | 
					
					
						|||
| 
						
						
							
						
						aa499bead5
	
				 | 
					
					
						
							
								
								
									
										21
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								README.md
									
									
									
									
									
								
							@@ -11,28 +11,33 @@ Another major difference is the amount and granularity of options. Better Contro
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping Sneak). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping `Control`). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
 | 
			
		||||
You can also bind a key that resets all **Toggle Keybinds** at once. That makes it easy to for ex. turn on walking, jumping, and sprinting, and then turn all of them off again by pressing one key instead of three.
 | 
			
		||||
 | 
			
		||||
#### Sprinting
 | 
			
		||||
 | 
			
		||||
* **Sprint Key Mode** changes how the Sprint key behaves. You can choose between *Tap To Start Sprinting*, *Tap To Start / Stop Sprinting*, and *Hold To Sprint*.
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off to prevent accidental sprinting.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** automatically presses the Sprint key once you are no longer touching any blocks (helpful when climbing hills, especially if the previous option is enabled).
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** re-activates sprinting once you are no longer touching any blocks.
 | 
			
		||||
 | 
			
		||||
#### Sneaking
 | 
			
		||||
 | 
			
		||||
* **Move Camera Smoothly** lets you disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
* **Move Camera Smoothly** can be turned off to disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
 | 
			
		||||
#### Gliding
 | 
			
		||||
 | 
			
		||||
* **Start a Glide** with a dedicated key.
 | 
			
		||||
* **Double Tap 'Jump' To Glide** can be turned off.
 | 
			
		||||
 | 
			
		||||
#### Flying
 | 
			
		||||
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off to prevent accidental flight toggling.
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off.
 | 
			
		||||
* **Disable Flight Inertia** stops you instantly when you stop holding movement keys.
 | 
			
		||||
* **Disable Field Of View Changing** prevents sprinting, potions, and other factors from changing the FOV while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode (and also lets you stop flying by tapping Sneak while touching the ground).
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes how fast you fly in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical speed boost while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode. Stop flying by tapping Sneak while touching the ground.
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes flight speed in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical flight speed boost in creative and spectator mode.
 | 
			
		||||
 | 
			
		||||
Both speed boosts can be configured separately for sprinting, which will be active when the Sprint key is held. Unlike in vanilla, the sprinting flight boost works in all directions.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,28 +6,33 @@ Another major difference is the amount and granularity of options. Better Contro
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping Sneak). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping `Control`). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
 | 
			
		||||
You can also bind a key that resets all **Toggle Keybinds** at once. That makes it easy to for ex. turn on walking, jumping, and sprinting, and then turn all of them off again by pressing one key instead of three.
 | 
			
		||||
 | 
			
		||||
#### Sprinting
 | 
			
		||||
 | 
			
		||||
* **Sprint Key Mode** changes how the Sprint key behaves. You can choose between *Tap To Start Sprinting*, *Tap To Start / Stop Sprinting*, and *Hold To Sprint*.
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off to prevent accidental sprinting.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** automatically presses the Sprint key once you are no longer touching any blocks (helpful when climbing hills, especially if the previous option is enabled).
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** re-activates sprinting once you are no longer touching any blocks.
 | 
			
		||||
 | 
			
		||||
#### Sneaking
 | 
			
		||||
 | 
			
		||||
* **Move Camera Smoothly** lets you disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
* **Move Camera Smoothly** can be turned off to disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
 | 
			
		||||
#### Gliding
 | 
			
		||||
 | 
			
		||||
* **Start a Glide** with a dedicated key.
 | 
			
		||||
* **Double Tap 'Jump' To Glide** can be turned off.
 | 
			
		||||
 | 
			
		||||
#### Flying
 | 
			
		||||
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off to prevent accidental flight toggling.
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off.
 | 
			
		||||
* **Disable Flight Inertia** stops you instantly when you stop holding movement keys.
 | 
			
		||||
* **Disable Field Of View Changing** prevents sprinting, potions, and other factors from changing the FOV while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode (and also lets you stop flying by tapping Sneak while touching the ground).
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes how fast you fly in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical speed boost while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode. Stop flying by tapping Sneak while touching the ground.
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes flight speed in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical flight speed boost in creative and spectator mode.
 | 
			
		||||
 | 
			
		||||
Both speed boosts can be configured separately for sprinting, which will be active when the Sprint key is held. Unlike in vanilla, the sprinting flight boost works in all directions.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,28 +6,33 @@ Another major difference is the amount and granularity of options. Better Contro
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping Sneak). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
The mod adds **Toggle Keybinds** for sprinting, sneaking, flying (creative mode), walking, and jumping. You can use modifier keys (`Control` / `Shift` / `Alt`) for each, including for example setting `Control` to Sneak, and `Control + Y` to Toggle Sneak. If you press the original key, the toggle will be canceled (in the previous example, you can Toggle Sneak by pressing `Control + Y`, and stop sneaking by simply tapping `Control`). Note that the vanilla options for toggling sprinting/sneaking are disabled to avoid conflicts with the custom keybinds.
 | 
			
		||||
 | 
			
		||||
You can also bind a key that resets all **Toggle Keybinds** at once. That makes it easy to for ex. turn on walking, jumping, and sprinting, and then turn all of them off again by pressing one key instead of three.
 | 
			
		||||
 | 
			
		||||
#### Sprinting
 | 
			
		||||
 | 
			
		||||
* **Sprint Key Mode** changes how the Sprint key behaves. You can choose between *Tap To Start Sprinting*, *Tap To Start / Stop Sprinting*, and *Hold To Sprint*.
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off to prevent accidental sprinting.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** automatically presses the Sprint key once you are no longer touching any blocks (helpful when climbing hills, especially if the previous option is enabled).
 | 
			
		||||
* **Double Tap 'Walk Forwards' To Sprint** can be turned off.
 | 
			
		||||
* **Resume Sprinting After Hitting Obstacle** re-activates sprinting once you are no longer touching any blocks.
 | 
			
		||||
 | 
			
		||||
#### Sneaking
 | 
			
		||||
 | 
			
		||||
* **Move Camera Smoothly** lets you disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
* **Move Camera Smoothly** can be turned off to disable the smooth movement when sneaking or unsneaking.
 | 
			
		||||
 | 
			
		||||
#### Gliding
 | 
			
		||||
 | 
			
		||||
* **Start a Glide** with a dedicated key.
 | 
			
		||||
* **Double Tap 'Jump' To Glide** can be turned off.
 | 
			
		||||
 | 
			
		||||
#### Flying
 | 
			
		||||
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off to prevent accidental flight toggling.
 | 
			
		||||
* **Double Tap 'Jump' To Fly** can be turned off.
 | 
			
		||||
* **Disable Flight Inertia** stops you instantly when you stop holding movement keys.
 | 
			
		||||
* **Disable Field Of View Changing** prevents sprinting, potions, and other factors from changing the FOV while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode (and also lets you stop flying by tapping Sneak while touching the ground).
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes how fast you fly in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical speed boost while flying in creative and spectator mode.
 | 
			
		||||
* **Fly On Ground** lets you fly while touching the ground in creative mode. Stop flying by tapping Sneak while touching the ground.
 | 
			
		||||
* **Flight Speed Multiplier** (0.25x - 8x) changes flight speed in creative and spectator mode.
 | 
			
		||||
* **Vertical Speed Boost** (up to +300%) adds additional vertical flight speed boost in creative and spectator mode.
 | 
			
		||||
 | 
			
		||||
Both speed boosts can be configured separately for sprinting, which will be active when the Sprint key is held. Unlike in vanilla, the sprinting flight boost works in all directions.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ modId=bettercontrols
 | 
			
		||||
modName=Better Controls
 | 
			
		||||
modDescription=Adds many powerful key bindings and options to control your movement.\\n\\nThe features complement vanilla mechanics without giving unfair advantages, so server use should be fine.
 | 
			
		||||
modAuthor=chylex
 | 
			
		||||
modVersion=1.4.0
 | 
			
		||||
modVersion=1.5.0
 | 
			
		||||
modLicense=MPL-2.0
 | 
			
		||||
modSourcesURL=https://github.com/chylex/Better-Controls
 | 
			
		||||
modIssuesURL=https://github.com/chylex/Better-Controls/issues
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										42
									
								
								src/main/java/chylex/bettercontrols/Mixins.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/main/java/chylex/bettercontrols/Mixins.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package chylex.bettercontrols;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessCameraFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessClientPlayerFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessKeyMappingFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessPlayerFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessToggleKeyMappingFields;
 | 
			
		||||
import net.minecraft.client.Camera;
 | 
			
		||||
import net.minecraft.client.KeyMapping;
 | 
			
		||||
import net.minecraft.client.ToggleKeyMapping;
 | 
			
		||||
import net.minecraft.client.player.LocalPlayer;
 | 
			
		||||
import net.minecraft.world.entity.player.Player;
 | 
			
		||||
 | 
			
		||||
@SuppressWarnings("CastToIncompatibleInterface")
 | 
			
		||||
public final class Mixins {
 | 
			
		||||
	private Mixins() {}
 | 
			
		||||
	
 | 
			
		||||
	@SuppressWarnings("unchecked")
 | 
			
		||||
	public static <T> T me(Object object) {
 | 
			
		||||
		return (T) object;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static AccessCameraFields cameraFields(Camera camera) {
 | 
			
		||||
		return (AccessCameraFields) camera;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static AccessClientPlayerFields clientPlayerFields(LocalPlayer localPlayer) {
 | 
			
		||||
		return (AccessClientPlayerFields) localPlayer;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static AccessKeyMappingFields keyMappingFields(KeyMapping keyMapping) {
 | 
			
		||||
		return (AccessKeyMappingFields) keyMapping;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static AccessPlayerFields playerFields(Player player) {
 | 
			
		||||
		return (AccessPlayerFields) player;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static AccessToggleKeyMappingFields toggleKeyMappingFields(ToggleKeyMapping toggleKeyMapping) {
 | 
			
		||||
		return (AccessToggleKeyMappingFields) toggleKeyMapping;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -27,6 +27,9 @@ public final class BetterControlsConfig {
 | 
			
		||||
	public final KeyBindingWithModifier keyToggleSneak = new KeyBindingWithModifier("key.bettercontrols.toggle_sneak");
 | 
			
		||||
	public boolean sneakingMovesCameraSmoothly = true;
 | 
			
		||||
	
 | 
			
		||||
	public final KeyBindingWithModifier keyStartGlide = new KeyBindingWithModifier("key.bettercontrols.start_glide");
 | 
			
		||||
	public boolean doubleTapJumpToGlide = true;
 | 
			
		||||
	
 | 
			
		||||
	public final KeyBindingWithModifier keyToggleFlight = new KeyBindingWithModifier("key.bettercontrols.toggle_flight");
 | 
			
		||||
	public boolean doubleTapJumpToToggleFlight = true;
 | 
			
		||||
	public boolean disableFlightInertia = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -41,6 +41,9 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
 | 
			
		||||
		Json.writeKeyBinding(obj, "Sneak.KeyToggle", cfg.keyToggleSneak);
 | 
			
		||||
		Json.setBool(obj, "Sneak.SmoothCamera", cfg.sneakingMovesCameraSmoothly);
 | 
			
		||||
		
 | 
			
		||||
		Json.writeKeyBinding(obj, "Glide.KeyStart", cfg.keyStartGlide);
 | 
			
		||||
		Json.setBool(obj, "Glide.DoubleTapJump", cfg.doubleTapJumpToGlide);
 | 
			
		||||
		
 | 
			
		||||
		Json.writeKeyBinding(obj, "Flight.KeyToggle.Creative", cfg.keyToggleFlight);
 | 
			
		||||
		Json.setBool(obj, "Flight.DoubleTapJump", cfg.doubleTapJumpToToggleFlight);
 | 
			
		||||
		Json.setBool(obj, "Flight.DisableInertia", cfg.disableFlightInertia);
 | 
			
		||||
@@ -80,6 +83,9 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
 | 
			
		||||
		Json.readKeyBinding(obj, "Sneak.KeyToggle", cfg.keyToggleSneak);
 | 
			
		||||
		cfg.sneakingMovesCameraSmoothly = Json.getBool(obj, "Sneak.SmoothCamera", cfg.sneakingMovesCameraSmoothly);
 | 
			
		||||
		
 | 
			
		||||
		Json.readKeyBinding(obj, "Glide.KeyStart", cfg.keyStartGlide);
 | 
			
		||||
		cfg.doubleTapJumpToGlide = Json.getBool(obj, "Glide.DoubleTapJump", cfg.doubleTapJumpToGlide);
 | 
			
		||||
		
 | 
			
		||||
		Json.readKeyBinding(obj, "Flight.KeyToggle.Creative", cfg.keyToggleFlight);
 | 
			
		||||
		cfg.doubleTapJumpToToggleFlight = Json.getBool(obj, "Flight.DoubleTapJump", cfg.doubleTapJumpToToggleFlight);
 | 
			
		||||
		cfg.disableFlightInertia = Json.getBool(obj, "Flight.DisableInertia", cfg.disableFlightInertia);
 | 
			
		||||
 
 | 
			
		||||
@@ -83,6 +83,18 @@ public class BetterControlsScreen extends OptionsSubScreen {
 | 
			
		||||
		return y;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private int generateGlidingOptions(int y, List<GuiEventListener> elements) {
 | 
			
		||||
		BetterControlsConfig cfg = BetterControlsCommon.getConfig();
 | 
			
		||||
		
 | 
			
		||||
		generateKeyBindingWithModifierRow(y, elements, text("Start a Glide"), cfg.keyStartGlide);
 | 
			
		||||
		y += ROW_HEIGHT;
 | 
			
		||||
		
 | 
			
		||||
		generateBooleanOptionRow(y, elements, text("Double Tap 'Jump' To Start a Glide"), cfg.doubleTapJumpToGlide, value -> cfg.doubleTapJumpToGlide = value);
 | 
			
		||||
		y += ROW_HEIGHT;
 | 
			
		||||
		
 | 
			
		||||
		return y;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private int generateFlightOptions(int y, List<GuiEventListener> elements) {
 | 
			
		||||
		BetterControlsConfig cfg = BetterControlsCommon.getConfig();
 | 
			
		||||
		
 | 
			
		||||
@@ -113,7 +125,7 @@ public class BetterControlsScreen extends OptionsSubScreen {
 | 
			
		||||
		generateBooleanOptionRow(y, elements, text("Disable Field Of View Changing"), cfg.disableChangingFovWhileFlying, value -> cfg.disableChangingFovWhileFlying = value);
 | 
			
		||||
		y += ROW_HEIGHT;
 | 
			
		||||
		
 | 
			
		||||
		generateBooleanOptionRow(y, elements, text("Fly On Ground (Creative Mode)"), cfg.flyOnGroundInCreative, value -> cfg.flyOnGroundInCreative = value);
 | 
			
		||||
		generateBooleanOptionRow(y, elements, text("Fly On Ground (Creative)"), cfg.flyOnGroundInCreative, value -> cfg.flyOnGroundInCreative = value);
 | 
			
		||||
		y += ROW_HEIGHT;
 | 
			
		||||
		
 | 
			
		||||
		y += ROW_HEIGHT / 3;
 | 
			
		||||
@@ -223,6 +235,9 @@ public class BetterControlsScreen extends OptionsSubScreen {
 | 
			
		||||
		elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Sneaking"), CENTER));
 | 
			
		||||
		y = generateSneakingOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
 | 
			
		||||
		
 | 
			
		||||
		elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Gliding"), CENTER));
 | 
			
		||||
		y = generateGlidingOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
 | 
			
		||||
		
 | 
			
		||||
		elements.add(new TextWidget(0, y, ROW_WIDTH, ROW_HEIGHT, text("Flying"), CENTER));
 | 
			
		||||
		y = generateFlightOptions(y + ROW_HEIGHT, elements) + TITLE_MARGIN_TOP;
 | 
			
		||||
		
 | 
			
		||||
 
 | 
			
		||||
@@ -6,15 +6,19 @@ public class ToggleTracker {
 | 
			
		||||
	protected final KeyMapping bindingToggle;
 | 
			
		||||
	protected final KeyMapping bindingReset;
 | 
			
		||||
	
 | 
			
		||||
	protected boolean isToggled;
 | 
			
		||||
	
 | 
			
		||||
	private boolean isToggled;
 | 
			
		||||
	private boolean waitForRelease;
 | 
			
		||||
	private boolean hasToggledWhileHoldingReset;
 | 
			
		||||
	private boolean skipNextToggle;
 | 
			
		||||
	
 | 
			
		||||
	public ToggleTracker(KeyMapping bindingToggle, KeyMapping bindingReset) {
 | 
			
		||||
	protected ToggleTracker(KeyMapping bindingToggle, KeyMapping bindingReset, boolean initialState) {
 | 
			
		||||
		this.bindingToggle = bindingToggle;
 | 
			
		||||
		this.bindingReset = bindingReset;
 | 
			
		||||
		this.isToggled = initialState;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public ToggleTracker(KeyMapping bindingToggle, KeyMapping bindingReset) {
 | 
			
		||||
		this(bindingToggle, bindingReset, false);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	/*
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,36 @@
 | 
			
		||||
package chylex.bettercontrols.input;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessKeyBindingFields;
 | 
			
		||||
import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import net.minecraft.client.KeyMapping;
 | 
			
		||||
import net.minecraft.client.OptionInstance;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public final class ToggleTrackerForStickyKey extends ToggleTracker {
 | 
			
		||||
	private static final Set<KeyMapping> enabledOverrides = new HashSet<>();
 | 
			
		||||
	
 | 
			
		||||
	@SuppressWarnings("StaticMethodOnlyUsedInOneClass")
 | 
			
		||||
	public static boolean isOverrideEnabled(KeyMapping binding) {
 | 
			
		||||
		return enabledOverrides.contains(binding);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private final BooleanConsumer setToggleState;
 | 
			
		||||
	private final OptionInstance<Boolean> toggleOption;
 | 
			
		||||
	
 | 
			
		||||
	public ToggleTrackerForStickyKey(KeyMapping bindingToggle, KeyMapping bindingStickyReset, BooleanConsumer setToggleState) {
 | 
			
		||||
		super(bindingToggle, bindingStickyReset);
 | 
			
		||||
		this.setToggleState = setToggleState;
 | 
			
		||||
		this.setToggleState.accept(false);
 | 
			
		||||
	public ToggleTrackerForStickyKey(KeyMapping bindingToggle, KeyMapping bindingStickyReset, OptionInstance<Boolean> toggleOption) {
 | 
			
		||||
		super(bindingToggle, bindingStickyReset, toggleOption.get().booleanValue());
 | 
			
		||||
		this.toggleOption = toggleOption;
 | 
			
		||||
		enabledOverrides.add(bindingStickyReset);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	public boolean tick() {
 | 
			
		||||
		boolean isToggled = super.tick();
 | 
			
		||||
		setToggleState.accept(isToggled);
 | 
			
		||||
		toggleOption.set(Boolean.valueOf(isToggled));
 | 
			
		||||
		return isToggled;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Override
 | 
			
		||||
	protected boolean isResetKeyPressed() {
 | 
			
		||||
		return ((AccessKeyBindingFields)bindingReset).isPressedField();
 | 
			
		||||
		return Mixins.keyMappingFields(bindingReset).isPressedField();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,8 @@ import org.spongepowered.asm.mixin.gen.Accessor;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Mixin(KeyMapping.class)
 | 
			
		||||
public interface AccessKeyBindingFields {
 | 
			
		||||
@SuppressWarnings("StaticMethodOnlyUsedInOneClass")
 | 
			
		||||
public interface AccessKeyMappingFields {
 | 
			
		||||
	@Accessor("CATEGORY_SORT_ORDER")
 | 
			
		||||
	static Map<String, Integer> getCategoryOrderMap() {
 | 
			
		||||
		throw new AssertionError();
 | 
			
		||||
@@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
 | 
			
		||||
import java.util.function.BooleanSupplier;
 | 
			
		||||
 | 
			
		||||
@Mixin(ToggleKeyMapping.class)
 | 
			
		||||
public interface AccessStickyKeyBindingStateGetter {
 | 
			
		||||
public interface AccessToggleKeyMappingFields {
 | 
			
		||||
	@Accessor
 | 
			
		||||
	BooleanSupplier getNeedsToggle();
 | 
			
		||||
	
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.player.PlayerTicker;
 | 
			
		||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
 | 
			
		||||
import net.minecraft.client.player.AbstractClientPlayer;
 | 
			
		||||
@@ -14,9 +15,9 @@ public abstract class HookClientPlayerFOV {
 | 
			
		||||
		at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/player/Abilities;getWalkingSpeed()F")
 | 
			
		||||
	)
 | 
			
		||||
	private float overrideWalkingSpeed(float walkingSpeed) {
 | 
			
		||||
		AbstractClientPlayer me = (AbstractClientPlayer)(Object)this;
 | 
			
		||||
		AbstractClientPlayer me = Mixins.me(this);
 | 
			
		||||
		
 | 
			
		||||
		if (me instanceof LocalPlayer localPlayer && PlayerTicker.get(localPlayer).shouldResetFOV(localPlayer)) {
 | 
			
		||||
		if (me instanceof LocalPlayer localPlayer && PlayerTicker.shouldResetFOV(localPlayer)) {
 | 
			
		||||
			return 0F;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 | 
			
		||||
import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER;
 | 
			
		||||
 | 
			
		||||
@Mixin(KeyboardInput.class)
 | 
			
		||||
@SuppressWarnings({ "MethodMayBeStatic", "UnreachableCode" })
 | 
			
		||||
@SuppressWarnings("MethodMayBeStatic")
 | 
			
		||||
public abstract class HookClientPlayerInputTick {
 | 
			
		||||
	@Inject(
 | 
			
		||||
		method = "tick",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.player.PlayerTicker;
 | 
			
		||||
import com.mojang.authlib.GameProfile;
 | 
			
		||||
import net.minecraft.client.multiplayer.ClientLevel;
 | 
			
		||||
@@ -12,7 +13,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 | 
			
		||||
import static org.spongepowered.asm.mixin.injection.At.Shift.AFTER;
 | 
			
		||||
 | 
			
		||||
@Mixin(LocalPlayer.class)
 | 
			
		||||
@SuppressWarnings("UnreachableCode")
 | 
			
		||||
public abstract class HookClientPlayerTick extends AbstractClientPlayer {
 | 
			
		||||
	protected HookClientPlayerTick(ClientLevel world, GameProfile profile) {
 | 
			
		||||
		super(world, profile);
 | 
			
		||||
@@ -20,22 +20,19 @@ public abstract class HookClientPlayerTick extends AbstractClientPlayer {
 | 
			
		||||
	
 | 
			
		||||
	@Inject(method = "aiStep()V", at = @At("HEAD"))
 | 
			
		||||
	private void atHead(CallbackInfo info) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		LocalPlayer player = (LocalPlayer)(Object)this;
 | 
			
		||||
		LocalPlayer player = Mixins.me(this);
 | 
			
		||||
		PlayerTicker.get(player).atHead(player);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/ClientInput;tick()V", ordinal = 0, shift = AFTER))
 | 
			
		||||
	private void afterInputTick(CallbackInfo info) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		LocalPlayer player = (LocalPlayer)(Object)this;
 | 
			
		||||
		LocalPlayer player = Mixins.me(this);
 | 
			
		||||
		PlayerTicker.get(player).afterInputTick(player);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	@Inject(method = "aiStep()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/AbstractClientPlayer;aiStep()V", ordinal = 0, shift = AFTER))
 | 
			
		||||
	private void afterSuperCall(CallbackInfo info) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		LocalPlayer player = (LocalPlayer)(Object)this;
 | 
			
		||||
		LocalPlayer player = Mixins.me(this);
 | 
			
		||||
		PlayerTicker.get(player).afterSuperCall(player);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.player.FlightHelper;
 | 
			
		||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
 | 
			
		||||
import net.minecraft.client.player.LocalPlayer;
 | 
			
		||||
@@ -11,7 +12,6 @@ import org.spongepowered.asm.mixin.injection.At;
 | 
			
		||||
import org.spongepowered.asm.mixin.injection.Slice;
 | 
			
		||||
 | 
			
		||||
@Mixin(LocalPlayer.class)
 | 
			
		||||
@SuppressWarnings({ "SameReturnValue", "UnreachableCode" })
 | 
			
		||||
public abstract class HookClientPlayerVerticalFlightSpeed extends LivingEntity {
 | 
			
		||||
	protected HookClientPlayerVerticalFlightSpeed(EntityType<? extends LivingEntity> type, Level world) {
 | 
			
		||||
		super(type, world);
 | 
			
		||||
@@ -26,8 +26,7 @@ public abstract class HookClientPlayerVerticalFlightSpeed extends LivingEntity {
 | 
			
		||||
		)
 | 
			
		||||
	)
 | 
			
		||||
	private float modifyVerticalFlightSpeed(float flyingSpeed) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		LocalPlayer me = (LocalPlayer)(Object)this;
 | 
			
		||||
		LocalPlayer me = Mixins.me(this);
 | 
			
		||||
		return flyingSpeed * FlightHelper.getVerticalSpeedMultiplier(me);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.gui.BetterControlsScreen;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.Options;
 | 
			
		||||
@@ -17,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@Mixin(ControlsScreen.class)
 | 
			
		||||
@SuppressWarnings("UnreachableCode")
 | 
			
		||||
public abstract class HookControlsScreen extends OptionsSubScreen {
 | 
			
		||||
	public HookControlsScreen(Screen parentScreen, Options options, Component title) {
 | 
			
		||||
		super(parentScreen, options, title);
 | 
			
		||||
@@ -26,8 +26,7 @@ public abstract class HookControlsScreen extends OptionsSubScreen {
 | 
			
		||||
	@Inject(method = "addOptions", at = @At("RETURN"))
 | 
			
		||||
	public void afterAddOptions(CallbackInfo ci) {
 | 
			
		||||
		if (list != null) {
 | 
			
		||||
			@SuppressWarnings("ConstantConditions")
 | 
			
		||||
			ControlsScreen screen = (ControlsScreen)(Object)this;
 | 
			
		||||
			ControlsScreen screen = Mixins.me(this);
 | 
			
		||||
			MutableComponent buttonTitle = BetterControlsScreen.TITLE.plainCopy().append("...");
 | 
			
		||||
			list.addSmall(List.of(Button.builder(buttonTitle, btn -> showOptionsScreen(screen)).build()));
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,6 @@ public abstract class HookLoadGameOptions {
 | 
			
		||||
		
 | 
			
		||||
		hasLoaded = true;
 | 
			
		||||
		keyMappings = ArrayUtils.addAll(keyMappings, config.getAllKeyBindings());
 | 
			
		||||
		AccessKeyBindingFields.getCategoryOrderMap().put(KeyBindingWithModifier.CATEGORY, Integer.valueOf(Integer.MAX_VALUE));
 | 
			
		||||
		AccessKeyMappingFields.getCategoryOrderMap().put(KeyBindingWithModifier.CATEGORY, Integer.valueOf(Integer.MAX_VALUE));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,23 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.player.FlightHelper;
 | 
			
		||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
 | 
			
		||||
import net.minecraft.client.player.LocalPlayer;
 | 
			
		||||
import org.spongepowered.asm.mixin.Mixin;
 | 
			
		||||
import org.spongepowered.asm.mixin.injection.At;
 | 
			
		||||
import org.spongepowered.asm.mixin.injection.Slice;
 | 
			
		||||
 | 
			
		||||
@Mixin(LocalPlayer.class)
 | 
			
		||||
@SuppressWarnings("MethodMayBeStatic")
 | 
			
		||||
public abstract class HookPlayerGliding {
 | 
			
		||||
	@ModifyExpressionValue(
 | 
			
		||||
		method = "aiStep",
 | 
			
		||||
		at = @At(value = "INVOKE:LAST", target = "Lnet/minecraft/world/entity/player/Input;jump()Z"),
 | 
			
		||||
		slice = @Slice(
 | 
			
		||||
			to = @At(value = "INVOKE", target = "Lnet/minecraft/client/player/LocalPlayer;tryToStartFallFlying()Z")
 | 
			
		||||
		)
 | 
			
		||||
	)
 | 
			
		||||
	private boolean shouldStartGliding(boolean isHoldingJump) {
 | 
			
		||||
		return FlightHelper.shouldStartGliding(isHoldingJump);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.player.FlightHelper;
 | 
			
		||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
 | 
			
		||||
import com.llamalad7.mixinextras.injector.ModifyReturnValue;
 | 
			
		||||
@@ -13,7 +14,6 @@ import org.spongepowered.asm.mixin.injection.At;
 | 
			
		||||
import org.spongepowered.asm.mixin.injection.Slice;
 | 
			
		||||
 | 
			
		||||
@Mixin(Player.class)
 | 
			
		||||
@SuppressWarnings({ "SameReturnValue", "UnreachableCode" })
 | 
			
		||||
public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity {
 | 
			
		||||
	protected HookPlayerHorizontalFlightSpeed(EntityType<? extends LivingEntity> type, Level world) {
 | 
			
		||||
		super(type, world);
 | 
			
		||||
@@ -29,8 +29,7 @@ public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity {
 | 
			
		||||
		)
 | 
			
		||||
	)
 | 
			
		||||
	private boolean disableVanillaSprintBoost(boolean isSprinting) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		Player me = (Player)(Object)this;
 | 
			
		||||
		Player me = Mixins.me(this);
 | 
			
		||||
		
 | 
			
		||||
		if (me instanceof LocalPlayer localPlayer && FlightHelper.isFlyingCreativeOrSpectator(localPlayer)) {
 | 
			
		||||
			return false;
 | 
			
		||||
@@ -42,8 +41,7 @@ public abstract class HookPlayerHorizontalFlightSpeed extends LivingEntity {
 | 
			
		||||
	
 | 
			
		||||
	@ModifyReturnValue(method = "getFlyingSpeed", at = @At("RETURN"))
 | 
			
		||||
	private float modifyHorizontalFlyingSpeed(float flyingSpeed) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		Player me = (Player)(Object)this;
 | 
			
		||||
		Player me = Mixins.me(this);
 | 
			
		||||
		
 | 
			
		||||
		if (me instanceof LocalPlayer localPlayer && localPlayer.getAbilities().flying) {
 | 
			
		||||
			return flyingSpeed * FlightHelper.getHorizontalSpeedMultiplier(localPlayer);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
 | 
			
		||||
import net.minecraft.client.KeyMapping;
 | 
			
		||||
import net.minecraft.client.ToggleKeyMapping;
 | 
			
		||||
@@ -24,7 +25,7 @@ public abstract class HookStickyKeyBindingState extends KeyMapping {
 | 
			
		||||
	@Inject(method = "setDown", at = @At("HEAD"), cancellable = true)
 | 
			
		||||
	public void setPressed(boolean pressed, CallbackInfo info) {
 | 
			
		||||
		if (ToggleTrackerForStickyKey.isOverrideEnabled(this)) {
 | 
			
		||||
			((AccessKeyBindingFields)this).setPressedField(pressed);
 | 
			
		||||
			Mixins.keyMappingFields(this).setPressedField(pressed);
 | 
			
		||||
			info.cancel();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
package chylex.bettercontrols.mixin;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import net.minecraft.client.OptionInstance;
 | 
			
		||||
import net.minecraft.client.Options;
 | 
			
		||||
import net.minecraft.client.gui.components.AbstractWidget;
 | 
			
		||||
@@ -10,12 +11,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
 | 
			
		||||
import java.util.function.Consumer;
 | 
			
		||||
 | 
			
		||||
@Mixin(OptionInstance.class)
 | 
			
		||||
@SuppressWarnings("UnreachableCode")
 | 
			
		||||
public abstract class HookToggleOptionButtons {
 | 
			
		||||
	@Inject(method = "createButton(Lnet/minecraft/client/Options;IIILjava/util/function/Consumer;)Lnet/minecraft/client/gui/components/AbstractWidget;", at = @At("RETURN"))
 | 
			
		||||
	private <T> void disableToggleOptions(Options options, int x, int y, int width, Consumer<T> callback, CallbackInfoReturnable<AbstractWidget> cir) {
 | 
			
		||||
		@SuppressWarnings("ConstantConditions")
 | 
			
		||||
		OptionInstance<?> me = (OptionInstance<?>)(Object)this;
 | 
			
		||||
		OptionInstance<?> me = Mixins.me(this);
 | 
			
		||||
		
 | 
			
		||||
		if (me == options.toggleCrouch() || me == options.toggleSprint()) {
 | 
			
		||||
			cir.getReturnValue().active = false;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,9 @@
 | 
			
		||||
package chylex.bettercontrols.player;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.BetterControlsCommon;
 | 
			
		||||
import chylex.bettercontrols.config.BetterControlsConfig;
 | 
			
		||||
import net.minecraft.client.KeyMapping;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.player.LocalPlayer;
 | 
			
		||||
import static chylex.bettercontrols.BetterControlsCommon.getConfig;
 | 
			
		||||
 | 
			
		||||
public final class FlightHelper {
 | 
			
		||||
	private FlightHelper() {}
 | 
			
		||||
@@ -15,8 +14,8 @@ public final class FlightHelper {
 | 
			
		||||
		return KEY_SPRINT.isDown();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static BetterControlsConfig cfg() {
 | 
			
		||||
		return BetterControlsCommon.getConfig();
 | 
			
		||||
	public static boolean shouldStartGliding(boolean isHoldingJump) {
 | 
			
		||||
		return getConfig().keyStartGlide.isDown() || (getConfig().doubleTapJumpToGlide && isHoldingJump);
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static boolean isFlyingCreativeOrSpectator(LocalPlayer player) {
 | 
			
		||||
@@ -24,15 +23,15 @@ public final class FlightHelper {
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	static boolean shouldFlyOnGround(LocalPlayer player) {
 | 
			
		||||
		return cfg().flyOnGroundInCreative && player.isCreative() && player.getAbilities().flying;
 | 
			
		||||
		return getConfig().flyOnGroundInCreative && player.isCreative() && player.getAbilities().flying;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public static float getHorizontalSpeedMultiplier(LocalPlayer player) {
 | 
			
		||||
		if (player.isCreative()) {
 | 
			
		||||
			return isSprinting() ? cfg().flightHorizontalSpeedMpCreativeSprinting : cfg().flightHorizontalSpeedMpCreativeDefault;
 | 
			
		||||
			return isSprinting() ? getConfig().flightHorizontalSpeedMpCreativeSprinting : getConfig().flightHorizontalSpeedMpCreativeDefault;
 | 
			
		||||
		}
 | 
			
		||||
		else if (player.isSpectator()) {
 | 
			
		||||
			return isSprinting() ? cfg().flightHorizontalSpeedMpSpectatorSprinting : cfg().flightHorizontalSpeedMpSpectatorDefault;
 | 
			
		||||
			return isSprinting() ? getConfig().flightHorizontalSpeedMpSpectatorSprinting : getConfig().flightHorizontalSpeedMpSpectatorDefault;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			return 1F;
 | 
			
		||||
@@ -41,10 +40,10 @@ public final class FlightHelper {
 | 
			
		||||
	
 | 
			
		||||
	public static float getVerticalSpeedMultiplier(LocalPlayer player) {
 | 
			
		||||
		if (player.isCreative()) {
 | 
			
		||||
			return isSprinting() ? cfg().flightVerticalSpeedMpCreativeSprinting : cfg().flightVerticalSpeedMpCreativeDefault;
 | 
			
		||||
			return isSprinting() ? getConfig().flightVerticalSpeedMpCreativeSprinting : getConfig().flightVerticalSpeedMpCreativeDefault;
 | 
			
		||||
		}
 | 
			
		||||
		else if (player.isSpectator()) {
 | 
			
		||||
			return isSprinting() ? cfg().flightVerticalSpeedMpSpectatorSprinting : cfg().flightVerticalSpeedMpSpectatorDefault;
 | 
			
		||||
			return isSprinting() ? getConfig().flightVerticalSpeedMpSpectatorSprinting : getConfig().flightVerticalSpeedMpSpectatorDefault;
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			return 1F;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,28 @@
 | 
			
		||||
package chylex.bettercontrols.player;
 | 
			
		||||
 | 
			
		||||
import chylex.bettercontrols.BetterControlsCommon;
 | 
			
		||||
import chylex.bettercontrols.config.BetterControlsConfig;
 | 
			
		||||
import chylex.bettercontrols.Mixins;
 | 
			
		||||
import chylex.bettercontrols.gui.BetterControlsScreen;
 | 
			
		||||
import chylex.bettercontrols.input.SprintMode;
 | 
			
		||||
import chylex.bettercontrols.input.ToggleTracker;
 | 
			
		||||
import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessCameraFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessClientPlayerFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessPlayerFields;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessStickyKeyBindingStateGetter;
 | 
			
		||||
import chylex.bettercontrols.mixin.AccessToggleKeyMappingFields;
 | 
			
		||||
import net.minecraft.client.Camera;
 | 
			
		||||
import net.minecraft.client.KeyMapping;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.client.Options;
 | 
			
		||||
import net.minecraft.client.ToggleKeyMapping;
 | 
			
		||||
import net.minecraft.client.player.ClientInput;
 | 
			
		||||
import net.minecraft.client.player.LocalPlayer;
 | 
			
		||||
import net.minecraft.world.entity.player.Input;
 | 
			
		||||
import java.lang.ref.WeakReference;
 | 
			
		||||
import java.util.function.BooleanSupplier;
 | 
			
		||||
import static chylex.bettercontrols.BetterControlsCommon.getConfig;
 | 
			
		||||
 | 
			
		||||
public final class PlayerTicker {
 | 
			
		||||
	private static final Minecraft MINECRAFT = Minecraft.getInstance();
 | 
			
		||||
	private static final Options OPTIONS = MINECRAFT.options;
 | 
			
		||||
	
 | 
			
		||||
	private static final KeyMapping KEY_SPRINT = OPTIONS.keySprint;
 | 
			
		||||
	private static final ToggleKeyMapping KEY_SPRINT = (ToggleKeyMapping) OPTIONS.keySprint;
 | 
			
		||||
	private static final KeyMapping KEY_SNEAK = OPTIONS.keyShift;
 | 
			
		||||
	private static final KeyMapping KEY_FORWARD = OPTIONS.keyUp;
 | 
			
		||||
	private static final KeyMapping KEY_JUMP = OPTIONS.keyJump;
 | 
			
		||||
@@ -39,10 +37,6 @@ public final class PlayerTicker {
 | 
			
		||||
		return ticker;
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private static BetterControlsConfig cfg() {
 | 
			
		||||
		return BetterControlsCommon.getConfig();
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	private final WeakReference<LocalPlayer> ref;
 | 
			
		||||
	
 | 
			
		||||
	private PlayerTicker(LocalPlayer player) {
 | 
			
		||||
@@ -52,10 +46,10 @@ public final class PlayerTicker {
 | 
			
		||||
	
 | 
			
		||||
	// Logic
 | 
			
		||||
	
 | 
			
		||||
	private final ToggleTracker toggleSprint = new ToggleTrackerForStickyKey(cfg().keyToggleSprint, KEY_SPRINT, OPTIONS.toggleSprint()::set);
 | 
			
		||||
	private final ToggleTracker toggleSneak = new ToggleTrackerForStickyKey(cfg().keyToggleSneak, KEY_SNEAK, OPTIONS.toggleCrouch()::set);
 | 
			
		||||
	private final ToggleTracker toggleWalkForward = new ToggleTracker(cfg().keyToggleWalkForward, KEY_FORWARD);
 | 
			
		||||
	private final ToggleTracker toggleJump = new ToggleTracker(cfg().keyToggleJump, KEY_JUMP);
 | 
			
		||||
	private final ToggleTracker toggleSprint = new ToggleTrackerForStickyKey(getConfig().keyToggleSprint, KEY_SPRINT, OPTIONS.toggleSprint());
 | 
			
		||||
	private final ToggleTracker toggleSneak = new ToggleTrackerForStickyKey(getConfig().keyToggleSneak, KEY_SNEAK, OPTIONS.toggleCrouch());
 | 
			
		||||
	private final ToggleTracker toggleWalkForward = new ToggleTracker(getConfig().keyToggleWalkForward, KEY_FORWARD);
 | 
			
		||||
	private final ToggleTracker toggleJump = new ToggleTracker(getConfig().keyToggleJump, KEY_JUMP);
 | 
			
		||||
	
 | 
			
		||||
	private boolean waitingForSprintKeyRelease = false;
 | 
			
		||||
	private boolean stopSprintingAfterReleasingSprintKey = false;
 | 
			
		||||
@@ -69,7 +63,7 @@ public final class PlayerTicker {
 | 
			
		||||
	private int temporaryFlyOnGroundTimer = 0;
 | 
			
		||||
	
 | 
			
		||||
	private void setup() {
 | 
			
		||||
		AccessStickyKeyBindingStateGetter sprint = (AccessStickyKeyBindingStateGetter)KEY_SPRINT;
 | 
			
		||||
		AccessToggleKeyMappingFields sprint = Mixins.toggleKeyMappingFields(KEY_SPRINT);
 | 
			
		||||
		BooleanSupplier getter = sprint.getNeedsToggle();
 | 
			
		||||
		
 | 
			
		||||
		if (getter instanceof SprintPressGetter g) {
 | 
			
		||||
@@ -84,15 +78,15 @@ public final class PlayerTicker {
 | 
			
		||||
			player.setOnGround(false);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (!cfg().doubleTapForwardToSprint) {
 | 
			
		||||
			((AccessClientPlayerFields)player).setSprintTriggerTime(0);
 | 
			
		||||
		if (!getConfig().doubleTapForwardToSprint) {
 | 
			
		||||
			Mixins.clientPlayerFields(player).setSprintTriggerTime(0);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (!cfg().doubleTapJumpToToggleFlight) {
 | 
			
		||||
			((AccessPlayerFields)player).setJumpTriggerTime(0);
 | 
			
		||||
		if (!getConfig().doubleTapJumpToToggleFlight) {
 | 
			
		||||
			Mixins.playerFields(player).setJumpTriggerTime(0);
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		SprintMode sprintMode = cfg().sprintMode;
 | 
			
		||||
		SprintMode sprintMode = getConfig().sprintMode;
 | 
			
		||||
		boolean wasSprintToggled = Boolean.TRUE.equals(OPTIONS.toggleSprint().get());
 | 
			
		||||
		boolean isSprintToggled = toggleSprint.tick();
 | 
			
		||||
		
 | 
			
		||||
@@ -170,7 +164,7 @@ public final class PlayerTicker {
 | 
			
		||||
			player.input.makeJump();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (cfg().resumeSprintingAfterHittingObstacle) {
 | 
			
		||||
		if (getConfig().resumeSprintingAfterHittingObstacle) {
 | 
			
		||||
			if (wasHittingObstacle != player.horizontalCollision) {
 | 
			
		||||
				if (!wasHittingObstacle) {
 | 
			
		||||
					wasSprintingBeforeHittingObstacle = player.isSprinting() || KEY_SPRINT.isDown();
 | 
			
		||||
@@ -229,7 +223,7 @@ public final class PlayerTicker {
 | 
			
		||||
			holdingSneakWhileTouchingGround = false;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (FlightHelper.isFlyingCreativeOrSpectator(player) && cfg().disableFlightInertia) {
 | 
			
		||||
		if (FlightHelper.isFlyingCreativeOrSpectator(player) && getConfig().disableFlightInertia) {
 | 
			
		||||
			ClientInput input = player.input;
 | 
			
		||||
			
 | 
			
		||||
			if (input.forwardImpulse == 0F && input.leftImpulse == 0F) {
 | 
			
		||||
@@ -242,7 +236,7 @@ public final class PlayerTicker {
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (player.isCreative()) {
 | 
			
		||||
			if (cfg().keyToggleFlight.consumeClick()) {
 | 
			
		||||
			if (getConfig().keyToggleFlight.consumeClick()) {
 | 
			
		||||
				boolean isFlying = !player.getAbilities().flying;
 | 
			
		||||
				
 | 
			
		||||
				player.getAbilities().flying = isFlying;
 | 
			
		||||
@@ -267,27 +261,27 @@ public final class PlayerTicker {
 | 
			
		||||
			temporaryFlyOnGroundTimer = 0;
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (!cfg().sneakingMovesCameraSmoothly) {
 | 
			
		||||
		if (!getConfig().sneakingMovesCameraSmoothly) {
 | 
			
		||||
			Camera camera = MINECRAFT.gameRenderer.getMainCamera();
 | 
			
		||||
			
 | 
			
		||||
			if (camera.getEntity() == player) {
 | 
			
		||||
				((AccessCameraFields)camera).setEyeHeight(player.getEyeHeight());
 | 
			
		||||
				Mixins.cameraFields(camera).setEyeHeight(player.getEyeHeight());
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (cfg().keyResetAllToggles.consumeClick()) {
 | 
			
		||||
		if (getConfig().keyResetAllToggles.consumeClick()) {
 | 
			
		||||
			toggleSprint.reset();
 | 
			
		||||
			toggleSneak.reset();
 | 
			
		||||
			toggleWalkForward.reset();
 | 
			
		||||
			toggleJump.reset();
 | 
			
		||||
		}
 | 
			
		||||
		
 | 
			
		||||
		if (cfg().keyOpenMenu.isDown()) {
 | 
			
		||||
		if (getConfig().keyOpenMenu.isDown()) {
 | 
			
		||||
			MINECRAFT.setScreen(new BetterControlsScreen(null));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	public boolean shouldResetFOV(LocalPlayer player) {
 | 
			
		||||
		return cfg().disableChangingFovWhileFlying && FlightHelper.isFlyingCreativeOrSpectator(player);
 | 
			
		||||
	public static boolean shouldResetFOV(LocalPlayer player) {
 | 
			
		||||
		return getConfig().disableChangingFovWhileFlying && FlightHelper.isFlyingCreativeOrSpectator(player);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,9 +7,9 @@
 | 
			
		||||
  "client": [
 | 
			
		||||
    "AccessCameraFields",
 | 
			
		||||
    "AccessClientPlayerFields",
 | 
			
		||||
    "AccessKeyBindingFields",
 | 
			
		||||
    "AccessKeyMappingFields",
 | 
			
		||||
    "AccessPlayerFields",
 | 
			
		||||
    "AccessStickyKeyBindingStateGetter",
 | 
			
		||||
    "AccessToggleKeyMappingFields",
 | 
			
		||||
    "HookClientPlayerFOV",
 | 
			
		||||
    "HookClientPlayerInputTick",
 | 
			
		||||
    "HookClientPlayerTick",
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
    "HookControlsListWidget",
 | 
			
		||||
    "HookControlsScreen",
 | 
			
		||||
    "HookLoadGameOptions",
 | 
			
		||||
    "HookPlayerGliding",
 | 
			
		||||
    "HookPlayerHorizontalFlightSpeed",
 | 
			
		||||
    "HookStickyKeyBindingState",
 | 
			
		||||
    "HookToggleOptionButtons"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user