Untitled

mail@pastecode.io avatar
unknown
plain_text
15 days ago
5.1 kB
2
Indexable
Never
extends Node

## This is an autoload. It has a global name `SaveSystem`.

const NUM_SAVEABLE_NPCS := 100	

# Set this to true if you want to print debug info to console.
static var _print_debug_info := false

static var savedata := {				# Overwritten on:
	"scene_path": "",						# Save.
	"save_time": "", 
	"npc_fed_status": false_array(NUM_SAVEABLE_NPCS),	# Npc feed (NPC.gd).
	"pan_sens": FryingPan.PAN_SENS_DEFAULT,
	"mouse_sens": 1.0, 						# Settings close (Pause.gd).
	"gamepad_sens": 1.0,
	"master_vol": 1.0,
	"music_vol": 1.0,
	"sfx_vol": 1.0,
	"fullscreen_status": true
}

static func false_array(size: int) -> Array[bool]:
	var arr: Array[bool] = []
	arr.resize(size)
	arr.fill(false)
	return arr

# Externally set on NPC `_ready` for validation. ----------
static var readied_npcs: Array[int] = [] 
static var npc_loaded_at_least_once_status: Array[bool] = []
# ---------------------------------------------------------

static var _has_entered_tree_before := false
static var last_saveslot := 1

func _enter_tree() -> void:
	if _has_entered_tree_before: # TODO: Fix this. It's shit.
		return
	
	_has_entered_tree_before = true
	@warning_ignore("static_called_on_instance")
	npc_loaded_at_least_once_status = false_array(NUM_SAVEABLE_NPCS)

func savedata_to_disk(saveslot: int) -> void:
	last_saveslot = saveslot
	
	var scene_name = get_tree().current_scene.name
	savedata["scene_path"] = (
		LevelPaths.docks if scene_name == "Docks"
		else LevelPaths.dome if scene_name == "Dome"
		else LevelPaths.rooftops if scene_name == "Rooftops"
		else LevelPaths.closet if scene_name == "Closet"
		else LevelPaths.rooftops if scene_name == "Main"
		else ""
	)
	assert(savedata["scene_path"].length() > 0)
	savedata["save_time"] = Time.get_datetime_string_from_system(true)
	var save_json := JSON.stringify(savedata, "    ", false)
	var save_file := FileAccess.open("user://save_%d.arctic_eggs_save" %saveslot,
		 FileAccess.WRITE)
	save_file.store_line(save_json)
	if _print_debug_info:
		print("---------------------------------------------")
		print("Saved:")
		print(save_json)
		print("---------------------------------------------")

# An almost-pure function which returns the data from disk as JSON.
# Notably, if the output is missing keys, they are added and their
# values are set to defaults.
func get_data_from_disk_as_JSON(saveslot: int) -> JSON:
	var save_file := FileAccess.open(
		"user://save_%d.arctic_eggs_save" %saveslot,
		FileAccess.READ
	)
	
	var save_file_text : String
	if (save_file != null):
		save_file_text = save_file.get_as_text()
	else:
		print("`save_file_text` was null when getting from disk.")
		return null
	
	var json := JSON.new()
	var error := json.parse(save_file_text)
	if error != OK:
		print("Failed to parse data: ", json.get_error_message(), " in ",
			"user://save_%d.arctic_eggs_save" %saveslot, " at line ",
			json.get_error_line())
		return null
	
	for savekey in savedata:
		if !json.data.has(savekey):
			if _print_debug_info:
				print("Loaded data was missing key `", savekey,
					"`. This likely means the save
					format was changed, or an empty save was
					peeked. Using default value.")
			match savekey:
				"scene_path": json.data[savekey] = ""
				"save_time": json.data[savekey] = ""
				"npc_fed_status": 
					var default_false_array: Array[bool] = []
					default_false_array.resize(NUM_SAVEABLE_NPCS)
					default_false_array.fill(false)
					json.data[savekey] = default_false_array
				"pan_sens": json.data[savekey] = FryingPan.PAN_SENS_DEFAULT
				"mouse_sens": json.data[savekey] = 1.0
				"gamepad_sens": json.data[savekey] = 1.0
				"master_vol": json.data[savekey] = 1.0
				"music_vol": json.data[savekey] = 1.0
				"sfx_vol": json.data[savekey] = 1.0
				"fullscreen_status": json.data[savekey] = true
				_: print("Load data savekey validation is missing a case.")
	return json

func does_save_exist_on_disk() -> bool:
	for n in 3:
		var json = get_data_from_disk_as_JSON(n)
		if json != null:
			return true
	return false

# Updates last_saveslot and savedata. After calling, make sure to switch scenes.
# Whenever a scene is switch to, _ready gets called in each of it's children.
# So, savedata can be read from this global script in each needy child.
# In short, loaded data gets "applied" on scene load from the bottom up.
# Returns true if data on disk was valid (json exists, isn't empty).
func load_from_disk_into_savedata(saveslot: int) -> bool:
	last_saveslot = saveslot
	
	var json := get_data_from_disk_as_JSON(saveslot)
	
	if (json == null):
		print("`json` obtained from disk was null.")
		return false
	
	if json.data.is_empty():
		print("Data loaded from disk was empty.")
		return false
	
	if _print_debug_info:
		print("---------------------------------------------")
		print("savedata before load:")
		print(savedata)
	
	savedata = json.data
	
	if _print_debug_info:
		print("savedata after load:")
		print(savedata)
		print("---------------------------------------------")
	return true
Leave a Comment