DolfeMods-MultiplayerUtil icon

MultiplayerUtil

THIS MOD DOES NOT ADD MULTIPLAYER. It adds useful utilities for multiplayer mods to use.

Last updated 3 weeks ago
Total downloads 2505
Total rating 1 
Categories Libraries
Dependency string DolfeMods-MultiplayerUtil-1.5.4
Dependants 0 other packages depend on this package

This mod requires the following mods to function

BepInEx-BepInExPack-5.4.2304 icon
BepInEx-BepInExPack

BepInEx pack for Mono Unity games. Preconfigured and ready to use.

Preferred version: 5.4.2304

README

ULTRAKILL Multiplayer Utility

Author: Dolfe

ULTRAKILL Multiplayer Utility is a lightweight, Steam-based peer-to-peer (P2P) utility library for creating multiplayer features in ULTRAKILL mods using BepInEx. It provides a high-level interface for lobby creation, network messaging, data synchronization, and designed to reduce boilerplate and the pain of setting up steamworks.


Table of Contents


Features

  • Lightweight P2P communication built on Steam networking.
  • Easy-to-use data sending (reliable, unreliable, etc.).
  • Lobby creation, search, join, leave, and chat utils.
  • Automatic serialization and deserialization of data.
  • Custom type synchronization and event based observation.
  • Optional support for using steam 480 (for testing), or mods.
  • All LobbyManager methods are documented

TODO

Set lobby settings method
Add documentation for current_lobby


Getting Started

Prerequisites

  • ULTRAKILL installed via Steam.
  • BepInEx (x64) installed and functioning.
  • Your project or mod should reference MultiplayerUtil.dll.

Installation

  1. Place MultiplayerUtil.dll in the BepInEx/plugins/ directory.
  2. Ensure that any mod using this utility declares it as a dependency.
  3. Hook into MultiplayerUtil.Callbacks.StartupComplete before invoking any Steam functionality.

Lobby Management

You can easily manage Steam lobbies via static methods under MultiplayerUtil.LobbyManager:

// Create a new public lobby for 4 players
MU.LobbyManager.CreateLobby(
    lobbyName: "New lobby",
    maxPlayers: 4,
    publicLobby: true,
    cracked: false,
    mods: false,
    modIdentifier: ("YourMod", "Tag")
);
// Search for existing lobbies using your identifier
var lobbies = await LobbyManager.FetchLobbies(("YourMod", "Tag"));
// Join a lobby by its ulong ID
LobbyManager.JoinLobbyWithID(lobbyId);
// Disconnect from current lobby
LobbyManager.Disconnect();

Data Transmission

Sending Data

MyClass exampleData = new MyClass();
exampleData.playerPos = ...;
LobbyManager.SendData(exampleData, SendMethod.UnreliableNoDelay);
// Make sure your class is System.Serializable

Available send methods:

  • Unreliable Fast but no guarantee of delivery or order, Ok at what it does
  • UnreliableNoDelay Very fast, no delay, no guarantee of it arriving or being in order, Good for fast changing data such as player positions
  • Reliable Guaranteed delivery, but not necessarily ordered, Good for one time updates
  • ReliableWithBuffering Reliable and ensures they are sent in the right order, Good for bulk data sending

You can also:

LobbyManager.SendToLobbyOwner(data, SendMethod.Reliable);

Receiving Data

To observe incoming data:

ObserveManager.SubscribeToType(typeof(MyClass), out Callbacks.SenderUnityEvent myEvent);
myEvent.AddListener(payload =>
{
    var obj = Data.Deserialize<MyClass>(payload.Item1);
    var sender = payload.Item2;
});

Callbacks & Events

Hook into a range of events:

  • Callbacks.StartupComplete
  • Callbacks.TimeToSendImportantData
  • Callbacks.TimeToSendUnimportantData
  • Callbacks.OnLobbyMemberJoined
  • Callbacks.OnLobbyMemberLeave
  • Callbacks.OnChatMessageReceived
  • Callbacks.OnLobbyCreated
  • Callbacks.OnLobbyEntered
  • Callbacks.OnP2PConnectionFailed

Example:

Callbacks.OnChatMessageReceived.AddListener(msg => Debug.Log($"Chat: {msg}"));

Best Practices

  • Use UnreliableNoDelay for real-time data (e.g., positions).
  • Use ReliableWithBuffering for sequential state or synced actions.
  • Make sure the classes that contain the data you are sending are serialized
  • Keep serialized classes small and avoid large strings.
  • Use primitives (e.g., byte, short) when possible to reduce size.
  • Catch exceptions around network operations to avoid crashes.

Ideas Or additions

Just message me on discord (@dolfelive) or create a issue/pull request


Attribution

Wifi symbol in icon from wifi by Baboon designs from https://thenounproject.com/browse/icons/term/wifi/ Noun Project (CC BY 3.0)

License

Dolfe AGPLish License Refer to LICENSE.md