2023-12-09 19:39:38 +02:00
|
|
|
extends Node
|
|
|
|
|
|
|
|
const VariantSerializer = preload("res://lib/utils/variant_serializer.gd")
|
|
|
|
|
2023-12-20 02:54:22 +02:00
|
|
|
signal loaded()
|
|
|
|
signal unloaded()
|
|
|
|
|
|
|
|
var is_loaded := false
|
2024-01-22 17:54:15 +02:00
|
|
|
var export_config = ConfigFile.new()
|
|
|
|
var export_config_path = "res://export_presets.cfg"
|
2023-12-20 02:54:22 +02:00
|
|
|
|
2023-12-10 02:47:21 +02:00
|
|
|
func clear():
|
2023-12-13 23:37:36 +02:00
|
|
|
await _clear_save_tree(get_tree().root.get_node("Main"))
|
2023-12-20 02:54:22 +02:00
|
|
|
unloaded.emit()
|
|
|
|
is_loaded = false
|
2023-12-10 02:47:21 +02:00
|
|
|
|
2023-12-09 19:39:38 +02:00
|
|
|
func save():
|
|
|
|
if HomeApi.has_connected() == false:
|
|
|
|
return
|
|
|
|
|
|
|
|
var filename = HomeApi.api.url.split("//")[1].replace("/api/websocket", "").replace(".", "_").replace(":", "_")
|
|
|
|
|
|
|
|
var save_file = FileAccess.open("user://%s.save" % filename, FileAccess.WRITE)
|
|
|
|
|
|
|
|
if save_file == null:
|
|
|
|
return
|
|
|
|
|
|
|
|
var save_tree = _generate_save_tree(get_tree().root.get_node("Main"))
|
|
|
|
|
2024-01-22 17:54:15 +02:00
|
|
|
var json_text = JSON.stringify({
|
|
|
|
"version": "1.0.0",
|
|
|
|
"tree": save_tree
|
|
|
|
})
|
2023-12-09 19:39:38 +02:00
|
|
|
save_file.store_line(json_text)
|
|
|
|
|
|
|
|
func load():
|
2024-01-22 17:54:15 +02:00
|
|
|
await clear()
|
2023-12-11 16:24:10 +02:00
|
|
|
|
2023-12-09 19:39:38 +02:00
|
|
|
if HomeApi.has_connected() == false:
|
|
|
|
return
|
|
|
|
|
|
|
|
var filename = HomeApi.api.url.split("//")[1].replace("/api/websocket", "").replace(".", "_").replace(":", "_")
|
|
|
|
|
|
|
|
var save_file = FileAccess.open("user://%s.save" % filename, FileAccess.READ)
|
|
|
|
|
|
|
|
if save_file == null:
|
|
|
|
return
|
|
|
|
|
|
|
|
var json_text = save_file.get_line()
|
2024-01-22 17:54:15 +02:00
|
|
|
var save_data = JSON.parse_string(json_text)
|
|
|
|
|
|
|
|
save_data = migrate(save_data)
|
|
|
|
|
|
|
|
if save_data == null:
|
|
|
|
save()
|
|
|
|
return
|
|
|
|
|
|
|
|
var save_tree = save_data["tree"]
|
2023-12-09 19:39:38 +02:00
|
|
|
|
2024-01-16 16:00:30 +02:00
|
|
|
if save_tree == null:
|
|
|
|
return
|
|
|
|
|
2023-12-09 19:39:38 +02:00
|
|
|
if save_tree is Array:
|
|
|
|
for tree in save_tree:
|
|
|
|
_build_save_tree(tree)
|
|
|
|
else:
|
|
|
|
_build_save_tree(save_tree)
|
|
|
|
|
2023-12-20 02:54:22 +02:00
|
|
|
loaded.emit()
|
|
|
|
is_loaded = true
|
|
|
|
|
2024-01-22 17:54:15 +02:00
|
|
|
func migrate(data: Dictionary):
|
|
|
|
var migration_version = data["migration"]
|
|
|
|
var migrations = load_migrations()
|
|
|
|
|
|
|
|
if migration_version == null || migrations == {}:
|
|
|
|
return null
|
|
|
|
|
|
|
|
var migration_keys = migrations.keys().sort()
|
|
|
|
|
|
|
|
for key in migration_keys:
|
|
|
|
if is_migration_newer(migration_version, key):
|
|
|
|
var migration = migrations[key]
|
|
|
|
|
|
|
|
data = migration.migrate(data)
|
|
|
|
|
|
|
|
data["migration"] = key
|
|
|
|
|
|
|
|
return data
|
|
|
|
|
|
|
|
func is_migration_newer(version, new_version):
|
|
|
|
var version_split = version.split(".")
|
|
|
|
var new_version_split = new_version.split(".")
|
|
|
|
|
|
|
|
for i in range(0, 3):
|
|
|
|
if int(version_split[i]) > int(new_version_split[i]):
|
|
|
|
return false
|
|
|
|
elif int(version_split[i]) < int(new_version_split[i]):
|
|
|
|
return true
|
|
|
|
|
|
|
|
return false
|
|
|
|
|
|
|
|
func load_migrations():
|
|
|
|
var migrations = {}
|
|
|
|
var migrations_dir := DirAccess.open("res://lib/migrations")
|
|
|
|
|
|
|
|
if migrations == null:
|
|
|
|
return {}
|
|
|
|
|
|
|
|
migrations_dir.list_dir_begin()
|
|
|
|
var file_name = migrations_dir.get_next()
|
|
|
|
|
|
|
|
while file_name != "":
|
|
|
|
if file_name.ends_with(".gd"):
|
|
|
|
var version = file_name.substr(0, -3)
|
|
|
|
|
|
|
|
migrations[version] = load("res://lib/migrations/%s" % file_name)
|
|
|
|
|
|
|
|
file_name = migrations_dir.get_next()
|
|
|
|
|
|
|
|
migrations_dir.list_dir_end()
|
|
|
|
|
|
|
|
return migrations
|
|
|
|
|
|
|
|
func get_version():
|
|
|
|
var config_error = export_config.load(export_config_path)
|
|
|
|
|
|
|
|
if config_error != OK:
|
|
|
|
return null
|
|
|
|
|
|
|
|
var version = export_config.get_value("preset.1.options", "version/name")
|
|
|
|
|
|
|
|
if version == null:
|
|
|
|
return null
|
|
|
|
|
|
|
|
return version
|
|
|
|
|
2023-12-10 02:47:21 +02:00
|
|
|
func _clear_save_tree(node: Node):
|
|
|
|
for child in node.get_children():
|
2023-12-13 23:37:36 +02:00
|
|
|
await _clear_save_tree(child)
|
2023-12-10 02:47:21 +02:00
|
|
|
|
|
|
|
if node.has_method("_save"):
|
|
|
|
node.queue_free()
|
2023-12-13 23:37:36 +02:00
|
|
|
await node.tree_exited
|
2023-12-09 19:39:38 +02:00
|
|
|
|
|
|
|
func _generate_save_tree(node: Node):
|
|
|
|
var children = []
|
|
|
|
|
|
|
|
if node.has_method("_save") == false:
|
|
|
|
for child in node.get_children():
|
|
|
|
var data = _generate_save_tree(child)
|
|
|
|
|
|
|
|
if data is Array:
|
|
|
|
for child_data in data:
|
|
|
|
children.append(child_data)
|
|
|
|
else:
|
|
|
|
children.append(data)
|
|
|
|
return children
|
|
|
|
|
|
|
|
|
|
|
|
var save_tree = {
|
|
|
|
"data": VariantSerializer.stringify_value(node.call("_save")),
|
|
|
|
"parent": node.get_parent().get_path(),
|
|
|
|
"filename": node.get_scene_file_path()
|
|
|
|
}
|
|
|
|
|
|
|
|
for child in node.get_children():
|
|
|
|
var child_data = _generate_save_tree(child)
|
|
|
|
|
|
|
|
if child_data is Array:
|
|
|
|
for data in child_data:
|
|
|
|
children.append(data)
|
|
|
|
else:
|
|
|
|
children.append(child_data)
|
|
|
|
|
|
|
|
save_tree["children"] = children
|
|
|
|
|
|
|
|
return save_tree
|
|
|
|
|
|
|
|
func _build_save_tree(tree: Dictionary):
|
|
|
|
var new_object = load(tree["filename"]).instantiate()
|
|
|
|
|
|
|
|
if new_object.has_method("_load"):
|
|
|
|
new_object.call("_load", VariantSerializer.parse_value(tree["data"]))
|
|
|
|
else:
|
|
|
|
for key in tree["data"].keys():
|
|
|
|
new_object.set(key, VariantSerializer.parse_value(tree["data"][key]))
|
2023-12-11 10:39:34 +02:00
|
|
|
|
|
|
|
get_node(tree["parent"]).add_child(new_object)
|
|
|
|
|
|
|
|
for child in tree["children"]:
|
|
|
|
_build_save_tree(child)
|