Skip to content

Why Stratum Is a Fork

Tsu edited this page Jun 1, 2026 · 1 revision

This page covers why Stratum ships as a forked runtime instead of a normal server mod or a Harmony-patched mod.

Source of Truth

  • Launcher and bootstrap: StratumServer/Program.cs, StratumServer/VanillaBootstrap.cs, StratumServer/EmbeddedOverlay.cs
  • Stratum runtime and patch code: sources/VintagestoryLib/Vintagestory.Server/, patches/
  • Repository bootstrap and release flow: scripts/bootstrap.ps1, scripts/release-full.ps1

The Mod Boundary

Vintage Story server mods are loaded by ModLoader after the game assemblies are already in memory and after ServerMain has started running. From that point a mod can:

  • register block/item/entity classes, behaviors, recipes, and assets,
  • subscribe to events exposed on ICoreServerAPI,
  • replace certain registered implementations through the public API.

What a mod cannot do from inside that boundary:

  • change types and method bodies that the API never exposes (most of Vintagestory.Server, Vintagestory.Client.NoObf, network packet serializers, chunk pipeline),
  • run code before the game's own startup path (process launch, native search paths, asset folder layout, ServerMain.Start itself),
  • alter wire-level packet structs or their serializers,
  • swap assemblies that the runtime has already loaded.

Stratum has changes in every one of those categories, which is why it lives outside the mod API.

Why Not Harmony

Harmony rewrites IL at runtime by patching method bodies. It works well for hooking individual methods, but it does not cover Stratum's needs for several concrete reasons.

1. Field, type, and signature changes

Several Stratum hooks add or change fields, types, and method signatures on internal classes. Harmony patches do not introduce new fields or change method signatures; they replace method bodies. The kinds of changes in patches/VintagestoryLib/Vintagestory.Server/ include:

  • new methods and properties on ServerMain and ServerSystem subclasses,
  • new branches inside ServerMain startup that call into StratumRuntime,
  • new packet drain back-pressure inside the connection loop,
  • new internal types under Vintagestory.Server that other patched code references directly (StratumPacketLimiter, StratumPacketBackPressure, StratumBlockBreakGuard, StratumRuntime, etc.).

2. Logic that has to run during configuration, not after

ServerSystemStratum.OnBeginConfiguration runs in the server's configuration phase, before mods are even discovered. Two examples from that method:

  • Loading stratum.json (so packet limits, back-pressure, and block-break guards are armed for the very first tick).
  • Raising the Windows multimedia timer resolution so Thread.Sleep is accurate to ~1 ms instead of ~15.6 ms; without this, the server's Config.TickTime - elapsed sleep rounds up to the next scheduler tick and caps the achievable tickrate at ~25 tps on Windows.
// sources/VintagestoryLib/Vintagestory.Server/ServerSystemStratum.cs
public override void OnBeginConfiguration()
{
    bool loaded = StratumRuntime.LoadOrCreateConfig(server, out string message);
    ...
    StratumTimerResolutionConfig timerCfg = StratumRuntime.Config.Performance.TimerResolution;
    ...
}

A Harmony mod cannot install itself early enough to participate in that phase, because the mod loader only runs it later.

3. Identity that other mods can read

ServerSystemStratum.OnBeginRunGame writes Stratum identity into World.Config so any third-party mod can detect Stratum without an assembly reference:

server.World.Config.SetBool(StratumInfo.Id, true);
server.World.Config.SetString(StratumInfo.Id + "Version", StratumInfo.Version);
server.World.Config.SetString(StratumInfo.Id + "BaseGameVersion", StratumInfo.BaseGameVersion);

This works because the values are written from inside VintagestoryLib, in the server's own startup path, before mod Start runs. A Harmony mod could only set those keys after itself loaded, so a mod that loaded earlier could miss them.

4. Cross-mod ordering and reliability

Harmony patches are applied in load order and can collide silently when two mods patch the same method. Stratum's changes live in the patched DLLs themselves, so:

  • the shipped server already contains the change before any mod runs,
  • there is no patch resolution step at runtime that can fail or be reordered,
  • crash dumps point at real source lines under Vintagestory.Server, not at generated transpiler IL.

Practical Differences

Mod approach

  • Loaded by ModLoader after the runtime is up.
  • Limited to public API surface and the mod lifecycle.
  • Optional at runtime.
  • Patches via Harmony are method-body rewrites; no new fields, no changed signatures.

Fork approach (Stratum)

  • Ships modified VintagestoryLib.dll and VintagestoryAPI.dll in the install.
  • Can change startup, configuration, and runtime wiring.
  • Can add types, fields, and methods to existing classes.
  • Carries code that must exist before mod load.

Why Stratum Uses the Fork Model

Stratum touches startup, packet pipeline, chunk I/O, entity simulation, identity stamping, and tick scheduling. Those are not exposed through the mod API and are not safely expressible as Harmony patches. Shipping patched assemblies plus the launcher is the smallest mechanism that covers all of them and stays buildable from the open-source forks and decompiled baseline.

Related Pages

Clone this wiki locally