ModNet

v0.1.3·Updated 2026-10-07

Library for multiplayer mods: modded players exchange messages through the game's own network, with a handshake that lists each player's mods and versions. Other mods use it for shared emotes, models

About this mod Author’s original text

ModNet

Lets mods send messages to the other modded players in a multiplayer game, through the game's own network. Other

mods use it to share what only they know about, such as a player's emote or custom model, and to check that

everyone has the same mod version.

ModNet is a library. On its own it does nothing you can see in play. Every player who wants a mod's shared

features needs ModNet and that mod.

  • Hello handshake. Each modded player announces their installed mods and versions when they join.
  • Players card. With Mods Menu installed, Options → Mods has a

ModNet card listing who runs which mods, with version differences highlighted.

A game where some players don't have ModNet hasn't been tested yet.

Settings

| Setting | Default | |

|---|---|---|

| Enabled | on | Exchange messages with other modded players. Off: mods behave as if nobody else had them |

| Log Traffic | off | Log every message sent and received (turn on when reporting a multiplayer problem) |

| Test Tools | off | Ping and payload-size test buttons on the ModNet card |

The file is BepInEx\config\com.helvetica.modnet.cfg.

How it works

Each message is a string passed to the game's replicated Root.SetAnimationTrigger(Character, string). The host

relays it to every client. On a modded player, a Harmony prefix catches the string before it reaches the

Animator.

For mod developers

  • Add a soft dependency, so your mod still loads without ModNet:

[BepInDependency("com.helvetica.modnet", BepInDependency.DependencyFlags.SoftDependency)]

  • Reference ModNet.dll with Private="false", so it isn't copied next to your mod.
  • Put every ModNet call in one nested class, and only call into it after checking that ModNet is installed: the

runtime loads ModNet's types only when that class's code runs.

internal static class MySync

{

static bool _available;

internal static void Init() { _available = true; Bridge.Hook(); } // from OnModLoaded, if installed

internal static void Tell(Character c, string what) { if (_available) Bridge.Send(c, what); }

static class Bridge

{

internal static void Send(Character c, string p) => ModNetApi.Send("mymod", p, c);

internal static void Hook()

{

ModNetApi.Register("mymod", m => Handle(m.Character, m.Payload));

ModNetApi.PlayerHello += _ => ResendState(); // late joiners

}

}

}

// OnModLoaded: if (Chainloader.PluginInfos.ContainsKey("com.helvetica.modnet")) MySync.Init();

API (ModNetApi)

| Member | |

|---|---|

| Send(channel, payload, subject) | To every other modded player, not to yourself. subject = one of your characters; null = any. Returns false if not sent (true when queued) |

| Register(channel, handler) | NetMessage: Channel, Payload, Character (the subject), SenderOwnerId, Sender |

| Ready, IsMultiplayer, MyOwnerId | Sending starts about 3 s after your characters appear in the world |

| BecameReady | Raised once per session when sending starts |

| PlayerHello | Raised when a modded player is first heard from in a session. Re-send your state here |

| PlayerLeft | Raised when a player leaves |

| Players, GetPlayer(ownerId) | PlayerInfo: Name, IsMe, HasModNet, SteamId, Mods (GUID → version), Has(guid, version) |

| EveryoneHas(guid, version) | Gate for features that need every player to have the mod |

Rules

  • Events only. Send events, never per-frame data.
  • Size and rate. Payloads up to 1000 characters. Sending is throttled to 10 per second, with bursts of 20.
  • Sending from a handler is fine. A message sent while another one is being received (from a handler, or from

PlayerHello) is queued and goes out on the next frame.

  • Separator. Use | inside payloads. Channel names can't contain it.
  • Don't trust the sender. A message's Character is the sender's own character. Ignore messages that would

change your own characters.

  • Protocol version. ModNetApi.Protocol is part of the wire marker. Players on another protocol version ignore

each other.

Install & use Install: follow the bundled instructions

  1. Unzip the archive from playbuff and read the bundled readme / instructions first.
  2. Most mods rely on the game's mod loader — the usual route is a community mod manager (such as r2modman): pick this game, install, and it handles the loader and dependencies.
  3. For a manual install, put the mod files into the matching Mod / plugins folder inside the game directory.
  4. Launch the game to confirm it loaded; mods with listed dependencies need those installed as well.

Install locations vary a lot between mods — the bundled readme is the most reliable guide.

Dependencies

Install these first, or the mod will not work:

BepInEx-BepInExPackStolenRealmModding-StolenRealmModAPI

File & checksum

Filename
ModNet-0.1.3.zip
File size
24.2 KiB