xiandie/manager/archive_manager/archive_manager.gd

195 lines
6.1 KiB
GDScript3
Raw Normal View History

@tool
2024-12-23 01:29:31 +00:00
extends Node
signal archive_loaded
2024-12-24 11:24:55 +00:00
@export var user_root_dir := "user://data/" # must end with "/"
@export var archive_dir := "user://data/archives/"
@export var archive_prefix := "save"
@export var archive: AssembledArchive # current archive
2024-12-23 01:29:31 +00:00
var archives: Array[int] # archive id list in ascending order
var autosave_timer := Timer.new()
2024-12-24 01:16:06 +00:00
func _ready() -> void:
# 禁用默认退出行为,在 _notification 处理 NOTIFICATION_WM_CLOSE_REQUEST 时保存数据
get_tree().set_auto_accept_quit(false)
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
autosave_timer.timeout.connect(_try_auto_save)
autosave_timer.stop()
2024-12-24 11:24:55 +00:00
add_child(autosave_timer)
# config should be loaded first
load_config()
# 在 debug or editor 模式下,直接保证有 archive
if GlobalConfig.DEBUG or Engine.is_editor_hint():
2024-12-24 11:24:55 +00:00
if archives.size() == 0:
create_and_use_new_archive()
else:
GlobalConfigManager.config.current_selected_archive_id = archives[0]
func _notification(what):
# handle window close request
if what == NOTIFICATION_WM_CLOSE_REQUEST:
2025-01-07 10:54:50 +00:00
save_all()
if has_node("/root/Main"):
print("Saved all success before Quit")
SceneManager.pop_notification("已保存所有数据")
var tree = get_tree()
tree.create_timer(1.5).timeout.connect(tree.quit)
else:
get_tree().quit()
func _on_archive_id_changed():
2024-12-24 11:24:55 +00:00
var selected_id = GlobalConfigManager.config.current_selected_archive_id
if archive:
if selected_id != archive.archive_id:
ResourceSaver.save(archive)
archive = null
else:
return
if selected_id < 0:
return
var path = archive_dir + archive_prefix + str(selected_id) + GlobalConfig.RES_FILE_FORMAT
archive = ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE_DEEP)
if !archive:
create_and_use_new_archive(selected_id)
SceneManager.pop_notification("已创建新存档")
else:
load_archive()
# emit signal
archive_loaded.emit()
2024-12-23 01:29:31 +00:00
func check_autosave_options():
if not GlobalConfigManager.config.auto_save_enabled:
autosave_timer.stop()
elif archive and GlobalConfigManager.config.auto_save_seconds > 1:
2024-12-24 11:24:55 +00:00
# reset left time
autosave_timer.stop()
autosave_timer.one_shot = false
autosave_timer.wait_time = GlobalConfigManager.config.auto_save_seconds
2024-12-23 01:29:31 +00:00
autosave_timer.start()
if GlobalConfig.DEBUG:
print(
"check_autosave_options:",
GlobalConfigManager.config.auto_save_enabled,
autosave_timer.wait_time
)
2024-12-23 01:29:31 +00:00
func _try_auto_save():
2024-12-25 06:27:47 +00:00
if GlobalConfig.DEBUG:
print("Auto save")
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()
SceneManager.pop_notification("自动保存成功")
2024-12-24 11:24:55 +00:00
func _check_dirs_and_archives() -> bool:
if !DirAccess.dir_exists_absolute(user_root_dir):
DirAccess.make_dir_recursive_absolute(user_root_dir)
print("Create user_root_dir:", user_root_dir)
2024-12-23 01:29:31 +00:00
# Check if the archive directory is accessible
2024-12-24 11:24:55 +00:00
if !DirAccess.dir_exists_absolute(archive_dir):
DirAccess.make_dir_recursive_absolute(archive_dir)
print("Create archive_dir:", archive_dir)
var archive_dir_access = DirAccess.open(archive_dir)
2024-12-23 01:29:31 +00:00
if !archive_dir_access:
2024-12-24 11:24:55 +00:00
_handle_load_error("存档目录", "读取")
2024-12-23 01:29:31 +00:00
# TODO pop up a dialog to inform the user
return false
2025-01-14 00:56:51 +00:00
archives.clear()
2024-12-23 01:29:31 +00:00
var files = archive_dir_access.get_files()
# get archive number
for file in files:
2024-12-24 11:24:55 +00:00
if file.begins_with(archive_prefix):
var id_str = file.substr(archive_prefix.length())
2024-12-23 01:29:31 +00:00
var id = int(id_str)
archives.append(id)
archives.sort()
return true
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()
archive = AssembledArchive.new()
var archive_path = archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT
if id < 0:
id = 0
# find a new id
archive_path = (archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT)
while FileAccess.file_exists(archive_path):
id += 1
archive_path = (archive_dir + archive_prefix + str(id) + GlobalConfig.RES_FILE_FORMAT)
archive.resource_path = archive_path
2024-12-24 11:54:30 +00:00
archive.archive_id = id
2024-12-24 11:24:55 +00:00
archive.created_time = Time.get_datetime_string_from_system(false, true)
ResourceSaver.save(archive, archive_path)
archives.append(id)
# this will auto trigger signal and load the new archive
GlobalConfigManager.config.current_selected_archive_id = 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)
# player_global_position
var player = SceneManager.get_player() as MainPlayer
if archive and player:
archive.player_global_position = player.global_position
archive.player_direction = player.facing_direction
2024-12-24 11:24:55 +00:00
if archive:
ResourceSaver.save(archive)
# reset autosave timer
check_autosave_options()
2024-12-24 11:24:55 +00:00
func load_config() -> void:
if GlobalConfigManager.config:
2024-12-23 01:29:31 +00:00
return
2024-12-24 11:24:55 +00:00
var path = user_root_dir + "config" + GlobalConfig.RES_FILE_FORMAT
2024-12-23 01:29:31 +00:00
if FileAccess.file_exists(path):
2024-12-24 11:24:55 +00:00
var config = ResourceLoader.load(path)
GlobalConfigManager.config = config
2024-12-23 01:29:31 +00:00
else:
2024-12-24 11:24:55 +00:00
var config = GlobalConfig.new()
GlobalConfigManager.config = config
2024-12-23 01:29:31 +00:00
ResourceSaver.save(config, path)
2024-12-24 11:24:55 +00:00
GlobalConfigManager.config.resource_path = path
# connect signals
GlobalConfigManager.config.current_selected_archive_id_changed.connect(_on_archive_id_changed)
GlobalConfigManager.config.auto_save_seconds_changed.connect(check_autosave_options)
GlobalConfigManager.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()
var selected_id = GlobalConfigManager.config.current_selected_archive_id
if not archives.has(selected_id):
_handle_load_error(str(selected_id) + " 号存档", "查找")
return
var path = archive_dir + archive_prefix + str(selected_id) + GlobalConfig.RES_FILE_FORMAT
archive = ResourceLoader.load(path, "", ResourceLoader.CACHE_MODE_REPLACE_DEEP)
2024-12-24 11:24:55 +00:00
if !archive:
_handle_load_error(str(selected_id) + " 号存档", "加载")
2024-12-23 01:29:31 +00:00
return
2024-12-24 11:24:55 +00:00
archive.resource_path = path
check_autosave_options()
2024-12-24 11:24:55 +00:00
func _handle_load_error(target, action) -> void:
2024-12-24 11:54:30 +00:00
var msg = str(target) + " " + str(action) + " 失败,请检查文件访问权限"
2024-12-24 11:24:55 +00:00
SceneManager.pop_notification(msg)
printerr(msg)
# TODO handle error