Gesperrte Einstellungen nicht überschreiben
Wer eine Einstellung ändert, liest die Einstellungsdatei jetzt an derselben Stelle wie Schlüssel und Speicherstand. Ist sie gerade nicht lesbar, etwa weil ein anderes Programm sie hält, bleibt sie unverändert, statt nur mit dem neuen Wert überschrieben zu werden. Von einer beschädigten Datei bleibt, was Godot lesen konnte. Ein neuer Test deckt die gehaltene Datei ab. Der Parameter von set_player_name heißt jetzt new_name, damit er die Methode player_name nicht verdeckt. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,9 +14,10 @@ const KEEP_RECORDINGS := 10
|
|||||||
const KEY_BYTES := 16
|
const KEY_BYTES := 16
|
||||||
|
|
||||||
var base_dir: String
|
var base_dir: String
|
||||||
## The result of the last attempt to read the key or the save: OK, or why
|
## The result of the last attempt to read the key, the save or the settings:
|
||||||
## the file could not be read. A file that exists but cannot be read right
|
## OK, or why the file could not be read. A file that exists but cannot be
|
||||||
## now, for example because another program holds it, is never replaced.
|
## read right now, for example because another program holds it, is never
|
||||||
|
## replaced.
|
||||||
var last_read_error: Error = OK
|
var last_read_error: Error = OK
|
||||||
|
|
||||||
|
|
||||||
@@ -132,8 +133,8 @@ func player_name() -> String:
|
|||||||
return _setting("player", "name")
|
return _setting("player", "name")
|
||||||
|
|
||||||
|
|
||||||
func set_player_name(player_name: String) -> void:
|
func set_player_name(new_name: String) -> void:
|
||||||
_set_setting("player", "name", player_name)
|
_set_setting("player", "name", new_name)
|
||||||
|
|
||||||
|
|
||||||
## The address of the host the player joined last time, or an empty text.
|
## The address of the host the player joined last time, or an empty text.
|
||||||
@@ -146,21 +147,40 @@ func set_last_address(address: String) -> void:
|
|||||||
|
|
||||||
|
|
||||||
func _setting(section: String, key: String) -> String:
|
func _setting(section: String, key: String) -> String:
|
||||||
var settings := ConfigFile.new()
|
var settings := _read_settings(base_dir.path_join(SETTINGS_FILE))
|
||||||
if settings.load(base_dir.path_join(SETTINGS_FILE)) != OK:
|
if settings == null:
|
||||||
return ""
|
return ""
|
||||||
return str(settings.get_value(section, key, ""))
|
return str(settings.get_value(section, key, ""))
|
||||||
|
|
||||||
|
|
||||||
|
## Changes one setting and keeps the others. Settings that cannot be read
|
||||||
|
## right now stay as they are, because writing them would lose the others.
|
||||||
func _set_setting(section: String, key: String, value: String) -> void:
|
func _set_setting(section: String, key: String, value: String) -> void:
|
||||||
var path := base_dir.path_join(SETTINGS_FILE)
|
var path := base_dir.path_join(SETTINGS_FILE)
|
||||||
var settings := ConfigFile.new()
|
var settings := _read_settings(path)
|
||||||
settings.load(path)
|
if settings == null:
|
||||||
|
push_warning("settings could not be read at %s and stay as they are: %s" % [path, error_string(last_read_error)])
|
||||||
|
return
|
||||||
settings.set_value(section, key, value)
|
settings.set_value(section, key, value)
|
||||||
if settings.save(path) != OK:
|
if settings.save(path) != OK:
|
||||||
push_warning("settings could not be stored at %s" % path)
|
push_warning("settings could not be stored at %s" % path)
|
||||||
|
|
||||||
|
|
||||||
|
## The settings on disk, or null if the file exists but cannot be read right
|
||||||
|
## now; last_read_error then says why. A missing file gives empty settings.
|
||||||
|
## Of a damaged file, Godot reports the error and keeps what it read before
|
||||||
|
## it, and the next change of a setting writes the file anew.
|
||||||
|
func _read_settings(path: String) -> ConfigFile:
|
||||||
|
var settings := ConfigFile.new()
|
||||||
|
if not FileAccess.file_exists(path):
|
||||||
|
return settings
|
||||||
|
var text := _read_file(path).get_string_from_utf8()
|
||||||
|
if last_read_error != OK:
|
||||||
|
return null
|
||||||
|
settings.parse(text)
|
||||||
|
return settings
|
||||||
|
|
||||||
|
|
||||||
## Moves the backup back to the save if there is no save, see write_save.
|
## Moves the backup back to the save if there is no save, see write_save.
|
||||||
func _restore_backup() -> void:
|
func _restore_backup() -> void:
|
||||||
var path := base_dir.path_join(SAVE_FILE)
|
var path := base_dir.path_join(SAVE_FILE)
|
||||||
|
|||||||
@@ -174,3 +174,18 @@ func test_the_settings_are_kept() -> void:
|
|||||||
check_eq(later.player_name(), "Ada", "name")
|
check_eq(later.player_name(), "Ada", "name")
|
||||||
check_eq(later.last_address(), "192.168.1.20", "address")
|
check_eq(later.last_address(), "192.168.1.20", "address")
|
||||||
TestFiles.remove_dir(directory)
|
TestFiles.remove_dir(directory)
|
||||||
|
|
||||||
|
|
||||||
|
func test_settings_that_cannot_be_read_right_now_are_not_overwritten() -> void:
|
||||||
|
var directory := TestFiles.temporary_dir("held-settings")
|
||||||
|
var store := SaveStore.new(directory)
|
||||||
|
store.set_player_name("Ada")
|
||||||
|
store.set_last_address("192.168.1.20")
|
||||||
|
var held := HeldFileStore.new(directory)
|
||||||
|
held.unreadable = SaveStore.SETTINGS_FILE
|
||||||
|
check_eq(held.player_name(), "", "nothing read for now")
|
||||||
|
held.set_player_name("Grace")
|
||||||
|
var later := SaveStore.new(directory)
|
||||||
|
check_eq(later.player_name(), "Ada", "the name on disk is the old one")
|
||||||
|
check_eq(later.last_address(), "192.168.1.20", "the address is kept")
|
||||||
|
TestFiles.remove_dir(directory)
|
||||||
|
|||||||
Reference in New Issue
Block a user