Mastodon Politics, Power, and Science: Huge Refactor on my Campaign Manager.

Thursday, December 18, 2025

Huge Refactor on my Campaign Manager.

 For the last two weeks, I've been building the Codex Engine, a procedural VTT. The architecture was standard: a database with tables for mapsmarkersnpcs, and settings, with a Pygame frontend to render it all. It worked, but it was brittle. Adding a new feature meant changing schemas, writing new DB functions, and wiring up new UI.

Today, I threw that all away. I replaced the entire relational backend with a single, recursive table: a Unified Node Registry.

This wasn't a bug fix; it was a fundamental pivot. And the effect was transformative.

The Old Way: A Collection of Silos

Previously, the app was a collection of specialized parts. The CampaignMenu knew how to query the campaigns table. The GeoController knew how to query the vectors and markers tables. The SettingsEditor had hardcoded logic for managing a list of AI providers.

If I wanted to add a "Weather" system, I would have to:

  1. Add a weather table to the database.

  2. Add get_weather() and update_weather() to my DBManager.

  3. Write a new UI panel with hardcoded labels for "Wind Speed" and "Rain Chance".

This is the standard, brittle way we build software. The logic is spread everywhere, and the code is tightly coupled to the data.

The New Way: The World as a Graph

The new architecture is built on a single, powerful premise: everything in the world is a node in a tree.

My database now has one important table: registry.

SQL
CREATE TABLE registry (
    id INTEGER PRIMARY KEY,
    parent_id INTEGER,  -- The link that builds the tree
    type TEXT,          -- What is this? A 'map', a 'character', a 'setting'?
    name TEXT,          -- The human-readable name
    properties TEXT     -- A JSON blob holding all the data (HP, file path, port number)
);

A Campaign is a node. A World Map is a child of a Campaign. A Marker is a child of a Map. An NPC is a child of a Marker. Critically, an AI Provider Setting is just another node, a child of the AI Registry, which itself is a child of the global System Settings node.

The Payoff: UI That Builds Itself

This is where the magic happened. I refactored my UnifiedSettingsEditor. It no longer has hardcoded tabs for "Server" or "AI". Instead, its logic is simple:

  1. When opened, it's given a "root" node ID (e.g., the "System Settings" node).

  2. It calls db.get_children() on that root.

  3. For every child node it finds, it creates a new tab using the child's name.

  4. When a tab is clicked, it inspects that node's properties JSON blob and dynamically generates an editable input field for every key-value pair it finds.

The result is pure automation. I define the structure of my settings once in a config.json seed file. The bootstrap process translates that JSON into a tree of nodes in the database. From that moment on, the UI discovers the hierarchy and builds itself entirely from the data it finds.

Effortless Extensibility

This is the real victory. To add a new "Weather Engine" settings panel to my app, I no longer write a single line of Python.

I just add this to my config.json:

JSON
{
    "type": "weather_config",
    "name": "Weather Engine",
    "properties": { 
        "simulation_speed": 1.5, 
        "enable_rain": true 
    }
}

I run the app. The bootstrap creates the node. I open the settings menu, and a new "Weather Engine" tab appears, complete with editable fields for speed and rain. The rest of the program can now query for this node (db.find_node('weather_config')) and use its properties to drive simulations.

A Decoupled Platform

By making the database a self-describing graph, I've decoupled the World State from the Renderer.

  • Frontends (Web/Mobile): A web-based character sheet doesn't need to know about Pygame. It just needs to ask the database for the children of a character node and a way to update their properties.

  • Backends (AI/Importers): An AI that processes session transcripts can add new lore nodes to the graph without the main application even being aware of it. The new lore will simply appear the next time the relevant map is rendered.

I stopped building features and started building a system. The database is no longer just for storage; it is the operating system of the world. And the applications—whether Pygame, web, or AI—are just clients that read from and write to it.

No comments:

Post a Comment

It is mathematically possible for Democrats to gain a majority before the midterms.

It is mathematically possible for Democrats to gain significant power or even take a technical "majority" if enough Republicans re...