OptionalNetworkAPI
API for plugin developers to write networking for mods that don't require all players to have it.OptionalNetworkAPI
Adds an API for plugin developers to more easily write networking for mods that don't require all players to have the mod.
This primarily includes detecting other players with the mod or sending data to other players with the mod, and has numerous callbacks to facilitate custom behavior if needed.
API
The API is exposed under OptionalNetworking.OptionalNetworkAPI. The primary endpoint is RegisterMod:
ModInfo OptionalNetworkAPI.RegisterMod(string name);
You should only run this once for your mod on Load. This creates a ModInfo object that exposes callbacks and info. As some examples:
OtherPlayersreturns a collection of nonlocal players with the mod installed.OnPlayerJoinedcallbacks run when a player joins the lobby.OnPlayerModSetcallbacks run when a player's mod is set as enabled (or disabled, in some Bot cases).
Example code:
private static ModInfo _modInfo;
internal static void OnLoad()
{
_modInfo = OptionalNetworkAPI.RegisterMod("MyMod")
_modInfo.OnPlayerJoined += (player) => Logger.Log($"{player.NickName} joined the lobby")
_modInfo.OnPlayerModSet += (player, hasMod) => Logger.Log($"{player.NickName} mod installed: {hasMod}")
}
internal static void PrintModdedPlayers()
{
List<string> names = new();
foreach (var player in _modInfo.Players)
names.Add(player.NickName);
Logger.Log($"Players with the mod: {string.Join(", ", names)}");
}
CustomData
ModInfo objects also expose CustomDataSender<T> and CustomDataManager<T> objects. These are handy objects that can send or sync your own custom data with other modded players.
CustomDataSender<T> allows you to easily send data to all modded players, requiring only a function to call when data is received. You may provide a default data function to be sent to other players on initial connection. You can also specify on creation whether to include bots or yourself when sending data.
CustomDataManager<T> operates as an extension of CustomDataSender<T> that tracks data for each player. When host changes or a player leaves, it will automatically update or remove player/bot data from its internal storage. This abstracts away most of the player state tracking, only requiring you to add callbacks or retrieve the data when you need it.
Example code:
struct MyStruct
{
public float width;
public float height;
public MyStruct(float width, float height)
{
this.width = width;
this.height = height;
}
}
private static ModInfo _modInfo;
private static CustomDataManager<MyStruct> _dataManager;
internal static void OnLoad()
{
_modInfo = OptionalNetworkAPI.RegisterMod("MyMod");
_modInfo.OnPlayerSpawned += OnPlayerSpawned;
_dataManager = _modInfo.AddCustomDataManager(DefaultData);
_dataManager.OnDataSet += OnDataSet;
}
private static MyStruct DefaultData(SNet_Player player)
{
return new MyStruct(player.NickName == "Dinorush" ? 100 : 1, 1);
}
private static void OnDataSet(SNet_Player player, MyStruct data)
{
if (data.width > data.height / 2)
Logger.Log($"{player.NickName} is wide");
else
Logger.Log($"{player.NickName} is normal");
}
private static void OnPlayerSpawned(PlayerAgent agent)
{
if (_dataManager.TryGetData(agent.Owner, out var data))
Logger.Log($"{agent.Owner.NickName} dimensions: {data.width} x {data.height}");
}
