2025-01-16 12:24:21 +00:00
|
|
|
|
@tool
|
2024-12-23 01:29:31 +00:00
|
|
|
|
extends Node
|
|
|
|
|
|
2025-01-05 11:25:13 +00:00
|
|
|
|
signal archive_loaded
|
2025-01-03 08:07:35 +00:00
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
# Constants
|
|
|
|
|
const CURRENT_VERSION = 6
|
|
|
|
|
const ARCHIVE_ID_MIN = 0
|
|
|
|
|
const ARCHIVE_ID_MAX = 99
|
|
|
|
|
const ARCHIVE_ID_DIGITS = 3
|
|
|
|
|
|
|
|
|
|
# Static paths
|
2025-07-16 15:20:55 +00:00
|
|
|
|
static var user_data_root_dir := "user://data/" # must end with "/"
|
|
|
|
|
static var user_archives_dir := "user://data/archives/"
|
2025-07-16 11:56:21 +00:00
|
|
|
|
static var archive_prefix := "save"
|
|
|
|
|
|
|
|
|
|
# Archive management
|
2025-06-28 01:14:15 +00:00
|
|
|
|
var archive: AssembledArchive:
|
2025-05-14 20:43:55 +00:00
|
|
|
|
set(val):
|
|
|
|
|
archive = val
|
|
|
|
|
if archive:
|
2025-07-16 15:20:55 +00:00
|
|
|
|
# emit signal
|
|
|
|
|
archive_loaded.emit()
|
2025-07-05 08:40:30 +00:00
|
|
|
|
GlobalConfigManager.print_global_info()
|
2025-05-14 20:43:55 +00:00
|
|
|
|
print("use archive ", archive.resource_path)
|
2025-07-10 19:30:35 +00:00
|
|
|
|
archive.event_stage["release_stage"] = GlobalConfig.RELEASE_STAGE
|
|
|
|
|
print_rich("[color=brown] release_stage = %s[/color]" % GlobalConfig.RELEASE_STAGE)
|
|
|
|
|
|
|
|
|
|
|
2025-07-15 08:14:30 +00:00
|
|
|
|
var archives_dict: Dictionary[int, AssembledArchive] = {}
|
|
|
|
|
var archives_notes_dict: Dictionary[int, String] = {}
|
2024-12-23 01:29:31 +00:00
|
|
|
|
var autosave_timer := Timer.new()
|
|
|
|
|
|
2025-07-10 16:29:46 +00:00
|
|
|
|
# 供运行时缓存跨场景数据
|
|
|
|
|
var _runtime_global_dictionary: Dictionary[String, Variant] = {}
|
2024-12-24 01:16:06 +00:00
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
func _ready() -> void:
|
2025-01-14 10:20:31 +00:00
|
|
|
|
# 禁用默认退出行为,在 _notification 处理 NOTIFICATION_WM_CLOSE_REQUEST 时保存数据
|
2024-12-27 13:32:12 +00:00
|
|
|
|
get_tree().set_auto_accept_quit(false)
|
2025-04-01 08:16:29 +00:00
|
|
|
|
process_mode = Node.PROCESS_MODE_ALWAYS
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
if not _check_dirs_and_archives():
|
2024-12-24 11:54:30 +00:00
|
|
|
|
_handle_load_error("存档目录", "读写")
|
2024-12-23 01:29:31 +00:00
|
|
|
|
return
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
|
|
|
|
_setup_autosave_timer()
|
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
# config should be loaded first
|
|
|
|
|
load_config()
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2025-01-14 10:20:31 +00:00
|
|
|
|
# 在 debug or editor 模式下,直接保证有 archive
|
|
|
|
|
if GlobalConfig.DEBUG or Engine.is_editor_hint():
|
2025-07-16 11:56:21 +00:00
|
|
|
|
_ensure_debug_archive()
|
2024-12-24 11:24:55 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _notification(what: int) -> void:
|
2024-12-27 13:32:12 +00:00
|
|
|
|
# handle window close request
|
|
|
|
|
if what == NOTIFICATION_WM_CLOSE_REQUEST:
|
2025-01-07 10:54:50 +00:00
|
|
|
|
save_all()
|
2025-06-24 10:40:43 +00:00
|
|
|
|
print("Saved all success before Quit")
|
|
|
|
|
# 已保存所有数据 [ID:ui_saved_all]
|
2025-07-02 16:32:37 +00:00
|
|
|
|
SceneManager.pop_notification("ui_saved_all")
|
2025-06-24 10:40:43 +00:00
|
|
|
|
SceneManager.quit_game()
|
2024-12-27 13:32:12 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _setup_autosave_timer() -> void:
|
|
|
|
|
autosave_timer.timeout.connect(_try_auto_save)
|
|
|
|
|
autosave_timer.stop()
|
|
|
|
|
add_child(autosave_timer)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ensure_debug_archive() -> void:
|
|
|
|
|
if archives_dict.is_empty():
|
|
|
|
|
create_and_use_new_archive(0)
|
|
|
|
|
else:
|
|
|
|
|
# debug 模式下默认使用 0 号存档
|
|
|
|
|
GlobalConfigManager.config.current_selected_archive_id = 0
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _on_archive_id_changed() -> void:
|
2024-12-24 11:24:55 +00:00
|
|
|
|
var selected_id = GlobalConfigManager.config.current_selected_archive_id
|
2025-01-21 12:41:24 +00:00
|
|
|
|
if selected_id < 0:
|
|
|
|
|
return
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
print("_on_archive_id_changed id=", selected_id)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2025-07-15 08:14:30 +00:00
|
|
|
|
if not archives_dict.has(selected_id):
|
2025-05-14 20:43:55 +00:00
|
|
|
|
print("新建存档 ", selected_id)
|
2024-12-24 11:24:55 +00:00
|
|
|
|
create_and_use_new_archive(selected_id)
|
2025-01-24 14:19:17 +00:00
|
|
|
|
# 已创建新存档 [ID:ui_new_archive]
|
2025-07-02 16:32:37 +00:00
|
|
|
|
SceneManager.pop_notification("ui_new_archive")
|
2024-12-24 11:24:55 +00:00
|
|
|
|
else:
|
|
|
|
|
load_archive()
|
2024-12-23 01:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func check_autosave_options() -> void:
|
|
|
|
|
var config = GlobalConfigManager.config
|
|
|
|
|
var should_enable_autosave = (
|
|
|
|
|
config.auto_save_enabled
|
|
|
|
|
and archive
|
|
|
|
|
and config.auto_save_seconds > 1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if should_enable_autosave:
|
2024-12-24 11:24:55 +00:00
|
|
|
|
# reset left time
|
|
|
|
|
autosave_timer.stop()
|
|
|
|
|
autosave_timer.one_shot = false
|
2025-07-16 11:56:21 +00:00
|
|
|
|
autosave_timer.wait_time = config.auto_save_seconds
|
2024-12-23 01:29:31 +00:00
|
|
|
|
autosave_timer.start()
|
2025-01-21 12:41:24 +00:00
|
|
|
|
else:
|
|
|
|
|
autosave_timer.stop()
|
|
|
|
|
|
2025-01-16 12:24:21 +00:00
|
|
|
|
if GlobalConfig.DEBUG:
|
|
|
|
|
print(
|
2025-01-21 10:08:16 +00:00
|
|
|
|
"check_autosave_option: ",
|
2025-07-16 11:56:21 +00:00
|
|
|
|
config.auto_save_enabled,
|
2025-01-21 10:08:16 +00:00
|
|
|
|
" wait_time=",
|
2025-01-16 12:24:21 +00:00
|
|
|
|
autosave_timer.wait_time
|
|
|
|
|
)
|
2024-12-23 01:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _try_auto_save() -> void:
|
2024-12-25 06:27:47 +00:00
|
|
|
|
if GlobalConfig.DEBUG:
|
|
|
|
|
print("Auto save")
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
if archive and GlobalConfigManager.config.auto_save_seconds > 1:
|
2024-12-23 01:29:31 +00:00
|
|
|
|
save_all()
|
2025-01-24 14:19:17 +00:00
|
|
|
|
# 自动保存成功 [ID:ui_auto_saved]
|
2025-07-02 16:32:37 +00:00
|
|
|
|
SceneManager.pop_notification("ui_auto_saved")
|
2024-12-23 01:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
func _check_dirs_and_archives() -> bool:
|
2025-07-16 11:56:21 +00:00
|
|
|
|
# Ensure directories exist
|
2025-07-16 15:20:55 +00:00
|
|
|
|
_ensure_directory_exists(user_data_root_dir)
|
|
|
|
|
_ensure_directory_exists(user_archives_dir)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2024-12-23 01:29:31 +00:00
|
|
|
|
# Check if the archive directory is accessible
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var archive_dir_access = DirAccess.open(user_archives_dir)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
if not archive_dir_access:
|
2024-12-24 11:24:55 +00:00
|
|
|
|
_handle_load_error("存档目录", "读取")
|
2024-12-23 01:29:31 +00:00
|
|
|
|
return false
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
|
|
|
|
# Load existing archives
|
|
|
|
|
_load_existing_archives(archive_dir_access)
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _ensure_directory_exists(dir_path: String) -> void:
|
|
|
|
|
if not DirAccess.dir_exists_absolute(dir_path):
|
|
|
|
|
DirAccess.make_dir_recursive_absolute(dir_path)
|
|
|
|
|
print("Create directory:", dir_path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _load_existing_archives(dir_access: DirAccess) -> void:
|
|
|
|
|
var files = dir_access.get_files()
|
2025-01-21 12:41:24 +00:00
|
|
|
|
files.sort()
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2024-12-23 01:29:31 +00:00
|
|
|
|
for file in files:
|
2025-07-16 11:56:21 +00:00
|
|
|
|
if not _is_valid_archive_filename(file):
|
|
|
|
|
continue
|
|
|
|
|
var archive_info = _parse_archive_filename(file)
|
|
|
|
|
if not archive_info:
|
|
|
|
|
continue
|
|
|
|
|
var id = archive_info.id
|
|
|
|
|
var note = archive_info.note
|
|
|
|
|
archives_notes_dict[id] = note
|
|
|
|
|
if not archives_dict.has(id):
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var archive_resource = _load_archive_resource(user_archives_dir + file)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
if archive_resource:
|
|
|
|
|
archives_dict[id] = archive_resource
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _is_valid_archive_filename(filename: String) -> bool:
|
|
|
|
|
return filename.begins_with(archive_prefix) and filename.ends_with(GlobalConfig.RES_FILE_FORMAT)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _parse_archive_filename(filename: String) -> Dictionary:
|
|
|
|
|
# format: save012_xxxxx; save000
|
|
|
|
|
var basename = filename.get_basename()
|
|
|
|
|
var id_and_note = basename.substr(archive_prefix.length()).strip_escapes().split("_", true, 1)
|
|
|
|
|
var id_str = id_and_note[0]
|
|
|
|
|
# 非三位数的 id 会被忽略
|
|
|
|
|
if id_str.length() != ARCHIVE_ID_DIGITS:
|
|
|
|
|
return {}
|
|
|
|
|
var id = int(id_str)
|
|
|
|
|
# 读取范围是 0-99
|
|
|
|
|
if id < ARCHIVE_ID_MIN or id > ARCHIVE_ID_MAX:
|
|
|
|
|
return {}
|
|
|
|
|
var note_str = id_and_note[1] if id_and_note.size() >= 2 else (archive_prefix + id_str)
|
|
|
|
|
return {
|
|
|
|
|
"id": id,
|
|
|
|
|
"note": note_str
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _load_archive_resource(path: String) -> AssembledArchive:
|
|
|
|
|
var res = ResourceLoader.load(
|
|
|
|
|
path, "AssembledArchive", ResourceLoader.CACHE_MODE_REPLACE_DEEP
|
|
|
|
|
)
|
|
|
|
|
if is_instance_valid(res) and res.version >= CURRENT_VERSION:
|
|
|
|
|
return res
|
|
|
|
|
else:
|
|
|
|
|
printerr("SKIP INVALID ARCHIVE! path=", path)
|
|
|
|
|
return null
|
2024-12-23 01:29:31 +00:00
|
|
|
|
|
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
# id = -1 means create a new archive, otherwise create an archive with the given id
|
|
|
|
|
func create_and_use_new_archive(id := -1) -> void:
|
|
|
|
|
_check_dirs_and_archives()
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
if id < 0:
|
2025-03-11 09:16:24 +00:00
|
|
|
|
# 如果 id 小于 0,找到一个新的 id,创建新存档
|
2025-07-16 11:56:21 +00:00
|
|
|
|
id = _find_next_available_id()
|
2025-03-11 09:16:24 +00:00
|
|
|
|
_create_and_save_new_archive_resoure(id)
|
|
|
|
|
else:
|
|
|
|
|
# 如果 id 大于等于 0,创建指定 id 的存档
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var archive_path = get_archive_path(id)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
var take_over_path = FileAccess.file_exists(archive_path)
|
|
|
|
|
_create_and_save_new_archive_resoure(id, take_over_path)
|
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
# this will auto trigger signal and load the new archive
|
|
|
|
|
GlobalConfigManager.config.current_selected_archive_id = id
|
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _find_next_available_id() -> int:
|
|
|
|
|
var id = 0
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var archive_path = get_archive_path(id)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
while FileAccess.file_exists(archive_path) and id <= ARCHIVE_ID_MAX:
|
|
|
|
|
id += 1
|
2025-07-16 15:20:55 +00:00
|
|
|
|
archive_path = get_archive_path(id)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
return id
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _create_and_save_new_archive_resoure(id: int, take_over_path := false) -> void:
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var archive_path = get_archive_path(id)
|
2025-03-11 09:16:24 +00:00
|
|
|
|
archive = AssembledArchive.new() as Resource
|
2025-06-25 20:31:40 +00:00
|
|
|
|
archive.version = CURRENT_VERSION
|
2025-03-11 09:16:24 +00:00
|
|
|
|
if take_over_path:
|
|
|
|
|
archive.take_over_path(archive_path)
|
|
|
|
|
else:
|
|
|
|
|
archive.resource_path = archive_path
|
|
|
|
|
archive.archive_id = id
|
|
|
|
|
archive.created_time = Time.get_datetime_string_from_system(false, true)
|
|
|
|
|
ResourceSaver.save(archive, archive_path)
|
2025-07-15 08:14:30 +00:00
|
|
|
|
archives_dict[id] = archive
|
2025-03-11 09:16:24 +00:00
|
|
|
|
|
|
|
|
|
|
2025-01-21 12:41:24 +00:00
|
|
|
|
# 超过 999 个存档会出问题;不过这个游戏不会有这么多存档
|
2025-07-16 15:20:55 +00:00
|
|
|
|
func get_archive_path(id: int) -> String:
|
2025-07-16 11:56:21 +00:00
|
|
|
|
var id_str := str(id).pad_zeros(ARCHIVE_ID_DIGITS)
|
2025-07-16 15:20:55 +00:00
|
|
|
|
return user_archives_dir + archive_prefix + id_str + GlobalConfig.RES_FILE_FORMAT
|
2025-01-21 12:41:24 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-15 08:14:30 +00:00
|
|
|
|
func allow_resume(id := 1) -> bool:
|
|
|
|
|
return archives_dict.has(id)
|
|
|
|
|
|
|
|
|
|
|
2024-12-23 01:29:31 +00:00
|
|
|
|
func save_all() -> void:
|
|
|
|
|
# save config
|
|
|
|
|
var config = GlobalConfigManager.config
|
2024-12-24 11:24:55 +00:00
|
|
|
|
if config:
|
|
|
|
|
ResourceSaver.save(config)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
# save player state
|
|
|
|
|
_save_player_state()
|
|
|
|
|
# save archive
|
2024-12-24 11:24:55 +00:00
|
|
|
|
if archive:
|
|
|
|
|
ResourceSaver.save(archive)
|
|
|
|
|
# reset autosave timer
|
2025-01-16 12:24:21 +00:00
|
|
|
|
check_autosave_options()
|
2024-12-24 11:24:55 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _save_player_state() -> void:
|
|
|
|
|
if not archive:
|
|
|
|
|
return
|
|
|
|
|
var player = SceneManager.get_player() as MainPlayer
|
|
|
|
|
if player:
|
|
|
|
|
archive.player_global_position_x = player.global_position.x
|
|
|
|
|
archive.player_direction = player.facing_direction
|
|
|
|
|
|
|
|
|
|
|
2024-12-24 11:24:55 +00:00
|
|
|
|
func load_config() -> void:
|
|
|
|
|
if GlobalConfigManager.config:
|
2024-12-23 01:29:31 +00:00
|
|
|
|
return
|
2025-07-16 15:20:55 +00:00
|
|
|
|
var path = user_data_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
|
2024-12-23 01:29:31 +00:00
|
|
|
|
if FileAccess.file_exists(path):
|
2025-07-16 11:56:21 +00:00
|
|
|
|
var loaded_config = ResourceLoader.load(path)
|
|
|
|
|
if is_instance_valid(loaded_config) and loaded_config.version >= CURRENT_VERSION:
|
|
|
|
|
GlobalConfigManager.config = loaded_config
|
2025-06-25 20:31:40 +00:00
|
|
|
|
else:
|
|
|
|
|
printerr("SKIP INVALID CONFIG!")
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
|
|
|
|
if not GlobalConfigManager.config:
|
|
|
|
|
_create_default_config(path)
|
|
|
|
|
if not Engine.is_editor_hint():
|
|
|
|
|
_connect_config_signals()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _create_default_config(path: String) -> void:
|
|
|
|
|
var config = GlobalConfig.new()
|
|
|
|
|
config.version = CURRENT_VERSION
|
2025-07-16 15:20:55 +00:00
|
|
|
|
config.resource_path = path
|
2025-07-16 11:56:21 +00:00
|
|
|
|
GlobalConfigManager.config = config
|
|
|
|
|
ResourceSaver.save(config, path)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func _connect_config_signals() -> void:
|
|
|
|
|
var config = GlobalConfigManager.config
|
|
|
|
|
config.current_selected_archive_id_changed.connect(_on_archive_id_changed)
|
|
|
|
|
config.auto_save_seconds_changed.connect(check_autosave_options)
|
|
|
|
|
config.auto_save_enabled_changed.connect(check_autosave_options)
|
2024-12-24 11:24:55 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func load_archive() -> void:
|
|
|
|
|
_check_dirs_and_archives()
|
2025-07-01 14:32:30 +00:00
|
|
|
|
var selected_id = 0
|
|
|
|
|
if GlobalConfigManager.config:
|
|
|
|
|
selected_id = GlobalConfigManager.config.current_selected_archive_id
|
2025-07-16 11:56:21 +00:00
|
|
|
|
|
2025-05-14 20:43:55 +00:00
|
|
|
|
print("load_archive ", selected_id)
|
2025-07-15 08:14:30 +00:00
|
|
|
|
if not archives_dict.has(selected_id):
|
2024-12-24 11:24:55 +00:00
|
|
|
|
_handle_load_error(str(selected_id) + " 号存档", "查找")
|
|
|
|
|
return
|
2025-07-15 08:14:30 +00:00
|
|
|
|
archive = archives_dict[selected_id]
|
2025-01-16 12:24:21 +00:00
|
|
|
|
check_autosave_options()
|
2024-12-24 11:24:55 +00:00
|
|
|
|
|
|
|
|
|
|
2025-07-16 11:56:21 +00:00
|
|
|
|
func _handle_load_error(target: String, action: String) -> void:
|
2025-07-02 16:32:37 +00:00
|
|
|
|
var msg = str(target) + " " + str(action) + " failed. Permission Error."
|
2024-12-24 11:24:55 +00:00
|
|
|
|
SceneManager.pop_notification(msg)
|
|
|
|
|
printerr(msg)
|
|
|
|
|
# TODO handle error
|
2025-05-13 11:45:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func set_global_entry(property: StringName, value) -> void:
|
|
|
|
|
if not archive:
|
|
|
|
|
printerr("Archive is null, cannot set global entry")
|
|
|
|
|
return
|
|
|
|
|
archive.global_data_dict[property] = value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func get_global_value(property: StringName, default = null) -> Variant:
|
|
|
|
|
if not archive:
|
|
|
|
|
printerr("Archive is null, cannot get global value")
|
|
|
|
|
return default
|
|
|
|
|
var val = archive.global_data_dict.get(property)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
return default if val == null else val
|
2025-07-02 16:32:37 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func set_chapter_if_greater(c: int) -> void:
|
|
|
|
|
if not archive:
|
|
|
|
|
printerr("Archive is null, cannot set chapter")
|
|
|
|
|
return
|
|
|
|
|
# 1:序章;2-5:一~四章;6:结尾
|
2025-07-16 11:56:21 +00:00
|
|
|
|
const MIN_CHAPTER = 1
|
|
|
|
|
const MAX_CHAPTER = 6
|
|
|
|
|
if c < MIN_CHAPTER or c > MAX_CHAPTER:
|
2025-07-02 16:32:37 +00:00
|
|
|
|
printerr("[ArchiveManager] set_chapter_if_greater: invalid chapter value: " + str(c))
|
|
|
|
|
return
|
2025-07-06 07:12:11 +00:00
|
|
|
|
if EventManager.get_chapter_stage() >= c:
|
2025-07-02 16:32:37 +00:00
|
|
|
|
return
|
2025-07-06 07:12:11 +00:00
|
|
|
|
# 进入下一章
|
2025-07-02 16:32:37 +00:00
|
|
|
|
print("[ArchiveManager] set_chapter_if_greater: " + str(c))
|
2025-07-06 07:12:11 +00:00
|
|
|
|
EventManager.set_stage_if_greater("current_chapter_stage", c)
|
2025-07-05 17:04:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func unlock_memory(id: int) -> void:
|
2025-07-16 11:56:21 +00:00
|
|
|
|
if not archive:
|
2025-07-05 17:04:35 +00:00
|
|
|
|
printerr("Archive is null, cannot unlock memory. id=", id)
|
2025-07-16 11:56:21 +00:00
|
|
|
|
return
|
|
|
|
|
if archive.mem_display_dict.get(id):
|
|
|
|
|
print("memory already unlocked. id=", id)
|
|
|
|
|
return
|
|
|
|
|
archive.mem_display_dict[id] = true
|
2025-07-16 12:02:01 +00:00
|
|
|
|
SceneManager.pop_notification("ui_notify_mem_update")
|
2025-07-10 16:29:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 供运行时缓存跨场景数据
|
|
|
|
|
func runtime_set(key: String, value: Variant) -> void:
|
|
|
|
|
_runtime_global_dictionary[key] = value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func runtime_get(key: String, default_value: Variant = null) -> Variant:
|
|
|
|
|
return _runtime_global_dictionary.get(key, default_value)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func runtime_has(key: String) -> bool:
|
|
|
|
|
return _runtime_global_dictionary.has(key)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func runtime_remove(key: String) -> void:
|
|
|
|
|
_runtime_global_dictionary.erase(key)
|