DataCatalyst 0.1.0

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package DataCatalyst --version 0.1.0
                    
NuGet\Install-Package DataCatalyst -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DataCatalyst" Version="0.1.0">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DataCatalyst" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="DataCatalyst">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add DataCatalyst --version 0.1.0
                    
#r "nuget: DataCatalyst, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package DataCatalyst@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=DataCatalyst&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=DataCatalyst&version=0.1.0
                    
Install as a Cake Tool

DataCatalyst

NuGet Version CI Status License

Game modeling framework for C#/.NET.


Code itself has no game specific content. Game logic, behaviors, values, etc... should never be hardcoded. Designers parameterize everything to model the world.


High-Level Overview

graph TD
    WORLD[Game World]

    WORLD --> CONCEPTS[Concepts]
    WORLD --> ASPECTS[Aspects]

    CONCEPTS --> BEINGS[Beings]
    ASPECTS --> BEINGS

    BEINGS --> KNOWLEDGE[Knowledge Base]

    KNOWLEDGE --> CONSUMER[Materializers / Plugins]

    CONSUMER --> RUNTIME[Unity / Godot / ECS / Simulation]

🧬 Core Idea

Everything in DataCatalyst is built from three primitives: Aspect, Being, and Concept (the ABC model).

The ABC Model

graph TD
    Concept1[Concept A] --> Being((Being))
    Concept2[Concept B] --> Being
    Being --> Aspect1[Aspect X]
    Being --> Aspect2[Aspect Y]
    Being --> Aspect3[Aspect Z]
  • Aspect: An aspect of a being (e.g., Health, CombatStats). It defines a specific facet of data.
  • Being: A being that exists in the game world (e.g., Goblin, Arthur).
  • Concept: A concept that defines the nature or identity of a being (e.g., Creature, Enemy, Hero).

Orthogonality

For example, the being Goblin belongs to 2 Concepts (Creature, Enemy) and has 5 Aspects (Health, CombatStats, PatrolRadius, Stamina, Mana). Since Stamina and Mana are being-level aspects, they do not belong to the concept definitions but are still possessed by the being. Connecting these coordinate points on the XY axes reveals the closed geometric shape of the Goblin being:

Being Orthogonality

Mathematical Model

Mathematically, the game design database is a space defined by two orthogonal axes:

  • Concept Axis ($C$): The space of Concepts. A Being $B$ must map to at least one Concept ($|Concepts(B)| \ge 1$).
  • Aspect Axis ($A$): The space of Aspects. Aspects are free-floating and can belong to a Being directly or connect to a Concept.

A Being $B_i$ is a coordinate point in the Cartesian product of the Concept power set and Aspect power set:

B_i = (C_{B_i}, A_{B_i}) \quad \text{where} \quad C_{B_i} \subseteq C, \ A_{B_i} \subseteq A

🚀 Quick Start

1. Install

dotnet add package DataCatalyst
dotnet add package DataCatalyst.Loaders.Json

2. Write Data

Data/Creatures.json:

{
	"Goblin": {
		"$Creature": {
			"Health": { "Initial": 40, "Max": 40 },
			"CombatStats": { "BaseDamage": 6, "BaseDefense": 3 }
		},
		"$Enemy": {}
	}
}

3. Declare Concepts & Aspects

[GameConcept]
public record struct Creature : IConcept;

[GameConcept]
public record struct Enemy : IConcept;

[GameAspect]
public record struct Health { public int Initial; public int Max; }

[GameAspect]
public record struct CombatStats { public int BaseDamage; public int BaseDefense; }

4. Load, Build & Query

// Simple fluent API, mix & match your source
Knowledge knowledge = new Pipeline()
    .AddSource("Base", new JsonDataLoader(), "Data/")
    .Build(out var diagnostics);

// Access - type-safe and compile-time checked
int hp  = knowledge.Of<Creature>().At<Goblin>().Take<Health>().Initial;
int atk = knowledge.Of<Enemy>().At<Goblin>().Take<CombatStats>().BaseDamage;

Goblin is a generated being marker type implementing IBelongTo<Creature>, IBelongTo<Enemy>.


🏗️ Architecture

DataCatalyst processes your design GDD database through a statically resolved compilation pipeline, converting raw files into highly optimized flat memory layouts.

graph TD
    JSON[Raw JSON Files] --> LOADER[IDataLoader]
    LOADER --> PIPELINE[Pipeline]
    PIPELINE -->|1. Merge & Override| MERGE[Resolved Beings]
    MERGE -->|2. Inherit Prototypes| INHERIT[Inherited Aspects]
    INHERIT -->|3. Cross-Refs $ref| REFS[Linked Graph]
    REFS -->|4. Build Pools| KNOWLEDGE[Knowledge Base]
    KNOWLEDGE --> VIEW[Type-Safe Views]
    KNOWLEDGE --> MATERIALIZER[IMaterializer]
    MATERIALIZER --> RUNTIME[Unity / Godot / ECS / Custom Engine]

🧩 Usage

The framework workflow is divided into four main phases: Model, Compose, Access, and Integrate.


1. Model

Define your concepts, aspects, and beings to map out the structure of your game.

Concept

A Concept represents semantic classification. It is a marker type defined as a C# struct.

[GameConcept]
public record struct Creature : IConcept;
Aspect

An Aspect is a modular data struct attached to concepts or beings.

[GameAspect]
public record struct Health { public int Initial; public int Max; }

2. Compose

Leverage prototype inheritance and cross-references to assemble complex data profiles with minimal repetition.

Prototype Inheritance ($inherits / inherits)

Beings can inherit aspect values from another being. Unspecified fields in the child being fall back to the parent being's values.

{
	"BaseMonster": {
		"$Creature": {
			"Health": { "Initial": 100, "Max": 100 }
		}
	},
	"Goblin": {
		"$inherits": "BaseMonster",
		"$Creature": {
			"Health": { "Initial": 40 }
		}
	}
}

Result: Goblin overrides Health.Initial to 40, inheriting Health.Max as 100.

Cross-Reference ($ref)

You can reference other beings using the "$ref" key. The pipeline resolves these references at build time, replacing the reference object with the target being's key string.

{
	"Goblin": {
		"$Creature": {
			"InitialWeapon": { "WeaponId": { "$ref": "WoodenClub" } }
		}
	}
}

At runtime, InitialWeapon will be resolved to "WoodenClub".


3. Access

Query and traverse the compiled database using highly optimized, type-safe APIs.

Knowledge & Views

The final result of the pipeline is a Knowledge instance containing fast, flat-array storage pools.

// Direct lookup
var goblin = knowledge.Of<Creature>().At<Goblin>();
int maxHp = goblin.Take<Health>().Max;

// Concept-scoped view
var creatures = knowledge.Of<Creature>();
foreach (var record in BeingRegistry.All) {
    if (creatures.Has(record.BeingType)) {
        // Process creature beings
    }
}

4. Integrate

Bridge the engine-agnostic database to your specific game loader and engine objects.

Loader

Implement IDataLoader to support formats like CSV, YAML, MsgPack, etc.

public class CsvDataLoader : IDataLoader {
    public LoadResult Load(string content, string fallbackKey) {
        var result = new LoadResult();
        // Parse CSV string content -> RawBeing
        return result;
    }
    public LoadResult LoadFile(string path) => Load(File.ReadAllText(path), Path.GetFileNameWithoutExtension(path));
    public LoadResult LoadDirectory(string path) {
        var result = new LoadResult();
        foreach (var file in Directory.EnumerateFiles(path, "*.csv")) {
            result._beings.AddRange(LoadFile(file)._beings);
        }
        return result;
    }
}
Materializer

Bridge DataCatalyst's Knowledge to engine-specific game objects or entities. Define a pattern once, and SourceGen dispatches all aspects automatically.

[Materializer]
partial class EcsMaterializer : IMaterializer<Entity> {
    readonly Knowledge _k;
    void Apply<T>(Entity e, T c) where T : struct => _k.Add(e, c);
}

// Usage in Game Loop (Unity, Godot, ECS, etc.)
var mat = new EcsMaterializer(knowledge);
mat.Apply(entity, knowledge.Of<Creature>().At<Goblin>());

🔌 Bundled Plugin

StateEngine

StateEngine is a data-driven hierarchical FSM. FSM components (States, Sensors, and Transitions) are completely normalized into core ABC primitives, allowing you to modify complex behaviors and condition graphs purely via data declarations. Baking is integrated directly into the Core Pipeline, executing FSM compilation during database build.

graph TD
    JSON[Raw JSON Files] -->|1. Register StateEngineBaker| PIPELINE[Pipeline]
    PIPELINE -->|2. Build & Bake FSM| KNOWLEDGE[Knowledge Base]
    KNOWLEDGE -->|3. GetBaked BakedStateGroup| EVALUATOR[StateEngineEvaluator]
    EVALUATOR -->|4. Resolve Sensor Values| RUNTIME[Evaluate Current State]
Write State Data

Define states, sensors, and state groups as standard Being entities:

{
	"PlayerDistance": {
		"$Sensor": {}
	},
	"Chase": {
		"$State": {}
	},
	"Patrol": {
		"$State": {},
		"StateTransitions": {
			"Transitions": [
				{
					"TargetState": { "$ref": "Chase" },
					"Priority": 100,
					"Conditions": {
						"All": [
							{
								"Sensor": { "$ref": "PlayerDistance" },
								"Op": "<",
								"Value": 8.0
							}
						]
					}
				}
			]
		}
	},
	"GoblinAI": {
		"$GameState": {
			"StateGroup": {
				"DefaultState": { "$ref": "Patrol" },
				"States": [{ "$ref": "Patrol" }, { "$ref": "Chase" }],
				"PriorityTier": 0,
				"TierScale": 10000,
				"DepthPenalty": 1000
			}
		}
	}
}
Bake & Evaluate FSM

Register the baker in the pipeline and fetch the compiled graph directly from the knowledge base at runtime:

// 1. Build - Baker executes automatically during compilation
var knowledge = new Pipeline()
    .AddSource("Base", new JsonDataLoader(), "Data/")
    .AddBaker(new StateEngineBaker()) // Register the baker in the pipeline!
    .Build(out var diagnostics);

// 2. Retrieve - Get the pre-compiled FSM directly from Knowledge using Being type
var baked = knowledge.GetBaked<BakedStateGroup, GoblinAI>();

// 3. Evaluate - ONE evaluator engine for ALL entities
var result = StateEngineEvaluator.Evaluate(
    currentState, baked, viableStates,
    sensor => {
        if (sensor == typeof(PlayerDistance)) {
            return entity.DistanceToPlayer;
        }
        return 0f;
    }
);

📦 Packages

DataCatalyst is modular, letting you install only the components your project needs.

dotnet add package DataCatalyst                               # SourceGen + Core
dotnet add package DataCatalyst.Loaders.Json                  # JSON loader
dotnet add package DataCatalyst.Extensions                    # Compare, Composition, Materialization
dotnet add package DataCatalyst.Plugins.StateEngine
dotnet add package DataCatalyst.Plugins.StateEngine.SourceGen

SourceGen packages can be registered as analyzers in C# project files:

<PackageReference Include="DataCatalyst.SourceGen" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />

🛠️ Editor

A node graph editor is currently under development but will not be finished anytime soon.


⚖️ License

Distributed under the MIT License. See LICENSE

Star History Chart

There are no supported framework assets in this package.

Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1-alpha.0.4 53 6/27/2026
0.1.0 71 6/26/2026
0.1.0-alpha.2 61 6/26/2026
0.1.0-alpha.1 56 6/25/2026
0.0.1-alpha.9 56 6/22/2026
0.0.1-alpha.8 50 6/21/2026
0.0.1-alpha.7 52 6/21/2026
0.0.1-alpha.6 57 6/20/2026
0.0.1-alpha.5 54 6/20/2026
0.0.1-alpha.4 53 6/20/2026
0.0.1-alpha.3 67 6/18/2026
0.0.1-alpha.2 58 6/17/2026