Add gdlint and gdformat scripts

This commit is contained in:
2025-09-27 20:40:13 +04:00
parent 86439abea8
commit 06f0f87970
40 changed files with 2314 additions and 732 deletions

View File

@@ -7,24 +7,22 @@ const MAX_SETTING_STRING_LENGTH = 10 # Max length for string settings like lang
# dev `user://`=`%APPDATA%\Godot\app_userdata\Skelly`
# prod `user://`=`%APPDATA%\Skelly\`
var settings = {
var settings: Dictionary = {}
var default_settings: Dictionary = {
"master_volume": 0.50, "music_volume": 0.40, "sfx_volume": 0.50, "language": "en"
}
var default_settings = {
"master_volume": 0.50,
"music_volume": 0.40,
"sfx_volume": 0.50,
"language": "en"
}
var languages_data: Dictionary = {}
var languages_data = {}
func _ready():
func _ready() -> void:
DebugManager.log_info("SettingsManager ready", "SettingsManager")
load_languages()
load_settings()
func load_settings():
func load_settings() -> void:
var config = ConfigFile.new()
var load_result = config.load(SETTINGS_FILE)
@@ -39,16 +37,26 @@ func load_settings():
if _validate_setting_value(key, loaded_value):
settings[key] = loaded_value
else:
DebugManager.log_warn("Invalid setting value for '%s', using default: %s" % [key, str(default_settings[key])], "SettingsManager")
DebugManager.log_warn(
(
"Invalid setting value for '%s', using default: %s"
% [key, str(default_settings[key])]
),
"SettingsManager"
)
settings[key] = default_settings[key]
DebugManager.log_info("Settings loaded: " + str(settings), "SettingsManager")
else:
DebugManager.log_warn("No settings file found (Error code: %d), using defaults" % load_result, "SettingsManager")
DebugManager.log_warn(
"No settings file found (Error code: %d), using defaults" % load_result,
"SettingsManager"
)
settings = default_settings.duplicate()
# Apply settings with error handling
_apply_all_settings()
func _apply_all_settings():
DebugManager.log_info("Applying settings: " + str(settings), "SettingsManager")
@@ -64,17 +72,24 @@ func _apply_all_settings():
if master_bus >= 0 and "master_volume" in settings:
AudioServer.set_bus_volume_db(master_bus, linear_to_db(settings["master_volume"]))
else:
DebugManager.log_warn("Master audio bus not found or master_volume setting missing", "SettingsManager")
DebugManager.log_warn(
"Master audio bus not found or master_volume setting missing", "SettingsManager"
)
if music_bus >= 0 and "music_volume" in settings:
AudioServer.set_bus_volume_db(music_bus, linear_to_db(settings["music_volume"]))
else:
DebugManager.log_warn("Music audio bus not found or music_volume setting missing", "SettingsManager")
DebugManager.log_warn(
"Music audio bus not found or music_volume setting missing", "SettingsManager"
)
if sfx_bus >= 0 and "sfx_volume" in settings:
AudioServer.set_bus_volume_db(sfx_bus, linear_to_db(settings["sfx_volume"]))
else:
DebugManager.log_warn("SFX audio bus not found or sfx_volume setting missing", "SettingsManager")
DebugManager.log_warn(
"SFX audio bus not found or sfx_volume setting missing", "SettingsManager"
)
func save_settings():
var config = ConfigFile.new()
@@ -83,15 +98,19 @@ func save_settings():
var save_result = config.save(SETTINGS_FILE)
if save_result != OK:
DebugManager.log_error("Failed to save settings (Error code: %d)" % save_result, "SettingsManager")
DebugManager.log_error(
"Failed to save settings (Error code: %d)" % save_result, "SettingsManager"
)
return false
DebugManager.log_info("Settings saved: " + str(settings), "SettingsManager")
return true
func get_setting(key: String):
return settings.get(key)
func set_setting(key: String, value) -> bool:
if not key in default_settings:
DebugManager.log_error("Unknown setting key: " + key, "SettingsManager")
@@ -99,13 +118,16 @@ func set_setting(key: String, value) -> bool:
# Validate value type and range based on key
if not _validate_setting_value(key, value):
DebugManager.log_error("Invalid value for setting '%s': %s" % [key, str(value)], "SettingsManager")
DebugManager.log_error(
"Invalid value for setting '%s': %s" % [key, str(value)], "SettingsManager"
)
return false
settings[key] = value
_apply_setting_side_effect(key, value)
return true
func _validate_setting_value(key: String, value) -> bool:
match key:
"master_volume", "music_volume", "sfx_volume":
@@ -116,7 +138,9 @@ func _validate_setting_value(key: String, value) -> bool:
var float_value = float(value)
# Check for NaN and infinity
if is_nan(float_value) or is_inf(float_value):
DebugManager.log_warn("Invalid float value for %s: %s" % [key, str(value)], "SettingsManager")
DebugManager.log_warn(
"Invalid float value for %s: %s" % [key, str(value)], "SettingsManager"
)
return false
# Range validation
return float_value >= 0.0 and float_value <= 1.0
@@ -125,13 +149,17 @@ func _validate_setting_value(key: String, value) -> bool:
return false
# Prevent extremely long strings
if value.length() > MAX_SETTING_STRING_LENGTH:
DebugManager.log_warn("Language code too long: %d characters" % value.length(), "SettingsManager")
DebugManager.log_warn(
"Language code too long: %d characters" % value.length(), "SettingsManager"
)
return false
# Check for valid characters (alphanumeric and common separators only)
var regex = RegEx.new()
regex.compile("^[a-zA-Z0-9_-]+$")
if not regex.search(value):
DebugManager.log_warn("Language code contains invalid characters: %s" % value, "SettingsManager")
DebugManager.log_warn(
"Language code contains invalid characters: %s" % value, "SettingsManager"
)
return false
# Check if language is supported
if languages_data.has("languages") and languages_data.languages is Dictionary:
@@ -147,31 +175,40 @@ func _validate_setting_value(key: String, value) -> bool:
return false
return typeof(value) == typeof(default_value)
func _apply_setting_side_effect(key: String, value) -> void:
match key:
"language":
TranslationServer.set_locale(value)
"master_volume":
if AudioServer.get_bus_index("Master") >= 0:
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db(value))
AudioServer.set_bus_volume_db(
AudioServer.get_bus_index("Master"), linear_to_db(value)
)
"music_volume":
AudioManager.update_music_volume(value)
"sfx_volume":
if AudioServer.get_bus_index("SFX") >= 0:
AudioServer.set_bus_volume_db(AudioServer.get_bus_index("SFX"), linear_to_db(value))
func load_languages():
var file = FileAccess.open(LANGUAGES_JSON_PATH, FileAccess.READ)
if not file:
var error_code = FileAccess.get_open_error()
DebugManager.log_error("Could not open languages.json (Error code: %d)" % error_code, "SettingsManager")
DebugManager.log_error(
"Could not open languages.json (Error code: %d)" % error_code, "SettingsManager"
)
_load_default_languages()
return
# Check file size to prevent memory exhaustion
var file_size = file.get_length()
if file_size > MAX_JSON_FILE_SIZE:
DebugManager.log_error("Languages.json file too large: %d bytes (max %d)" % [file_size, MAX_JSON_FILE_SIZE], "SettingsManager")
DebugManager.log_error(
"Languages.json file too large: %d bytes (max %d)" % [file_size, MAX_JSON_FILE_SIZE],
"SettingsManager"
)
file.close()
_load_default_languages()
return
@@ -187,7 +224,9 @@ func load_languages():
file.close()
if file_error != OK:
DebugManager.log_error("Error reading languages.json (Error code: %d)" % file_error, "SettingsManager")
DebugManager.log_error(
"Error reading languages.json (Error code: %d)" % file_error, "SettingsManager"
)
_load_default_languages()
return
@@ -200,7 +239,10 @@ func load_languages():
var json = JSON.new()
var parse_result = json.parse(json_string)
if parse_result != OK:
DebugManager.log_error("JSON parsing failed at line %d: %s" % [json.error_line, json.error_string], "SettingsManager")
DebugManager.log_error(
"JSON parsing failed at line %d: %s" % [json.error_line, json.error_string],
"SettingsManager"
)
_load_default_languages()
return
@@ -216,21 +258,24 @@ func load_languages():
return
languages_data = json.data
DebugManager.log_info("Languages loaded successfully: " + str(languages_data.languages.keys()), "SettingsManager")
DebugManager.log_info(
"Languages loaded successfully: " + str(languages_data.languages.keys()), "SettingsManager"
)
func _load_default_languages():
# Fallback language data when JSON file fails to load
languages_data = {
"languages": {
"en": {"name": "English", "flag": "🇺🇸"},
"ru": {"name": "Русский", "flag": "🇷🇺"}
}
"languages":
{"en": {"name": "English", "flag": "🇺🇸"}, "ru": {"name": "Русский", "flag": "🇷🇺"}}
}
DebugManager.log_info("Default languages loaded as fallback", "SettingsManager")
func get_languages_data():
return languages_data
func reset_settings_to_defaults() -> void:
DebugManager.log_info("Resetting all settings to defaults", "SettingsManager")
for key in default_settings.keys():
@@ -242,6 +287,7 @@ func reset_settings_to_defaults() -> void:
else:
DebugManager.log_error("Failed to save reset settings", "SettingsManager")
func _validate_languages_structure(data: Dictionary) -> bool:
"""Validate the structure and content of languages.json data"""
if not data.has("languages"):
@@ -260,7 +306,9 @@ func _validate_languages_structure(data: Dictionary) -> bool:
# Validate each language entry
for lang_code in languages.keys():
if not lang_code is String:
DebugManager.log_error("Language code is not a string: %s" % str(lang_code), "SettingsManager")
DebugManager.log_error(
"Language code is not a string: %s" % str(lang_code), "SettingsManager"
)
return false
if lang_code.length() > MAX_SETTING_STRING_LENGTH:
@@ -269,12 +317,16 @@ func _validate_languages_structure(data: Dictionary) -> bool:
var lang_data = languages[lang_code]
if not lang_data is Dictionary:
DebugManager.log_error("Language data for '%s' is not a dictionary" % lang_code, "SettingsManager")
DebugManager.log_error(
"Language data for '%s' is not a dictionary" % lang_code, "SettingsManager"
)
return false
# Validate required fields in language data
if not lang_data.has("name") or not lang_data["name"] is String:
DebugManager.log_error("Language '%s' missing valid 'name' field" % lang_code, "SettingsManager")
DebugManager.log_error(
"Language '%s' missing valid 'name' field" % lang_code, "SettingsManager"
)
return false
return true