Files
MusicPlayer/common/ini_file.gd
Sansan d21b3e2ce0
Build / test (push) Successful in 45s
Build / build (push) Successful in 1m12s
Save fullscreen and read server, password and debug from config.ini
The settings the game saves itself, the quiz settings and now fullscreen, move
to settings.cfg (settings_debug.cfg in debug mode).

config.ini in the same folder is edited by hand: the server to start with, the
API password and debug mode. The game writes it with everything commented out
when it is missing and never changes it after that. IniFile reads it: plain
key = value lines, whole-line # or ; comments and optional quotes.
2026-10-07 20:12:59 +02:00

74 lines
2.6 KiB
GDScript

class_name IniFile
extends RefCounted
## A small INI file for settings people edit by hand: [code][section][/code] headers and
## [code]key = value[/code] lines.
##
## Lines starting with [code];[/code] or [code]#[/code] are comments. Comments take whole
## lines, so a value such as a password can hold any character. Quotes around a value are
## optional and removed. Section and key names are not case-sensitive.
const TRUE_WORDS: Array[String] = ["true", "yes", "on", "1"]
const FALSE_WORDS: Array[String] = ["false", "no", "off", "0"]
var _sections: Dictionary[String, Dictionary] = {}
## Reads INI [param text]. Lines that are neither a section, a setting nor a comment are
## skipped with a warning.
static func parse(text: String) -> IniFile:
var ini: IniFile = IniFile.new()
var section: String = ""
var line_number: int = 0
for raw_line: String in text.split("\n"):
line_number += 1
var line: String = raw_line.strip_edges()
if line.is_empty() or line.begins_with(";") or line.begins_with("#"):
continue
if line.begins_with("[") and line.ends_with("]"):
section = line.substr(1, line.length() - 2).strip_edges().to_lower()
continue
var equals: int = line.find("=")
if equals <= 0:
push_warning("Line %d is not a setting: %s" % [line_number, line])
continue
var key: String = line.substr(0, equals).strip_edges().to_lower()
var value: String = line.substr(equals + 1).strip_edges()
if value.length() >= 2 and value[0] in ["\"", "'"] and value[-1] == value[0]:
value = value.substr(1, value.length() - 2)
if !ini._sections.has(section):
ini._sections[section] = {}
ini._sections[section][key] = value
return ini
## Reads the INI file at [param path]. A missing file gives an empty [IniFile].
static func load_file(path: String) -> IniFile:
return parse(FileAccess.get_file_as_string(path))
func has_value(section: String, key: String) -> bool:
return _sections.get(section.to_lower(), {}).has(key.to_lower())
## The sections that have at least one setting.
func get_sections() -> Array[String]:
return _sections.keys()
func get_string(section: String, key: String, default: String = "") -> String:
return _sections.get(section.to_lower(), {}).get(key.to_lower(), default)
## Reads true/false, yes/no, on/off or 1/0. Anything else gives [param default] and a
## warning.
func get_bool(section: String, key: String, default: bool) -> bool:
if !has_value(section, key):
return default
var value: String = get_string(section, key).to_lower()
if value in TRUE_WORDS:
return true
if value in FALSE_WORDS:
return false
push_warning("%s in [%s] should be true or false, not %s" % [key, section, value])
return default