Skip to content

Commit

Permalink
feat: chunk unload warning
Browse files Browse the repository at this point in the history
  • Loading branch information
zomabies committed Mar 17, 2024
1 parent 7ebe94c commit 02e8aa0
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,13 @@ private ConfigCategory computers(Text name, ComputerConfig config, ComputerConfi
.controller(TickBoxControllerBuilder::create)
.build())

.option(LabelOption.create(Text.translatable("config.flightassistant.computers.chunk_state")))
.option(Option.<ComputerConfig.ProtectionMode>createBuilder()
.name(Text.translatable("config.flightassistant.computers.chunk_state.protection"))
.binding(defaults.unloadedChunkProtection, () -> config.unloadedChunkProtection, o -> config.unloadedChunkProtection = o)
.controller(opt -> EnumControllerBuilder.create(opt).enumClass(ComputerConfig.ProtectionMode.class))
.build())

.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ru.octol1ttle.flightassistant.alerts.nav;

import net.minecraft.client.font.TextRenderer;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.text.Text;
import org.jetbrains.annotations.NotNull;
import ru.octol1ttle.flightassistant.HudComponent;
import ru.octol1ttle.flightassistant.alerts.AlertSoundData;
import ru.octol1ttle.flightassistant.alerts.BaseAlert;
import ru.octol1ttle.flightassistant.alerts.IECAMAlert;
import ru.octol1ttle.flightassistant.computers.safety.ChunkStatusComputer;

public class UnloadedChunkAlert extends BaseAlert implements IECAMAlert {

private final ChunkStatusComputer chunkStatus;

public UnloadedChunkAlert(ChunkStatusComputer chunkStatus) {
this.chunkStatus = chunkStatus;
}

@Override
public boolean isTriggered() {
return chunkStatus.isInWarning();
}

@Override
public int render(TextRenderer textRenderer, DrawContext context, int x, int y, boolean highlight) {
return HudComponent.drawHighlightedText(textRenderer, context, Text.translatable("alerts.flightassistant.unloaded_chunk"), x, y,
chunkStatus.getIndicator(), highlight);
}

@Override
public @NotNull AlertSoundData getSoundData() {
return AlertSoundData.MASTER_WARNING;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import ru.octol1ttle.flightassistant.computers.autoflight.YawController;
import ru.octol1ttle.flightassistant.computers.navigation.FlightPlanner;
import ru.octol1ttle.flightassistant.computers.safety.AlertController;
import ru.octol1ttle.flightassistant.computers.safety.ChunkStatusComputer;
import ru.octol1ttle.flightassistant.computers.safety.ElytraStateController;
import ru.octol1ttle.flightassistant.computers.safety.GPWSComputer;
import ru.octol1ttle.flightassistant.computers.safety.StallComputer;
Expand All @@ -21,6 +22,7 @@
public class ComputerHost {
public final AirDataComputer data;
public final StallComputer stall;
public final ChunkStatusComputer chunkStatus;
public final GPWSComputer gpws;
public final VoidLevelComputer voidLevel;
public final FireworkController firework;
Expand All @@ -38,22 +40,23 @@ public ComputerHost(@NotNull MinecraftClient mc, HudRenderer renderer) {
this.data = new AirDataComputer(mc);
this.time = new TimeComputer();
this.firework = new FireworkController(mc, data, time);
this.chunkStatus = new ChunkStatusComputer(this, mc, data, time);
this.stall = new StallComputer(firework, data);
this.voidLevel = new VoidLevelComputer(data, firework, stall);
this.plan = new FlightPlanner(data);
this.gpws = new GPWSComputer(data, plan);
this.elytra = new ElytraStateController(data);

this.yaw = new YawController(time, data);
this.pitch = new PitchController(data, stall, time, voidLevel, gpws);
this.pitch = new PitchController(data, stall, time, voidLevel, gpws, chunkStatus);

this.autoflight = new AutoFlightComputer(data, gpws, plan, firework, pitch, yaw);

this.alert = new AlertController(this, mc.getSoundManager(), renderer);

// computers are sorted in the order they should be ticked to avoid errors
this.tickables = new ArrayList<>(List.of(
data, time, stall, gpws, voidLevel, elytra, plan, autoflight, firework, alert, pitch, yaw
data, time, stall, chunkStatus, gpws, voidLevel, elytra, plan, autoflight, firework, alert, pitch, yaw
));
Collections.reverse(this.tickables); // we tick computers in reverse, so reverse the collections so that the order is correct

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import ru.octol1ttle.flightassistant.computers.AirDataComputer;
import ru.octol1ttle.flightassistant.computers.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.TimeComputer;
import ru.octol1ttle.flightassistant.computers.safety.ChunkStatusComputer;
import ru.octol1ttle.flightassistant.computers.safety.GPWSComputer;
import ru.octol1ttle.flightassistant.computers.safety.StallComputer;
import ru.octol1ttle.flightassistant.computers.safety.VoidLevelComputer;
Expand All @@ -19,14 +20,16 @@ public class PitchController implements ITickableComputer {
private final TimeComputer time;
private final VoidLevelComputer voidLevel;
private final GPWSComputer gpws;
private final ChunkStatusComputer chunkStatus;
public Float targetPitch = null;

public PitchController(AirDataComputer data, StallComputer stall, TimeComputer time, VoidLevelComputer voidLevel, GPWSComputer gpws) {
public PitchController(AirDataComputer data, StallComputer stall, TimeComputer time, VoidLevelComputer voidLevel, GPWSComputer gpws, ChunkStatusComputer chunkStatus) {
this.data = data;
this.stall = stall;
this.time = time;
this.voidLevel = voidLevel;
this.gpws = gpws;
this.chunkStatus = chunkStatus;
}

@Override
Expand All @@ -45,9 +48,12 @@ public void tick() {
smoothSetPitch(90.0f, MathHelper.clamp(time.deltaTime / gpws.descentImpactTime, 0.001f, 1.0f));
} else if (gpws.shouldCorrectTerrain()) {
smoothSetPitch(FAMathHelper.toDegrees(MathHelper.atan2(gpws.terrainAvoidVector.y, gpws.terrainAvoidVector.x)), time.deltaTime);
} else if (chunkStatus.shouldCorrectTerrain()) {
smoothSetPitch(chunkStatus.recoverPitch, time.deltaTime);
} else {
smoothSetPitch(targetPitch, time.deltaTime);
}

}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import ru.octol1ttle.flightassistant.alerts.nav.MinimumsAlert;
import ru.octol1ttle.flightassistant.alerts.nav.gpws.ExcessiveDescentAlert;
import ru.octol1ttle.flightassistant.alerts.nav.gpws.ExcessiveTerrainClosureAlert;
import ru.octol1ttle.flightassistant.alerts.nav.UnloadedChunkAlert;
import ru.octol1ttle.flightassistant.alerts.nav.gpws.UnsafeTerrainClearanceAlert;
import ru.octol1ttle.flightassistant.alerts.other.ElytraHealthLowAlert;
import ru.octol1ttle.flightassistant.alerts.other.StallAlert;
Expand All @@ -37,6 +38,7 @@ public AlertController(ComputerHost host, SoundManager manager, HudRenderer rend
// TODO: ECAM actions
allAlerts = List.of(
new StallAlert(host.stall),
new UnloadedChunkAlert(host.chunkStatus),
new ExcessiveDescentAlert(host.data, host.gpws), new ExcessiveTerrainClosureAlert(host.gpws, host.time),
new UnsafeTerrainClearanceAlert(host.gpws, host.plan),
new AutopilotOffAlert(host.autoflight), new AutoFireworkOffAlert(host.autoflight),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package ru.octol1ttle.flightassistant.computers.safety;

import net.minecraft.client.MinecraftClient;
import ru.octol1ttle.flightassistant.computers.AirDataComputer;
import ru.octol1ttle.flightassistant.computers.ComputerHost;
import ru.octol1ttle.flightassistant.computers.ITickableComputer;
import ru.octol1ttle.flightassistant.computers.TimeComputer;
import ru.octol1ttle.flightassistant.config.FAConfig;

import java.awt.Color;

public class ChunkStatusComputer implements ITickableComputer {

private final ComputerHost host;
private final MinecraftClient mc;
private final AirDataComputer data;
private final TimeComputer time;

public final float recoverPitch = 10f;
private boolean isInWarning;
private boolean isLoaded;
private float lastEncounteredMS = 0f;
private float lastDiffMS = 0f;
private float offsetMS = 0f; // for single player pause

// milliseconds difference
private static final float WARN_THRESHOLD = 3200f;

public ChunkStatusComputer(ComputerHost host, MinecraftClient mc, AirDataComputer data, TimeComputer time) {
this.host = host;
this.mc = mc;
this.data = data;
this.time = time;
}

@Override
public void tick() {
if (!data.isFlying()) {
return;
}

isLoaded = data.isCurrentChunkLoaded;

if (isLoaded) {
if (!host.faulted.contains(time) && time.prevMillis != null) {
lastEncounteredMS = time.prevMillis;
}
isLoaded = false;
offsetMS = 0f;
}

final boolean isSinglePlayerPause = (mc.isInSingleplayer() && mc.isPaused());
if (isSinglePlayerPause && !isLoaded) {
offsetMS = ((time.prevMillis - lastEncounteredMS) - lastDiffMS);
}

if (time.prevMillis != null && lastEncounteredMS > 0f) {
lastDiffMS = (time.prevMillis - offsetMS) - lastEncounteredMS;
}

isInWarning = shouldWarn();
}

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

@Override
public void reset() {
isInWarning = false;
isLoaded = true;
lastDiffMS = 0f;
lastEncounteredMS = 0f;
offsetMS = 0f;
}

public boolean shouldCorrectTerrain() {
return FAConfig.computer().unloadedChunkProtection.recover() && isInWarning();
}

public boolean isInWarning() {
return isInWarning;
}

public float getLastDiffMS() {
return lastDiffMS;
}

public Color getIndicator() {
return FAConfig.indicator().warningColor;
}

private boolean shouldWarn() {
if (data.isFlying() && !data.isCurrentChunkLoaded) {
return lastDiffMS >= WARN_THRESHOLD;
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class ComputerConfig {
@SerialEntry
public boolean openElytraAutomatically = true;

@SerialEntry
public ProtectionMode unloadedChunkProtection = ProtectionMode.HARD;

public enum GlobalAutomationsMode implements NameableEnum {
FULL,
// TODO: LIMIT TO NO_OVERLAYS ON SERVERS
Expand Down
4 changes: 4 additions & 0 deletions src/main/resources/assets/flightassistant/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@
"config.flightassistant.computers.elytra_state": "Elytra state",
"config.flightassistant.computers.elytra_state.close_underwater": "Close Elytra when submerged in water",
"config.flightassistant.computers.elytra_state.open_automatically": "Open Elytra automatically",
"config.flightassistant.computers.chunk_state": "Chunk state",
"config.flightassistant.computers.chunk_state.protection": "Chunk state protection mode",

"commands.flightassistant.no_such_waypoint": "There is no waypoint at that index",
"commands.flightassistant.no_such_plan": "There is no plan with that name",
Expand All @@ -107,6 +109,7 @@
"alerts.flightassistant.stall": "STALL",
"alerts.flightassistant.terrain_ahead": "TERRAIN AHEAD",
"alerts.flightassistant.too_low_terrain": "TOO LOW - TERRAIN",
"alerts.flightassistant.unloaded_chunk": "UNLOADED CHUNK",

"alerts.flightassistant.elytra_health_low": "ELYTRA HEALTH LOW",

Expand All @@ -130,6 +133,7 @@
"alerts.flightassistant.fault.computers.void_level": "VOID LVL FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.yaw_ctl": "YAW CTL FAULT",
"alerts.flightassistant.fault.computers.elytra_state": "ELYTRA STATE FAULT (PROT LOST)",
"alerts.flightassistant.fault.computers.chunk_state": "CHUNK STATE FAULT (PROT LOST)",
"alerts.flightassistant.fault.indicators.alert": "ALERT INDICATOR FAULT",
"alerts.flightassistant.fault.indicators.altitude": "ALTITUDE INDICATOR FAULT",
"alerts.flightassistant.fault.indicators.elytra_health": "ELYTRA HEALTH INDICATOR FAULT",
Expand Down

0 comments on commit 02e8aa0

Please sign in to comment.