extends Node ## Autosave trigger — owns periodic + app-pause + focus-loss autosave logic. ## ## Does NOT own the write logic (that is SaveSystem.save_to_slot). This node ## only decides *when* to fire an autosave. It gates on _busy so we never ## start a save while another save/load is in-flight. ## ## Periodic cadence: every AUTOSAVE_INTERVAL_TICKS sim ticks (~5 in-game minutes ## at 20 Hz × Fast speed). The tick counter resets on every save_finished so ## that a manual save also resets the periodic clock. ## ## App-pause (mobile) and focus-loss (desktop) are immediate triggers. const AUTOSAVE_INTERVAL_TICKS: int = 6000 # 20 Hz × 300 s = 5 in-game minutes ## Set true while a save or load is in progress so we don't re-enter. var _busy: bool = false ## Counts sim ticks since the last autosave (or last save_finished, whichever ## came last) so we respect the interval even across manual saves. var _ticks_since_save: int = 0 func _ready() -> void: EventBus.sim_tick.connect(_on_sim_tick) EventBus.save_started.connect(_on_save_started) EventBus.save_finished.connect(_on_save_finished) EventBus.load_started.connect(_on_load_started) EventBus.load_finished.connect(_on_load_finished) Audit.log("autosave", "Autosave ready — interval %d ticks" % AUTOSAVE_INTERVAL_TICKS) func _notification(what: int) -> void: match what: NOTIFICATION_APPLICATION_PAUSED: # Mobile: app sent to background — save immediately. _trigger_autosave("app-pause") NOTIFICATION_WM_WINDOW_FOCUS_OUT: # Desktop: window lost focus — save immediately. _trigger_autosave("focus-loss") # ── signal handlers ─────────────────────────────────────────────────────────── func _on_sim_tick(tick_number: int) -> void: if _busy: return _ticks_since_save += 1 if _ticks_since_save >= AUTOSAVE_INTERVAL_TICKS: _trigger_autosave("periodic save at tick %d" % tick_number) func _on_save_started(_slot: StringName) -> void: _busy = true func _on_save_finished(_slot: StringName, _ok: bool) -> void: _busy = false # Reset the periodic counter so any save (manual or auto) restarts the clock. _ticks_since_save = 0 func _on_load_started(_slot: StringName) -> void: _busy = true func _on_load_finished(_slot: StringName, _ok: bool, _seconds: int) -> void: _busy = false _ticks_since_save = 0 # ── helpers ─────────────────────────────────────────────────────────────────── func _trigger_autosave(reason: String) -> void: if _busy: Audit.log("autosave", "skipped (%s) — save already in progress" % reason) return Audit.log("autosave", reason) SaveSystem.save_to_slot(&"autosave")