PEAKNetworkingLibrary
Network library for PEAK using Steam instead of PUN with offline compatiblity.
By DAa
| Date uploaded | 8 months ago |
| Version | 1.0.0 |
| Download link | DAa-PEAKNetworkingLibrary-1.0.0.zip |
| Downloads | 98 |
| Dependency string | DAa-PEAKNetworkingLibrary-1.0.0 |
This mod requires the following mods to function
BepInEx-BepInExPack_PEAK
BepInEx pack for PEAK. Preconfigured and ready to use.
Preferred version: 5.4.75301README
PEAKNetworkingLibrary v1.0.0: Release! 
Minimal, backend-agnostic networking for PEAK modders.
Works with the Steam adapter or the built-in Offline shim for testing.
Update Details & Plans & Features:
Update Details
- Released...
Plans
- Add chunked RPC transfer for very large payloads.
- Improve documentation.
Features [Not All]
-
Backend
INetworkingServiceprovides one surface mods use. Swap Steam vs Offline without code changes. -
Lobby key sync (host -> clients)
Host sets small authoritative strings viaSetLobbyData. Clients read withGetLobbyDataandLobbyDataChangedevent. -
RPC discovery & invocation
Discover methods marked[CustomRPC]withRegisterNetworkObjectand callRPC,RPCTarget, orRPCToHost. -
Message serialization
Messageclass supports: byte, int, uint, long, ulong, float, bool, string, byte[], Vector3, Quaternion, CSteamID. -
Reliable vs Unreliable
ReliableTypeenum supports Reliable, Unreliable, UnreliableNoDelay semantics. -
Security (optional)
Optional HMAC signing, per-mod signer hooks, sequence numbers, replay protection. -
Framing & priority
Per-message flags, msg-id, sequence, fragment metadata, priority queues. -
Offline shim for CI
Full in-process simulator to run tests without Steam. -
Incoming validation hook
IncomingValidatorlets consumers drop or accept messages before handler invocation. -
Poll-based receive loop
PollReceive()is required for Steam adapter; Offline shim is immediate.
API Refrences [Not All]
INetworkingService
- Initialize()
- Shutdown()
- CreateLobby(maxPlayers)
- JoinLobby(lobbySteamId64)
- LeaveLobby()
- RegisterLobbyDataKey(string key)
- SetLobbyData(string key, object value)
- T GetLobbyData<T>(string key)
- RegisterPlayerDataKey(string key)
- SetPlayerData(string key, object value)
- T GetPlayerData<T>(ulong steam64, string key)
- IDisposable RegisterNetworkObject(object instance, uint modId, int mask = 0)
- void DeregisterNetworkObject(object instance, uint modId, int mask = 0)
- void RPC(uint modId, string methodName, ReliableType reliable, params object[] parameters)
- void RPCTarget(uint modId, string methodName, ulong targetSteamId64, ReliableType reliable, params object[] parameters)
- void RPCToHost(uint modId, string methodName, ReliableType reliable, params object[] parameters)
- void PollReceive()
- Events: LobbyCreated, LobbyEntered, LobbyLeft, PlayerEntered(ulong), PlayerLeft(ulong),
LobbyDataChanged(string[] keys), PlayerDataChanged(ulong steam64, string[] keys)
- Func<Message, ulong, bool>? IncomingValidator { get; set; }
Examples [Not All]
All examples assume the networking service is already present (Steam or Offline). They show the smallest usable code for each feature.
1) Minimal host -> clients: Lobby key (recommended for package lists)
Host sets one string key. Clients read it on change.
Host: broadcast package list
// host only
void BroadcastLoadedPackages(INetworkingService svc, IEnumerable<string> packages)
{
const string KEY = "PEAK_PACKAGES_V1";
svc.RegisterLobbyDataKey(KEY); // safe to call on all peers
// serialize: escape '|' then join and compress+base64 option
string joined = string.Join("|", packages.Select(p => p.Replace("|","||")));
string payload = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(joined));
svc.SetLobbyData(KEY, payload); // host-only action
}
Client: receive update
void SubscribeToPackageUpdates(INetworkingService svc)
{
const string KEY = "PEAK_PACKAGES_V1";
svc.RegisterLobbyDataKey(KEY); // register the key used by host
svc.LobbyDataChanged += keys =>
{
if (!keys.Contains(KEY)) return;
var payload = svc.GetLobbyData<string>(KEY);
if (string.IsNullOrEmpty(payload)) return;
var joined = System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(payload));
var packages = joined.Length == 0 ? Array.Empty<string>() :
joined.Split('|').Select(s => s.Replace("||","|")).ToArray();
// now packages[] contains the host list
};
}
Notes:
- Lobby metadata is small and best for modest lists (tens of items).
- If payload grows large, compress it (gzip) before base64.
2) Minimal RPC broadcast (general notifications)
Use RPC when you need immediate notification or structured params.
Register and broadcast
const uint MOD = 0xDEADBEEF;
// on plugin init
IDisposable token = svc.RegisterNetworkObject(this, MOD);
// broadcast
svc.RPC(MOD, "NotifyPackages", ReliableType.Reliable, "GAME_PACKAGES_READY");
In same class: RPC handler
[CustomRPC]
void NotifyPackages(string tag)
{
// runs on all peers (including host by loopback)
Logger.LogInfo($"NotifyPackages received: {tag}");
}
Notes:
- Must call
PollReceive()each frame for Steam adapter. RegisterNetworkObjectdiscovers methods tagged[CustomRPC].
3) Targeted RPC to specific player
svc.RPCTarget(MOD, "PrivateMessage", targetSteamId64, ReliableType.Reliable, "hello");
Handler:
[CustomRPC]
void PrivateMessage(string text) { Debug.Log(text); }
4) IncomingValidator usage (drop unwanted messages)
svc.IncomingValidator = (msg, fromSteam64) =>
{
// drop messages with a specific method name
if (msg.MethodName == "DropMe") return false;
return true;
};
5) Offline shim for local tests
// Use this for unit tests or local dev when Steam not available.
INetworkingService svc = new OfflineNetworkingService();
svc.Initialize();
// Offline shim delivers messages immediately. PollReceive() is a no-op.
Efficiency guidance
- Lobby data: cheap for small text. Keep per-key payload < ~2–4 KB.
- RPC: use for immediate messages and structured params. Use Unreliable for high-rate telemetry.
- Compress large payloads (gzip) before base64. Or use chunked RPC transfer.
- HMAC/signing is optional. Enable when you need tamper detection.
Troubleshooting & tips
- Always call
PollReceive()inUpdate()when using Steam adapter. - Register lobby/player keys before calling
Get/Setto avoid warnings. - Use
RegisterNetworkObjectand keep the returnedIDisposablefor safe deregistration. - For very large lists prefer chunked RPC or a request-on-join RPC rather than putting everything in lobby metadata.
More details & Help
⠀ (!) If you encounter any issues with the mod, join the discord and message here.
CHANGELOG
Changelog
The format is based on Keep a Changelog.
1.0.7 23/11/2025
Added
- Table value support for messages.
Changed
- null
Fixed
- Patched issues with RPC events.
1.0.6 23/11/2025
Added
- null.
Changed
- null
Fixed
- I forgot to change reference link to the actual one.
1.0.5 22/11/2025
Added
- null.
Changed
- Simplified RPC structure for sending back messages to the caller / fetching the caller.
Fixed
- Made photon user to steam user mapping usable.
v1.0.4
- Patched something.
- Implemented IsHost bool.
v1.0.3
- Implemented helper functions to simplify usage of Library.
v1.0.2
- Fixed the README
v1.0.1
- Made it mote consumer friendly.
v1.0.0
- Release

