diff --git a/save_load/autoloads/save_game_manager.gd b/save_load/autoloads/save_game_manager.gd new file mode 100644 index 0000000..697f602 --- /dev/null +++ b/save_load/autoloads/save_game_manager.gd @@ -0,0 +1,32 @@ +## Performs the actual Saving[br][br] +## +## Below is a basic definition of various components and resources for reference:[br] +## * SaveLevelDataComponent - The root save component that performs saving and loading of the actual data from disk +## * SaveDataComponent - Attached to a node that has properties that need to be saved +## * Node Type Resources - Each type of node that requires saving, such as a TileMapLayer, needs a resource created +extends Node + + +func _unhandled_input(event: InputEvent) -> void: + if event.is_action_pressed("quick_save"): + save_game() + if event.is_action_pressed("quick_load"): + load_game() + + +func 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 + + save_level_data_component.save_game() + +func 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: # Nothing to load + return + + save_level_data_component.load_game() diff --git a/save_load/autoloads/save_game_manager.gd.uid b/save_load/autoloads/save_game_manager.gd.uid new file mode 100644 index 0000000..308cfeb --- /dev/null +++ b/save_load/autoloads/save_game_manager.gd.uid @@ -0,0 +1 @@ +uid://dau7tp2xpp0w diff --git a/save_load/components/save_data_component.gd b/save_load/components/save_data_component.gd new file mode 100644 index 0000000..631fff3 --- /dev/null +++ b/save_load/components/save_data_component.gd @@ -0,0 +1,26 @@ +## Add to any node that has data we need to save +## Each node type, such as TileMapLayer, will need a resource created for it +## See `res://save_load/resources/node_types/` +class_name SaveDataComponent +extends Node + + +@export var save_data_resource: NodeDataResource ## The resource describing the type of object being saved + +@onready var parent_node: Node3D = get_parent() + + +func _ready() -> void: + add_to_group("save_data_component") + + +func _save_data() -> Resource: + if parent_node == null: + return + + if save_data_resource == null: + push_error("save_data_resource not defined on node ", parent_node.name) + return + + save_data_resource._save_data(parent_node) + return save_data_resource diff --git a/save_load/components/save_data_component.gd.uid b/save_load/components/save_data_component.gd.uid new file mode 100644 index 0000000..a5b6b36 --- /dev/null +++ b/save_load/components/save_data_component.gd.uid @@ -0,0 +1 @@ +uid://b0400fjcqflgh diff --git a/save_load/components/save_data_component.tscn b/save_load/components/save_data_component.tscn new file mode 100644 index 0000000..ba91d49 --- /dev/null +++ b/save_load/components/save_data_component.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://baki8rbf1ti0r"] + +[ext_resource type="Script" uid="uid://b0400fjcqflgh" path="res://save_load/components/save_data_component.gd" id="1_nm1vf"] + +[node name="SaveDataComponent" type="Node"] +script = ExtResource("1_nm1vf") diff --git a/save_load/components/save_level_data_component.gd b/save_load/components/save_level_data_component.gd new file mode 100644 index 0000000..6a778e0 --- /dev/null +++ b/save_load/components/save_level_data_component.gd @@ -0,0 +1,66 @@ +## Performs the actual saving and loading of data related to this level/scene +## Utilized by the SaveGameManager +class_name SaveLevelDataComponent +extends Node + +## See documentation to where this path is: https://docs.godotengine.org/en/stable/tutorials/io/data_paths.html#accessing-persistent-user-data-user[br][br] +## Default Paths:[br] +## * Windows: %APPDATA%\Godot\app_userdata\[project_name][br] +## * macOS: ~/Library/Application Support/Godot/app_userdata/[project_name][br] +## * Linux: ~/.local/share/godot/app_userdata/[project_name][br] +@export var save_game_data_path: String = "user://game_data/" +@export var save_file_name: String = "save_%s_game_data.tres" + +var level_scene_name: String +var game_data_resource: SaveGameDataResource +var level_save_file_name: String +var save_game_file_path: String + + +func _ready() -> void: + add_to_group("save_level_data_component") + level_scene_name = get_parent().name + + level_save_file_name = save_file_name % level_scene_name + save_game_file_path = save_game_data_path + level_save_file_name + + +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: NodeDataResource = node._save_data() + var save_final_resource: NodeDataResource = save_data_resource.duplicate() + game_data_resource.save_data_nodes.append(save_final_resource) + +func save_game() -> void: + if !DirAccess.dir_exists_absolute(save_game_data_path): + DirAccess.make_dir_absolute(save_game_data_path) + + save_node_data() + + var result: int = ResourceSaver.save(game_data_resource, save_game_file_path) + print("Save Result: ", result) + + +func load_game() -> void: + if !FileAccess.file_exists(save_game_file_path): + #push_error("Save file does not exist: ", save_game_file_path) + return + + game_data_resource = ResourceLoader.load(save_game_file_path) + + if game_data_resource == null: + push_error("Could not load save file: ", 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 NodeDataResource: + (resource as NodeDataResource)._load_data(root_node) diff --git a/save_load/components/save_level_data_component.gd.uid b/save_load/components/save_level_data_component.gd.uid new file mode 100644 index 0000000..4e5b5f3 --- /dev/null +++ b/save_load/components/save_level_data_component.gd.uid @@ -0,0 +1 @@ +uid://c7x2qvyu62230 diff --git a/save_load/components/save_level_data_component.tscn b/save_load/components/save_level_data_component.tscn new file mode 100644 index 0000000..ccdc1d0 --- /dev/null +++ b/save_load/components/save_level_data_component.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://c3pqilb6yh5kc"] + +[ext_resource type="Script" uid="uid://c7x2qvyu62230" path="res://save_load/components/save_level_data_component.gd" id="1_exguq"] + +[node name="SaveLevelDataComponent" type="Node"] +script = ExtResource("1_exguq") diff --git a/save_load/components/test_scene_save_data_manager_component.gd b/save_load/components/test_scene_save_data_manager_component.gd new file mode 100644 index 0000000..e3ebe65 --- /dev/null +++ b/save_load/components/test_scene_save_data_manager_component.gd @@ -0,0 +1,13 @@ +## Basically just load any saved data for the scene that already exists +## Attach this to any test scene to automatically load any data found +class_name TestSceneSaveDataManagerComponent +extends Node + + +func _ready() -> void: + call_deferred("load_test_scene") + + +func load_test_scene() -> void: + SaveGameManager.load_game() + print("Save Game Data Loaded") diff --git a/save_load/components/test_scene_save_data_manager_component.gd.uid b/save_load/components/test_scene_save_data_manager_component.gd.uid new file mode 100644 index 0000000..d5f3a82 --- /dev/null +++ b/save_load/components/test_scene_save_data_manager_component.gd.uid @@ -0,0 +1 @@ +uid://b763cjyd7t2ju diff --git a/save_load/components/test_scene_save_data_manager_component.tscn b/save_load/components/test_scene_save_data_manager_component.tscn new file mode 100644 index 0000000..7101ad6 --- /dev/null +++ b/save_load/components/test_scene_save_data_manager_component.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dftxu6qsgxyjb"] + +[ext_resource type="Script" uid="uid://b763cjyd7t2ju" path="res://save_load/components/test_scene_save_data_manager_component.gd" id="1_toc0k"] + +[node name="TestSceneSaveDataManagerComponent" type="Node"] +script = ExtResource("1_toc0k") diff --git a/save_load/resources/node_types/block_data_resource.gd b/save_load/resources/node_types/block_data_resource.gd new file mode 100644 index 0000000..25ce0e3 --- /dev/null +++ b/save_load/resources/node_types/block_data_resource.gd @@ -0,0 +1,23 @@ +## The resource utilized for saving a Block +class_name BlockDataResource +extends NodeDataResource + + +@export var block_id: String = "001" + + +func _save_data(node: Node3D) -> void: + super._save_data(node) + + block_id = node.id + + +func _load_data(window: Window) -> void: + var scene_node: Node = window.get_node_or_null(node_path) + + if scene_node == null: return + + var block: Block = scene_node + block.transform = transform + block.set_id(block_id) + print("Loaded Block: ", block.name) diff --git a/save_load/resources/node_types/block_data_resource.gd.uid b/save_load/resources/node_types/block_data_resource.gd.uid new file mode 100644 index 0000000..ce2e53a --- /dev/null +++ b/save_load/resources/node_types/block_data_resource.gd.uid @@ -0,0 +1 @@ +uid://syaia0l6vjt1 diff --git a/save_load/resources/node_types/block_data_resource.tres b/save_load/resources/node_types/block_data_resource.tres new file mode 100644 index 0000000..8a2bee8 --- /dev/null +++ b/save_load/resources/node_types/block_data_resource.tres @@ -0,0 +1,12 @@ +[gd_resource type="Resource" script_class="BlockDataResource" load_steps=2 format=3 uid="uid://dfos8np8agysk"] + +[ext_resource type="Script" uid="uid://syaia0l6vjt1" path="res://save_load/resources/node_types/block_data_resource.gd" id="1_a06et"] + +[resource] +script = ExtResource("1_a06et") +block_id = "001" +block_position = Vector3(0, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) +node_path = NodePath("") +parent_node_path = NodePath("") +metadata/_custom_type_script = "uid://syaia0l6vjt1" diff --git a/save_load/resources/node_types/node_data_resource.gd b/save_load/resources/node_types/node_data_resource.gd new file mode 100644 index 0000000..45f9d9f --- /dev/null +++ b/save_load/resources/node_types/node_data_resource.gd @@ -0,0 +1,21 @@ +## The base resource for saving a specific Node +class_name NodeDataResource +extends Resource + + +@export var transform: Transform3D +@export var node_path: NodePath +@export var parent_node_path: NodePath + + + +func _load_data(_window: Window) -> void: + pass + +func _save_data(node: Node3D) -> void: + transform = node.transform + node_path = node.get_path() + + var parent_node: Node3D = node.get_parent() + if parent_node != null: + parent_node_path = parent_node.get_path() diff --git a/save_load/resources/node_types/node_data_resource.gd.uid b/save_load/resources/node_types/node_data_resource.gd.uid new file mode 100644 index 0000000..588b1a0 --- /dev/null +++ b/save_load/resources/node_types/node_data_resource.gd.uid @@ -0,0 +1 @@ +uid://drj0sfem1gmsk diff --git a/save_load/resources/node_types/node_data_resource.tres b/save_load/resources/node_types/node_data_resource.tres new file mode 100644 index 0000000..d97c773 --- /dev/null +++ b/save_load/resources/node_types/node_data_resource.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="NodeDataResource" load_steps=2 format=3 uid="uid://dald1lud7ktsj"] + +[ext_resource type="Script" uid="uid://drj0sfem1gmsk" path="res://save_load/resources/node_types/node_data_resource.gd" id="1_b70a7"] + +[resource] +script = ExtResource("1_b70a7") +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) +node_path = NodePath("") +parent_node_path = NodePath("") diff --git a/save_load/resources/node_types/player_data_resource.gd b/save_load/resources/node_types/player_data_resource.gd new file mode 100644 index 0000000..cb43adf --- /dev/null +++ b/save_load/resources/node_types/player_data_resource.gd @@ -0,0 +1,16 @@ +## The resource utilized for saving a Player +class_name PlayerDataResource +extends NodeDataResource + + +func _save_data(node: Node3D) -> void: + super._save_data(node) + # TODO: Save inventory or any other data + + +func _load_data(window: Window) -> void: + var scene_node: Node = window.get_node_or_null(node_path) + + if scene_node == null: return + + #var player: Player = scene_node diff --git a/save_load/resources/node_types/player_data_resource.gd.uid b/save_load/resources/node_types/player_data_resource.gd.uid new file mode 100644 index 0000000..76f78ef --- /dev/null +++ b/save_load/resources/node_types/player_data_resource.gd.uid @@ -0,0 +1 @@ +uid://dodqpooodtguo diff --git a/save_load/resources/node_types/player_data_resource.tres b/save_load/resources/node_types/player_data_resource.tres new file mode 100644 index 0000000..b1d3f4f --- /dev/null +++ b/save_load/resources/node_types/player_data_resource.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="PlayerDataResource" load_steps=2 format=3 uid="uid://bvsurbn5xgchr"] + +[ext_resource type="Script" uid="uid://dodqpooodtguo" path="res://save_load/resources/node_types/player_data_resource.gd" id="1_scty6"] + +[resource] +script = ExtResource("1_scty6") +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0) +node_path = NodePath("") +parent_node_path = NodePath("") +metadata/_custom_type_script = "uid://dodqpooodtguo" diff --git a/save_load/resources/save_game_data_resource.gd b/save_load/resources/save_game_data_resource.gd new file mode 100644 index 0000000..0bc84d2 --- /dev/null +++ b/save_load/resources/save_game_data_resource.gd @@ -0,0 +1,7 @@ +## The entire save structure that contains all NodeDataResources +## NodeDataResources will be located by the SaveLevelDataComponent +class_name SaveGameDataResource +extends Resource + + +@export var save_data_nodes: Array[NodeDataResource] diff --git a/save_load/resources/save_game_data_resource.gd.uid b/save_load/resources/save_game_data_resource.gd.uid new file mode 100644 index 0000000..887ce2e --- /dev/null +++ b/save_load/resources/save_game_data_resource.gd.uid @@ -0,0 +1 @@ +uid://di6ov7tpewhft diff --git a/save_load/resources/save_game_data_resource.tres b/save_load/resources/save_game_data_resource.tres new file mode 100644 index 0000000..18f86c8 --- /dev/null +++ b/save_load/resources/save_game_data_resource.tres @@ -0,0 +1,9 @@ +[gd_resource type="Resource" script_class="SaveGameDataResource" load_steps=3 format=3 uid="uid://dkniygoky2jcx"] + +[ext_resource type="Script" uid="uid://drj0sfem1gmsk" path="res://save_load/resources/node_types/node_data_resource.gd" id="1_7yx7n"] +[ext_resource type="Script" uid="uid://di6ov7tpewhft" path="res://save_load/resources/save_game_data_resource.gd" id="1_sbw5t"] + +[resource] +script = ExtResource("1_sbw5t") +save_data_nodes = Array[ExtResource("1_7yx7n")]([]) +metadata/_custom_type_script = "uid://di6ov7tpewhft" diff --git a/save_load/resources/scene_data_resource.gd b/save_load/resources/scene_data_resource.gd new file mode 100644 index 0000000..13f3e75 --- /dev/null +++ b/save_load/resources/scene_data_resource.gd @@ -0,0 +1,30 @@ +## Used with the SaveDataComponent for defining node and scene_file_path +class_name SceneDataResource +extends NodeDataResource + + +@export var node_name: String +@export var scene_file_path: String + + +func _save_data(node: Node3D) -> void: + super._save_data(node) + + node_name = node.name + scene_file_path = node.scene_file_path + + +func _load_data(window: Window) -> void: + var parent_node: Node3D + if parent_node_path != null: + parent_node = window.get_node_or_null(parent_node_path) + + var scene_node: Node3D + if node_path != null: + var scene_file_resource: Resource = load(scene_file_path) + scene_node = scene_file_resource.instantiate() + + if parent_node != null and scene_node != null: + #scene_node.position = position + print("Loading Child: ", scene_node.name) + parent_node.add_child(scene_node) diff --git a/save_load/resources/scene_data_resource.gd.uid b/save_load/resources/scene_data_resource.gd.uid new file mode 100644 index 0000000..76433c3 --- /dev/null +++ b/save_load/resources/scene_data_resource.gd.uid @@ -0,0 +1 @@ +uid://bxr74kmjt6heh diff --git a/save_load/resources/scene_data_resource.tres b/save_load/resources/scene_data_resource.tres new file mode 100644 index 0000000..dc3de75 --- /dev/null +++ b/save_load/resources/scene_data_resource.tres @@ -0,0 +1,10 @@ +[gd_resource type="Resource" script_class="SceneDataResource" load_steps=2 format=3 uid="uid://duqhhi2nlic6n"] + +[ext_resource type="Script" uid="uid://bxr74kmjt6heh" path="res://save_load/resources/scene_data_resource.gd" id="1_ihw72"] + +[resource] +script = ExtResource("1_ihw72") +global_position = Vector2(0, 0) +node_path = NodePath("") +parent_node_path = NodePath("") +metadata/_custom_type_script = "uid://bxr74kmjt6heh"