From bb4d218277a1f619825a4d1801f6c20fefe62815 Mon Sep 17 00:00:00 2001 From: Julian Murgia Date: Thu, 17 Feb 2022 22:23:41 +0100 Subject: [PATCH] Fix crash when save folder is empty and manage corrupted savegame file (#497) --- .../save_data/esc_save_manager.gd | 39 ++++++++++++------- .../menus/load_save/load/load_game.gd | 9 ++--- .../menus/load_save/save/save_game.gd | 9 ++--- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd b/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd index 23790d21..7cd3efa3 100644 --- a/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd +++ b/addons/escoria-core/game/core-scripts/save_data/esc_save_manager.gd @@ -59,7 +59,7 @@ func _init(): # Return a list of savegames metadata (id, date, name and game version) func get_saves_list() -> Dictionary: var regex = RegEx.new() - regex.compile("save_([0-9]{3})\\.tres") + regex.compile("save_(?[0-9]{3})\\.tres") var saves = {} var dirsave = Directory.new() @@ -70,18 +70,30 @@ func get_saves_list() -> Dictionary: var save_path = save_folder.plus_file(nextfile) var file: File = File.new() var save_game_res: Resource = load(save_path) - var save_game_data = { - "date": save_game_res["date"], - "name": save_game_res["name"], - "game_version": save_game_res["game_version"], - } - - var id: int - var matches = regex.search(nextfile) - if matches.strings.size() > 1: - id = int(matches.strings[1]) - saves[id] = save_game_data + if save_game_res == null: + escoria.logger.report_warnings( + "esc_save_manager.gd", + ["Savegame file %s is corrupted. Skipping." % save_path] + ) + else: + var save_game_data = { + "date": save_game_res["date"], + "name": save_game_res["name"], + "game_version": save_game_res["game_version"], + } + + var matches = regex.search(nextfile) + if matches != null and matches.get_string("slotnumber") != null: + saves[int(matches.get_string("slotnumber"))] = save_game_data + else: + escoria.logger.report_warnings( + "esc_save_manager.gd", + [ + "Savegame file %s contains valid data but doesn't match filename format %s. Skipping." + % [save_path, regex.get_pattern()] + ] + ) nextfile = dirsave.get_next() return saves @@ -226,8 +238,7 @@ func load_game(id: int): "res://addons/escoria-core/game/core-scripts/migrations/versions" ) - # Migrate savegame through game versions - + # Migrate savegame through game versions if escoria.project_settings_manager.get_setting( escoria.project_settings_manager.GAME_VERSION ) != save_game.game_version \ diff --git a/addons/escoria-core/ui_library/menus/load_save/load/load_game.gd b/addons/escoria-core/ui_library/menus/load_save/load/load_game.gd index ae07bb36..8dd42e92 100644 --- a/addons/escoria-core/ui_library/menus/load_save/load/load_game.gd +++ b/addons/escoria-core/ui_library/menus/load_save/load/load_game.gd @@ -34,12 +34,11 @@ func refresh_savegames(): $VBoxContainer/ScrollContainer/slots.remove_child(slot) var saves_list = escoria.save_manager.get_saves_list() - for i in range(saves_list.keys().max() + 1): - if saves_list.has(i): - var save_data = saves_list[i] + if not saves_list.empty(): + for save_key in saves_list.keys(): var new_slot = slot_ui_scene.instance() $VBoxContainer/ScrollContainer/slots.add_child( new_slot ) - new_slot.set_slot_name_date(save_data["name"], save_data["date"]) - new_slot.connect("pressed", self, "_on_slot_pressed", [i]) + new_slot.set_slot_name_date(saves_list[save_key]["name"], saves_list[save_key]["date"]) + new_slot.connect("pressed", self, "_on_slot_pressed", [save_key]) diff --git a/addons/escoria-core/ui_library/menus/load_save/save/save_game.gd b/addons/escoria-core/ui_library/menus/load_save/save/save_game.gd index 97644154..87f33a80 100644 --- a/addons/escoria-core/ui_library/menus/load_save/save/save_game.gd +++ b/addons/escoria-core/ui_library/menus/load_save/save/save_game.gd @@ -34,13 +34,12 @@ func refresh_savegames(): _slots.remove_child(slot) var saves_list = escoria.save_manager.get_saves_list() - for i in range(saves_list.keys().max() + 1): - if saves_list.has(i): - var save_data = saves_list[i] + if not saves_list.empty(): + for save_key in saves_list.keys(): var new_slot = slot_ui_scene.instance() _slots.add_child(new_slot) - new_slot.set_slot_name_date(save_data["name"], save_data["date"]) - new_slot.connect("pressed", self, "_on_slot_pressed", [i]) + new_slot.set_slot_name_date(saves_list[save_key]["name"], saves_list[save_key]["date"]) + new_slot.connect("pressed", self, "_on_slot_pressed", [save_key]) var datetime = OS.get_datetime() var datetime_string = "%02d/%02d/%02d %02d:%02d" % [