From 8a7e96f8ecb34cf41725b75d62fa470401abb848 Mon Sep 17 00:00:00 2001 From: Octol1ttle Date: Thu, 5 Oct 2023 16:14:08 +0500 Subject: [PATCH] The refactor starts now. Signed-off-by: Octol1ttle --- build.gradle | 2 +- gradle.properties | 2 +- .../flighthud/AutoFlightManager.java | 106 --------- .../net/torocraft/flighthud/FlightHud.java | 96 +------- .../flighthud/FlightSafetyMonitor.java | 182 --------------- .../net/torocraft/flighthud/HudRenderer.java | 23 +- .../java/net/torocraft/flighthud/Util.java | 9 + .../alerts/AutoThrustLimitedAlert.java | 24 -- .../alerts/{Alert.java => ECAMAlert.java} | 14 +- .../FireworkActivationFailureAlert.java | 32 --- .../alerts/FlightProtectionsOffAlert.java | 25 -- .../flighthud/alerts/GPWSOffAlert.java | 25 -- .../torocraft/flighthud/alerts/IAlert.java | 12 + .../alerts/LowElytraHealthAlert.java | 17 -- .../flighthud/alerts/LowFireworksAlert.java | 25 -- .../flighthud/alerts/NoFireworksAlert.java | 28 --- .../alerts/PassengerDismountedAlert.java | 17 -- .../flighthud/alerts/ThrustLockedAlert.java | 32 --- .../alerts/UnsafeFireworksAlert.java | 42 ---- .../alerts/nav/gpws/UnsafeSinkrateAlert.java | 34 +++ .../commands/AltitudeResetCommand.java | 14 -- .../commands/AltitudeSelectCommand.java | 15 -- .../commands/DestinationResetCommand.java | 15 -- .../commands/DestinationSelectCommand.java | 16 -- .../components/AltitudeIndicator.java | 2 +- .../components/ElytraHealthIndicator.java | 6 +- .../components/FlightPathIndicator.java | 18 +- .../components/FlightStatusIndicator.java | 218 ------------------ .../components/HeadingIndicator.java | 2 +- .../flighthud/components/PitchIndicator.java | 5 +- .../flighthud/components/SpeedIndicator.java | 9 +- .../computers/AutoFlightComputer.java | 26 +++ .../{ => computers}/FlightComputer.java | 104 +++++---- .../flighthud/computers/GPWSComputer.java | 50 ++++ .../flighthud/computers/PitchController.java | 21 ++ .../torocraft/flighthud/config/HudConfig.java | 5 +- .../flighthud/config/SettingsConfig.java | 5 - .../ClientPlayerInteractionManagerMixin.java | 7 +- .../flighthud/mixin/EntityMixin.java | 6 +- .../flighthud/mixin/GameRendererMixin.java | 11 +- .../flighthud/mixin/InGameHudMixin.java | 15 +- .../flighthud/mixin/LivingEntityMixin.java | 7 +- .../resources/assets/flighthud/sounds.json | 21 +- .../assets/flighthud/sounds/alert.ogg | Bin 9475 -> 0 bytes .../assets/flighthud/sounds/caution.wav | Bin 0 -> 44340 bytes .../assets/flighthud/sounds/stall_warning.ogg | 0 .../assets/flighthud/sounds/stick_shaker.ogg | Bin 20791 -> 0 bytes .../assets/flighthud/sounds/warning.wav | Bin 0 -> 132514 bytes 48 files changed, 283 insertions(+), 1062 deletions(-) delete mode 100644 src/main/java/net/torocraft/flighthud/AutoFlightManager.java delete mode 100644 src/main/java/net/torocraft/flighthud/FlightSafetyMonitor.java create mode 100644 src/main/java/net/torocraft/flighthud/Util.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/AutoThrustLimitedAlert.java rename src/main/java/net/torocraft/flighthud/alerts/{Alert.java => ECAMAlert.java} (63%) delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/FireworkActivationFailureAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/FlightProtectionsOffAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/GPWSOffAlert.java create mode 100644 src/main/java/net/torocraft/flighthud/alerts/IAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/LowElytraHealthAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/LowFireworksAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/NoFireworksAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/PassengerDismountedAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/ThrustLockedAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/alerts/UnsafeFireworksAlert.java create mode 100644 src/main/java/net/torocraft/flighthud/alerts/nav/gpws/UnsafeSinkrateAlert.java delete mode 100644 src/main/java/net/torocraft/flighthud/commands/AltitudeResetCommand.java delete mode 100644 src/main/java/net/torocraft/flighthud/commands/AltitudeSelectCommand.java delete mode 100644 src/main/java/net/torocraft/flighthud/commands/DestinationResetCommand.java delete mode 100644 src/main/java/net/torocraft/flighthud/commands/DestinationSelectCommand.java delete mode 100644 src/main/java/net/torocraft/flighthud/components/FlightStatusIndicator.java create mode 100644 src/main/java/net/torocraft/flighthud/computers/AutoFlightComputer.java rename src/main/java/net/torocraft/flighthud/{ => computers}/FlightComputer.java (52%) create mode 100644 src/main/java/net/torocraft/flighthud/computers/GPWSComputer.java create mode 100644 src/main/java/net/torocraft/flighthud/computers/PitchController.java delete mode 100644 src/main/resources/assets/flighthud/sounds/alert.ogg create mode 100644 src/main/resources/assets/flighthud/sounds/caution.wav delete mode 100644 src/main/resources/assets/flighthud/sounds/stall_warning.ogg delete mode 100644 src/main/resources/assets/flighthud/sounds/stick_shaker.ogg create mode 100644 src/main/resources/assets/flighthud/sounds/warning.wav diff --git a/build.gradle b/build.gradle index 3041eb90..14f93bf8 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '1.2-SNAPSHOT' + id 'fabric-loom' version '1.4-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index 72a7c8a8..25c904b3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,6 +14,6 @@ loader_version=0.14.7 fabric_version=0.83.0 immediatelyfast_version=1.2.0 # Mod Properties -mod_version=1.20.1-fabric-8 +mod_version=2.0.0-alpha.1+mc1.20.1 maven_group=net.torocraft archives_base_name=flighthud diff --git a/src/main/java/net/torocraft/flighthud/AutoFlightManager.java b/src/main/java/net/torocraft/flighthud/AutoFlightManager.java deleted file mode 100644 index a8a4441a..00000000 --- a/src/main/java/net/torocraft/flighthud/AutoFlightManager.java +++ /dev/null @@ -1,106 +0,0 @@ -package net.torocraft.flighthud; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.Util; -import net.minecraft.util.math.MathHelper; - -import static net.torocraft.flighthud.FlightSafetyMonitor.correctThreshold; -import static net.torocraft.flighthud.FlightSafetyMonitor.gpwsLampColor; -import static net.torocraft.flighthud.FlightSafetyMonitor.lastFireworkActivationTimeMs; -import static net.torocraft.flighthud.FlightSafetyMonitor.maximumSafePitch; -import static net.torocraft.flighthud.FlightSafetyMonitor.secondsUntilTerrainImpact; -import static net.torocraft.flighthud.FlightSafetyMonitor.thrustLocked; -import static net.torocraft.flighthud.FlightSafetyMonitor.thrustSet; -import static net.torocraft.flighthud.FlightSafetyMonitor.usableFireworkHand; -import static net.torocraft.flighthud.HudComponent.CONFIG; -import static net.torocraft.flighthud.HudComponent.wrapHeading; - -public class AutoFlightManager { - public static Long lastUpdateTimeMs = null; - public static Float deltaTime; - - public static boolean flightDirectorsEnabled = false; - public static boolean autoThrustEnabled = false; - public static boolean autoPilotEnabled = false; - - public static Integer destinationX = null; - public static Integer destinationZ = null; - public static Integer targetAltitude = null; - - public static Float targetPitch = null; - public static Float targetYaw = null; - public static Float targetHeading = null; - public static Double distanceToTarget = null; - - public static String statusString = ""; - - public static void update(MinecraftClient mc, FlightComputer computer) { - statusString = ""; - long currentTimeMs = Util.getMeasuringTimeMs(); - if (lastUpdateTimeMs != null) - deltaTime = Math.min(1, (currentTimeMs - lastUpdateTimeMs) * 0.001f); - else - deltaTime = 1f / mc.options.getMaxFps().getValue(); - lastUpdateTimeMs = currentTimeMs; - - if (CONFIG == null || mc.player == null || !mc.player.isFallFlying() || mc.interactionManager == null) - return; - boolean approachingDestination = distanceToTarget != null && distanceToTarget < Math.max(40, computer.velocityPerSecond.horizontalLength()); - - if (computer.speed > 30) thrustSet = true; - - if (autoThrustEnabled && usableFireworkHand != null) { - if (!thrustLocked && gpwsLampColor == CONFIG.color && computer.velocityPerSecond.horizontalLength() > 0.01 && computer.pitch > (autoPilotEnabled ? 0 : 10) && !approachingDestination) { - if (thrustSet && (computer.speed < 28 || computer.velocityPerSecond.y < -8)) { - mc.interactionManager.interactItem(mc.player, usableFireworkHand); - lastFireworkActivationTimeMs = lastUpdateTimeMs; - } - statusString += "THR MCT"; - } else statusString += "THR IDLE"; - } - - targetPitch = null; - if (AutoFlightManager.autoPilotEnabled && (secondsUntilTerrainImpact <= correctThreshold || computer.velocityPerSecond.horizontalLength() < 0.01)) { - targetPitch = -maximumSafePitch; - statusString += "".equals(statusString) ? "GPWS" : " | GPWS"; - } else if (approachingDestination || FlightSafetyMonitor.fireworkCount <= 0 || (AutoFlightManager.autoThrustEnabled && usableFireworkHand == null)) { - targetPitch = 2.2f; - statusString += "".equals(statusString) ? "OPT GLD" : " | OPT GLD"; - } else if (targetAltitude != null) { - float pitchLimiter = (float) (Math.abs(targetAltitude - mc.player.getY()) + computer.velocityPerSecond.length()); - targetPitch = (float) Math.max(-maximumSafePitch, Math.toDegrees(-Math.asin((targetAltitude - mc.player.getY()) / pitchLimiter))); - statusString += "".equals(statusString) ? "ALT" : " | ALT"; - } - - - if (destinationX != null && destinationZ != null) { - targetYaw = (float) Math.toDegrees(Math.atan2(-(destinationX - mc.player.getX()), destinationZ - mc.player.getZ())); - targetHeading = (targetYaw + 180) % 360; - distanceToTarget = Math.sqrt(mc.player.getPos().squaredDistanceTo(destinationX, mc.player.getY(), destinationZ)); - statusString += "".equals(statusString) ? "NAV" : " | NAV"; - } else { - targetYaw = null; - targetHeading = null; - distanceToTarget = null; - } - - if (autoPilotEnabled) { - float deltaHeading = targetHeading != null ? wrapHeading(targetHeading) - wrapHeading(computer.heading) : 0.0f; - if (deltaHeading < -180) { - deltaHeading += 360; - } - - changeLookDirection(mc.player, targetPitch != null ? (targetPitch + computer.pitch) * deltaTime : 0.0f, - deltaHeading * deltaTime * 1.25f); - statusString += "".equals(statusString) ? "A/P" : " | A/P"; - } - } - - public static void changeLookDirection(PlayerEntity player, float pitch, float yaw) { - player.setPitch(MathHelper.clamp(player.getPitch() + pitch, -90.0F, 90.0F)); - player.setYaw(player.getYaw() + yaw); - player.prevPitch = MathHelper.clamp(player.prevPitch + pitch, -90.0F, 90.0F); - player.prevYaw += yaw; - } -} diff --git a/src/main/java/net/torocraft/flighthud/FlightHud.java b/src/main/java/net/torocraft/flighthud/FlightHud.java index f2babde3..e0b87a32 100644 --- a/src/main/java/net/torocraft/flighthud/FlightHud.java +++ b/src/main/java/net/torocraft/flighthud/FlightHud.java @@ -1,21 +1,13 @@ package net.torocraft.flighthud; -import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.tree.LiteralCommandNode; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; -import net.torocraft.flighthud.alerts.Alert; -import net.torocraft.flighthud.commands.AltitudeResetCommand; -import net.torocraft.flighthud.commands.AltitudeSelectCommand; -import net.torocraft.flighthud.commands.DestinationResetCommand; -import net.torocraft.flighthud.commands.DestinationSelectCommand; import net.torocraft.flighthud.commands.SwitchDisplayModeCommand; -import net.torocraft.flighthud.components.FlightStatusIndicator; import net.torocraft.flighthud.config.HudConfig; import net.torocraft.flighthud.config.SettingsConfig; import net.torocraft.flighthud.config.loader.ConfigLoader; @@ -23,7 +15,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal; public class FlightHud implements ClientModInitializer { @@ -52,91 +43,16 @@ public class FlightHud implements ClientModInitializer { config -> FlightHud.CONFIG_MIN = config); private static KeyBinding keyBinding; - private static KeyBinding hideAlertSwitch; - private static KeyBinding showAlertSwitch; - private static KeyBinding flightLawSwitch; - private static KeyBinding gpwsSwitch; - private static KeyBinding fdSwitch; - private static KeyBinding aThrSwitch; - private static KeyBinding apSwitch; private static void setupKeycCode() { keyBinding = new KeyBinding("key.flighthud.toggleDisplayMode", InputUtil.Type.KEYSYM, GLFW.GLFW_KEY_GRAVE_ACCENT, "category.flighthud.toggleDisplayMode"); - hideAlertSwitch = new KeyBinding("key.flighthud.hideAlertSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_0, "category.flighthud.toggleDisplayMode"); - - showAlertSwitch = new KeyBinding("key.flighthud.showAlertSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_DECIMAL, "category.flighthud.toggleDisplayMode"); - - flightLawSwitch = new KeyBinding("key.flighthud.flightLawSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_ENTER, "category.flighthud.toggleDisplayMode"); - - gpwsSwitch = new KeyBinding("key.flighthud.gpwsSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_ADD, "category.flighthud.toggleDisplayMode"); - - fdSwitch = new KeyBinding("key.flighthud.fdSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_1, "category.flighthud.toggleDisplayMode"); - - aThrSwitch = new KeyBinding("key.flighthud.aThrSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_2, "category.flighthud.toggleDisplayMode"); - - apSwitch = new KeyBinding("key.flighthud.apSwitch", InputUtil.Type.KEYSYM, - GLFW.GLFW_KEY_KP_3, "category.flighthud.toggleDisplayMode"); - - KeyBindingHelper.registerKeyBinding(keyBinding); - KeyBindingHelper.registerKeyBinding(hideAlertSwitch); - KeyBindingHelper.registerKeyBinding(showAlertSwitch); - KeyBindingHelper.registerKeyBinding(flightLawSwitch); - KeyBindingHelper.registerKeyBinding(gpwsSwitch); - KeyBindingHelper.registerKeyBinding(fdSwitch); - KeyBindingHelper.registerKeyBinding(aThrSwitch); - KeyBindingHelper.registerKeyBinding(apSwitch); ClientTickEvents.END_CLIENT_TICK.register(client -> { while (keyBinding.wasPressed()) { CONFIG_SETTINGS.toggleDisplayMode(); } - - while (hideAlertSwitch.wasPressed()) { - for (Alert alert : FlightStatusIndicator.activeAlerts) { - if (alert.hidden) continue; - alert.hidden = true; - break; - } - } - - while (showAlertSwitch.wasPressed()) { - for (int i = FlightStatusIndicator.activeAlerts.size() - 1; i >= 0; i--) { - Alert alert = FlightStatusIndicator.activeAlerts.get(i); - if (!alert.hidden) continue; - alert.hidden = false; - break; - } - } - - while (flightLawSwitch.wasPressed()) { - FlightSafetyMonitor.flightProtectionsEnabled = !FlightSafetyMonitor.flightProtectionsEnabled; - } - - while (gpwsSwitch.wasPressed()) { - CONFIG_SETTINGS.gpws = !CONFIG_SETTINGS.gpws; - } - - while (fdSwitch.wasPressed()) { - AutoFlightManager.flightDirectorsEnabled = !AutoFlightManager.flightDirectorsEnabled; - } - - while (aThrSwitch.wasPressed()) { - AutoFlightManager.autoThrustEnabled = !AutoFlightManager.autoThrustEnabled; - if (!AutoFlightManager.autoThrustEnabled) - FlightSafetyMonitor.thrustLocked = false; - } - - while (apSwitch.wasPressed()) { - AutoFlightManager.autoPilotEnabled = !AutoFlightManager.autoPilotEnabled; - } }); } @@ -145,17 +61,7 @@ private static void setupCommand() { LiteralCommandNode node = dispatcher.register(literal("flighthud") .then(literal("toggle").executes(new SwitchDisplayModeCommand())) - .then(literal("nav") - .then(argument("destinationX", IntegerArgumentType.integer(-30_000_000, 30_000_000)) - .then(argument("destinationZ", IntegerArgumentType.integer(-30_000_000, 30_000_000)) - .executes(new DestinationSelectCommand()))) - .then(literal("reset") - .executes(new DestinationResetCommand()))) - .then(literal("alt") - .then(argument("targetAltitude", IntegerArgumentType.integer(0, 640)) - .executes(new AltitudeSelectCommand())) - .then(literal("reset") - .executes(new AltitudeResetCommand())))); + ); dispatcher.register(literal("fhud").redirect(node)); dispatcher.register(literal("fh").redirect(node)); }); diff --git a/src/main/java/net/torocraft/flighthud/FlightSafetyMonitor.java b/src/main/java/net/torocraft/flighthud/FlightSafetyMonitor.java deleted file mode 100644 index eb597bb9..00000000 --- a/src/main/java/net/torocraft/flighthud/FlightSafetyMonitor.java +++ /dev/null @@ -1,182 +0,0 @@ -package net.torocraft.flighthud; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import java.util.List; -import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.FireworkRocketItem; -import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.util.Hand; -import net.minecraft.util.hit.BlockHitResult; -import net.minecraft.util.hit.HitResult; -import net.minecraft.util.math.Direction; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.RaycastContext; - -import static net.torocraft.flighthud.AutoFlightManager.changeLookDirection; -import static net.torocraft.flighthud.AutoFlightManager.deltaTime; -import static net.torocraft.flighthud.FlightHud.CONFIG_SETTINGS; -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class FlightSafetyMonitor { - public static List unsafeFireworkHands = new ObjectArrayList<>(2); - public static Hand usableFireworkHand = null; - - public static boolean isElytraLow = false; - - public static boolean isStalling = false; - public static float maximumSafePitch = 0.0f; - - public static float secondsUntilGroundImpact = 0.0f; - public static float secondsUntilTerrainImpact = 0.0f; - public static float terrainDetectionTimer = 0.0f; - public static int gpwsLampColor; - - public static float lampThreshold = 0.0f; - public static float cautionThreshold = 0.0f; - public static float warningThreshold = 0.0f; - public static float correctThreshold = 0.0f; - - public static boolean flightProtectionsEnabled = true; - - public static boolean thrustSet = true; - public static boolean havePassengersDismounted = false; - public static long lastFireworkActivationTimeMs = 0; - - public static int fireworkCount = Integer.MAX_VALUE; - public static boolean thrustLocked = false; - private static int lastPassengers = 0; - - public static void update(MinecraftClient mc, FlightComputer computer) { - if (CONFIG == null || mc.world == null || mc.player == null || !mc.player.isFallFlying()) { - flightProtectionsEnabled = thrustSet = true; - thrustLocked = havePassengersDismounted = false; - lastPassengers = 0; - return; - } - maximumSafePitch = updateMaximumSafePitch(computer); - secondsUntilGroundImpact = updateUnsafeSinkrate(computer); - - boolean hasCeiling = mc.player.getWorld().getDimension().hasCeiling(); - lampThreshold = hasCeiling ? 7.5f : 10.0f; - cautionThreshold = hasCeiling ? 5.0f : 7.5f; - warningThreshold = hasCeiling ? 2.5f : 5.0f; - correctThreshold = hasCeiling ? 1.0f : 2.5f; - - if (secondsUntilGroundImpact <= warningThreshold || secondsUntilTerrainImpact <= warningThreshold) - gpwsLampColor = CONFIG.alertColor; - else if (secondsUntilGroundImpact <= lampThreshold || secondsUntilTerrainImpact <= lampThreshold) - gpwsLampColor = CONFIG.amberColor; - else - gpwsLampColor = CONFIG.color; - - isStalling = updateStallStatus(computer); - isElytraLow = updateElytraLow(computer); - secondsUntilTerrainImpact = updateUnsafeTerrainClearance(mc.player, computer); - updateUnsafeFireworks(mc.player); - fireworkCount = countSafeFireworks(mc.player); - - havePassengersDismounted = updatePassengersDismounted(mc); - - if (flightProtectionsEnabled) { // Make corrections to flight path to ensure safety - float delta = deltaTime / Math.min(1, secondsUntilGroundImpact); - if (computer.distanceFromGround > 3 && computer.pitch > maximumSafePitch) - changeLookDirection(mc.player, Math.max(0, computer.pitch - maximumSafePitch) * delta, 0); - - else if (secondsUntilGroundImpact <= correctThreshold) - changeLookDirection(mc.player, Math.min(0, computer.pitch) * delta, 0); - } - } - - private static boolean updatePassengersDismounted(MinecraftClient mc) { - int currentPassengers = (int) mc.player.getPassengerList().stream().flatMap(Entity::streamSelfAndPassengers).count(); - boolean b = currentPassengers < lastPassengers; - lastPassengers = currentPassengers; - return b; - } - - private static void updateUnsafeFireworks(PlayerEntity player) { - unsafeFireworkHands.clear(); - if (!CONFIG_SETTINGS.unsafeFireworksAlert) return; - - ItemStack main = player.getMainHandStack(); - ItemStack off = player.getOffHandStack(); - - usableFireworkHand = null; - if (off.getItem() instanceof FireworkRocketItem) { - NbtCompound nbtCompound = off.getSubNbt("Fireworks"); - if (nbtCompound != null && !nbtCompound.getList("Explosions", 10).isEmpty()) - unsafeFireworkHands.add(Hand.OFF_HAND); - else usableFireworkHand = Hand.OFF_HAND; - } - if (main.getItem() instanceof FireworkRocketItem) { - NbtCompound nbtCompound = main.getSubNbt("Fireworks"); - if (nbtCompound != null && !nbtCompound.getList("Explosions", 10).isEmpty()) - unsafeFireworkHands.add(Hand.MAIN_HAND); - else usableFireworkHand = Hand.MAIN_HAND; - } - } - - private static boolean updateElytraLow(FlightComputer computer) { - return CONFIG_SETTINGS.lowElytraHealthAlarm && computer.elytraHealth != null && computer.elytraHealth <= CONFIG_SETTINGS.lowElytraHealthAlarmThreshold; - } - - private static boolean updateStallStatus(FlightComputer computer) { - return computer.pitch > 0 && computer.distanceFromGround > 3 && computer.velocity.horizontalLength() < -computer.velocity.y; - } - - private static float updateMaximumSafePitch(FlightComputer computer) { - return isStalling && computer.velocityPerSecond.y <= -10 ? 0.0f : computer.speed * 3; - } - - private static float updateUnsafeSinkrate(FlightComputer computer) { - if (!CONFIG_SETTINGS.gpws || isStalling || computer.distanceFromGround <= 3 || computer.velocityPerSecond.y > -10) - return Float.MAX_VALUE; - return (float) (computer.distanceFromGround / -computer.velocityPerSecond.y); - } - - private static float updateUnsafeTerrainClearance(PlayerEntity player, FlightComputer computer) { - if (!CONFIG_SETTINGS.gpws || isStalling || computer.velocityPerSecond.horizontalLength() <= 15) - return Float.MAX_VALUE; - Vec3d vec = raycast(player, computer, 10); - float f = vec == null ? Float.MAX_VALUE : (float) (vec.subtract(player.getPos()).horizontalLength() / computer.velocityPerSecond.horizontalLength()); - if (f <= 10.0f) { - f = Math.min(f, secondsUntilTerrainImpact); - terrainDetectionTimer = Math.min(0.5f, terrainDetectionTimer + deltaTime); - } else { - terrainDetectionTimer = Math.max(0.0f, terrainDetectionTimer - deltaTime); - if (terrainDetectionTimer > 0.0f) - f = Math.min(f, secondsUntilTerrainImpact); - } - - return f > 10.0f || terrainDetectionTimer >= Math.min(0.5f, f * 0.2f) ? f : Float.MAX_VALUE; - } - - private static int countSafeFireworks(PlayerEntity player) { - int i = 0; - - for (int j = 0; j < player.getInventory().size(); j++) { - ItemStack stack = player.getInventory().getStack(j); - if (stack.getItem().equals(Items.FIREWORK_ROCKET)) { - NbtCompound nbtCompound = stack.getSubNbt("Fireworks"); - if (nbtCompound == null || nbtCompound.getList("Explosions", 10).isEmpty()) - i += stack.getCount(); - } - } - - return i; - } - - public static Vec3d raycast(PlayerEntity player, FlightComputer computer, int seconds) { - Vec3d vel = computer.velocityPerSecond; - Vec3d end = player.getPos().add(vel.multiply(seconds)); - - BlockHitResult result = player.getWorld().raycast(new RaycastContext(player.getPos(), end, RaycastContext.ShapeType.COLLIDER, RaycastContext.FluidHandling.ANY, player)); - if (result.getType() != HitResult.Type.BLOCK || result.getSide() == Direction.UP || result.getSide() == Direction.DOWN) - return null; - return result.getPos(); - } -} diff --git a/src/main/java/net/torocraft/flighthud/HudRenderer.java b/src/main/java/net/torocraft/flighthud/HudRenderer.java index d76f0ed9..9fd1bb8f 100644 --- a/src/main/java/net/torocraft/flighthud/HudRenderer.java +++ b/src/main/java/net/torocraft/flighthud/HudRenderer.java @@ -6,24 +6,30 @@ import net.torocraft.flighthud.components.AltitudeIndicator; import net.torocraft.flighthud.components.ElytraHealthIndicator; import net.torocraft.flighthud.components.FlightPathIndicator; -import net.torocraft.flighthud.components.FlightStatusIndicator; import net.torocraft.flighthud.components.HeadingIndicator; import net.torocraft.flighthud.components.LocationIndicator; import net.torocraft.flighthud.components.PitchIndicator; import net.torocraft.flighthud.components.SpeedIndicator; +import net.torocraft.flighthud.computers.FlightComputer; import net.torocraft.flighthud.config.SettingsConfig.DisplayMode; public class HudRenderer extends HudComponent { - public static final HudRenderer INSTANCE = new HudRenderer(); private static final String FULL = DisplayMode.FULL.toString(); private static final String MIN = DisplayMode.MIN.toString(); - public final FlightComputer computer = new FlightComputer(); + public static HudRenderer INSTANCE; + public final FlightComputer computer; private final Dimensions dim = new Dimensions(); - private final HudComponent[] components = - new HudComponent[]{new FlightPathIndicator(computer, dim), new LocationIndicator(dim), - new HeadingIndicator(computer, dim), new SpeedIndicator(computer, dim), - new AltitudeIndicator(computer, dim), new PitchIndicator(computer, dim), - new ElytraHealthIndicator(computer, dim), new FlightStatusIndicator(computer, dim)}; + private final HudComponent[] components; + + public HudRenderer(MinecraftClient mc) { + this.computer = new FlightComputer(mc); + this.components = new HudComponent[]{ + new FlightPathIndicator(computer, dim), new LocationIndicator(dim), + new HeadingIndicator(computer, dim), new SpeedIndicator(computer, dim), + new AltitudeIndicator(computer, dim), new PitchIndicator(computer, dim), + new ElytraHealthIndicator(computer, dim) + }; + } private void setupConfig(MinecraftClient client) { HudComponent.CONFIG = null; @@ -45,7 +51,6 @@ private void setupConfig(MinecraftClient client) { @Override public void render(DrawContext context, MinecraftClient client) { setupConfig(client); - ((FlightStatusIndicator) components[components.length - 1]).tryStopEvents(client.player, client.getSoundManager()); if (HudComponent.CONFIG == null) { return; diff --git a/src/main/java/net/torocraft/flighthud/Util.java b/src/main/java/net/torocraft/flighthud/Util.java new file mode 100644 index 00000000..2c69487d --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/Util.java @@ -0,0 +1,9 @@ +package net.torocraft.flighthud; + +import net.minecraft.util.math.Vec3d; + +public class Util { + public static Vec3d copyVec3d(Vec3d from) { + return new Vec3d(from.x, from.y, from.z); + } +} diff --git a/src/main/java/net/torocraft/flighthud/alerts/AutoThrustLimitedAlert.java b/src/main/java/net/torocraft/flighthud/alerts/AutoThrustLimitedAlert.java deleted file mode 100644 index a3b50331..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/AutoThrustLimitedAlert.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class AutoThrustLimitedAlert extends Alert { - @Override - public boolean shouldActivate() { - return AutoFlightManager.autoThrustEnabled && FlightSafetyMonitor.usableFireworkHand == null; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawCaution(mc, context, x, y, highlight, "AUTO THRUST LIMITED"); - if (FlightSafetyMonitor.fireworkCount > 0) - i += HudComponent.drawFont(mc, context, " -FRWKS: SELECT", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/Alert.java b/src/main/java/net/torocraft/flighthud/alerts/ECAMAlert.java similarity index 63% rename from src/main/java/net/torocraft/flighthud/alerts/Alert.java rename to src/main/java/net/torocraft/flighthud/alerts/ECAMAlert.java index 203098ba..0c17a25c 100644 --- a/src/main/java/net/torocraft/flighthud/alerts/Alert.java +++ b/src/main/java/net/torocraft/flighthud/alerts/ECAMAlert.java @@ -6,7 +6,7 @@ import static net.torocraft.flighthud.HudComponent.CONFIG; -public abstract class Alert { +public abstract class ECAMAlert implements IAlert { public boolean hidden; public static int drawWarning(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight, String text) { @@ -20,16 +20,8 @@ public static int drawWarning(MinecraftClient mc, DrawContext context, float x, } public static int drawCaution(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight, String text) { - if (highlight) { - HudComponent.drawTextHighlight(mc.textRenderer, context, x, y, text, CONFIG.amberColor); - HudComponent.drawFont(mc, context, text, x, y, CONFIG.black); - return 1; - } - HudComponent.drawFont(mc, context, text, x, y, CONFIG.amberColor); + HudComponent.drawTextHighlight(mc.textRenderer, context, x, y, text, CONFIG.amberColor); + HudComponent.drawFont(mc, context, text, x, y, CONFIG.black); return 1; } - - public abstract boolean shouldActivate(); - - public abstract int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight); } diff --git a/src/main/java/net/torocraft/flighthud/alerts/FireworkActivationFailureAlert.java b/src/main/java/net/torocraft/flighthud/alerts/FireworkActivationFailureAlert.java deleted file mode 100644 index a2406a0b..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/FireworkActivationFailureAlert.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.AutoFlightManager.lastUpdateTimeMs; -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class FireworkActivationFailureAlert extends Alert { - @Override - public boolean shouldActivate() { - return !FlightSafetyMonitor.thrustSet && lastUpdateTimeMs - FlightSafetyMonitor.lastFireworkActivationTimeMs > 1000; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawWarning(mc, context, x, y, highlight, "FRWK ACTIVATION FAIL"); - if (AutoFlightManager.flightDirectorsEnabled) - i += HudComponent.drawFont(mc, context, " -FD: OFF", x, y += 9, CONFIG.adviceColor); - if (AutoFlightManager.autoThrustEnabled) - i += HudComponent.drawFont(mc, context, " -A/THR: OFF", x, y += 9, CONFIG.adviceColor); - if (AutoFlightManager.autoPilotEnabled) - i += HudComponent.drawFont(mc, context, " -A/P: OFF", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -PITCH: MAX SAFE UP", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -FRWKS: DO NOT USE", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " SPD MAY BE UNRELIABLE", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/FlightProtectionsOffAlert.java b/src/main/java/net/torocraft/flighthud/alerts/FlightProtectionsOffAlert.java deleted file mode 100644 index 5960f932..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/FlightProtectionsOffAlert.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class FlightProtectionsOffAlert extends Alert { - @Override - public boolean shouldActivate() { - return !FlightSafetyMonitor.flightProtectionsEnabled; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawCaution(mc, context, x, y, highlight, "FLIGHT PROTECTIONS OFF"); - i += HudComponent.drawFont(mc, context, " MAX PITCH: 40* UP", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " MIN V/S: -8 BPS", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -FRWKS: CONFIRM SAFE", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " MANEUVER WITH CARE", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/GPWSOffAlert.java b/src/main/java/net/torocraft/flighthud/alerts/GPWSOffAlert.java deleted file mode 100644 index d2cc3c58..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/GPWSOffAlert.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.FlightHud.CONFIG_SETTINGS; -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class GPWSOffAlert extends Alert { - @Override - public boolean shouldActivate() { - return !CONFIG_SETTINGS.gpws; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawCaution(mc, context, x, y, highlight, "GPWS OFF"); - i += HudComponent.drawFont(mc, context, " BELOW 320M", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -A/P: DO NOT USE", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " BELOW 320M", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -A/THR: DO NOT USE", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/IAlert.java b/src/main/java/net/torocraft/flighthud/alerts/IAlert.java new file mode 100644 index 00000000..00984aec --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/alerts/IAlert.java @@ -0,0 +1,12 @@ +package net.torocraft.flighthud.alerts; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; + +public interface IAlert { + boolean isTriggered(); + + void tick(); + + int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight); +} diff --git a/src/main/java/net/torocraft/flighthud/alerts/LowElytraHealthAlert.java b/src/main/java/net/torocraft/flighthud/alerts/LowElytraHealthAlert.java deleted file mode 100644 index dc12e516..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/LowElytraHealthAlert.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.FlightSafetyMonitor; - -public class LowElytraHealthAlert extends Alert { - @Override - public boolean shouldActivate() { - return FlightSafetyMonitor.isElytraLow; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - return drawWarning(mc, context, x, y, highlight, "ELYTRA HEALTH LOW"); - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/LowFireworksAlert.java b/src/main/java/net/torocraft/flighthud/alerts/LowFireworksAlert.java deleted file mode 100644 index c50c665c..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/LowFireworksAlert.java +++ /dev/null @@ -1,25 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class LowFireworksAlert extends Alert { - @Override - public boolean shouldActivate() { - return FlightSafetyMonitor.fireworkCount > 0 && FlightSafetyMonitor.fireworkCount < 24; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawCaution(mc, context, x, y, highlight, "FRWK CNT BELOW 24"); - if (AutoFlightManager.autoThrustEnabled) - i += HudComponent.drawFont(mc, context, " -A/THR: OFF", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " -CLIMB: INITIATE", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/NoFireworksAlert.java b/src/main/java/net/torocraft/flighthud/alerts/NoFireworksAlert.java deleted file mode 100644 index e0e81e99..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/NoFireworksAlert.java +++ /dev/null @@ -1,28 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class NoFireworksAlert extends Alert { - @Override - public boolean shouldActivate() { - return FlightSafetyMonitor.fireworkCount <= 0; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawWarning(mc, context, x, y, highlight, "FRWK CNT ZERO"); - if (AutoFlightManager.autoThrustEnabled) - i += HudComponent.drawFont(mc, context, " -A/THR: OFF", x, y += 9, CONFIG.adviceColor); - if (AutoFlightManager.targetAltitude != null) - i += HudComponent.drawFont(mc, context, " -A/P ALT: RESET", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " GLDG DIST:", x, y += 9, CONFIG.adviceColor); - i += HudComponent.drawFont(mc, context, " 100 BLKS/10 M", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/PassengerDismountedAlert.java b/src/main/java/net/torocraft/flighthud/alerts/PassengerDismountedAlert.java deleted file mode 100644 index e8e1a85f..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/PassengerDismountedAlert.java +++ /dev/null @@ -1,17 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.FlightSafetyMonitor; - -public class PassengerDismountedAlert extends Alert { - @Override - public boolean shouldActivate() { - return FlightSafetyMonitor.havePassengersDismounted; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - return drawWarning(mc, context, x, y, highlight, "PAX DISMOUNTED"); - } -} \ No newline at end of file diff --git a/src/main/java/net/torocraft/flighthud/alerts/ThrustLockedAlert.java b/src/main/java/net/torocraft/flighthud/alerts/ThrustLockedAlert.java deleted file mode 100644 index ff68611e..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/ThrustLockedAlert.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.FlightHud.CONFIG_SETTINGS; -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class ThrustLockedAlert extends Alert { - @Override - public boolean shouldActivate() { - return FlightSafetyMonitor.thrustLocked; - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int i = drawCaution(mc, context, x, y, highlight, "THRUST LOCKED"); - if (!CONFIG_SETTINGS.gpws) - i += HudComponent.drawFont(mc, context, "-GPWS: ON", x, y += 9, CONFIG.adviceColor); - if (!AutoFlightManager.autoPilotEnabled) - i += HudComponent.drawFont(mc, context, "-A/P: ON", x, y += 9, CONFIG.adviceColor); - if (!AutoFlightManager.autoThrustEnabled) { - i += HudComponent.drawFont(mc, context, "-A/THR: ON THEN OFF", x, y + 9, CONFIG.adviceColor); - return i; - } - i += HudComponent.drawFont(mc, context, "-A/THR: OFF", x, y + 9, CONFIG.adviceColor); - return i; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/UnsafeFireworksAlert.java b/src/main/java/net/torocraft/flighthud/alerts/UnsafeFireworksAlert.java deleted file mode 100644 index acc42258..00000000 --- a/src/main/java/net/torocraft/flighthud/alerts/UnsafeFireworksAlert.java +++ /dev/null @@ -1,42 +0,0 @@ -package net.torocraft.flighthud.alerts; - -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.util.Hand; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.HudComponent.CONFIG; - -public class UnsafeFireworksAlert extends Alert { - - @Override - public boolean shouldActivate() { - return !FlightSafetyMonitor.unsafeFireworkHands.isEmpty(); - } - - @Override - public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { - int linesDrawn = 0; - if (highlight) { - for (Hand hand : FlightSafetyMonitor.unsafeFireworkHands) { - String handStr = hand.toString().replace('_', ' '); - String text = handStr + " FRWKS UNSAFE"; - HudComponent.drawTextHighlight(mc.textRenderer, context, x, y, text, CONFIG.alertColor); - HudComponent.drawFont(mc, context, text, x, y, CONFIG.white); - y += 9; - linesDrawn++; - } - return linesDrawn; - } - - for (Hand hand : FlightSafetyMonitor.unsafeFireworkHands) { - String handStr = hand.toString().replace('_', ' '); - String result = handStr + " FRWKS UNSAFE"; - HudComponent.drawFont(mc, context, result, x, y, CONFIG.alertColor); - y += 9; - linesDrawn++; - } - return linesDrawn; - } -} diff --git a/src/main/java/net/torocraft/flighthud/alerts/nav/gpws/UnsafeSinkrateAlert.java b/src/main/java/net/torocraft/flighthud/alerts/nav/gpws/UnsafeSinkrateAlert.java new file mode 100644 index 00000000..d79f06e4 --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/alerts/nav/gpws/UnsafeSinkrateAlert.java @@ -0,0 +1,34 @@ +package net.torocraft.flighthud.alerts.nav.gpws; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.DrawContext; +import net.torocraft.flighthud.alerts.IAlert; +import net.torocraft.flighthud.computers.FlightComputer; + +public class UnsafeSinkrateAlert implements IAlert { + private final FlightComputer computer; + + public UnsafeSinkrateAlert(FlightComputer computer) { + this.computer = computer; + } + + @Override + public boolean isTriggered() { + return computer.gpws.getImpactTime() >= 0; + } + + @Override + public void tick() { + boolean shouldLevelOff = computer.gpws.getImpactTime() <= 2.5f; + if (shouldLevelOff) { + // Looks like it's trying to kill us. + computer.autoflight.disconnectAutopilot(true); + } + computer.pitchController.forceLevelOff = shouldLevelOff; + } + + @Override + public int drawText(MinecraftClient mc, DrawContext context, float x, float y, boolean highlight) { + return 0; + } +} diff --git a/src/main/java/net/torocraft/flighthud/commands/AltitudeResetCommand.java b/src/main/java/net/torocraft/flighthud/commands/AltitudeResetCommand.java deleted file mode 100644 index aebc9ed9..00000000 --- a/src/main/java/net/torocraft/flighthud/commands/AltitudeResetCommand.java +++ /dev/null @@ -1,14 +0,0 @@ -package net.torocraft.flighthud.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.torocraft.flighthud.AutoFlightManager; - -public class AltitudeResetCommand implements Command { - @Override - public int run(CommandContext context) { - AutoFlightManager.targetAltitude = null; - return 0; - } -} diff --git a/src/main/java/net/torocraft/flighthud/commands/AltitudeSelectCommand.java b/src/main/java/net/torocraft/flighthud/commands/AltitudeSelectCommand.java deleted file mode 100644 index 8de69f10..00000000 --- a/src/main/java/net/torocraft/flighthud/commands/AltitudeSelectCommand.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.torocraft.flighthud.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.torocraft.flighthud.AutoFlightManager; - -public class AltitudeSelectCommand implements Command { - @Override - public int run(CommandContext context) { - AutoFlightManager.targetAltitude = IntegerArgumentType.getInteger(context, "targetAltitude"); - return 0; - } -} diff --git a/src/main/java/net/torocraft/flighthud/commands/DestinationResetCommand.java b/src/main/java/net/torocraft/flighthud/commands/DestinationResetCommand.java deleted file mode 100644 index f3c3f049..00000000 --- a/src/main/java/net/torocraft/flighthud/commands/DestinationResetCommand.java +++ /dev/null @@ -1,15 +0,0 @@ -package net.torocraft.flighthud.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.torocraft.flighthud.AutoFlightManager; - -public class DestinationResetCommand implements Command { - @Override - public int run(CommandContext context) { - AutoFlightManager.destinationX = null; - AutoFlightManager.destinationZ = null; - return 0; - } -} diff --git a/src/main/java/net/torocraft/flighthud/commands/DestinationSelectCommand.java b/src/main/java/net/torocraft/flighthud/commands/DestinationSelectCommand.java deleted file mode 100644 index 0925d7be..00000000 --- a/src/main/java/net/torocraft/flighthud/commands/DestinationSelectCommand.java +++ /dev/null @@ -1,16 +0,0 @@ -package net.torocraft.flighthud.commands; - -import com.mojang.brigadier.Command; -import com.mojang.brigadier.arguments.IntegerArgumentType; -import com.mojang.brigadier.context.CommandContext; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.torocraft.flighthud.AutoFlightManager; - -public class DestinationSelectCommand implements Command { - @Override - public int run(CommandContext context) { - AutoFlightManager.destinationX = IntegerArgumentType.getInteger(context, "destinationX"); - AutoFlightManager.destinationZ = IntegerArgumentType.getInteger(context, "destinationZ"); - return 0; - } -} diff --git a/src/main/java/net/torocraft/flighthud/components/AltitudeIndicator.java b/src/main/java/net/torocraft/flighthud/components/AltitudeIndicator.java index 7ca083f5..dd173f0b 100644 --- a/src/main/java/net/torocraft/flighthud/components/AltitudeIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/AltitudeIndicator.java @@ -3,8 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; import net.torocraft.flighthud.HudComponent; +import net.torocraft.flighthud.computers.FlightComputer; public class AltitudeIndicator extends HudComponent { private final Dimensions dim; diff --git a/src/main/java/net/torocraft/flighthud/components/ElytraHealthIndicator.java b/src/main/java/net/torocraft/flighthud/components/ElytraHealthIndicator.java index edbfd7af..59162802 100644 --- a/src/main/java/net/torocraft/flighthud/components/ElytraHealthIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/ElytraHealthIndicator.java @@ -3,10 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.FlightHud.CONFIG_SETTINGS; +import net.torocraft.flighthud.computers.FlightComputer; public class ElytraHealthIndicator extends HudComponent { @@ -24,7 +22,7 @@ public void render(DrawContext context, MinecraftClient mc) { float y = dim.hScreen * CONFIG.elytra_y; if (CONFIG.elytra_showHealth && computer.elytraHealth != null) { - int color = computer.elytraHealth <= CONFIG_SETTINGS.lowElytraHealthAlarmThreshold ? CONFIG.alertColor : CONFIG.color; + int color = CONFIG.color; drawBox(context, x - 3.5f, y - 1.5f, 30, color); drawFont(mc, context, "E", x - 10, y, color); drawFont(mc, context, String.format("%d", i(computer.elytraHealth)) + "%", x, y, color); diff --git a/src/main/java/net/torocraft/flighthud/components/FlightPathIndicator.java b/src/main/java/net/torocraft/flighthud/components/FlightPathIndicator.java index 88aa1309..a624ec48 100644 --- a/src/main/java/net/torocraft/flighthud/components/FlightPathIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/FlightPathIndicator.java @@ -3,10 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.FlightSafetyMonitor.gpwsLampColor; +import net.torocraft.flighthud.computers.FlightComputer; public class FlightPathIndicator extends HudComponent { private final Dimensions dim; @@ -45,14 +43,14 @@ public void render(DrawContext context, MinecraftClient client) { float t = y - 3 - CONFIG.halfThickness; float b = y + 3 - CONFIG.halfThickness; - drawVerticalLine(context, l, t, b, gpwsLampColor); - drawVerticalLine(context, r, t, b, gpwsLampColor); + drawVerticalLine(context, l, t, b, CONFIG.color); + drawVerticalLine(context, r, t, b, CONFIG.color); - drawHorizontalLine(context, l, r, t, gpwsLampColor); - drawHorizontalLine(context, l, r, b, gpwsLampColor); + drawHorizontalLine(context, l, r, t, CONFIG.color); + drawHorizontalLine(context, l, r, b, CONFIG.color); - drawVerticalLine(context, x, t - 5, t, gpwsLampColor); - drawHorizontalLine(context, l - 4, l, y - CONFIG.halfThickness, gpwsLampColor); - drawHorizontalLine(context, r, r + 4, y - CONFIG.halfThickness, gpwsLampColor); + drawVerticalLine(context, x, t - 5, t, CONFIG.color); + drawHorizontalLine(context, l - 4, l, y - CONFIG.halfThickness, CONFIG.color); + drawHorizontalLine(context, r, r + 4, y - CONFIG.halfThickness, CONFIG.color); } } diff --git a/src/main/java/net/torocraft/flighthud/components/FlightStatusIndicator.java b/src/main/java/net/torocraft/flighthud/components/FlightStatusIndicator.java deleted file mode 100644 index 19d12fe7..00000000 --- a/src/main/java/net/torocraft/flighthud/components/FlightStatusIndicator.java +++ /dev/null @@ -1,218 +0,0 @@ -package net.torocraft.flighthud.components; - -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import java.util.ArrayList; -import java.util.List; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.sound.SoundManager; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.util.Identifier; -import net.torocraft.flighthud.AlertSoundInstance; -import net.torocraft.flighthud.AutoFlightManager; -import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; -import net.torocraft.flighthud.FlightSafetyMonitor; -import net.torocraft.flighthud.HudComponent; -import net.torocraft.flighthud.alerts.Alert; -import net.torocraft.flighthud.alerts.AutoThrustLimitedAlert; -import net.torocraft.flighthud.alerts.FireworkActivationFailureAlert; -import net.torocraft.flighthud.alerts.FlightProtectionsOffAlert; -import net.torocraft.flighthud.alerts.GPWSOffAlert; -import net.torocraft.flighthud.alerts.LowElytraHealthAlert; -import net.torocraft.flighthud.alerts.LowFireworksAlert; -import net.torocraft.flighthud.alerts.NoFireworksAlert; -import net.torocraft.flighthud.alerts.PassengerDismountedAlert; -import net.torocraft.flighthud.alerts.ThrustLockedAlert; -import net.torocraft.flighthud.alerts.UnsafeFireworksAlert; - -import static net.torocraft.flighthud.AutoFlightManager.deltaTime; -import static net.torocraft.flighthud.AutoFlightManager.lastUpdateTimeMs; -import static net.torocraft.flighthud.FlightHud.CONFIG_SETTINGS; - -public class FlightStatusIndicator extends HudComponent { - public static final SoundEvent ALERT = SoundEvent.of(new Identifier("flighthud:alert")); - public static final SoundEvent STICK_SHAKER = SoundEvent.of(new Identifier("flighthud:stick_shaker")); - public static final SoundEvent STALL_WARNING = SoundEvent.of(new Identifier("flighthud:stall_warning")); - public static final SoundEvent SINKRATE = SoundEvent.of(new Identifier("flighthud:sinkrate")); - public static final SoundEvent TERRAIN = SoundEvent.of(new Identifier("flighthud:terrain")); - public static final SoundEvent PULL_UP = SoundEvent.of(new Identifier("flighthud:pull_up")); - public static final SoundEvent AUTOPILOT_DISCONNECT = SoundEvent.of(new Identifier("flighthud:autopilot_disconnect")); - public static final Alert[] registeredAlerts = { - new AutoThrustLimitedAlert(), new ThrustLockedAlert(), - new FlightProtectionsOffAlert(), new GPWSOffAlert(), - new LowElytraHealthAlert(), - new LowFireworksAlert(), new NoFireworksAlert(), - new UnsafeFireworksAlert(), new FireworkActivationFailureAlert(), - new PassengerDismountedAlert() - }; - public static final List activeAlerts = new ArrayList<>(); - private static long lastHighlightTimeMs = 0L; - - private final List activeEvents = new ObjectArrayList<>(2); - private final Dimensions dim; - private final FlightComputer computer; - public boolean highlight = true; - private boolean lastAutopilotState = false; - private AlertSoundInstance stickShakerInstance; - - public FlightStatusIndicator(FlightComputer computer, Dimensions dim) { - this.dim = dim; - this.computer = computer; - } - - @Override - public void render(DrawContext context, MinecraftClient mc) { - if (mc.world == null || mc.player == null || !mc.player.isFallFlying()) return; - if (lastUpdateTimeMs - lastHighlightTimeMs >= 500) { - highlight = !highlight; - lastHighlightTimeMs = lastUpdateTimeMs; - } - - float x = dim.lFrame + 5; - float xRight = dim.rFrame - 5; - float y = dim.tFrame + 15; - float yRight = y - 10; - - for (Alert alert : registeredAlerts) { - if (!activeAlerts.contains(alert) && alert.shouldActivate()) { - playOnce(mc, ALERT, 0.75f, false); - alert.hidden = false; - activeAlerts.add(alert); - } - } - - for (Alert alert : activeAlerts) { - if (alert.hidden) continue; - y += 9 * alert.drawText(mc, context, x, y, highlight); - } - - int fwobLampColor = FlightSafetyMonitor.fireworkCount > 0 - ? (FlightSafetyMonitor.fireworkCount < 24 ? CONFIG.amberColor : CONFIG.color) - : CONFIG.alertColor; - drawRightAlignedFont(mc, context, "FRWK CNT: " + FlightSafetyMonitor.fireworkCount, xRight, yRight += 9, fwobLampColor); - // Right-side ECAM - if (AutoFlightManager.flightDirectorsEnabled) { - drawRightAlignedFont(mc, context, "FD", xRight, yRight += 9, CONFIG.color); - - // Flight directors - if (AutoFlightManager.targetPitch != null) { - float deltaPitch = computer.pitch + AutoFlightManager.targetPitch; - float fdY = Math.max(dim.tFrame, Math.min(dim.bFrame, dim.yMid + i(deltaPitch * dim.degreesPerPixel))); - drawHorizontalLine(context, dim.xMid - dim.wFrame * 0.15f, dim.xMid + dim.wFrame * 0.15f, fdY, CONFIG.adviceColor); - } - - if (AutoFlightManager.targetHeading != null) { - float deltaHeading = wrapHeading(AutoFlightManager.targetHeading) - wrapHeading(computer.heading); - if (deltaHeading < -180) { - deltaHeading += 360; - } - - float fdX = Math.max(dim.lFrame, Math.min(dim.rFrame, dim.xMid + i(deltaHeading * dim.degreesPerPixel))); - drawVerticalLine(context, fdX, dim.yMid - dim.hFrame * 0.15f, dim.yMid + dim.hFrame * 0.15f, CONFIG.adviceColor); - } - } - if (AutoFlightManager.distanceToTarget != null) { - drawRightAlignedFont(mc, context, String.format("DIST: %.0f", AutoFlightManager.distanceToTarget), xRight, yRight + 9, CONFIG.color); - } - drawCenteredFont(mc, context, AutoFlightManager.statusString, dim.wScreen, dim.tFrame + 15, CONFIG.color); - - if (lastAutopilotState) { - if (!AutoFlightManager.autoPilotEnabled) - playOnce(mc, AUTOPILOT_DISCONNECT, 1f, false); - else stopEvent(mc, AUTOPILOT_DISCONNECT); - } - lastAutopilotState = AutoFlightManager.autoPilotEnabled; - - tryPlayStickShaker(mc, context); - - if (FlightSafetyMonitor.secondsUntilGroundImpact <= FlightSafetyMonitor.warningThreshold || FlightSafetyMonitor.secondsUntilTerrainImpact <= FlightSafetyMonitor.warningThreshold) { - playOnce(mc, PULL_UP, 0.75f, true); - drawCenteredWarning(mc, context, dim.wScreen, dim.hScreen / 2 + 10, highlight, "PULL UP"); - } else if (FlightSafetyMonitor.secondsUntilTerrainImpact <= FlightSafetyMonitor.cautionThreshold) - playOnce(mc, TERRAIN, 0.5f, true); - else if (FlightSafetyMonitor.secondsUntilGroundImpact <= FlightSafetyMonitor.cautionThreshold) - playOnce(mc, SINKRATE, 0.5f, true); - else - stopGpwsEvents(mc); - } - - public void drawCenteredWarning(MinecraftClient mc, DrawContext context, float width, float y, boolean highlight, String text) { - float x = (width - mc.textRenderer.getWidth(text)) / 2; - if (highlight) { - HudComponent.drawUnbatched(drawContext -> { - HudComponent.drawTextHighlight(mc.textRenderer, drawContext, x, y, text, CONFIG.alertColor); - HudComponent.drawCenteredFont(mc, drawContext, text, width, y, CONFIG.white); - }, context); - return; - } - HudComponent.drawCenteredFont(mc, context, text, width, y, CONFIG.alertColor); - } - - public void tryStopEvents(PlayerEntity player, SoundManager manager) { - if (!player.isFallFlying()) { - if (!activeEvents.isEmpty()) { - for (SoundEvent event : activeEvents) - manager.stopSounds(event.getId(), SoundCategory.MASTER); - activeEvents.clear(); - } - if (stickShakerInstance != null) { - manager.stop(stickShakerInstance); - stickShakerInstance = null; - } - } - activeAlerts.removeIf(alert -> !alert.shouldActivate()); - } - - private void playOnce(MinecraftClient mc, SoundEvent event, float volume, boolean limit) { - if (!limit || !activeEvents.contains(event)) { - mc.getSoundManager().play(new AlertSoundInstance(event, volume, mc.player, false)); - if (limit) - activeEvents.add(event); - } - } - - private void tryPlayStickShaker(MinecraftClient mc, DrawContext context) { - if (FlightSafetyMonitor.isStalling) { - if (CONFIG_SETTINGS.stickShaker) { - if (stickShakerInstance == null) { - mc.getSoundManager().play(stickShakerInstance = new AlertSoundInstance(STICK_SHAKER, 0.0f, mc.player, true)); - } - - stickShakerInstance.setVolume(stickShakerInstance.getVolume() + deltaTime * 2.0f); - } - - if (computer.velocityPerSecond.y <= -10) { - playOnce(mc, STALL_WARNING, 1.0f, true); - } else - stopEvent(mc, STALL_WARNING); - drawCenteredWarning(mc, context, dim.wScreen, dim.hScreen / 2 + 10, highlight, "STALL"); - return; - } - - stopEvent(mc, STALL_WARNING); - - if (stickShakerInstance == null) { - return; - } - - stickShakerInstance.setVolume(stickShakerInstance.getVolume() - deltaTime * 2.0f); - if (stickShakerInstance.getVolume() <= 0.0f) { - mc.getSoundManager().stop(stickShakerInstance); - stickShakerInstance = null; - } - } - - private void stopGpwsEvents(MinecraftClient mc) { - stopEvent(mc, TERRAIN); - stopEvent(mc, SINKRATE); - stopEvent(mc, PULL_UP); - } - - private void stopEvent(MinecraftClient mc, SoundEvent event) { - mc.getSoundManager().stopSounds(event.getId(), SoundCategory.MASTER); - activeEvents.remove(event); - } -} diff --git a/src/main/java/net/torocraft/flighthud/components/HeadingIndicator.java b/src/main/java/net/torocraft/flighthud/components/HeadingIndicator.java index 4bd8aff1..0457ad41 100644 --- a/src/main/java/net/torocraft/flighthud/components/HeadingIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/HeadingIndicator.java @@ -3,8 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; import net.torocraft.flighthud.HudComponent; +import net.torocraft.flighthud.computers.FlightComputer; public class HeadingIndicator extends HudComponent { diff --git a/src/main/java/net/torocraft/flighthud/components/PitchIndicator.java b/src/main/java/net/torocraft/flighthud/components/PitchIndicator.java index 09d0c575..3fa58340 100644 --- a/src/main/java/net/torocraft/flighthud/components/PitchIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/PitchIndicator.java @@ -4,9 +4,8 @@ import net.minecraft.client.gui.DrawContext; import net.minecraft.util.math.RotationAxis; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; -import net.torocraft.flighthud.FlightSafetyMonitor; import net.torocraft.flighthud.HudComponent; +import net.torocraft.flighthud.computers.FlightComputer; public class PitchIndicator extends HudComponent { private final Dimensions dim; @@ -43,7 +42,7 @@ public void render(DrawContext context, MinecraftClient mc) { drawReferenceMark(context, yHorizon, CONFIG.pitchLadder_optimumClimbAngle, CONFIG.color); drawReferenceMark(context, yHorizon, CONFIG.pitchLadder_optimumGlideAngle, CONFIG.color); - drawReferenceMark(context, yHorizon, FlightSafetyMonitor.maximumSafePitch, CONFIG.alertColor); + //drawReferenceMark(context, yHorizon, FlightSafetyMonitor.maximumSafePitch, CONFIG.alertColor); if (CONFIG.pitchLadder_showHorizon) { pitchData.l1 -= pitchData.margin; diff --git a/src/main/java/net/torocraft/flighthud/components/SpeedIndicator.java b/src/main/java/net/torocraft/flighthud/components/SpeedIndicator.java index 85916e9c..dbc01749 100644 --- a/src/main/java/net/torocraft/flighthud/components/SpeedIndicator.java +++ b/src/main/java/net/torocraft/flighthud/components/SpeedIndicator.java @@ -3,10 +3,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.DrawContext; import net.torocraft.flighthud.Dimensions; -import net.torocraft.flighthud.FlightComputer; import net.torocraft.flighthud.HudComponent; - -import static net.torocraft.flighthud.FlightSafetyMonitor.isStalling; +import net.torocraft.flighthud.computers.FlightComputer; public class SpeedIndicator extends HudComponent { private final Dimensions dim; @@ -32,9 +30,8 @@ public void render(DrawContext context, MinecraftClient mc) { float xSpeedText = left - 5; if (CONFIG.speed_showReadout) { - int color = isStalling ? CONFIG.alertColor : CONFIG.color; - drawRightAlignedFont(mc, context, String.format("%.2f", computer.speed), xSpeedText, dim.yMid - 3, color); - drawBox(context, xSpeedText - 29.5f, dim.yMid - 4.5f, 30, color); + drawRightAlignedFont(mc, context, String.format("%.2f", computer.speed), xSpeedText, dim.yMid - 3, CONFIG.color); + drawBox(context, xSpeedText - 29.5f, dim.yMid - 4.5f, 30, CONFIG.color); float frameWidth = dim.rFrame - dim.lFrame; drawFont(mc, context, String.format("G/S: %.2f", computer.velocityPerSecond.horizontalLength()), dim.lFrame + frameWidth * 0.25f, dim.hScreen * 0.8f, CONFIG.color); diff --git a/src/main/java/net/torocraft/flighthud/computers/AutoFlightComputer.java b/src/main/java/net/torocraft/flighthud/computers/AutoFlightComputer.java new file mode 100644 index 00000000..15685334 --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/computers/AutoFlightComputer.java @@ -0,0 +1,26 @@ +package net.torocraft.flighthud.computers; + +public class AutoFlightComputer { + private final FlightComputer computer; + private float targetPitch; + + public AutoFlightComputer(FlightComputer computer) { + this.computer = computer; + } + + public void setTargetPitch(float pitch) { + this.targetPitch = pitch; + } + + public void disconnectAutopilot(boolean force) { + + } + + public void disconnectAutoThrust(boolean force) { + + } + + public void tick() { + + } +} diff --git a/src/main/java/net/torocraft/flighthud/FlightComputer.java b/src/main/java/net/torocraft/flighthud/computers/FlightComputer.java similarity index 52% rename from src/main/java/net/torocraft/flighthud/FlightComputer.java rename to src/main/java/net/torocraft/flighthud/computers/FlightComputer.java index 90578531..68398780 100644 --- a/src/main/java/net/torocraft/flighthud/FlightComputer.java +++ b/src/main/java/net/torocraft/flighthud/computers/FlightComputer.java @@ -1,21 +1,33 @@ -package net.torocraft.flighthud; +package net.torocraft.flighthud.computers; import net.minecraft.block.BlockState; import net.minecraft.client.MinecraftClient; -import net.minecraft.entity.Entity; import net.minecraft.entity.EquipmentSlot; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3d; +import net.torocraft.flighthud.FlightHud; +import org.jetbrains.annotations.NotNull; import org.joml.Matrix3f; -public class FlightComputer { - private static final float TICKS_PER_SECOND = 20; +import static net.minecraft.SharedConstants.TICKS_PER_SECOND; +public class FlightComputer { + public final GPWSComputer gpws = new GPWSComputer(this); + @NotNull + private final MinecraftClient mc; + @NotNull + private final PlayerEntity player; + public AutoFlightComputer autoflight = new AutoFlightComputer(this); + public PitchController pitchController = new PitchController(); + + public Vec3d position; public Vec3d velocity; public Vec3d velocityPerSecond; + public Vec3d acceleration; public float speed; public float pitch; public float heading; @@ -28,32 +40,44 @@ public class FlightComputer { public float distanceFromGround; public Float elytraHealth; - public static boolean isGround(BlockPos pos, MinecraftClient client) { - BlockState block = client.world.getBlockState(pos); + public FlightComputer(MinecraftClient mc) { + this.mc = mc; + assert mc.player != null; + this.player = mc.player; + } + + public boolean isGround(BlockPos pos) { + assert mc.world != null; + BlockState block = mc.world.getBlockState(pos); return !block.isAir(); } - public void update(MinecraftClient client, Matrix3f normal) { - velocity = client.player.getVelocity(); + public void tick() { + position = player.getPos(); + acceleration = player.getVelocity().subtract(velocity); + velocity = player.getVelocity(); velocityPerSecond = velocity.multiply(TICKS_PER_SECOND); - pitch = computePitch(client); - speed = computeSpeed(client); - roll = computeRoll(normal); - heading = computeHeading(client); - altitude = computeAltitude(client); - groundLevel = computeGroundLevel(client); + pitch = computePitch(); + speed = computeSpeed(); + heading = computeHeading(); + altitude = computeAltitude(); + groundLevel = computeGroundLevel(); distanceFromGround = computeDistanceFromGround(altitude, groundLevel); flightPitch = computeFlightPitch(velocity, pitch); - flightYaw = computeFlightYaw(velocity, client.player.getYaw()); + flightYaw = computeFlightYaw(velocity, player.getYaw()); flightHeading = toHeading(flightYaw); - elytraHealth = computeElytraHealth(client); + elytraHealth = computeElytraHealth(); - AutoFlightManager.update(client, this); - FlightSafetyMonitor.update(client, this); + gpws.tick(); + autoflight.tick(); } - private Float computeElytraHealth(MinecraftClient client) { - ItemStack stack = client.player.getEquippedStack(EquipmentSlot.CHEST); + public void updateRoll(Matrix3f normal) { + roll = computeRoll(normal); + } + + private Float computeElytraHealth() { + ItemStack stack = player.getEquippedStack(EquipmentSlot.CHEST); if (stack != null && stack.getItem() == Items.ELYTRA) { float remain = ((float) stack.getMaxDamage() - (float) stack.getDamage()) / (float) stack.getMaxDamage(); return remain * 100f; @@ -86,23 +110,23 @@ private float computeRoll(Matrix3f normalMatrix) { return (float) Math.toDegrees(Math.atan2(y, x)); } - private float computePitch(MinecraftClient client) { - return -client.player.getPitch(); + private float computePitch() { + return -player.getPitch(); } - public BlockPos findGround(MinecraftClient client) { - BlockPos.Mutable pos = client.player.getBlockPos().mutableCopy(); + public BlockPos findGround() { + BlockPos.Mutable pos = player.getBlockPos().mutableCopy(); while (pos.getY() >= -64) { - if (isGround(pos.move(Direction.DOWN), client)) { + if (isGround(pos.move(Direction.DOWN))) { return pos; } } return null; } - private int computeGroundLevel(MinecraftClient client) { - BlockPos ground = findGround(client); - return ground == null ? Math.min(client.player.getBlockY() + 4, -50) : ground.getY(); + private int computeGroundLevel() { + BlockPos ground = findGround(); + return ground == null ? Math.min(player.getBlockY() + 4, -50) : ground.getY(); } private float computeDistanceFromGround(float altitude, @@ -110,27 +134,23 @@ private float computeDistanceFromGround(float altitude, return Math.max(-64f, altitude - groundLevel); } - private float computeAltitude(MinecraftClient client) { - return (float) client.player.getPos().y - 1; + private float computeAltitude() { + return (float) player.getPos().y - 1; } - private float computeHeading(MinecraftClient client) { - return toHeading(client.player.getYaw()); + private float computeHeading() { + return toHeading(player.getYaw()); } - private float computeSpeed(MinecraftClient client) { - float speed; - var player = client.player; - if (player.hasVehicle()) { - Entity entity = player.getVehicle(); - speed = (float) entity.getVelocity().length() * TICKS_PER_SECOND; - } else { - speed = (float) client.player.getVelocity().length() * TICKS_PER_SECOND; - } - return speed; + private float computeSpeed() { + return (float) velocityPerSecond.length(); } private float toHeading(float yawDegrees) { return (yawDegrees + 180) % 360; } + + public void tickPitchController(float tickDelta) { + pitchController.tick(player, tickDelta); + } } diff --git a/src/main/java/net/torocraft/flighthud/computers/GPWSComputer.java b/src/main/java/net/torocraft/flighthud/computers/GPWSComputer.java new file mode 100644 index 00000000..c41549dc --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/computers/GPWSComputer.java @@ -0,0 +1,50 @@ +package net.torocraft.flighthud.computers; + +import net.minecraft.util.math.Vec3d; +import net.torocraft.flighthud.Util; + +import static net.minecraft.SharedConstants.TICKS_PER_SECOND; + +public class GPWSComputer { + private static final int MAX_SAFE_SINKRATE = -10; + private static final int STATUS_VERTICAL_SPEED_SAFE = -1; + private static final int MAX_SIMULATION_TICKS = 10 * TICKS_PER_SECOND; + private static final int STATUS_SIMULATION_TIME_EXCEEDED = -2; + private static final float PITCH_CORRECT_THRESHOLD = 2.5f; + private final FlightComputer computer; + private float impactTime; + + public GPWSComputer(FlightComputer computer) { + this.computer = computer; + } + + public void tick() { + impactTime = this.computeImpactTime(); + } + + public float getImpactTime() { + return impactTime; + } + + public boolean shouldCorrectPitch() { + return getImpactTime() <= PITCH_CORRECT_THRESHOLD; + } + + private float computeImpactTime() { + if (computer.velocity.y > MAX_SAFE_SINKRATE) { + return STATUS_VERTICAL_SPEED_SAFE; + } + + Vec3d position = Util.copyVec3d(computer.position); + Vec3d velocity = Util.copyVec3d(computer.velocity); + for (int ticks = 0; ticks < MAX_SIMULATION_TICKS; ticks++) { + velocity.add(computer.acceleration); + position.add(velocity); + if (position.y <= computer.groundLevel) { + return (float) ticks / TICKS_PER_SECOND; + } + } + + return STATUS_SIMULATION_TIME_EXCEEDED; + } +} diff --git a/src/main/java/net/torocraft/flighthud/computers/PitchController.java b/src/main/java/net/torocraft/flighthud/computers/PitchController.java new file mode 100644 index 00000000..1d18eddb --- /dev/null +++ b/src/main/java/net/torocraft/flighthud/computers/PitchController.java @@ -0,0 +1,21 @@ +package net.torocraft.flighthud.computers; + +import net.minecraft.entity.player.PlayerEntity; + +public class PitchController { + + /** + * USE MINECRAFT PITCH (minus is up and plus is down) + **/ + public float targetPitch; + public boolean forceLevelOff = false; + + public void tick(PlayerEntity player, float tickDelta) { + if (forceLevelOff) { + player.setPitch(player.getPitch() - player.getPitch() * tickDelta); + return; + } + + player.setPitch(player.getPitch() - (player.getPitch() - targetPitch) * tickDelta); + } +} diff --git a/src/main/java/net/torocraft/flighthud/config/HudConfig.java b/src/main/java/net/torocraft/flighthud/config/HudConfig.java index 510fdc13..383650c2 100644 --- a/src/main/java/net/torocraft/flighthud/config/HudConfig.java +++ b/src/main/java/net/torocraft/flighthud/config/HudConfig.java @@ -1,13 +1,12 @@ package net.torocraft.flighthud.config; -import net.torocraft.flighthud.config.loader.IConfig; - import java.awt.*; +import net.torocraft.flighthud.config.loader.IConfig; public class HudConfig implements IConfig { public transient int color = Color.GREEN.getRGB(); public transient int alertColor = Color.RED.getRGB(); - public transient int amberColor = Color.YELLOW.getRGB(); + public transient int amberColor = Color.ORANGE.getRGB(); public transient int adviceColor = Color.CYAN.getRGB(); public transient int black = Color.BLACK.getRGB(); public transient int white = Color.WHITE.getRGB(); diff --git a/src/main/java/net/torocraft/flighthud/config/SettingsConfig.java b/src/main/java/net/torocraft/flighthud/config/SettingsConfig.java index 4a803b9f..15902a2e 100644 --- a/src/main/java/net/torocraft/flighthud/config/SettingsConfig.java +++ b/src/main/java/net/torocraft/flighthud/config/SettingsConfig.java @@ -10,11 +10,6 @@ public class SettingsConfig implements IConfig { public String displayModeWhenFlying = DisplayMode.FULL.toString(); public String displayModeWhenNotFlying = DisplayMode.NONE.toString(); public boolean calculateRoll = true; - public boolean gpws = true; - public boolean stickShaker = true; - public boolean lowElytraHealthAlarm = true; - public int lowElytraHealthAlarmThreshold = 10; - public boolean unsafeFireworksAlert = true; private static String toggle(String curr) { DisplayMode m = parseDisplayMode(curr); diff --git a/src/main/java/net/torocraft/flighthud/mixin/ClientPlayerInteractionManagerMixin.java b/src/main/java/net/torocraft/flighthud/mixin/ClientPlayerInteractionManagerMixin.java index 3e51e5be..2958b189 100644 --- a/src/main/java/net/torocraft/flighthud/mixin/ClientPlayerInteractionManagerMixin.java +++ b/src/main/java/net/torocraft/flighthud/mixin/ClientPlayerInteractionManagerMixin.java @@ -2,11 +2,8 @@ import net.minecraft.client.network.ClientPlayerInteractionManager; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.FireworkRocketItem; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; -import net.minecraft.util.Util; -import net.torocraft.flighthud.FlightSafetyMonitor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -16,7 +13,7 @@ public class ClientPlayerInteractionManagerMixin { @Inject(method = "interactItem", at = @At("HEAD"), cancellable = true) public void disallowUnsafeFireworks(PlayerEntity player, Hand hand, CallbackInfoReturnable cir) { - if (!player.isFallFlying()) return; + /*if (!player.isFallFlying()) return; if (FlightSafetyMonitor.flightProtectionsEnabled && FlightSafetyMonitor.unsafeFireworkHands.contains(hand)) cir.setReturnValue(ActionResult.FAIL); @@ -28,6 +25,6 @@ else if (player.getStackInHand(hand).getItem() instanceof FireworkRocketItem) { FlightSafetyMonitor.lastFireworkActivationTimeMs = Util.getMeasuringTimeMs(); FlightSafetyMonitor.thrustSet = false; } - } + }*/ } } diff --git a/src/main/java/net/torocraft/flighthud/mixin/EntityMixin.java b/src/main/java/net/torocraft/flighthud/mixin/EntityMixin.java index fcc5a9f8..35d4828a 100644 --- a/src/main/java/net/torocraft/flighthud/mixin/EntityMixin.java +++ b/src/main/java/net/torocraft/flighthud/mixin/EntityMixin.java @@ -1,8 +1,6 @@ package net.torocraft.flighthud.mixin; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.Entity; -import net.torocraft.flighthud.FlightSafetyMonitor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -12,13 +10,13 @@ public abstract class EntityMixin { @Inject(method = "setPitch", at = @At("HEAD"), cancellable = true) public void preventUpsetPitch(float pitch, CallbackInfo ci) { - Entity that = (Entity) (Object) this; + /*Entity that = (Entity) (Object) this; if (that instanceof ClientPlayerEntity cpe && cpe.isFallFlying() && FlightSafetyMonitor.flightProtectionsEnabled) { boolean approachingStall = pitch < that.getPitch() && pitch < -FlightSafetyMonitor.maximumSafePitch; boolean highSinkRate = pitch > that.getPitch() && FlightSafetyMonitor.secondsUntilGroundImpact <= 5.0f; if (approachingStall || highSinkRate) ci.cancel(); - } + }*/ } } diff --git a/src/main/java/net/torocraft/flighthud/mixin/GameRendererMixin.java b/src/main/java/net/torocraft/flighthud/mixin/GameRendererMixin.java index 1e9f6ae6..b54c85c5 100644 --- a/src/main/java/net/torocraft/flighthud/mixin/GameRendererMixin.java +++ b/src/main/java/net/torocraft/flighthud/mixin/GameRendererMixin.java @@ -1,24 +1,17 @@ package net.torocraft.flighthud.mixin; import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.math.MatrixStack; import net.torocraft.flighthud.HudRenderer; import org.joml.Matrix3f; -import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GameRenderer.class) public class GameRendererMixin { - @Shadow - @Final - MinecraftClient client; - @Inject( method = "renderWorld", at = @At( @@ -33,6 +26,8 @@ private void renderWorld(float tickDelta, CallbackInfo ci ) { Matrix3f inverseViewRotationMatrix = RenderSystem.getInverseViewRotationMatrix(); - HudRenderer.INSTANCE.computer.update(client, inverseViewRotationMatrix.invert()); + if (HudRenderer.INSTANCE != null) { + HudRenderer.INSTANCE.computer.updateRoll(inverseViewRotationMatrix); + } } } diff --git a/src/main/java/net/torocraft/flighthud/mixin/InGameHudMixin.java b/src/main/java/net/torocraft/flighthud/mixin/InGameHudMixin.java index 950ad43d..321d3cb6 100644 --- a/src/main/java/net/torocraft/flighthud/mixin/InGameHudMixin.java +++ b/src/main/java/net/torocraft/flighthud/mixin/InGameHudMixin.java @@ -17,8 +17,19 @@ public class InGameHudMixin { @Shadow private MinecraftClient client; - @Inject(method = "render", at = @At("RETURN")) + @Inject(method = "render", at = @At("TAIL")) private void render(DrawContext context, float tickDelta, CallbackInfo ci) { - HudRenderer.INSTANCE.render(context, client); + if (HudRenderer.INSTANCE != null) { + HudRenderer.INSTANCE.render(context, client); + HudRenderer.INSTANCE.computer.tickPitchController(tickDelta); + } + } + + @Inject(method = "tick()V", at = @At("TAIL")) + private void tick(CallbackInfo ci) { + if (HudRenderer.INSTANCE == null) { + HudRenderer.INSTANCE = new HudRenderer(client); + } + HudRenderer.INSTANCE.computer.tick(); } } diff --git a/src/main/java/net/torocraft/flighthud/mixin/LivingEntityMixin.java b/src/main/java/net/torocraft/flighthud/mixin/LivingEntityMixin.java index e9975ddf..f41246b7 100644 --- a/src/main/java/net/torocraft/flighthud/mixin/LivingEntityMixin.java +++ b/src/main/java/net/torocraft/flighthud/mixin/LivingEntityMixin.java @@ -1,10 +1,7 @@ package net.torocraft.flighthud.mixin; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.damage.DamageSource; -import net.minecraft.entity.damage.DamageTypes; -import net.torocraft.flighthud.FlightSafetyMonitor; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,9 +11,9 @@ public class LivingEntityMixin { @Inject(method = "onDamaged", at = @At("HEAD")) public void detectWallCollision(DamageSource damageSource, CallbackInfo ci) { - LivingEntity $this = (LivingEntity) (Object) this; + /*LivingEntity $this = (LivingEntity) (Object) this; if ($this instanceof ClientPlayerEntity && damageSource.isOf(DamageTypes.FLY_INTO_WALL)) { FlightSafetyMonitor.thrustLocked = true; - } + }*/ } } diff --git a/src/main/resources/assets/flighthud/sounds.json b/src/main/resources/assets/flighthud/sounds.json index 0d159459..1a17085a 100644 --- a/src/main/resources/assets/flighthud/sounds.json +++ b/src/main/resources/assets/flighthud/sounds.json @@ -1,17 +1,17 @@ { - "alert": { + "autopilot_disconnect": { "sounds": [ - "flighthud:alert" + "flighthud:autopilot_disconnect" ] }, - "stick_shaker": { + "caution": { "sounds": [ - "flighthud:stick_shaker" + "flighthud:caution" ] }, - "stall_warning": { + "pull_up": { "sounds": [ - "flighthud:stall_warning" + "flighthud:pull_up" ] }, "sinkrate": { @@ -24,14 +24,9 @@ "flighthud:terrain" ] }, - "pull_up": { + "warning": { "sounds": [ - "flighthud:pull_up" - ] - }, - "autopilot_disconnect": { - "sounds": [ - "flighthud:autopilot_disconnect" + "flighthud:warning" ] } } diff --git a/src/main/resources/assets/flighthud/sounds/alert.ogg b/src/main/resources/assets/flighthud/sounds/alert.ogg deleted file mode 100644 index e0c84f5240fa990856cd86fe591eca342506607a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9475 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 HU($a7I*sk6 literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/flighthud/sounds/stall_warning.ogg b/src/main/resources/assets/flighthud/sounds/stall_warning.ogg deleted file mode 100644 index e69de29b..00000000 diff --git a/src/main/resources/assets/flighthud/sounds/stick_shaker.ogg b/src/main/resources/assets/flighthud/sounds/stick_shaker.ogg deleted file mode 100644 index eace9615bfd31d677d01974f7ff22a04002251dd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20791 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 diff --git a/src/main/resources/assets/flighthud/sounds/warning.wav b/src/main/resources/assets/flighthud/sounds/warning.wav new file mode 100644 index 0000000000000000000000000000000000000000..0cb51e66bdf15a13094a9f793699f6f91cbbed0f GIT binary patch literal 132514 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