Skip to content

Configuration System

Relevant source files

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.


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

mod_main.gd L33-L96


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.

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

mod_main.gd L12-L89

MethodSignatureDescription
_init()func _init() -> voidInitializes _config with defaults, then calls load_config()
load_config()func load_config() -> voidReads JSON file, merges with defaults, preserves extra keys
save_config()func save_config() -> voidWrites _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) -> voidUpdates _config[key] and immediately calls save_config()
get_all()func get_all() -> DictionaryReturns a duplicate of the entire config dictionary
reset_to_defaults()func reset_to_defaults() -> voidDeletes user file, resets _config to DEFAULT_CONFIG

Sources: extensions/scripts/utilities/config_manager.gd L58-L133


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

  1. Tier 1 - User Configuration: If the key exists in the in-memory _config dictionary (loaded from user://tajs_mod_config.json), return that value
  2. Tier 2 - Method Override: If a default_override parameter was provided to get_value(), return that
  3. Tier 3 - Default Configuration: If the key exists in DEFAULT_CONFIG, return the hardcoded default
  4. 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


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.

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

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

When load_config() runs, it performs smart merging to handle version updates:

  1. Iterate through all keys in DEFAULT_CONFIG and add them to _config if missing from the user file
  2. Preserve any extra keys from the user file that aren’t in defaults (e.g., wire_colors_hex custom data)
  3. 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


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


The DEFAULT_CONFIG dictionary defines 40+ configuration keys organized into logical categories. Each category corresponds to a tab in the Settings UI.

KeyTypeDefaultDescription
node_limitint400Maximum nodes allowed (-1 for unlimited)
select_all_enabledbooltrueEnable Ctrl+A to select all nodes
command_palette_enabledbooltrueEnable MMB command palette
wire_drop_menu_enabledbooltrueShow quick-add menu on wire drop
right_click_clear_enabledbooltrueRight-click output slots to disconnect
goto_group_enabledbooltrueShow “Go To Group” button
buy_max_enabledbooltrueShow “Buy Max” button in upgrades
z_order_fix_enabledbooltrueFix z-order of nested groups
disable_slider_scrollboolfalseBlock scroll wheel on sliders
six_input_containersbooltrueAllow 6-input containers (requires restart)
upgrade_multiplierint10Ctrl+click upgrade multiplier

Sources: extensions/scripts/utilities/config_manager.gd L12-L36

KeyTypeDefaultDescription
extra_glowboolfalseEnable enhanced glow effects
glow_intensityfloat2.0Glow brightness multiplier
glow_strengthfloat1.3Glow spread strength
glow_bloomfloat0.2Bloom effect amount
glow_sensitivityfloat0.8HDR threshold sensitivity
ui_opacityfloat100.0UI transparency (50-100%)
custom_wire_colorsbooltrueEnable custom wire colors
wire_colors_hexDictionary{}Custom wire colors by resource ID

Sources: extensions/scripts/utilities/config_manager.gd L36-L42

KeyTypeDefaultDescription
screenshot_qualityint2JPEG quality (0=Low, 1=Med, 2=High)
screenshot_watermarkbooltrueAdd “Taj’s Mod” watermark
screenshot_folderString"user://screenshots"Output directory path

Sources: extensions/scripts/utilities/config_manager.gd L14-L16

KeyTypeDefaultDescription
mute_on_focus_lossbooltrueReduce volume when window loses focus
background_volumefloat0.0Volume percentage when unfocused (0-100)

Sources: extensions/scripts/utilities/config_manager.gd L29-L31

KeyTypeDefaultDescription
highlight_disconnected_enabledbooltrueHighlight unconnected nodes
highlight_disconnected_styleString"pulse"Style: “pulse” or “outline”
highlight_disconnected_intensityfloat0.5Effect intensity (0.0-1.0)
highlight_disconnected_debugboolfalseEnable debug logging

Sources: extensions/scripts/utilities/config_manager.gd L45-L49

KeyTypeDefaultDescription
custom_boot_screenbooltrueShow custom boot screen (requires restart)
debug_modeboolfalseEnable verbose debug logging
disable_controller_inputboolfalseBlock all controller inputs

Sources: extensions/scripts/utilities/config_manager.gd L52-L53


Components integrate with the configuration system through several patterns:

Early initialization components read configuration directly during mod_main._init():

Sources: mod_main.gd L88-L96

Feature managers receive the config instance via a setup() method:

Sources: mod_main.gd L104-L418

The Settings UI registers callbacks that call config.set_value() and apply changes immediately:

Sources: mod_main.gd L467-L497

Command palette toggles modify config and sync UI state:

Sources: mod_main.gd L1150-L1154

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


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

To add a new configuration option:

  1. Add the key and default value to DEFAULT_CONFIG in config_manager.gd
  2. Create UI controls in the appropriate settings tab in mod_main._build_settings_menu()
  3. Connect the UI control’s signal to a callback that calls config.set_value()
  4. Consume the setting in the relevant manager or component via config.get_value()
  5. If the setting requires a restart, add it to _restart_original_values and call _check_restart_required()

Sources: extensions/scripts/utilities/config_manager.gd L12-L54

mod_main.gd L462-L688