From ebd522dca77cfd496d171a11a5439d3b2706ca85 Mon Sep 17 00:00:00 2001
From: chylex <contact@chylex.com>
Date: Mon, 26 Oct 2020 21:27:41 +0100
Subject: [PATCH] Add option to prevent FOV changing while flying

---
 .../bettercontrols/config/BetterControlsConfig.java |  1 +
 .../bettercontrols/config/ConfigSerializer.java     |  2 ++
 .../bettercontrols/gui/BetterControlsScreen.java    |  5 +++++
 .../mixin/AccessGameRendererFields.java             | 13 +++++++++++++
 .../chylex/bettercontrols/player/FlightHelper.java  |  4 ++++
 .../chylex/bettercontrols/player/PlayerTicker.java  |  9 ++++++++-
 src/main/resources/bettercontrols.mixins.json       |  1 +
 7 files changed, 34 insertions(+), 1 deletion(-)
 create mode 100644 src/main/java/chylex/bettercontrols/mixin/AccessGameRendererFields.java

diff --git a/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java b/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java
index 9080b92..2f5bd6a 100644
--- a/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java
+++ b/src/main/java/chylex/bettercontrols/config/BetterControlsConfig.java
@@ -21,6 +21,7 @@ public final class BetterControlsConfig{
 	
 	public final KeyBindingWithModifier keyToggleFlight = new KeyBindingWithModifier("key.bettercontrols.toggle_flight");
 	public SprintMode sprintModeWhileFlying = SprintMode.TAP_TO_START;
+	public boolean disableChangingFovWhileFlying = false;
 	public boolean flyOnGroundInCreative = false;
 	public float flightSpeedMpCreativeDefault = 1F;
 	public float flightSpeedMpCreativeSprinting = 2F;
diff --git a/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java b/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java
index 16363f9..03cd58c 100644
--- a/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java
+++ b/src/main/java/chylex/bettercontrols/config/ConfigSerializer.java
@@ -42,6 +42,7 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
 		
 		Json.writeKeyBinding(obj, "Flight.KeyToggle.Creative", cfg.keyToggleFlight);
 		Json.setEnum(obj, "Flight.SprintMode", cfg.sprintModeWhileFlying);
+		Json.setBool(obj, "Flight.DisableChangingFOV", cfg.disableChangingFovWhileFlying);
 		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);
@@ -75,6 +76,7 @@ final class ConfigSerializer implements JsonSerializer<BetterControlsConfig>, Js
 		
 		Json.readKeyBinding(obj, "Flight.KeyToggle.Creative", cfg.keyToggleFlight);
 		cfg.sprintModeWhileFlying = Json.getEnum(obj, "Flight.SprintMode", cfg.sprintModeWhileFlying, SprintMode.class);
+		cfg.disableChangingFovWhileFlying = Json.getBool(obj, "Flight.DisableChangingFOV", cfg.disableChangingFovWhileFlying);
 		cfg.flyOnGroundInCreative = Json.getBool(obj, "Flight.FlyOnGround.Creative", cfg.flyOnGroundInCreative);
 		cfg.flightSpeedMpCreativeDefault = MathHelper.clamp(Json.getFloat(obj, "Flight.SpeedMp.Creative.Default", cfg.flightSpeedMpCreativeDefault), 0.25F, 8F);
 		cfg.flightSpeedMpCreativeSprinting = MathHelper.clamp(Json.getFloat(obj, "Flight.SpeedMp.Creative.Sprinting", cfg.flightSpeedMpCreativeSprinting), 0.25F, 8F);
diff --git a/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java b/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java
index af08d8c..d95a169 100644
--- a/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java
+++ b/src/main/java/chylex/bettercontrols/gui/BetterControlsScreen.java
@@ -112,6 +112,11 @@ public class BetterControlsScreen extends GameOptionsScreen{
 		
 		y += ROW_HEIGHT;
 		
+		generateLeftSideText(y, elements, Text.of("Disable Field Of View Changing"));
+		elements.add(new BooleanValueWidget(col2(1), y, COL2_W, cfg.disableChangingFovWhileFlying, value -> cfg.disableChangingFovWhileFlying = value));
+		
+		y += ROW_HEIGHT;
+		
 		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));
 		
diff --git a/src/main/java/chylex/bettercontrols/mixin/AccessGameRendererFields.java b/src/main/java/chylex/bettercontrols/mixin/AccessGameRendererFields.java
new file mode 100644
index 0000000..6781f6e
--- /dev/null
+++ b/src/main/java/chylex/bettercontrols/mixin/AccessGameRendererFields.java
@@ -0,0 +1,13 @@
+package chylex.bettercontrols.mixin;
+import net.minecraft.client.render.GameRenderer;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.gen.Accessor;
+
+@Mixin(GameRenderer.class)
+public interface AccessGameRendererFields{
+	@Accessor
+	void setMovementFovMultiplier(float value);
+	
+	@Accessor
+	void setLastMovementFovMultiplier(float value);
+}
diff --git a/src/main/java/chylex/bettercontrols/player/FlightHelper.java b/src/main/java/chylex/bettercontrols/player/FlightHelper.java
index 8324a68..8092db7 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 isFlyingCreativeOrSpectator(final ClientPlayerEntity player){
+		return player.abilities.flying && (player.isCreative() || player.isSpectator());
+	}
+	
 	static boolean shouldFlyOnGround(final ClientPlayerEntity player){
 		return cfg().flyOnGroundInCreative && player.isCreative() && player.abilities.flying;
 	}
diff --git a/src/main/java/chylex/bettercontrols/player/PlayerTicker.java b/src/main/java/chylex/bettercontrols/player/PlayerTicker.java
index 0346db7..5714163 100644
--- a/src/main/java/chylex/bettercontrols/player/PlayerTicker.java
+++ b/src/main/java/chylex/bettercontrols/player/PlayerTicker.java
@@ -7,6 +7,7 @@ import chylex.bettercontrols.input.ToggleTracker;
 import chylex.bettercontrols.input.ToggleTrackerForStickyKey;
 import chylex.bettercontrols.mixin.AccessCameraFields;
 import chylex.bettercontrols.mixin.AccessClientPlayerFields;
+import chylex.bettercontrols.mixin.AccessGameRendererFields;
 import chylex.bettercontrols.mixin.AccessStickyKeyBindingStateGetter;
 import net.minecraft.client.MinecraftClient;
 import net.minecraft.client.input.KeyboardInput;
@@ -81,7 +82,7 @@ public final class PlayerTicker{
 		
 		final SprintMode sprintMode;
 		
-		if (player.abilities.flying && (player.isCreative() || player.isSpectator())){
+		if (FlightHelper.isFlyingCreativeOrSpectator(player)){
 			sprintMode = cfg().sprintModeWhileFlying;
 		}
 		else{
@@ -180,6 +181,12 @@ public final class PlayerTicker{
 			wasHittingObstacle = player.horizontalCollision;
 			wasSprintingBeforeHittingObstacle = false;
 		}
+		
+		if (cfg().disableChangingFovWhileFlying && FlightHelper.isFlyingCreativeOrSpectator(player)){
+			final AccessGameRendererFields renderer = (AccessGameRendererFields)mc().gameRenderer;
+			renderer.setMovementFovMultiplier(1F);
+			renderer.setLastMovementFovMultiplier(1F);
+		}
 	}
 	
 	public void afterSuperCall(final ClientPlayerEntity player){
diff --git a/src/main/resources/bettercontrols.mixins.json b/src/main/resources/bettercontrols.mixins.json
index 8e417d6..5ddcae2 100644
--- a/src/main/resources/bettercontrols.mixins.json
+++ b/src/main/resources/bettercontrols.mixins.json
@@ -8,6 +8,7 @@
     "AccessClientPlayerFields",
     "AccessControlsListCategory",
     "AccessControlsListKeyBinding",
+    "AccessGameRendererFields",
     "AccessKeyBindingFields",
     "AccessScreenButtons",
     "AccessStickyKeyBindingStateGetter",