Skip to content

Commit

Permalink
feat: flight phase computer (preparation for autopilot rework)
Browse files Browse the repository at this point in the history
  • Loading branch information
Octol1ttle committed Apr 16, 2024
1 parent 86a120c commit 089738f
Show file tree
Hide file tree
Showing 11 changed files with 238 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
import ru.octol1ttle.flightassistant.computers.api.IComputer;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.impl.AirDataComputer;
import ru.octol1ttle.flightassistant.computers.impl.FlightPhaseComputer;
import ru.octol1ttle.flightassistant.computers.impl.TimeComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutoFlightComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.FireworkController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.PitchController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.YawController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch.AutopilotPitchController;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch.ProtectionsPitchController;
import ru.octol1ttle.flightassistant.computers.impl.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.computers.impl.safety.AlertController;
Expand Down Expand Up @@ -43,6 +45,8 @@ public ComputerHost(@NotNull MinecraftClient mc) {
ComputerRegistry.register(new ElytraStateController());
ComputerRegistry.register(new YawController());
ComputerRegistry.register(new AutoFlightComputer());
ComputerRegistry.register(new FlightPhaseComputer());
ComputerRegistry.register(new AutopilotPitchController());
ComputerRegistry.register(new AlertController(mc.getSoundManager()));

CustomComputerRegistrationCallback.EVENT.invoker().registerCustomComputers();
Expand All @@ -59,7 +63,7 @@ public void tick() {

try {
tickable.tick();
} catch (AssertionError e) {
} catch (AssertionError e) { // TODO: stop using AssertionErrors
ComputerRegistry.markFaulted(computer, e, "Invalid data encountered by computer");
} catch (Throwable t) {
ComputerRegistry.markFaulted(computer, t, "Exception ticking computer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public boolean isGround(BlockPos pos) {
return !block.isAir();
}

public BlockPos findGround(BlockPos.Mutable from) { // TODO: use heightmap
public BlockPos findGround(BlockPos.Mutable from) { // TODO: use heightmap/raycast
if (!isChunkLoadedAt(from)) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package ru.octol1ttle.flightassistant.computers.impl;

import net.minecraft.text.Text;
import net.minecraft.util.math.MathHelper;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutoFlightComputer;
import ru.octol1ttle.flightassistant.computers.impl.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.registries.ComputerRegistry;

public class FlightPhaseComputer implements ITickableComputer {
private final AirDataComputer data = ComputerRegistry.resolve(AirDataComputer.class);
private final AutoFlightComputer autoflight = ComputerRegistry.resolve(AutoFlightComputer.class);
private final FlightPlanner plan = ComputerRegistry.resolve(FlightPlanner.class);
public FlightPhase phase = FlightPhase.UNKNOWN;
private float minimumHeight = Float.MAX_VALUE;
private boolean wasAutolandAllowed = true;

@SuppressWarnings("DataFlowIssue")
@Override
public void tick() {
if (data.player().isOnGround()) {
phase = FlightPhase.ON_GROUND;
}

if (!isAboutToLand()) {
minimumHeight = Float.MAX_VALUE;
}

if (!data.isFlying()) {
return;
}

Integer cruiseAltitude = plan.getCruiseAltitude();
Integer targetAltitude = autoflight.getTargetAltitude();
if (cruiseAltitude == null || targetAltitude == null) {
phase = FlightPhase.UNKNOWN;
return;
}

if (phase == FlightPhase.ON_GROUND) {
phase = FlightPhase.TAKEOFF;
}

if (phase == FlightPhase.TAKEOFF && data.heightAboveGround() <= 10.0f) {
return;
}

if (!isNearDestination()) {
if (data.altitude() - targetAltitude <= 5.0f) {
phase = FlightPhase.CLIMB;
} else {
phase = FlightPhase.DESCENT;
}

if (targetAltitude.equals(cruiseAltitude) && Math.abs(cruiseAltitude - data.altitude()) <= 5.0f) {
phase = FlightPhase.CRUISE;
}
}

if (phase == FlightPhase.GO_AROUND) {
if (plan.getDistanceToWaypoint() > 150.0f) {
phase = FlightPhase.APPROACH;
}
} else {
if (plan.isOnApproach()) {
phase = FlightPhase.APPROACH;
}

if (phase == FlightPhase.APPROACH && plan.autolandAllowed) {
phase = FlightPhase.LAND;
}
}

if (isAboutToLand() && plan.landAltitude != null) {
float heightAboveDestination = data.altitude() - plan.landAltitude;
minimumHeight = MathHelper.clamp(heightAboveDestination, 0.0f, minimumHeight);

if (heightAboveDestination - minimumHeight >= 5.0f || (wasAutolandAllowed && !plan.autolandAllowed)) {
phase = FlightPhase.GO_AROUND;
}
}

wasAutolandAllowed = plan.autolandAllowed;
}

private boolean isAboutToLand() {
return phase == FlightPhase.APPROACH || phase == FlightPhase.LAND;
}

private boolean isNearDestination() {
return isAboutToLand() || phase == FlightPhase.GO_AROUND;
}

@Override
public String getId() {
return "flight_phase";
}

@Override
public void reset() {
phase = FlightPhase.UNKNOWN;
minimumHeight = Float.MAX_VALUE;
wasAutolandAllowed = true;
}

public enum FlightPhase {
ON_GROUND("on_ground"),
TAKEOFF("takeoff"),
CLIMB("climb"),
CRUISE("cruise"),
DESCENT("descent"),
APPROACH("approach"),
LAND("land"),
GO_AROUND("go_around"),
UNKNOWN("");

public final Text text;

FlightPhase(Text text) {
this.text = text;
}

FlightPhase(String key) {
this(Text.translatable("status.flightassistant.phase." + key));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ public void tick() {
lastPriority = controller.getPriority();
}
}

//smoothSetPitch(TODO autopilotTargetPitch, time.deltaTime);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package ru.octol1ttle.flightassistant.computers.impl.autoflight.pitch;

import net.minecraft.util.Pair;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import ru.octol1ttle.flightassistant.computers.api.IPitchController;
import ru.octol1ttle.flightassistant.computers.api.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.AutoFlightComputer;
import ru.octol1ttle.flightassistant.registries.ComputerRegistry;

public class AutopilotPitchController implements ITickableComputer, IPitchController {
private final AutoFlightComputer autoflight = ComputerRegistry.resolve(AutoFlightComputer.class);

@Override
public void tick() {
// TODO
autoflight.disconnectAutopilot(true);
}

@Override
public @Nullable Pair<@NotNull Float, @NotNull Float> getTargetPitch() {
return null;
}

@Override
public Priority getPriority() {
return Priority.NORMAL;
}

@Override
public String getId() {
return "autopilot_pitch_ctl";
}

@Override
public void reset() {
autoflight.disconnectAutopilot(true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import ru.octol1ttle.flightassistant.computers.impl.autoflight.PitchController;
import ru.octol1ttle.flightassistant.registries.ComputerRegistry;

// TODO: this handles too much stuff
public class FlightPlanner extends ArrayList<Waypoint> implements ITickableComputer {
private final AirDataComputer data = ComputerRegistry.resolve(AirDataComputer.class);
private @Nullable Waypoint targetWaypoint;
Expand Down Expand Up @@ -176,6 +177,20 @@ public boolean isBelowMinimums() {
return data.isFlying() && minimums != null && data.altitude() <= minimums;
}

public Integer getCruiseAltitude() {
Integer cruiseAltitude = null;
for (Waypoint waypoint : this) {
if (waypoint.targetAltitude() != null) {
if (cruiseAltitude == null) {
cruiseAltitude = waypoint.targetAltitude();
}
cruiseAltitude = Math.max(cruiseAltitude, waypoint.targetAltitude());
}
}

return cruiseAltitude;
}

public void execute(int waypointIndex) {
targetWaypoint = this.get(waypointIndex);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ private BlockPos findHighest(BlockPos.Mutable at) {

@Override
public boolean blockPitchChange(Direction direction) {
if (direction != Direction.UP) {
return false;
}

return FAConfig.computer().sinkrateProtection.override() && positiveLessOrEquals(descentImpactTime, PULL_UP_THRESHOLD)
|| FAConfig.computer().terrainProtection.override() && positiveLessOrEquals(terrainImpactTime, PULL_UP_THRESHOLD);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.text.Text;
import ru.octol1ttle.flightassistant.Dimensions;
import ru.octol1ttle.flightassistant.DrawHelper;
import ru.octol1ttle.flightassistant.computers.impl.FlightPhaseComputer;
import ru.octol1ttle.flightassistant.computers.impl.autoflight.FireworkController;
import ru.octol1ttle.flightassistant.computers.impl.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.config.FAConfig;
Expand All @@ -16,6 +17,7 @@ public class StatusDisplay implements IHudDisplay {
private final Dimensions dim;
private final FireworkController firework = ComputerRegistry.resolve(FireworkController.class);
private final FlightPlanner plan = ComputerRegistry.resolve(FlightPlanner.class);
private final FlightPhaseComputer phase = ComputerRegistry.resolve(FlightPhaseComputer.class);

public StatusDisplay(Dimensions dim) {
this.dim = dim;
Expand Down Expand Up @@ -45,9 +47,13 @@ public void render(DrawContext context, TextRenderer textRenderer) {
if (distance != null) {
DrawHelper.drawRightAlignedText(textRenderer, context,
Text.translatable("status.flightassistant.waypoint_distance", distance.intValue()),
x, y + 10, FAConfig.indicator().statusColor);
x, y += 10, FAConfig.indicator().statusColor);
}
}

if (phase.phase != FlightPhaseComputer.FlightPhase.UNKNOWN) {
DrawHelper.drawRightAlignedText(textRenderer, context, phase.phase.text, x, y + 10, FAConfig.indicator().statusColor);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static void markFaulted(IComputer computer, Throwable cause, @Nullable St
throw new IllegalStateException("Computer already marked as faulted");
}

computer.reset();
faulted.add(clazz);
FlightAssistant.LOGGER.error(Objects.requireNonNullElse(message, "Computer encountered a fault"), cause);
}
Expand Down
22 changes: 16 additions & 6 deletions src/main/resources/assets/flightassistant/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,19 +126,21 @@
"alerts.flightassistant.firework.unsafe": "FRWK EXPLOSIVE",
"alerts.flightassistant.fault.computers.air_data": "ADC FAULT (INSTRUMENTS LOST)",
"alerts.flightassistant.fault.computers.time_prvd": "TIME PRVD FAULT",
"alerts.flightassistant.fault.computers.auto_flt": "AUTO FLIGHT FAULT",
"alerts.flightassistant.fault.computers.auto_flt": "AUTO FLT SYS FAULT",
"alerts.flightassistant.fault.computers.frwk_ctl": "AUTO FRWK CTL FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.pitch_ctl": "AUTO PITCH CTL FAULT",
"alerts.flightassistant.fault.computers.flt_plan": "FLT PLAN FAULT",
"alerts.flightassistant.fault.computers.alert_mgr": "ALERT MGR FAULT (ALL ALERTS LOST)",
"alerts.flightassistant.fault.computers.flt_plan": "F/PLAN FAULT",
"alerts.flightassistant.fault.computers.alert_mgr": "ALERT SYS FAULT (ALL ALERTS LOST)",
"alerts.flightassistant.fault.computers.gpws": "GPWS FAULT",
"alerts.flightassistant.fault.computers.stall_det": "STALL DET FAULT",
"alerts.flightassistant.fault.computers.void_level": "VOID LVL FAULT",
"alerts.flightassistant.fault.computers.void_level": "VOID LVL SYS FAULT",
"alerts.flightassistant.fault.computers.yaw_ctl": "AUTO YAW CTL FAULT",
"alerts.flightassistant.fault.computers.elytra_state": "ELYTRA STATE FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.chunk_state": "CHUNK STATE FAULT",
"alerts.flightassistant.fault.computers.elytra_state": "ELYTRA SYS FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.chunk_state": "CHUNK SYS FAULT",
"alerts.flightassistant.fault.computers.pitch_normal_law": "F/CTL ALTN LAW (PROT LOST)",
"alerts.flightassistant.fault.computers.pitch_limit": "PITCH LIMIT FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.autopilot_pitch_ctl": "AUTOPILOT FAULT",
"alerts.flightassistant.fault.computers.flight_phase": "F/PHASE SYS FAULT",
"alerts.flightassistant.fault.hud.alert": "ALERT DISPLAY FAULT",
"alerts.flightassistant.fault.hud.altitude": "ALT DISPLAY FAULT",
"alerts.flightassistant.fault.hud.elytra_health": "E/HLTH DISPLAY FAULT",
Expand All @@ -156,6 +158,14 @@

"status.flightassistant.firework_count": "FRWK CNT: %s",
"status.flightassistant.waypoint_distance": "WP/DIST: %s",
"status.flightassistant.phase.on_ground": "ON GROUND",
"status.flightassistant.phase.takeoff": "TAKEOFF",
"status.flightassistant.phase.climb": "CLIMB",
"status.flightassistant.phase.cruise": "CRUISE",
"status.flightassistant.phase.descent": "DESCENT",
"status.flightassistant.phase.approach": "APPROACH",
"status.flightassistant.phase.land": "LAND",
"status.flightassistant.phase.go_around": "GO AROUND",

"mode.flightassistant.minimums.absolute": "MINIM %s",
"mode.flightassistant.minimums.relative": "MINIM +%s",
Expand Down
Loading

0 comments on commit 089738f

Please sign in to comment.