|
@@ -65,7 +65,7 @@ The save function will look like this:
|
|
|
|
|
|
func save():
|
|
|
var save_dict = {
|
|
|
- "filename" : get_filename(),
|
|
|
+ "filename" : get_scene_file_path(),
|
|
|
"parent" : get_parent().get_path(),
|
|
|
"pos_x" : position.x, # Vector2 is not supported by JSON
|
|
|
"pos_y" : position.y,
|
|
@@ -88,11 +88,11 @@ The save function will look like this:
|
|
|
|
|
|
.. code-tab:: csharp
|
|
|
|
|
|
- public Godot.Collections.Dictionary<string, object> Save()
|
|
|
+ public Godot.Collections.Dictionary<string, Variant> Save()
|
|
|
{
|
|
|
- return new Godot.Collections.Dictionary<string, object>()
|
|
|
+ return new Godot.Collections.Dictionary<string, Variant>()
|
|
|
{
|
|
|
- { "Filename", GetFilename() },
|
|
|
+ { "Filename", SceneFilePath },
|
|
|
{ "Parent", GetParent().GetPath() },
|
|
|
{ "PosX", Position.x }, // Vector2 is not supported by JSON
|
|
|
{ "PosY", Position.y },
|
|
@@ -136,12 +136,11 @@ way to pull the data out of the file as well.
|
|
|
# Go through everything in the persist category and ask them to return a
|
|
|
# dict of relevant variables.
|
|
|
func save_game():
|
|
|
- var save_game = File.new()
|
|
|
- save_game.open("user://savegame.save", File.WRITE)
|
|
|
+ var save_game = FileAccess.open("user://savegame.save", FileAccess.WRITE)
|
|
|
var save_nodes = get_tree().get_nodes_in_group("Persist")
|
|
|
for node in save_nodes:
|
|
|
# Check the node is an instanced scene so it can be instanced again during load.
|
|
|
- if node.filename.empty():
|
|
|
+ if node.scene_file_path.is_empty():
|
|
|
print("persistent node '%s' is not an instanced scene, skipped" % node.name)
|
|
|
continue
|
|
|
|
|
@@ -158,7 +157,6 @@ way to pull the data out of the file as well.
|
|
|
|
|
|
# Store the save dictionary as a new line in the save file.
|
|
|
save_game.store_line(json_string)
|
|
|
- save_game.close()
|
|
|
|
|
|
.. code-tab:: csharp
|
|
|
|
|
@@ -168,34 +166,34 @@ way to pull the data out of the file as well.
|
|
|
// dict of relevant variables.
|
|
|
public void SaveGame()
|
|
|
{
|
|
|
- var saveGame = new File();
|
|
|
- saveGame.Open("user://savegame.save", (int)File.ModeFlags.Write);
|
|
|
+ using var saveGame = FileAccess.Open("user://savegame.save", FileAccess.ModeFlags.Write);
|
|
|
|
|
|
var saveNodes = GetTree().GetNodesInGroup("Persist");
|
|
|
foreach (Node saveNode in saveNodes)
|
|
|
{
|
|
|
// Check the node is an instanced scene so it can be instanced again during load.
|
|
|
- if (saveNode.Filename.Empty())
|
|
|
+ if (string.IsNullOrEmpty(saveNode.SceneFilePath))
|
|
|
{
|
|
|
- GD.Print(String.Format("persistent node '{0}' is not an instanced scene, skipped", saveNode.Name));
|
|
|
+ GD.Print($"persistent node '{saveNode.Name}' is not an instanced scene, skipped");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// Check the node has a save function.
|
|
|
if (!saveNode.HasMethod("Save"))
|
|
|
{
|
|
|
- GD.Print(String.Format("persistent node '{0}' is missing a Save() function, skipped", saveNode.Name));
|
|
|
+ GD.Print($"persistent node '{saveNode.Name}' is missing a Save() function, skipped");
|
|
|
continue;
|
|
|
}
|
|
|
|
|
|
// Call the node's save function.
|
|
|
var nodeData = saveNode.Call("Save");
|
|
|
|
|
|
+ // JSON provides a static method to serialized JSON string
|
|
|
+ var jsonString = JSON.Stringify(nodeData);
|
|
|
+
|
|
|
// Store the save dictionary as a new line in the save file.
|
|
|
- saveGame.StoreLine(JSON.Print(nodeData));
|
|
|
+ saveGame.StoreLine(jsonString);
|
|
|
}
|
|
|
-
|
|
|
- saveGame.Close();
|
|
|
}
|
|
|
|
|
|
|
|
@@ -212,8 +210,7 @@ load function:
|
|
|
# Note: This can be called from anywhere inside the tree. This function
|
|
|
# is path independent.
|
|
|
func load_game():
|
|
|
- var save_game = File.new()
|
|
|
- if not save_game.file_exists("user://savegame.save"):
|
|
|
+ if not FileAccess.file_exists("user://savegame.save"):
|
|
|
return # Error! We don't have a save to load.
|
|
|
|
|
|
# We need to revert the game state so we're not cloning objects
|
|
@@ -226,8 +223,10 @@ load function:
|
|
|
|
|
|
# Load the file line by line and process that dictionary to restore
|
|
|
# the object it represents.
|
|
|
- save_game.open("user://savegame.save", File.READ)
|
|
|
- while save_game.get_position() < save_game.get_len():
|
|
|
+ var save_game = FileAccess.open("user://savegame.save", FileAccess.READ)
|
|
|
+ while save_game.get_position() < save_game.get_length():
|
|
|
+ var json_string = save_game.get_line()
|
|
|
+
|
|
|
# Creates the helper class to interact with JSON
|
|
|
var json = JSON.new()
|
|
|
|
|
@@ -251,16 +250,13 @@ load function:
|
|
|
continue
|
|
|
new_object.set(i, node_data[i])
|
|
|
|
|
|
- save_game.close()
|
|
|
-
|
|
|
.. code-tab:: csharp
|
|
|
|
|
|
// Note: This can be called from anywhere inside the tree. This function is
|
|
|
// path independent.
|
|
|
public void LoadGame()
|
|
|
{
|
|
|
- var saveGame = new File();
|
|
|
- if (!saveGame.FileExists("user://savegame.save"))
|
|
|
+ if (!FileAccess.FileExists("user://savegame.save"))
|
|
|
return; // Error! We don't have a save to load.
|
|
|
|
|
|
// We need to revert the game state so we're not cloning objects during loading.
|
|
@@ -273,30 +269,39 @@ load function:
|
|
|
|
|
|
// Load the file line by line and process that dictionary to restore the object
|
|
|
// it represents.
|
|
|
- saveGame.Open("user://savegame.save", (int)File.ModeFlags.Read);
|
|
|
+ using var saveGame = FileAccess.Open("user://savegame.save", FileAccess.ModeFlags.Read);
|
|
|
|
|
|
- while (saveGame.GetPosition() < saveGame.GetLen())
|
|
|
+ while (saveGame.GetPosition() < saveGame.GetLength())
|
|
|
{
|
|
|
- // Get the saved dictionary from the next line in the save file
|
|
|
- var nodeData = new Godot.Collections.Dictionary<string, object>((Godot.Collections.Dictionary)JSON.Parse(saveGame.GetLine()).Result);
|
|
|
+ var jsonString = saveGame.GetLine();
|
|
|
+
|
|
|
+ // Creates the helper class to interact with JSON
|
|
|
+ var json = new JSON();
|
|
|
+ var parseResult = json.Parse(jsonString);
|
|
|
+ if (parseResult != Error.Ok)
|
|
|
+ {
|
|
|
+ GD.Print($"JSON Parse Error: {json.GetErrorMessage()} in {jsonString} at line {json.GetErrorLine()}");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Get the data from the JSON object
|
|
|
+ var nodeData = new Godot.Collections.Dictionary<string, Variant>((Godot.Collections.Dictionary)json.Data);
|
|
|
|
|
|
// Firstly, we need to create the object and add it to the tree and set its position.
|
|
|
var newObjectScene = (PackedScene)ResourceLoader.Load(nodeData["Filename"].ToString());
|
|
|
var newObject = (Node)newObjectScene.Instantiate();
|
|
|
GetNode(nodeData["Parent"].ToString()).AddChild(newObject);
|
|
|
- newObject.Set("Position", new Vector2((float)nodeData["PosX"], (float)nodeData["PosY"]));
|
|
|
+ newObject.Set("position", new Vector2((float)nodeData["PosX"], (float)nodeData["PosY"]));
|
|
|
|
|
|
// Now we set the remaining variables.
|
|
|
- foreach (KeyValuePair<string, object> entry in nodeData)
|
|
|
+ foreach (KeyValuePair<string, Variant> entry in nodeData)
|
|
|
{
|
|
|
- string key = entry.Key.ToString();
|
|
|
+ string key = entry.Key;
|
|
|
if (key == "Filename" || key == "Parent" || key == "PosX" || key == "PosY")
|
|
|
continue;
|
|
|
newObject.Set(key, entry.Value);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- saveGame.Close();
|
|
|
}
|
|
|
|
|
|
|