Preserve data across the Straywild transition

This commit is contained in:
Alexander Sellite 2026-08-25 22:18:20 -04:00
parent 737d1cf2e0
commit 98a27e2f53
28 changed files with 577 additions and 94 deletions

View file

@ -2,6 +2,7 @@ class_name ProgressionSaveCodec
extends RefCounted
const MAGIC := "straywild_PROGRESSION_CONTAINER"
const LEGACY_MAGIC := "NETFISHING_PROGRESSION_CONTAINER"
const FORMAT_VERSION := 1
const LOCAL_KIND := "local_save"
const ARCHIVE_KIND := "portable_archive"
@ -9,8 +10,10 @@ const MAX_CONTAINER_BYTES := 16 * 1024 * 1024
# This key keeps routine progression files opaque to casual editing. Since the
# client is open source, it is intentionally not treated as a security secret.
# Its original value is a stable file-format detail so released saves remain
# readable after the Straywild rebrand.
const CONTAINER_PASSPHRASE := (
"straywild progression container v1 / not an identity credential"
"NETfishing progression container v1 / not an identity credential"
)
@ -102,15 +105,9 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
or FileAccess.get_size(path) > MAX_CONTAINER_BYTES
):
return {"ok": false, "message": "progression file is unavailable."}
var file: FileAccess = FileAccess.open_encrypted_with_pass(
path,
FileAccess.READ,
CONTAINER_PASSPHRASE,
)
if file == null:
var envelope_text: String = _read_encrypted_text(path)
if envelope_text.is_empty():
return {"ok": false, "message": "progression file could not be opened."}
var envelope_text: String = file.get_as_text()
file.close()
var envelope_json := JSON.new()
if (
envelope_json.parse(envelope_text) != OK
@ -118,8 +115,9 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
):
return {"ok": false, "message": "progression container is malformed."}
var envelope: Dictionary = envelope_json.data
var legacy_container: bool = envelope.get("magic") == LEGACY_MAGIC
if (
envelope.get("magic") != MAGIC
envelope.get("magic") not in [MAGIC, LEGACY_MAGIC]
or int(envelope.get("format_version", -1)) != FORMAT_VERSION
or str(envelope.get("kind", "")) != expected_kind
):
@ -144,9 +142,23 @@ static func _read_container(path: String, expected_kind: String) -> Dictionary:
"game_version": str(envelope.get("game_version", "")),
"created_at_unix": int(envelope.get("created_at_unix", 0)),
"legacy_plaintext": false,
"legacy_container": legacy_container,
}
static func _read_encrypted_text(path: String) -> String:
var file: FileAccess = FileAccess.open_encrypted_with_pass(
path,
FileAccess.READ,
CONTAINER_PASSPHRASE,
)
if file == null:
return ""
var text: String = file.get_as_text()
file.close()
return text
static func _read_plaintext_dictionary(path: String) -> Dictionary:
var bytes: PackedByteArray = PortableFileGuard.read_bytes(
path,