Writing Mods
The Gnosis Engine features a data-driven, lifecycle-aware modding system that allows for extensive customization through state patching, asset overrides, and Lua scripting.
Mod Structure
All mods must reside in Application.persistentDataPath/Mods/{modId}/.
Mods/{modId}/
├── manifest.json
├── Scripts/ # Logic (.lua)
├── Assets/ # Loose files (.png, .wav, .ogg)
└── Data/ # State and Configuration
├── persistent.json # Global state patches
├── ephemeral.json # Run-start state patches
└── Configuration/ # Custom registry foldersManifest (manifest.json)
Defines the mod’s identity, version, and loading priority.
{
"modId": "com.dev.vampire",
"name": "Vampire Mod",
"description": "Adds life-steal mechanics.",
"version": "1.0.0",
"author": "Dracula",
"loadPriority": 5,
"dependencies": []
}Data Layer
State Patching
persistent.json: Deep-merged once into thePersistentstate branch during engine initialization.ephemeral.json: Deep-merged into theEphemeralbranch at the start of every new run.
Configuration
Use Data/Configuration/configuration.json to define how the engine should process custom data folders. Supported kinds include indexed (individual files), domains (merged registries), and object (single file).
Assets Layer
Any file placed in Assets/ is automatically registered with a global ID (the filename without extension).
- Images (.png, .jpg) ->
Sprite - Audio (.wav, .mp3, .ogg) ->
AudioClip
If a mod asset matches an existing ID, it overwrites the previous one (higher loadPriority wins).
Logic Layer (Lua)
Every mod must have a Scripts/main.lua. Mods run in an isolated Lua sandbox and can communicate with the engine via the Gnosis bridge object.
Bridge API
| Method | Description |
|---|---|
Subscribe(id, callback) | Listen for engine events (Facts/Requests). |
Publish(id, data) | Trigger an engine event. |
Call(svc, fn, params) | Call any Gnosis Service function. |
Get(path) | Read from the Gnosis State Tree. |
Set(path, value) | Write to the Gnosis State Tree. |
GetAsset(assetId) | Resolve a Sprite or AudioClip ID. |
Example: Life Steal Script
-- Subscribe to damage events
Gnosis.Subscribe("FACT_DAMAGE_DEALT", function(data)
local damage = data.amount
local healAmount = damage * 0.1
-- Call the ephemeral Heal function on the Player
Gnosis.Call("EphemeralMod.Vampire", "Heal", { amount = healAmount })
end)