186 lines
6.0 KiB
GDScript
186 lines
6.0 KiB
GDScript
@tool
|
|
class_name SaveGame extends Resource
|
|
|
|
var _is_initialised: bool = false
|
|
|
|
@export var filepath: String:
|
|
set(value):
|
|
filepath = value
|
|
if _is_initialised:
|
|
read_save_file()
|
|
changed.emit()
|
|
@export var unique_save_name: String = "frame_of_mind_%s_%s" % [Time.get_date_string_from_system(), Time.get_time_string_from_system().replace(":", "-")]:
|
|
set(value):
|
|
unique_save_name = value
|
|
if _is_initialised: changed.emit()
|
|
@export var current_room: State.rooms = State.rooms.NULL:
|
|
set(value):
|
|
current_room = value
|
|
if _is_initialised: changed.emit()
|
|
@export_flags("Intro", "Childhood", "Voice Training", "Jui Jutsu") var mementos_complete: int = 0:
|
|
set(value):
|
|
mementos_complete = value
|
|
if _is_initialised: changed.emit()
|
|
@export var board_state: Dictionary = {"cards": {}, "stickies": {}}:
|
|
set(value):
|
|
board_state = value
|
|
if _is_initialised: changed.emit()
|
|
@export var thumbnail: Texture = preload("res://import/interface-elements/empty_save_slot.png"):
|
|
set(value):
|
|
thumbnail = value
|
|
if _is_initialised: changed.emit()
|
|
@export var last_saved: int = int(Time.get_unix_time_from_system()):
|
|
set(value):
|
|
last_saved = value
|
|
if _is_initialised: changed.emit()
|
|
|
|
@export var is_valid: bool = false
|
|
@export var is_empty: bool = true:
|
|
get():
|
|
return not FileAccess.file_exists("%s.json:" % filepath)
|
|
@export var save_manually: bool = false:
|
|
set(val):
|
|
if val: save_to_file(thumbnail)
|
|
|
|
func _validate_property(property: Dictionary):
|
|
if property.name == filepath:
|
|
property.usage |= PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED
|
|
if property.name == "thumbnail":
|
|
property.usage |= PROPERTY_USAGE_READ_ONLY
|
|
if property.name == "is_valid":
|
|
property.usage |= PROPERTY_USAGE_READ_ONLY
|
|
if property.name == "is_empty":
|
|
property.usage |= PROPERTY_USAGE_READ_ONLY
|
|
|
|
func _init(initial_filepath = "") -> void:
|
|
if initial_filepath == "":
|
|
filepath = "%s/%s" % [State.user_saves_path, unique_save_name]
|
|
else:
|
|
filepath = initial_filepath
|
|
unique_save_name = initial_filepath.get_file()
|
|
read_save_file()
|
|
_is_initialised = true
|
|
|
|
func read_save_file():
|
|
print("Opening Savegame: %s.json" % filepath)
|
|
|
|
if FileAccess.file_exists("%s.json" % filepath):
|
|
var file = FileAccess.open("%s.json" % filepath, FileAccess.READ)
|
|
var raw_json = FileAccess.get_file_as_string("%s.json" % filepath)
|
|
file.close()
|
|
var parsed: Dictionary = JSON.parse_string(raw_json)
|
|
|
|
var tmp_img: Image
|
|
|
|
if FileAccess.file_exists("%s/thumbnails/%s.png" % [filepath.get_base_dir(), unique_save_name]):
|
|
tmp_img = Image.load_from_file("%s/thumbnails/%s.png" % [filepath.get_base_dir(), unique_save_name])
|
|
|
|
var are_types_valid = (
|
|
parsed["unique_save_name"] is String and
|
|
parsed["current_room"] is float and
|
|
parsed["mementos_complete"] is float and
|
|
parsed["board_state"] is Dictionary and
|
|
parsed["last_saved"] is float and last_saved != 0
|
|
)
|
|
|
|
if are_types_valid:
|
|
for key in parsed.keys():
|
|
set(key, parsed[key])
|
|
|
|
for dict:Dictionary in board_state.values():
|
|
for key in dict.keys():
|
|
if dict[key] is String:
|
|
if dict[key].begins_with("("):
|
|
dict[key] = parse_vec_from_string(dict[key])
|
|
|
|
var cards: Dictionary[StringName, Variant]
|
|
var stickies: Dictionary[StringName, Variant]
|
|
|
|
for cardname:String in board_state["cards"]:
|
|
cards[StringName(cardname)] = board_state["cards"][cardname]
|
|
for sticky_name:String in board_state["stickies"]:
|
|
stickies[StringName(sticky_name)] = board_state["stickies"][sticky_name]
|
|
|
|
board_state = {
|
|
"cards": cards,
|
|
"stickies": stickies
|
|
}
|
|
|
|
is_valid = are_types_valid \
|
|
and current_room >= 0 \
|
|
and current_room < State.rooms.keys().size() \
|
|
and validate_board_state()
|
|
|
|
if not is_valid:
|
|
push_error("Parsing of Save failed.")
|
|
|
|
if tmp_img != null:
|
|
thumbnail = ImageTexture.create_from_image(tmp_img)
|
|
is_empty = false
|
|
else:
|
|
is_valid = true
|
|
|
|
func _get_save_dict() -> Dictionary:
|
|
return {
|
|
"unique_save_name": unique_save_name,
|
|
"current_room": current_room,
|
|
"mementos_complete": mementos_complete,
|
|
"board_state": board_state,
|
|
"last_saved": last_saved
|
|
}
|
|
|
|
func save_to_file(current_screen: Texture):
|
|
# FIXME
|
|
if OS.has_feature("Demo") or OS.has_feature("Debug"): return
|
|
last_saved = Time.get_unix_time_from_system()
|
|
|
|
var thumbnail_image: Image = current_screen.get_image()
|
|
thumbnail_image.resize(384, 261, Image.INTERPOLATE_LANCZOS) # nonexistent call in ViewportTexturew
|
|
|
|
var thumbnail_path: String = "%s/thumbnails/%s.png" % [filepath.get_base_dir(), unique_save_name]
|
|
var save_dir = DirAccess.open(filepath.get_base_dir())
|
|
if not save_dir.dir_exists("thumbnails"):
|
|
save_dir.make_dir("thumbnails")
|
|
|
|
thumbnail_image.save_png("%s/thumbnails/%s.png" % [filepath.get_base_dir(), unique_save_name])
|
|
#thumbnail_image.save_png("%s/test.png" % State.user_saves_path)
|
|
print(filepath.get_base_dir())
|
|
var file = FileAccess.open("%s.json" % filepath, FileAccess.WRITE)
|
|
file.store_string(JSON.stringify(_get_save_dict()))
|
|
file.close()
|
|
|
|
|
|
func calculate_completed_sequences() -> int:
|
|
var i: int = mementos_complete - ((mementos_complete >> 1) & 0x55555555);
|
|
i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
|
|
i = (i + (i >> 4)) & 0x0F0F0F0F;
|
|
i *= 0x01010101;
|
|
return i >> 24;
|
|
|
|
func calculate_total_connections() -> int:
|
|
var connections:= 0
|
|
|
|
for sticky_position in board_state.stickies.values():
|
|
connections += int(sticky_position is String)
|
|
|
|
return connections
|
|
|
|
func validate_board_state() -> bool:
|
|
if board_state.keys().has("cards") and board_state.keys().has("stickies"):
|
|
for card in board_state.cards.values():
|
|
if not card is Vector2:
|
|
push_error("Save %s could not be parsed: Corrupted Cards." % unique_save_name)
|
|
return false
|
|
for sticky in board_state.stickies.values():
|
|
if not (sticky == -1 or sticky is Vector2 or board_state.cards.keys.has(sticky)):
|
|
push_error("Save %s could not be parsed: Corrupted Sticky Notes.")
|
|
return false
|
|
|
|
return true
|
|
|
|
return false
|
|
|
|
func parse_vec_from_string(string: String) -> Vector2:
|
|
var string_array = string.replace("(", "").replace(")", "").split(", ")
|
|
return Vector2(float(string_array[0]), float(string_array[1]))
|