Auto-resume flight across chunk unload/reload
When the ship's chunk unloads the CC computer powers off and its redstone outputs reset to 0, so on return the ship dropped and the pilot had to re-ENGAGE every time. Flight state now survives the reboot: - engaged.txt flag written while flying, cleared on pilot STOP. - On boot, if engaged + profile present: drive the hover baseline immediately (closes the fall gap), then runStandby(true) re-enters the flight loop automatically with the persisted target -- no manual ENGAGE. - runFly drives hover before its first sleep so no entry path leaves a 0-output gap. - Cleanup no longer lifts a PARKED ship: Ctrl+T out of standby holds hover only when engaged, else valves off. - engaged.txt registered as per-ship state (gitignore, installer keep/reset, menu reset, build excludes). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,20 @@ local function profileComplete()
|
||||
return loadCalib().signMeasured == true
|
||||
end
|
||||
|
||||
-- ENGASJERT-flagg: finnes filen <=> autopiloten FLYR aktivt (etter ENGAGE/FLY, foer STOP).
|
||||
-- Dette er kjernen i restart-overlevelsen: en chunk-unload slaar av datamaskinen, og reboot
|
||||
-- nullstiller redstone -> skipet ville falle. Ligger flagget der ved boot, gjenopptar vi flukten
|
||||
-- automatisk (og holder hover umiddelbart), i stedet for aa vente i standby paa manuell ENGAGE.
|
||||
local ENGAGED_FILE = "engaged.txt"
|
||||
local function setEngaged(on)
|
||||
if on then
|
||||
local f = fs.open(ENGAGED_FILE, "w"); f.write("1"); f.close()
|
||||
elseif fs.exists(ENGAGED_FILE) then
|
||||
fs.delete(ENGAGED_FILE)
|
||||
end
|
||||
end
|
||||
local function isEngaged() return fs.exists(ENGAGED_FILE) end
|
||||
|
||||
-- live brukerinnstillinger (justeres fra pilot-konsollen), persistert. Syntetiske noekler -> cfg.
|
||||
local SETTINGS_FILE = "settings.txt"
|
||||
local function saveSettings(t) local f = fs.open(SETTINGS_FILE, "w"); f.write(textutils.serialise(t)); f.close() end
|
||||
@@ -713,6 +727,11 @@ local function runFly()
|
||||
print(""); print("[Enter]"); read(); return
|
||||
end
|
||||
|
||||
-- driv hover FOERST -- lukker fall-gapet (spesielt paa auto-resume etter reboot der
|
||||
-- redstone kom tilbake paa 0) foer loopen og status-broadcasten kommer i gang.
|
||||
driveValves(calib.uHoverFront, calib.uHoverRear)
|
||||
setEngaged(true) -- markér at vi FLYR -> overlever chunk-reload (auto-resume ved boot)
|
||||
|
||||
local launchAlt = sensors.readAltitude() or 0
|
||||
local target = loadTarget() or (launchAlt + cfg.takeoffOffset)
|
||||
local est = Estimator.new(cfg)
|
||||
@@ -739,6 +758,8 @@ local function runFly()
|
||||
elseif msg.cmd == "set" then applySetting(msg.key, msg.value, true)
|
||||
elseif msg.cmd == "stop" then stopReq = true end
|
||||
end
|
||||
-- pilot-STOP er en eksplisitt "slutt aa fly" -> ryd engasjert-flagget saa en senere reload
|
||||
-- IKKE gjenopptar av seg selv. (Ctrl+T beholder flagget: da vil du typisk fortsette senere.)
|
||||
-- vent ~dt sekunder MEN behandle innkommende kommandoer underveis (ikke-blokkerende styring)
|
||||
local function serve(secs)
|
||||
local timer = os.startTimer(secs)
|
||||
@@ -823,7 +844,10 @@ local function runFly()
|
||||
})
|
||||
|
||||
serve(cfg.dt) -- vent dt + behandle pilot-kommandoer (erstatter sleep)
|
||||
if stopReq then print("Pilot STOP -- holding hover, back to standby."); break end
|
||||
if stopReq then
|
||||
setEngaged(false) -- eksplisitt stopp -> ikke auto-resume etter neste reload
|
||||
print("Pilot STOP -- holding hover, back to standby."); break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -898,7 +922,21 @@ local function awaitCmd(secs)
|
||||
end
|
||||
end
|
||||
|
||||
local function runStandby()
|
||||
local function runStandby(autoResume)
|
||||
link.open()
|
||||
-- AUTO-RESUME: fl...y da chunken unloadet -> gjenoppta UMIDDELBART (ingen fall, ingen manuell
|
||||
-- ENGAGE). Bare paa boot-inngangen; manuell "standby" fra menyen gjor det ikke.
|
||||
if autoResume and isEngaged() and fs.exists(CALIB_FILE) then
|
||||
term.clear(); term.setCursorPos(1, 1)
|
||||
print("==== RESUMING FLIGHT ====")
|
||||
print("Autopilot was flying before the chunk")
|
||||
print("reloaded -- re-engaging automatically.")
|
||||
print("(Pilot STOP to stop; it will NOT resume")
|
||||
print(" after a stop.)")
|
||||
sleep(0.6)
|
||||
runFly() -- blokkerer til STOP / Ctrl+T
|
||||
local c = loadCalib(); driveValves(c.uHoverFront, c.uHoverRear)
|
||||
end
|
||||
while true do
|
||||
-- re-proev modem hver runde: fanger et modem som plugges til mens vi staar i standby
|
||||
local hasModem = link.open()
|
||||
@@ -939,6 +977,11 @@ end
|
||||
-- Foerste boot uten komplett profil -> tilby wizarden. Timeout -> standby, slik at en ubemannet
|
||||
-- reboot (chunk-reload) aldri blir staaende og vente paa tastetrykk.
|
||||
local function runBoot()
|
||||
-- ALLER FOERST: fl...y vi da chunken unloadet? Driv hover UMIDDELBART saa skipet ikke rekker
|
||||
-- aa falle mens vi tegner skjerm / venter. runStandby(true) gjenopptar selve reguleringen.
|
||||
if isEngaged() and fs.exists(CALIB_FILE) then
|
||||
local c = loadCalib(); driveValves(c.uHoverFront, c.uHoverRear)
|
||||
end
|
||||
if not profileComplete() then
|
||||
term.clear(); term.setCursorPos(1, 1)
|
||||
print("==== AIRSHIP AUTOPILOT ====")
|
||||
@@ -959,7 +1002,7 @@ local function runBoot()
|
||||
end
|
||||
end
|
||||
end
|
||||
runStandby()
|
||||
runStandby(true) -- true = auto-resume flukt hvis vi fløy da chunken unloadet
|
||||
end
|
||||
|
||||
-- ============================ PROFIL / MENY ============================
|
||||
@@ -1015,7 +1058,7 @@ local function menu()
|
||||
term.clear(); term.setCursorPos(1, 1); showProfile()
|
||||
print("\nR = reset SHIP PROFILE (new ship), Enter = back"); local a = read():lower()
|
||||
if a == "r" then
|
||||
for _, f in ipairs({ CALIB_FILE, SIDES_FILE, TARGET_FILE, SETTINGS_FILE }) do
|
||||
for _, f in ipairs({ CALIB_FILE, SIDES_FILE, TARGET_FILE, SETTINGS_FILE, ENGAGED_FILE }) do
|
||||
if fs.exists(f) then fs.delete(f) end
|
||||
end
|
||||
print("Ship profile reset -- setup wizard on next boot."); print("[Enter]"); read()
|
||||
@@ -1060,20 +1103,24 @@ local function runMode(mode, a2, a3)
|
||||
end)
|
||||
-- opprydding: aktive driv-modus -> hold hover (aldri etterlat drivende uten beskjed);
|
||||
-- monitor styrer ingenting (la utgangene staa).
|
||||
local function holdHoverOut()
|
||||
if fs.exists(CALIB_FILE) then
|
||||
local c = loadCalib(); driveValves(c.uHoverFront, c.uHoverRear) -- hold, ikke null (aldri stup)
|
||||
else
|
||||
allOff()
|
||||
end
|
||||
end
|
||||
if mode == "manual" or mode == "wiring" then
|
||||
allOff()
|
||||
elseif mode == "signtest" or mode == "setup" then
|
||||
-- Ctrl+T midt i sign-testen: luftbaaren -> hold hover (ALDRI frittfall); paa bakken -> alt av
|
||||
if signtestAirborne then
|
||||
local c = loadCalib(); driveValves(c.uHoverFront, c.uHoverRear)
|
||||
else
|
||||
allOff()
|
||||
end
|
||||
elseif mode == "cal" or mode == "fly" or mode == "observe" or mode == "standby" or mode == "boot" then
|
||||
if fs.exists(CALIB_FILE) then
|
||||
local c = loadCalib(); driveValves(c.uHoverFront, c.uHoverRear) -- hold, ikke null (aldri stup)
|
||||
else
|
||||
allOff() -- aldri floeyet under vaar kontroll -> skipet staar paa bakken; ikke varm brennere
|
||||
if signtestAirborne then holdHoverOut() else allOff() end
|
||||
elseif mode == "cal" or mode == "fly" or mode == "observe" then
|
||||
holdHoverOut() -- disse fl...yr aktivt -> hold hover ved avslutning
|
||||
elseif mode == "boot" or mode == "standby" then
|
||||
-- Ctrl+T ut av standby: hold hover KUN hvis vi faktisk fløy (engasjert). Et parkert skip
|
||||
-- paa bakken skal IKKE begynne aa varme brennere og lette av seg selv.
|
||||
if isEngaged() then holdHoverOut() else allOff()
|
||||
end
|
||||
end
|
||||
if not ok and err ~= "Terminated" then print("ERROR: " .. tostring(err)); print("[Enter]"); read() end
|
||||
|
||||
Reference in New Issue
Block a user