Configuration System
Relevant source files
Purpose and Scope
Section titled “Purpose and Scope”The Configuration System manages persistent storage and retrieval of all user settings in Taj’s Mod. It provides a centralized ConfigManager class that handles JSON-based persistence, default value fallbacks, and write-through caching to ensure settings survive game restarts.
This page covers the configuration architecture, persistence strategy, and integration patterns. For information about the Settings UI that allows users to modify these values, see Settings Panel UI. For the command palette’s settings toggle commands, see Command Definitions and Registry.
Architecture Overview
Section titled “Architecture Overview”The configuration system follows a write-through caching pattern with a three-tier fallback hierarchy. All settings are stored in a single JSON file and accessed through a centralized manager instance.
flowchart TD
DEFAULT_CONFIG["DEFAULT_CONFIG<br>(Hardcoded Dictionary)<br>config_manager.gd:12-54"]
UserFile["user://tajs_mod_config.json<br>(Persistent Storage)"]
ConfigManager["TajsModConfigManager<br>config_manager.gd:6"]
LoadConfig["load_config()<br>Merges user + defaults"]
SaveConfig["save_config()<br>Write-through to disk"]
GetValue["get_value(key, override)<br>3-tier fallback"]
SetValue["set_value(key, value)<br>Immediate persist"]
ModMain["mod_main.gd<br>Orchestrator"]
SettingsUI["Settings UI Panels<br>Checkboxes/Sliders"]
Commands["Palette Commands<br>Toggle actions"]
Managers["Feature Managers<br>Screenshot, BuyMax, etc"]
GlobalsState["Globals.custom_node_limit<br>Globals.select_all_enabled<br>Globals.custom_upgrade_multiplier"]
ComponentState["Manager Properties<br>screenshot_manager.quality<br>focus_handler.enabled"]
DEFAULT_CONFIG --> LoadConfig
UserFile --> LoadConfig
SaveConfig --> UserFile
ModMain --> ConfigManager
SettingsUI --> SetValue
Commands --> SetValue
ConfigManager --> Managers
ConfigManager --> GlobalsState
Managers --> ComponentState
GetValue --> UserFile
GetValue --> DEFAULT_CONFIG
subgraph subGraph3 ["Runtime State"]
GlobalsState
ComponentState
end
subgraph subGraph2 ["Configuration Consumers"]
ModMain
SettingsUI
Commands
Managers
end
subgraph subGraph1 ["Configuration Manager"]
ConfigManager
LoadConfig
SaveConfig
GetValue
SetValue
LoadConfig --> ConfigManager
ConfigManager --> GetValue
ConfigManager --> SetValue
SetValue --> SaveConfig
end
subgraph subGraph0 ["Configuration Sources"]
DEFAULT_CONFIG
UserFile
end
Sources: extensions/scripts/utilities/config_manager.gd L1-L134
The ConfigManager Class
Section titled “The ConfigManager Class”The TajsModConfigManager class is a RefCounted singleton that manages all configuration operations. It is instantiated early in the mod lifecycle and passed to components that need configuration access.
Class Definition
Section titled “Class Definition”classDiagram
class TajsModConfigManager {
-Dictionary _config
+const String CONFIG_PATH
+const Dictionary DEFAULT_CONFIG
+_init()
+load_config() : void
+save_config() : void
+get_value(key, default_override) : Variant
+set_value(key, value) : void
+get_all() : Dictionary
+reset_to_defaults() : void
}
class ModMain {
+TajsModConfigManager config
+_init()
+_ready()
}
class SettingsUI {
+TajsModConfigManager config
+set_config(config)
}
class FeatureManager {
«interface»
+setup(config)
}
ModMain --> TajsModConfigManager : instantiates
SettingsUI --> TajsModConfigManager : reads/writes
FeatureManager --> TajsModConfigManager : consumes
Sources: extensions/scripts/utilities/config_manager.gd L6-L134
Key Methods
Section titled “Key Methods”| Method | Signature | Description |
|---|---|---|
_init() | func _init() -> void | Initializes _config with defaults, then calls load_config() |
load_config() | func load_config() -> void | Reads JSON file, merges with defaults, preserves extra keys |
save_config() | func save_config() -> void | Writes _config to JSON file with tab indentation |
get_value() | func get_value(key: String, default_override = null) | Returns value with 3-tier fallback |
set_value() | func set_value(key: String, value) -> void | Updates _config[key] and immediately calls save_config() |
get_all() | func get_all() -> Dictionary | Returns a duplicate of the entire config dictionary |
reset_to_defaults() | func reset_to_defaults() -> void | Deletes user file, resets _config to DEFAULT_CONFIG |
Sources: extensions/scripts/utilities/config_manager.gd L58-L133
Configuration Hierarchy
Section titled “Configuration Hierarchy”The configuration system uses a three-tier fallback mechanism when retrieving values. This allows new settings to be added in updates without breaking existing user configurations.
flowchart TD Start["get_value(key, default_override)"] CheckConfig["Key exists in<br>_config?"] ReturnConfig["Return _config[key]"] CheckOverride["default_override<br>!= null?"] ReturnOverride["Return default_override"] CheckDefault["Key exists in<br>DEFAULT_CONFIG?"] ReturnDefault["Return DEFAULT_CONFIG[key]"] ReturnNull["Return null"] Start --> CheckConfig CheckConfig --> ReturnConfig CheckConfig --> CheckOverride CheckOverride --> ReturnOverride CheckOverride --> CheckDefault CheckDefault --> ReturnDefault CheckDefault --> ReturnNull
Sources: extensions/scripts/utilities/config_manager.gd L110-L117
Fallback Behavior
Section titled “Fallback Behavior”- Tier 1 - User Configuration: If the key exists in the in-memory
_configdictionary (loaded fromuser://tajs_mod_config.json), return that value - Tier 2 - Method Override: If a
default_overrideparameter was provided toget_value(), return that - Tier 3 - Default Configuration: If the key exists in
DEFAULT_CONFIG, return the hardcoded default - Tier 4 - Null: If none of the above, return
null
This hierarchy ensures backward compatibility when new settings are added. The load_config() method explicitly preserves extra keys from the user file that aren’t in DEFAULT_CONFIG:
Sources: extensions/scripts/utilities/config_manager.gd L62-L117
Persistence Strategy
Section titled “Persistence Strategy”The configuration system uses a write-through caching strategy where every modification immediately persists to disk. This ensures no settings are lost even if the game crashes.
Write-Through Workflow
Section titled “Write-Through Workflow”sequenceDiagram
participant Settings UI / Command
participant ConfigManager
participant _config Dictionary
participant tajs_mod_config.json
participant Component
Settings UI / Command->>ConfigManager: set_value("extra_glow", true)
ConfigManager->>_config Dictionary: _config["extra_glow"] = true
ConfigManager->>ConfigManager: save_config()
ConfigManager->>tajs_mod_config.json: Write JSON to file
ConfigManager-->>Settings UI / Command: Return
note over tajs_mod_config.json: Settings persisted immediately
Component->>ConfigManager: get_value("extra_glow")
ConfigManager->>_config Dictionary: Read from _config
ConfigManager-->>Component: Return true
Sources: extensions/scripts/utilities/config_manager.gd L100-L121
File Format
Section titled “File Format”The configuration file is stored as formatted JSON with tab indentation at user://tajs_mod_config.json. Example content:
{ "node_limit": 400, "extra_glow": false, "glow_intensity": 2, "screenshot_quality": 2, "command_palette_enabled": true, "wire_colors_hex": { "money":"#FFD700","research": "#00BFFF"; }}Sources: extensions/scripts/utilities/config_manager.gd L10-L108
Smart Merging on Load
Section titled “Smart Merging on Load”When load_config() runs, it performs smart merging to handle version updates:
- Iterate through all keys in
DEFAULT_CONFIGand add them to_configif missing from the user file - Preserve any extra keys from the user file that aren’t in defaults (e.g.,
wire_colors_hexcustom data) - Log success or errors
This allows new default settings to be added in updates without requiring users to reset their configuration.
Sources: extensions/scripts/utilities/config_manager.gd L79-L98
Configuration Lifecycle
Section titled “Configuration Lifecycle”The configuration system is initialized early in the mod lifecycle and remains active throughout the game session.
sequenceDiagram
participant Mod Loader
participant mod_main.gd
participant ConfigManager
participant JSON File
participant SettingsUI
participant Feature Managers
Mod Loader->>mod_main.gd: _init()
mod_main.gd->>ConfigManager: new ConfigManager()
ConfigManager->>ConfigManager: _config = DEFAULT_CONFIG.duplicate()
ConfigManager->>ConfigManager: load_config()
ConfigManager->>JSON File: FileAccess.open(READ)
loop [File exists]
JSON File-->>ConfigManager: JSON data
ConfigManager->>ConfigManager: Merge with defaults
ConfigManager->>JSON File: save_config() (create defaults)
ConfigManager-->>mod_main.gd: Return instance
mod_main.gd->>mod_main.gd: Apply early configs
note over mod_main.gd: screenshot_manager.quality = config.get_value(...)
note over mod_main.gd: Globals.custom_node_limit = config.get_value(...)
mod_main.gd->>mod_main.gd: _ready() / _setup_for_main()
mod_main.gd->>SettingsUI: new SettingsUI()
mod_main.gd->>SettingsUI: set_config(config)
mod_main.gd->>Feature Managers: setup(config)
SettingsUI->>ConfigManager: set_value("extra_glow", true)
ConfigManager->>JSON File: save_config()
ConfigManager->>Feature Managers: Notify/Apply
end
Sources: mod_main.gd L72-L339
extensions/scripts/utilities/config_manager.gd L58-L108
Configuration Categories
Section titled “Configuration Categories”The DEFAULT_CONFIG dictionary defines 40+ configuration keys organized into logical categories. Each category corresponds to a tab in the Settings UI.
General Tab
Section titled “General Tab”| Key | Type | Default | Description |
|---|---|---|---|
node_limit | int | 400 | Maximum nodes allowed (-1 for unlimited) |
select_all_enabled | bool | true | Enable Ctrl+A to select all nodes |
command_palette_enabled | bool | true | Enable MMB command palette |
wire_drop_menu_enabled | bool | true | Show quick-add menu on wire drop |
right_click_clear_enabled | bool | true | Right-click output slots to disconnect |
goto_group_enabled | bool | true | Show “Go To Group” button |
buy_max_enabled | bool | true | Show “Buy Max” button in upgrades |
z_order_fix_enabled | bool | true | Fix z-order of nested groups |
disable_slider_scroll | bool | false | Block scroll wheel on sliders |
six_input_containers | bool | true | Allow 6-input containers (requires restart) |
upgrade_multiplier | int | 10 | Ctrl+click upgrade multiplier |
Sources: extensions/scripts/utilities/config_manager.gd L12-L36
Visuals Tab
Section titled “Visuals Tab”| Key | Type | Default | Description |
|---|---|---|---|
extra_glow | bool | false | Enable enhanced glow effects |
glow_intensity | float | 2.0 | Glow brightness multiplier |
glow_strength | float | 1.3 | Glow spread strength |
glow_bloom | float | 0.2 | Bloom effect amount |
glow_sensitivity | float | 0.8 | HDR threshold sensitivity |
ui_opacity | float | 100.0 | UI transparency (50-100%) |
custom_wire_colors | bool | true | Enable custom wire colors |
wire_colors_hex | Dictionary | {} | Custom wire colors by resource ID |
Sources: extensions/scripts/utilities/config_manager.gd L36-L42
Screenshot Settings
Section titled “Screenshot Settings”| Key | Type | Default | Description |
|---|---|---|---|
screenshot_quality | int | 2 | JPEG quality (0=Low, 1=Med, 2=High) |
screenshot_watermark | bool | true | Add “Taj’s Mod” watermark |
screenshot_folder | String | "user://screenshots" | Output directory path |
Sources: extensions/scripts/utilities/config_manager.gd L14-L16
Audio Settings
Section titled “Audio Settings”| Key | Type | Default | Description |
|---|---|---|---|
mute_on_focus_loss | bool | true | Reduce volume when window loses focus |
background_volume | float | 0.0 | Volume percentage when unfocused (0-100) |
Sources: extensions/scripts/utilities/config_manager.gd L29-L31
Highlight Disconnected Nodes
Section titled “Highlight Disconnected Nodes”| Key | Type | Default | Description |
|---|---|---|---|
highlight_disconnected_enabled | bool | true | Highlight unconnected nodes |
highlight_disconnected_style | String | "pulse" | Style: “pulse” or “outline” |
highlight_disconnected_intensity | float | 0.5 | Effect intensity (0.0-1.0) |
highlight_disconnected_debug | bool | false | Enable debug logging |
Sources: extensions/scripts/utilities/config_manager.gd L45-L49
Debug Settings
Section titled “Debug Settings”| Key | Type | Default | Description |
|---|---|---|---|
custom_boot_screen | bool | true | Show custom boot screen (requires restart) |
debug_mode | bool | false | Enable verbose debug logging |
disable_controller_input | bool | false | Block all controller inputs |
Sources: extensions/scripts/utilities/config_manager.gd L52-L53
Integration Points
Section titled “Integration Points”Components integrate with the configuration system through several patterns:
Pattern 1: Direct Read in _init()
Section titled “Pattern 1: Direct Read in _init()”Early initialization components read configuration directly during mod_main._init():
Sources: mod_main.gd L88-L96
Pattern 2: Manager Setup Method
Section titled “Pattern 2: Manager Setup Method”Feature managers receive the config instance via a setup() method:
Sources: mod_main.gd L104-L418
Pattern 3: SettingsUI Callbacks
Section titled “Pattern 3: SettingsUI Callbacks”The Settings UI registers callbacks that call config.set_value() and apply changes immediately:
Sources: mod_main.gd L467-L497
Pattern 4: Palette Commands
Section titled “Pattern 4: Palette Commands”Command palette toggles modify config and sync UI state:
Sources: mod_main.gd L1150-L1154
Pattern 5: Restart-Required Settings
Section titled “Pattern 5: Restart-Required Settings”Some settings require a game restart to take effect. These track their original values and show a banner if changed:
Sources: mod_main.gd L473-L1174
Default Configuration Reference
Section titled “Default Configuration Reference”The complete DEFAULT_CONFIG dictionary serves as the schema for all available settings. It is defined as a constant at the top of the ConfigManager class:
flowchart TD
General["General Settings<br>11 keys"]
Visuals["Visual Settings<br>8 keys"]
Audio["Audio Settings<br>2 keys"]
Screenshot["Screenshot Settings<br>3 keys"]
Highlight["Disconnected Highlight<br>4 keys"]
Misc["Miscellaneous<br>5 keys"]
DEFAULT_CONFIG["DEFAULT_CONFIG<br>const Dictionary"]
DEFAULT_CONFIG --> General
DEFAULT_CONFIG --> Visuals
DEFAULT_CONFIG --> Audio
DEFAULT_CONFIG --> Screenshot
DEFAULT_CONFIG --> Highlight
DEFAULT_CONFIG --> Misc
subgraph subGraph0 ["DEFAULT_CONFIG Structure"]
General
Visuals
Audio
Screenshot
Highlight
Misc
end
Sources: extensions/scripts/utilities/config_manager.gd L12-L54
Adding New Settings
Section titled “Adding New Settings”To add a new configuration option:
- Add the key and default value to
DEFAULT_CONFIGinconfig_manager.gd - Create UI controls in the appropriate settings tab in
mod_main._build_settings_menu() - Connect the UI control’s signal to a callback that calls
config.set_value() - Consume the setting in the relevant manager or component via
config.get_value() - If the setting requires a restart, add it to
_restart_original_valuesand call_check_restart_required()
Sources: extensions/scripts/utilities/config_manager.gd L12-L54