Table of Contents

Class ModManager

Namespace
GrindFest
Assembly
GrindFest.dll

Central mod manager. Handles discovery, deployment, and hot-reload of all mod types.

Currently supports:

  • Ink Story mods (.ink files → runtime compilation → world regeneration)
  • UI mods (JavaScript/TypeScript → OneJS ScriptEngine eval)

Future:

  • Prefab mods (Addressable prefab overrides)
  • Script mods (C# bot scripts)

Folder structure: persistentDataPath/Mods/GrindFest/Story/ — base story mod (smart-copied from StreamingAssets) persistentDataPath/Mods/[ModName]/Story/ — additional story mods persistentDataPath/Mods/[ModName]/UI/dist/index.js — UI mod entry point (eval'd after app.js) persistentDataPath/Mods/[ModName]/Prefabs/ — (future) prefab overrides persistentDataPath/Mods/[ModName]/Scripts/ — (future) script mods

In Editor, can optionally use Assets/_GrindFest/Story/ directly (toggle via UseEditorStoryFiles).

[DefaultExecutionOrder(-50)]
public class ModManager : Singleton<ModManager>
Inheritance
object
ModManager
Inherited Members

Fields

HotReloadEnabled
Mods
ReopenModBrowserAfterReload

Re-discover all mods and trigger a full UI reload via Runner. Call this after subscribing/unsubscribing to workshop mods. Sets GrindFest.ModManager._uiModDirty so Runner.Reload() happens safely on the next frame (avoids destroying the JS engine while JS code is still on the call stack).

UIModHotReloadEnabled
UIModsEnabled
UseEditorStoryFiles

Properties

ActiveStoryDirectory

The active story directory used for compilation. In Editor with UseEditorStoryFiles=true: Assets/_GrindFest/Story/ Otherwise: persistentDataPath/Mods/GrindFest/Story/

BaseModStoryDirectory

Base mod directory: persistentDataPath/Mods/GrindFest/Story/

EditorStoryDirectory

Editor source: Assets/_GrindFest/Story/

LoadedUIMods

Discovered UI mods: modName → full path to index.js

ModsRootDirectory

Root mods directory: persistentDataPath/Mods/

StreamingAssetsStoryDirectory

StreamingAssets story source: StreamingAssets/Mods/GrindFest/Story/

TypingsDirectory

Shared typings directory: persistentDataPath/typings/ (sibling to Mods/)

Methods

CompileStory()

Compile Story.ink from the active directory (with mod injection) and return a Story object. Returns null on compilation failure.

DeployBaseStoryMod()

Deploy base .ink files to Mods/GrindFest/Story/ (persistentDataPath). Uses hash-based detection to avoid overwriting player-modified files. In editor: copies from Assets/_GrindFest/Story/ directly (.ink files). In builds: copies from StreamingAssets/Story/ (.inkdata files, renamed to .ink). StoryBuildPreprocessor uses .inkdata extension to avoid Ink editor auto-compilation.

DeployStoryToModsFolder()

Copy .ink files from Assets/_GrindFest/Story/ to persistentDataPath/Mods/GrindFest/Story/. Use this to test the mod pipeline: toggle UseEditorStoryFiles off, then edit files in the Mods folder.

DiscoverMods()

Discover all mods from local Mods/ folder and Steam Workshop. Populates the Mods list with ModDefinitions. Local mods take priority (if same Name exists in both).

GetAllModPaths()

Get all mod folder paths (local + Workshop). Used by JS-side loadUIMods to find UI/dist/index.js files.

RecompileStoryAndReload()

Recompile ink and reload the story + world.

RefreshAndReload()

Events

OnCompilationError

Fired when compilation fails. Listeners receive the error message.

OnStoryRecompiled

Fired when story is recompiled from .ink sources. Listeners receive the compiled Story object.

OnUIModError

Fired when a UI mod fails to load. Listeners receive (modName, error).

OnUIModLoaded

Fired when a UI mod is loaded. Listeners receive (modName, modPath).