iter51-卡2
This commit is contained in:
1 parent
1cd6e2b1b0
commit
372b4fdc31
27 files changed
+1231
-356
No files matched your search
+33
-13
@@ -48,7 +48,7 @@ func _init(path: String = "") -> void:
|
||||
# 无激活态(注入路径空,一切写盘路径拒绝并返回 false);玩家侧经选档界面显式进档/新档后才可写。
|
||||
# 旧隐式单档一次性迁入槽 1(Q1 甲,sv12)在本口执行。
|
||||
func _ready() -> void:
|
||||
slots._migrate_legacy_save(LEGACY_SAVE_PATH, slots.slot_path(1), LEGACY_SAVE_PATH + LEGACY_MIGRATED_SUFFIX)
|
||||
slots.migrate_legacy_save(LEGACY_SAVE_PATH, slots.slot_path(1), LEGACY_SAVE_PATH + LEGACY_MIGRATED_SUFFIX)
|
||||
|
||||
|
||||
# 迁移注册口:from_version → from_version+1 的升级函数(读档时链式调用)。fn 契约:
|
||||
@@ -63,10 +63,10 @@ func register_migration(from_version: int, fn: Callable) -> void:
|
||||
# 损坏兜底:原文件改名 <path>.corrupt.bak(已存在则覆盖)+ push_warning + 默认数据继续——不静默丢档。
|
||||
func load_from_disk() -> bool:
|
||||
_read_only = false
|
||||
if not FileAccess.file_exists(slots._path):
|
||||
if not FileAccess.file_exists(slots.active_path()):
|
||||
_data = _default_data() # 新档合法态
|
||||
return true
|
||||
var f := FileAccess.open(slots._path, FileAccess.READ)
|
||||
var f := FileAccess.open(slots.active_path(), FileAccess.READ)
|
||||
if f == null:
|
||||
return _corrupt_fallback("读打开失败(%s)" % error_string(FileAccess.get_open_error()))
|
||||
return _load_parsed(f)
|
||||
@@ -102,21 +102,21 @@ func _load_parsed(f: FileAccess) -> bool:
|
||||
# 无激活态一律拒绝并返回 false(sv3:启动态不隐式激活,盘面零触碰);
|
||||
# 高版本拒读态一律拒绝(契约 4 禁写);写失败返回 false。
|
||||
func write_to_disk() -> bool:
|
||||
if slots._path == "":
|
||||
if slots.active_path() == "":
|
||||
push_error("[存档序列化] 写盘拒绝——无激活存档位(启动态不隐式激活;经选档进档/新档后落盘)")
|
||||
return false
|
||||
if _read_only:
|
||||
push_error("[存档序列化] 写盘拒绝——档案版本高于当前(拒读禁写态)")
|
||||
return false
|
||||
var tmp := slots._path + ".tmp"
|
||||
var tmp := slots.active_path() + ".tmp"
|
||||
var f := FileAccess.open(tmp, FileAccess.WRITE)
|
||||
if f == null:
|
||||
push_error("[存档序列化] 临时文件打开失败:%s(%s)" % [tmp, error_string(FileAccess.get_open_error())])
|
||||
return false
|
||||
f.store_string(JSON.stringify(_data, "\t", true))
|
||||
f.close()
|
||||
if not _rename_overwrite(tmp, slots._path):
|
||||
push_error("[存档序列化] 原子改名失败(tmp 保留待查):%s → %s" % [tmp, slots._path])
|
||||
if not rename_overwrite(tmp, slots.active_path()):
|
||||
push_error("[存档序列化] 原子改名失败(tmp 保留待查):%s → %s" % [tmp, slots.active_path()])
|
||||
return false
|
||||
return true
|
||||
|
||||
@@ -214,7 +214,7 @@ func _peek_migrated(parsed: Variant, fail: Array) -> Variant:
|
||||
|
||||
## 摘要窥视内核(只读推演单点——SlotStore 两 peek 方法经槽路径派生委托至此;
|
||||
## 迁移链在此只读推演——生产迁移 Callable 为纯函数,零盘面副作用)
|
||||
func _peek_summary_at(path: String) -> Dictionary:
|
||||
func peek_summary_at(path: String) -> Dictionary:
|
||||
var out := {"readable": false, "has_file": false, "keystone": 0, "cleared": 0, "total": 0}
|
||||
if not FileAccess.file_exists(path):
|
||||
out["readable"] = true # 空槽=可读零值合法态
|
||||
@@ -275,15 +275,35 @@ func _default_data() -> Dictionary[String, Variant]:
|
||||
}
|
||||
|
||||
|
||||
# 原地重置默认态(SlotStore 槽位原语的协作口——激活/建删/换注回默认数据)
|
||||
func _reset_to_default() -> void:
|
||||
# 原地重置默认态(SlotStore 槽位原语的协作口——激活/建删/换注回默认数据;
|
||||
# 公开化〔5.1 封装修复——SlotStore 反向私取承接,_reset_to_default 更名非并存〕)
|
||||
func reset_to_default() -> void:
|
||||
_data = _default_data()
|
||||
|
||||
|
||||
# 禁写位公开面(SlotStore 激活/换注三态恢复消费——一行转发自有成员,零逻辑增量)
|
||||
func set_read_only(v: bool) -> void:
|
||||
_read_only = v
|
||||
|
||||
|
||||
func read_only() -> bool:
|
||||
return _read_only
|
||||
|
||||
|
||||
# 数据快照还原公开面(SlotStore 激活/新建失败回退三态恢复消费——零拷贝语义:snapshot 返 _data
|
||||
# 本引用、restore 直还引用,行为与原 _data 直读写逐位等价)
|
||||
func data_snapshot() -> Dictionary[String, Variant]:
|
||||
return _data
|
||||
|
||||
|
||||
func restore_data(data: Dictionary[String, Variant]) -> void:
|
||||
_data = data
|
||||
|
||||
|
||||
# 损坏兜底:坏档改名 .corrupt.bak(已存在则覆盖)→ 默认数据继续。不静默丢档(警告留痕)、不 crash。
|
||||
func _corrupt_fallback(reason: String) -> bool:
|
||||
var bak := slots._path + ".corrupt.bak"
|
||||
if not _rename_overwrite(slots._path, bak):
|
||||
var bak := slots.active_path() + ".corrupt.bak"
|
||||
if not rename_overwrite(slots.active_path(), bak):
|
||||
push_warning("[存档序列化] 坏档备份改名失败(原文件保留原地):%s——%s" % [bak, reason])
|
||||
else:
|
||||
push_warning("[存档序列化] 检测到损坏档案,已备份为 %s——%s(用默认新档继续)" % [bak, reason])
|
||||
@@ -314,7 +334,7 @@ func _normalize(data: Dictionary) -> Dictionary[String, Variant]:
|
||||
|
||||
# 覆盖式改名(Windows 原生 rename 目标已存在时会失败——先删后改,显式覆盖语义;IO 原语单点——
|
||||
# SlotStore 迁移流经本件调用)
|
||||
func _rename_overwrite(from: String, to: String) -> bool:
|
||||
func rename_overwrite(from: String, to: String) -> bool:
|
||||
var dir := DirAccess.open(from.get_base_dir())
|
||||
if dir == null:
|
||||
return false
|
||||
|
||||
Reference in new issue
Block a user