initial shit
This commit is contained in:
121
addons/savekit/README.md
Normal file
121
addons/savekit/README.md
Normal file
@@ -0,0 +1,121 @@
|
||||
# SaveKit for Godot
|
||||
|
||||
A library for saving and loading game state in Godot 4, with pluggable save file formats and a focus on ease of use.
|
||||
|
||||
Key features:
|
||||
|
||||
- **Easy to get started.** Add nodes to the `saveable` group, then use `SaveManager.save_game()` and `SaveManager.load_game()`.
|
||||
- **Saves nodes and resources.** Built-in resources, like textures and packed scenes, are saved as references, while data from nodes and custom `SaveKitResource` subclasses is saved in its entirety. This avoids the code injection risks of Godot's `ResourceLoader`, while supporting complex data.
|
||||
- **JSON and binary serialization built-in**, or implement your own custom save file format by extending `SaveKitSerializer` and `SaveKitDeserializer`.
|
||||
- **Automatic by default, manual when you need it.** Reflection picks up exported properties for saving/loading automatically, or you can implement custom `save_to_dict` and `load_from_dict` methods for full control.
|
||||
|
||||
## Getting started
|
||||
|
||||
1. Enable the plugin in **Project > Project Settings > Plugins**. This also installs a `SaveManager` autoload.
|
||||
2. Add all the nodes you want saved to the `saveable` group.
|
||||
3. Call one method to save, another to load:
|
||||
|
||||
```gdscript
|
||||
# Save to disk under user://save_games/MyGame/Slot 1.json
|
||||
SaveManager.save_game(PackedStringArray(["MyGame", "Slot 1"]))
|
||||
|
||||
# Load it back later
|
||||
SaveManager.load_game(PackedStringArray(["MyGame", "Slot 1"]))
|
||||
```
|
||||
|
||||
This will iterate through nodes in the `saveable` group, serialize each node's exported properties, and write the file into `user://save_games/`. Then the reverse is done on load—creating or freeing nodes as needed so the scene tree matches the save file.
|
||||
|
||||
There are also other methods offering finer-grained control over the save/load process:
|
||||
|
||||
```gdscript
|
||||
func save_scene_tree_in_memory() -> PackedByteArray
|
||||
func save_scene_tree_to_disk(absolute_path: String) -> Error
|
||||
|
||||
func load_scene_tree_from_memory(data: PackedByteArray) -> bool
|
||||
func load_scene_tree_from_file(absolute_path: String) -> Error
|
||||
```
|
||||
|
||||
## Saving nodes
|
||||
|
||||
By default, SaveKit uses reflection to save all `@export` and `@export_storage` properties whose values differ from their defaults. For a lot of nodes, this is all you need:
|
||||
|
||||
```gdscript
|
||||
extends CharacterBody2D
|
||||
|
||||
@export var health: int = 100
|
||||
@export var player_name: String = ""
|
||||
@export_storage var checkpoint: Vector2
|
||||
```
|
||||
|
||||
When you need additional control, implement `save_to_dict` and `load_from_dict`:
|
||||
|
||||
```gdscript
|
||||
extends RigidBody2D
|
||||
|
||||
func save_to_dict(s: SaveKitSerializer) -> Dictionary:
|
||||
return {
|
||||
"transform": s.encode_var(transform),
|
||||
"linear_velocity": s.encode_var(linear_velocity),
|
||||
}
|
||||
|
||||
func load_from_dict(s: SaveKitDeserializer, data: Dictionary) -> void:
|
||||
var t: Transform2D = s.decode_var(data["transform"], TYPE_TRANSFORM2D)
|
||||
PhysicsServer2D.body_set_state(get_rid(), PhysicsServer2D.BODY_STATE_TRANSFORM, t)
|
||||
|
||||
linear_velocity = s.decode_var(data["linear_velocity"], TYPE_VECTOR2)
|
||||
```
|
||||
|
||||
You can also mix the two approaches by calling `serializer.default_save_to_dict()` and `deserializer.default_load_from_dict()` from your implementation.
|
||||
|
||||
### Node instantiation
|
||||
|
||||
If a saved node isn't in the scene tree at load time, SaveKit will instantiate it from the `scene_file_path` it was saved with and parent it where it belongs. Conversely, nodes in the `saveable` group that *aren't* in the save data are freed, so the scene tree always matches the save file after loading.
|
||||
|
||||
## Saving resources
|
||||
|
||||
For resources that represent persisted data—e.g., inventories, quest state, per-entity stat blocks—extend `SaveKitResource` rather than plain `Resource`:
|
||||
|
||||
```gdscript
|
||||
class_name Inventory
|
||||
extends SaveKitResource
|
||||
|
||||
@export var gold: int = 0
|
||||
@export var items: Array[Item]
|
||||
```
|
||||
|
||||
Any `SaveKitResource` referenced from a saved node is serialized automatically, and deduplicated. Like nodes, `SaveKitResource` uses reflection over exported properties by default, but you can always implement `save_to_dict` and `load_from_dict` for custom behavior.
|
||||
|
||||
Note that plain `Resource` references (textures, scenes, and other things baked into the PCK) are saved as path/UID references. SaveKit will only ever load such resources from within the `res://` filesystem, avoiding the risk of code injection from user-provided resource files.
|
||||
|
||||
## Lifecycle hooks
|
||||
|
||||
There are a variety of signals and methods to hook into the saving and loading process—`before_save`, `after_save`, `before_load`, `after_load`, etc. See the `SaveManager` API documentation for more details.
|
||||
|
||||
## Save file formats
|
||||
|
||||
SaveKit includes two built-in file formats:
|
||||
|
||||
- **JSON** (`json_serializer.gd`, `json_deserializer.gd`) — human-readable, easy to diff and debug.
|
||||
- **Binary** (`binary_serializer.gd`, `binary_deserializer.gd`) — compact, obfuscated.
|
||||
|
||||
JSON, the default, is recommended in most cases. File size is rarely a concern, and making saves human-readable is more friendly to your players.
|
||||
|
||||
You can also implement a custom file format by extending `SaveKitSerializer` and `SaveKitDeserializer` and implementing the abstract methods.
|
||||
|
||||
Assign `SaveManager.serializer_script` and `SaveManager.deserializer_script` to switch between formats or use your own:
|
||||
|
||||
```gdscript
|
||||
SaveManager.serializer_script = preload("res://addons/savekit/binary_serializer.gd")
|
||||
SaveManager.deserializer_script = preload("res://addons/savekit/binary_deserializer.gd")
|
||||
SaveManager.save_file_extension = ".sav"
|
||||
```
|
||||
|
||||
## Learn more
|
||||
|
||||
The [included demo](demo/) has a small interactive scene that is fully saveable, and includes a live view into the JSON file format.
|
||||
|
||||
All public classes (`SaveManager`, `SaveKitSerializer`, `SaveKitDeserializer`, `SaveKitResource`) have documentation comments that work with Godot's built-in help. Browse them from the editor for the full API reference.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License. See [LICENSE](LICENSE) for details.
|
||||
Reference in New Issue
Block a user