feat(save-manager): Introduce save/load methods and auto-play state management in SaveManager

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-14 18:07:21 -07:00
parent 03d17555be
commit 26c1dbf98f

View file

@ -105,10 +105,19 @@ static func _ensure_save_dir() -> Error:
return err
static func _write_slot(slot_name: String) -> Error:
var dir_err: Error = _ensure_save_dir()
if dir_err != OK:
return dir_err
static func save_to_path(abs_path: String, indented: bool = false) -> Error:
## Write a full GameState envelope to an arbitrary absolute path. Creates the
## containing directory if missing. Sorted keys are always on so re-saving the
## same state is byte-identical; `indented` toggles tab indent (true) vs
## compact (false). Compact is intended for hot-path per-turn saves.
var dir_path: String = abs_path.get_base_dir()
if dir_path != "" and not DirAccess.dir_exists_absolute(dir_path):
var dir_err: Error = DirAccess.make_dir_recursive_absolute(dir_path)
if dir_err != OK:
push_error(
"SaveManager: cannot create '%s': %s" % [dir_path, error_string(dir_err)]
)
return dir_err
var envelope: Dictionary = {
"version": SAVE_VERSION,
@ -116,14 +125,14 @@ static func _write_slot(slot_name: String) -> Error:
"game_state": GameState.serialize(),
}
# Sorted keys + tab indent so re-saving the same state is byte-identical.
var json_text: String = JSON.stringify(envelope, "\t", true)
var path: String = _path_for(slot_name)
var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
# Sorted keys always on so re-saving the same state is byte-identical.
var indent: String = "\t" if indented else ""
var json_text: String = JSON.stringify(envelope, indent, true)
var file: FileAccess = FileAccess.open(abs_path, FileAccess.WRITE)
if file == null:
var open_err: Error = FileAccess.get_open_error()
push_error(
"SaveManager: cannot write '%s': %s" % [path, error_string(open_err)]
"SaveManager: cannot write '%s': %s" % [abs_path, error_string(open_err)]
)
return open_err if open_err != OK else FAILED
@ -132,6 +141,10 @@ static func _write_slot(slot_name: String) -> Error:
return OK
static func _write_slot(slot_name: String) -> Error:
return save_to_path(_path_for(slot_name), true)
static func _read_slot(slot_name: String) -> Error:
var envelope: Dictionary = _read_envelope(slot_name)
if envelope.is_empty():