Skip to content

ModRegistry

Kanisuko edited this page May 29, 2026 · 8 revisions

ModRegistry

Namespace: ScavLib.mods

A registry for mod metadata and optional lifecycle wiring. Register your mod so other mods and ScavLib tooling can discover it at runtime. As of v0.4.0, you can also attach an IModLifecycle object to receive automatic callbacks on world events. As of v0.5.0, each registration is backed by a ModSession that you can query at runtime.


Registering Your Mod

Basic Registration

Call ModRegistry.Register() in your plugin's Awake():

using ScavLib.mods;

ModRegistry.Register(new ModInfo(
    name:        "MyMod",
    version:     "1.0.0",
    description: "Does cool things.",
    author:      "YourName"
));

ScavLib registers itself automatically on load.

Registration with Lifecycle (v0.4.0+)

Pass an IModLifecycle implementation as the second argument. ScavLib will automatically wire its callbacks into the EventBus — you do not need to call EventBus.Register() manually for the lifecycle object.

OnEnabled() is called immediately upon successful registration.

using ScavLib.mods;
using ScavLib.event_bus.events;
using ScavLib.util;

public class MyLifecycle : ModLifecycleBase
{
    public override void OnEnabled()
    {
        ScavLibPlugin.Log.LogInfo("MyMod enabled.");
    }

    public override void OnWorldLoaded(WorldLoadedEvent e)
    {
        PlayerUtil.HealAll();
    }

    public override void OnLayerLoaded(LayerLoadedEvent e)
    {
        GameUtil.Log($"Entered layer {e.BiomeDepth}.");
    }
}

// In your plugin's Awake():
ModRegistry.Register(
    new ModInfo("MyMod", "1.0.0", "Does cool things.", "YourName"),
    new MyLifecycle()
);

See the Lifecycle System page for the full callback set.


ModInfo Fields

Field Type Description
Name string Display name of the mod.
Version string Version string, e.g. "1.0.0".
Description string Short description of what the mod does.
Author string Author name(s). Defaults to "Unknown" if omitted.
VersionedDependencies VersionedDependency[] Structured dependencies with optional version ranges.
Dependencies string[] Backward-compatible shim — returns dependency names only, derived from VersionedDependencies.

ModInfo.ToString() returns "{Name} v{Version} by {Author}".

Constructors

ModInfo provides several constructors that all chain to the most specific one, so older 0.4.x call sites keep compiling:

// No dependencies
new ModInfo("MyMod", "1.0.0", "desc");
new ModInfo("MyMod", "1.0.0", "desc", "Author");

// Legacy string-array dependencies (0.4.x compat)
new ModInfo("MyMod", "1.0.0", "desc", "Author",
    new[] { "ScavLib", "OtherMod" });

// Full versioned dependencies (0.5.0)
new ModInfo("MyMod", "1.0.0", "desc", "Author",
    new[] { new VersionedDependency("ScavLib", minVersion: "0.5.0") });

Declaring Dependencies

Dependencies are advisory only. A missing or version-mismatched dependency logs a LogWarning at registration time but never blocks your mod from loading. For actual load-order enforcement, use BepInEx's [BepInDependency] attribute (see Getting Started).

VersionedDependency (v0.5.0)

VersionedDependency adds optional MinVersion / MaxVersion bounds on top of a dependency name.

Member Type Description
Name string Dependency mod name.
MinVersion string Optional inclusive lower bound, e.g. "0.5.0".
MaxVersion string Optional inclusive upper bound.
IsSatisfiedBy(string actualVersion) bool True if actualVersion falls within the range.
// Require ScavLib 0.5.0 or newer
new VersionedDependency("ScavLib", minVersion: "0.5.0");

// Require a specific range
new VersionedDependency("OtherMod", "1.2.0", "1.9.9");

Version strings are parsed loosely: any - or + suffix (pre-release / build metadata) is stripped before comparison, and a bare "1" is treated as "1.0". If a version string cannot be parsed, the check is skipped (treated as satisfied) and a warning is logged rather than failing the registration.

VersionedDependency.ToString() renders the range for display:

  • name only → ScavLib
  • min only → ScavLib (>=0.5.0)
  • max only → ScavLib (<=1.9.9)
  • both → ScavLib (0.5.0~1.9.9)

Declared dependencies appear in scavlib status:

MyMod v1.0.0 by Author [F] Deps: [ScavLib (>=0.5.0), OtherMod]

Querying the Registry

Method Returns Description
GetAll() IReadOnlyList<ModInfo> All registered mods, in registration order.
TryFind(string name, out ModInfo info) bool Find a mod by name (case-insensitive). Returns the first match. O(1) lookup since 0.4.1.
IsRegistered(string name) bool Quick check whether a mod with the given name is registered. O(1) since 0.4.1.
HasLifecycle(ModInfo mod) bool true if the mod was registered with an IModLifecycle.
GetLifecycle(ModInfo mod) IModLifecycle The lifecycle object, or null if none was registered.
GetSession(string name) ModSession (0.5.0) The runtime session for a mod, or null if not registered.
// Check if a dependency is loaded before using its features
if (!ModRegistry.IsRegistered("SomeDependencyMod"))
{
    Logger.LogWarning("SomeDependencyMod is not installed. Some features disabled.");
    return;
}

// Enumerate all mods
foreach (var mod in ModRegistry.GetAll())
    GameUtil.Log(mod.ToString());

// Inspect a runtime session
var session = ModRegistry.GetSession("MyMod");
if (session != null)
    GameUtil.Log($"{session.Info.Name} enabled={session.IsEnabled} " +
                 $"hasLifecycle={session.Lifecycle != null}");

ModSession (v0.5.0)

Internally, 0.5.0 migrated the registry to a ModSession-keyed store. A ModSession is the runtime state of a registered mod and is returned by GetSession(name).

Member Type Description
Info ModInfo The ModInfo this session represents.
Lifecycle IModLifecycle The attached lifecycle object, or null.
IsEnabled bool Whether the mod is currently enabled. 0.5.0: always true. Toggling arrives in 0.5.1.

ModSession is a pure data structure in 0.5.0. The internal EventBus adapter handle is retained on the session so the planned 0.5.1 enable/disable flow can unregister cleanly, but no enable/disable operations are exposed yet.


The [F] Tag

In scavlib status output, mods registered with a lifecycle object are annotated with [F] (think "Functional / lifecycle integration"):

Registered Mods (2):
  MyMod v1.0.0 by YourName [F] Deps: [ScavLib]
  LegacyMod v2.0.0 by Someone

LegacyMod above was registered with the basic Register(ModInfo) overload and has no lifecycle — this is fully supported and backward compatible.


Duplicate Registration

If a mod with the same name is registered more than once, a warning is logged but both entries are kept in GetAll(). Only the first registration under a given name enters the name-lookup index, so TryFind() / GetSession() return that first one. Avoid registering the same mod name twice — dependency lookups would otherwise be ambiguous.

Clone this wiki locally