149 lines
4.5 KiB
GDScript
149 lines
4.5 KiB
GDScript
extends Node
|
|
|
|
enum VNLoadSource {
|
|
NEW_GAME = 300,
|
|
FROM_MANUAL_SAVE = 301,
|
|
FROM_AUTOSAVE = 302,
|
|
}
|
|
|
|
enum VNSaveTarget {
|
|
MANUAL_SAVE = 401,
|
|
AUTOSAVE = 402,
|
|
}
|
|
|
|
const GLOBAL_DATA_PATH = "user://data.json"
|
|
const SAVES_DIR = "user://saves"
|
|
const MAX_SAVES = 24
|
|
|
|
signal loaded
|
|
signal updated_save_files(save_file_list)
|
|
signal new_manual_save(save_file)
|
|
signal new_autosave(save_file)
|
|
|
|
var has_loaded = false
|
|
var can_continue = false
|
|
var current_load_source: VNLoadSource = VNLoadSource.NEW_GAME
|
|
var current_load_path = ""
|
|
var current_load_file = null
|
|
var save_files = []
|
|
var global_data = null
|
|
|
|
var new_game_save_file = {}
|
|
|
|
func _ready():
|
|
DirAccess.make_dir_recursive_absolute(SAVES_DIR)
|
|
|
|
# Populate previously saved files
|
|
for file_name in DirAccess.get_files_at(SAVES_DIR):
|
|
if file_name.length() == 7 and file_name.right(5) == ".json":
|
|
can_continue = true
|
|
var path = "%s/%s" % [SAVES_DIR, file_name]
|
|
var file = FileAccess.open(path, FileAccess.READ)
|
|
var data = JSON.parse_string(file.get_as_text())
|
|
file.close()
|
|
save_files.append({
|
|
"idx": int(file_name.left(2)),
|
|
"path": path,
|
|
"timestamp": data["timestamp"],
|
|
"name": data["name"],
|
|
"is_autosave": data.get("is_autosave", false),
|
|
})
|
|
save_files.sort_custom(func (a, b): return Time.get_unix_time_from_datetime_string(a["timestamp"]) > Time.get_unix_time_from_datetime_string(b["timestamp"]))
|
|
|
|
has_loaded = true
|
|
loaded.emit()
|
|
|
|
func create_save_file(target: VNSaveTarget, data: Variant, save_name: String = "") -> String:
|
|
var timestamp = Time.get_datetime_string_from_system(false, true)
|
|
var idx = 1
|
|
var path = ""
|
|
var is_autosave = target == VNSaveTarget.AUTOSAVE
|
|
can_continue = true
|
|
|
|
if save_files.size() > 0:
|
|
idx = save_files[0]["idx"] % 99 + 1 # Avoid creating a 00.json file
|
|
path = "%s/%02d.json" % [SAVES_DIR, idx]
|
|
for i in range(save_files.size() - 1, -1, -1):
|
|
# Remove file if MAX_SAVES limit would be exceeded or if "idx" wraps around and overwrites this
|
|
if i >= MAX_SAVES - 1 or save_files[i]["idx"] == idx:
|
|
# Should be safe to remove, since we're resizing from the right
|
|
var save_to_delete = save_files.pop_at(i)
|
|
DirAccess.remove_absolute(save_to_delete["path"])
|
|
|
|
var file = FileAccess.open(path, FileAccess.WRITE)
|
|
file.store_string(JSON.stringify({
|
|
"timestamp": timestamp,
|
|
"name": save_name,
|
|
"is_autosave": is_autosave,
|
|
"data": data,
|
|
}))
|
|
file.close()
|
|
save_files.push_front({
|
|
"idx": idx,
|
|
"path": path,
|
|
"timestamp": timestamp,
|
|
"name": save_name,
|
|
"is_autosave": is_autosave,
|
|
})
|
|
match target:
|
|
VNSaveTarget.MANUAL_SAVE:
|
|
new_manual_save.emit(save_files[0])
|
|
VNSaveTarget.AUTOSAVE:
|
|
new_autosave.emit(save_files[0])
|
|
_:
|
|
assert(false, "Unknown save target %s" % target)
|
|
return path
|
|
|
|
func load_save_file(load_target: VNLoadSource, load_file = null) -> Variant:
|
|
current_load_source = load_target
|
|
match load_target:
|
|
VNLoadSource.NEW_GAME:
|
|
return new_game_save_file
|
|
#VNLoadSource.FROM_MANUAL_SAVE when not load_file:
|
|
# current_load_source = VNLoadSource.FROM_AUTOSAVE
|
|
VNLoadSource.FROM_AUTOSAVE:
|
|
current_load_path = load_file["path"]
|
|
VNLoadSource.FROM_MANUAL_SAVE:
|
|
current_load_path = load_file["path"]
|
|
_:
|
|
assert(false, "Can't figure out where to load saved data from!")
|
|
if not FileAccess.file_exists(current_load_path):
|
|
push_warning("Load file not found, returning new game data...")
|
|
current_load_path = ""
|
|
current_load_source = VNLoadSource.NEW_GAME
|
|
return {}
|
|
return JSON.parse_string(FileAccess.open(current_load_path, FileAccess.READ).get_as_text())["data"]
|
|
|
|
func delete_save_file(load_file = null):
|
|
var i = save_files.find(load_file)
|
|
if i == -1:
|
|
push_warning("Couldn't locate file for deletion!")
|
|
return
|
|
DirAccess.remove_absolute(load_file["path"])
|
|
save_files.remove_at(i)
|
|
updated_save_files.emit(save_files)
|
|
|
|
func set_global_data(key: String, value: Variant):
|
|
if FileAccess.file_exists(GLOBAL_DATA_PATH):
|
|
var file = FileAccess.open(GLOBAL_DATA_PATH, FileAccess.READ)
|
|
global_data = JSON.parse_string(file.get_as_text())
|
|
file.close()
|
|
elif not global_data:
|
|
global_data = {}
|
|
var prev_value = global_data.get(key)
|
|
global_data[key] = value
|
|
if value != prev_value:
|
|
var file = FileAccess.open(GLOBAL_DATA_PATH, FileAccess.WRITE)
|
|
file.store_string(JSON.stringify(global_data))
|
|
file.close()
|
|
return prev_value
|
|
|
|
func get_global_data(key: String, default = null):
|
|
if not global_data:
|
|
if FileAccess.file_exists(GLOBAL_DATA_PATH):
|
|
var file = FileAccess.open(GLOBAL_DATA_PATH, FileAccess.READ)
|
|
global_data = JSON.parse_string(file.get_as_text())
|
|
file.close()
|
|
else:
|
|
global_data = {}
|
|
return global_data.get(key, default)
|