|
|
@ -18,9 +18,18 @@ signal quick_save |
|
|
|
signal quick_load |
|
|
|
|
|
|
|
|
|
|
|
var _game_data_resource: SaveGameDataResource |
|
|
|
var _save_level_data_component: SaveLevelDataComponent ## Contains the save paths and filenames |
|
|
|
|
|
|
|
|
|
|
|
func _ready() -> void: |
|
|
|
quick_load.connect(quick_load_game) |
|
|
|
quick_save.connect(quick_load_game) |
|
|
|
create_save_file.connect(_save_game_as_resource) |
|
|
|
load_save_file.connect(_load_game_resource) |
|
|
|
|
|
|
|
_load_save_level_data_component() |
|
|
|
|
|
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void: |
|
|
|
if event.is_action_pressed("quick_save"): |
|
|
@ -29,22 +38,108 @@ func _unhandled_input(event: InputEvent) -> void: |
|
|
|
quick_load_game() |
|
|
|
|
|
|
|
|
|
|
|
func list_saves() -> Array[SaveFileDetailsResource]: |
|
|
|
var save_files: Array[SaveFileDetailsResource] = [] |
|
|
|
if not _load_save_level_data_component(): |
|
|
|
return save_files |
|
|
|
|
|
|
|
var save_game_data_path: String = _save_level_data_component.save_game_data_path |
|
|
|
if !DirAccess.dir_exists_absolute(save_game_data_path): |
|
|
|
return save_files |
|
|
|
|
|
|
|
for filename: String in ResourceLoader.list_directory(save_game_data_path): |
|
|
|
if !filename.begins_with("save_"): continue |
|
|
|
if !filename.ends_with(".tres"): continue # Screenshots, etc |
|
|
|
|
|
|
|
var _save_path: String = save_game_data_path + filename |
|
|
|
var _save_icon: String = filename.replace(".tres", ".png") |
|
|
|
var _save_resource: SaveFileDetailsResource = SaveFileDetailsResource.new() |
|
|
|
|
|
|
|
# TODO: Reconsider loading the save to get the name |
|
|
|
# This could be a large save making opening each one slow |
|
|
|
# Should work out a better method for getting the save name (filename != save name) |
|
|
|
var _save_file: SaveGameDataResource = ResourceLoader.load(_save_path) |
|
|
|
_save_resource.save_name = _save_file.save_name |
|
|
|
|
|
|
|
_save_resource.filename = filename |
|
|
|
_save_resource.date_created = Time.get_datetime_string_from_unix_time(FileAccess.get_modified_time(_save_path)) |
|
|
|
|
|
|
|
## In 4.5, this can probably be replaced with FileAccess.get_size(_save_path) |
|
|
|
## This should reduce the need for opening the file here |
|
|
|
var _loaded_file: FileAccess = FileAccess.open(_save_path, FileAccess.READ) |
|
|
|
_save_resource.filesize = _loaded_file.get_length() |
|
|
|
|
|
|
|
if FileAccess.file_exists(save_game_data_path + _save_icon): |
|
|
|
_save_resource.save_icon = _save_icon |
|
|
|
|
|
|
|
save_files.append(_save_resource) |
|
|
|
|
|
|
|
return save_files |
|
|
|
|
|
|
|
func quick_save_game() -> void: |
|
|
|
var save_level_data_component: SaveLevelDataComponent = get_tree().get_first_node_in_group("save_level_data_component") |
|
|
|
if save_level_data_component == null: |
|
|
|
push_error("Could not find SaveLevelDataComponent node in level") |
|
|
|
return |
|
|
|
if not _load_save_level_data_component(): return |
|
|
|
|
|
|
|
save_level_data_component.quick_save_game() |
|
|
|
_save_game_as_resource(_save_level_data_component.quicksave_file_name) |
|
|
|
game_saved.emit() |
|
|
|
|
|
|
|
func quick_load_game() -> void: |
|
|
|
var save_level_data_component: SaveLevelDataComponent = get_tree().get_first_node_in_group("save_level_data_component") |
|
|
|
if save_level_data_component == null: |
|
|
|
push_error("Could not find SaveLevelDataComponent node in level") |
|
|
|
return |
|
|
|
if not _load_save_level_data_component(): return |
|
|
|
|
|
|
|
# TODO: Don't reset world if quicksave not found |
|
|
|
EntityManager.reset_world.emit() |
|
|
|
save_level_data_component.quick_load_game() |
|
|
|
_load_game_resource(_save_level_data_component.quicksave_file_name) |
|
|
|
game_loaded.emit() |
|
|
|
|
|
|
|
|
|
|
|
## Find the SaveLevelDataComponent within the level which stores the save paths and filenames |
|
|
|
func _load_save_level_data_component() -> bool: |
|
|
|
_save_level_data_component = get_tree().get_first_node_in_group("save_level_data_component") |
|
|
|
if _save_level_data_component == null: |
|
|
|
push_error("Could not find SaveLevelDataComponent node in level") |
|
|
|
return false |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
func _load_game_resource(resource_filename: String) -> void: |
|
|
|
if not _load_save_level_data_component(): return |
|
|
|
var save_game_file_path: String = _save_level_data_component.save_game_data_path + resource_filename |
|
|
|
if !FileAccess.file_exists(save_game_file_path): |
|
|
|
printerr("Failed to load save. File does not exist: ", save_game_file_path) |
|
|
|
return |
|
|
|
|
|
|
|
_game_data_resource = ResourceLoader.load(save_game_file_path) |
|
|
|
if _game_data_resource == null: |
|
|
|
printerr("Failed to load save. Unknown format? ", save_game_file_path) |
|
|
|
return |
|
|
|
|
|
|
|
var root_node: Window = get_tree().root |
|
|
|
for resource: Resource in _game_data_resource.save_data_nodes: |
|
|
|
if resource is Node3DDataResource: |
|
|
|
(resource as Node3DDataResource)._load_data(root_node) |
|
|
|
|
|
|
|
func _save_game_as_resource(resource_filename: String) -> void: |
|
|
|
if not _load_save_level_data_component(): return |
|
|
|
|
|
|
|
if !DirAccess.dir_exists_absolute(_save_level_data_component.save_game_data_path): |
|
|
|
DirAccess.make_dir_absolute(_save_level_data_component.save_game_data_path) |
|
|
|
|
|
|
|
var save_game_file_path: String = _save_level_data_component.save_game_data_path + resource_filename |
|
|
|
_save_node_data() |
|
|
|
|
|
|
|
var result: int = ResourceSaver.save(_game_data_resource, save_game_file_path) |
|
|
|
if result != OK: |
|
|
|
printerr("Failed to save game: ", result) |
|
|
|
|
|
|
|
## Save the properties defined on the SaveDataComponents attached to various nodes (such as Block) |
|
|
|
func _save_node_data() -> void: |
|
|
|
var nodes: Array = get_tree().get_nodes_in_group("save_data_component") |
|
|
|
|
|
|
|
if nodes == null: return |
|
|
|
|
|
|
|
_game_data_resource = SaveGameDataResource.new() |
|
|
|
for node: Node in nodes: |
|
|
|
if node is SaveDataComponent: |
|
|
|
@warning_ignore("unsafe_method_access") |
|
|
|
var save_data_resource: Node3DDataResource = node._save_data() |
|
|
|
var save_final_resource: Node3DDataResource = save_data_resource.duplicate() |
|
|
|
_game_data_resource.save_data_nodes.append(save_final_resource) |