summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/SMultiplayer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework/SMultiplayer.cs')
-rw-r--r--src/SMAPI/Framework/SMultiplayer.cs89
1 files changed, 43 insertions, 46 deletions
diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs
index de3c25a5..e41e7edc 100644
--- a/src/SMAPI/Framework/SMultiplayer.cs
+++ b/src/SMAPI/Framework/SMultiplayer.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using System;
using System.Collections.Generic;
using System.IO;
@@ -61,7 +59,7 @@ namespace StardewModdingAPI.Framework
private readonly PerScreen<IDictionary<long, MultiplayerPeer>> PeersImpl = new(() => new Dictionary<long, MultiplayerPeer>());
/// <summary>The backing field for <see cref="HostPeer"/>.</summary>
- private readonly PerScreen<MultiplayerPeer> HostPeerImpl = new();
+ private readonly PerScreen<MultiplayerPeer?> HostPeerImpl = new();
/*********
@@ -71,7 +69,7 @@ namespace StardewModdingAPI.Framework
public IDictionary<long, MultiplayerPeer> Peers => this.PeersImpl.Value;
/// <summary>The metadata for the host player, if the current player is a farmhand.</summary>
- public MultiplayerPeer HostPeer
+ public MultiplayerPeer? HostPeer
{
get => this.HostPeerImpl.Value;
private set => this.HostPeerImpl.Value = value;
@@ -115,13 +113,13 @@ namespace StardewModdingAPI.Framework
{
case LidgrenClient:
{
- string address = this.Reflection.GetField<string>(client, "address").GetValue();
+ string address = this.Reflection.GetField<string?>(client, "address").GetValue() ?? throw new InvalidOperationException("Can't initialize base networking client: no valid address found.");
return new SLidgrenClient(address, this.OnClientProcessingMessage, this.OnClientSendingMessage);
}
case GalaxyNetClient:
{
- GalaxyID address = this.Reflection.GetField<GalaxyID>(client, "lobbyId").GetValue();
+ GalaxyID address = this.Reflection.GetField<GalaxyID?>(client, "lobbyId").GetValue() ?? throw new InvalidOperationException("Can't initialize GOG networking client: no valid address found.");
return new SGalaxyNetClient(address, this.OnClientProcessingMessage, this.OnClientSendingMessage);
}
@@ -139,13 +137,13 @@ namespace StardewModdingAPI.Framework
{
case LidgrenServer:
{
- IGameServer gameServer = this.Reflection.GetField<IGameServer>(server, "gameServer").GetValue();
+ IGameServer gameServer = this.Reflection.GetField<IGameServer?>(server, "gameServer").GetValue() ?? throw new InvalidOperationException("Can't initialize base networking client: the required 'gameServer' field wasn't found.");
return new SLidgrenServer(gameServer, this, this.OnServerProcessingMessage);
}
case GalaxyNetServer:
{
- IGameServer gameServer = this.Reflection.GetField<IGameServer>(server, "gameServer").GetValue();
+ IGameServer gameServer = this.Reflection.GetField<IGameServer?>(server, "gameServer").GetValue() ?? throw new InvalidOperationException("Can't initialize GOG networking client: the required 'gameServer' field wasn't found.");
return new SGalaxyNetServer(gameServer, this, this.OnServerProcessingMessage);
}
@@ -194,7 +192,7 @@ namespace StardewModdingAPI.Framework
case (byte)MessageType.ModContext:
{
// parse message
- RemoteContextModel model = this.ReadContext(message.Reader);
+ RemoteContextModel? model = this.ReadContext(message.Reader);
this.Monitor.Log($"Received context for farmhand {message.FarmerID} running {(model != null ? $"SMAPI {model.ApiVersion} with {model.Mods.Length} mods" : "vanilla")}.");
// store peer
@@ -290,7 +288,7 @@ namespace StardewModdingAPI.Framework
case (byte)MessageType.ModContext:
{
// parse message
- RemoteContextModel model = this.ReadContext(message.Reader);
+ RemoteContextModel? model = this.ReadContext(message.Reader);
this.Monitor.Log($"Received context for {(model?.IsHost == true ? "host" : "farmhand")} {message.FarmerID} running {(model != null ? $"SMAPI {model.ApiVersion} with {model.Mods.Length} mods" : "vanilla")}.");
// store peer
@@ -334,7 +332,7 @@ namespace StardewModdingAPI.Framework
case (byte)MessageType.PlayerIntroduction:
{
// store peer
- if (!this.Peers.TryGetValue(message.FarmerID, out MultiplayerPeer peer))
+ if (!this.Peers.TryGetValue(message.FarmerID, out MultiplayerPeer? peer))
{
peer = new MultiplayerPeer(
playerID: message.FarmerID,
@@ -367,7 +365,7 @@ namespace StardewModdingAPI.Framework
{
foreach (long playerID in this.disconnectingFarmers)
{
- if (this.Peers.TryGetValue(playerID, out MultiplayerPeer peer))
+ if (this.Peers.TryGetValue(playerID, out MultiplayerPeer? peer))
{
this.Monitor.Log($"Player quit: {playerID}");
this.Peers.Remove(playerID);
@@ -384,7 +382,7 @@ namespace StardewModdingAPI.Framework
/// <param name="fromModID">The unique ID of the mod sending the message.</param>
/// <param name="toModIDs">The mod IDs which should receive the message on the destination computers, or <c>null</c> for all mods. Specifying mod IDs is recommended to improve performance, unless it's a general-purpose broadcast.</param>
/// <param name="toPlayerIDs">The <see cref="Farmer.UniqueMultiplayerID" /> values for the players who should receive the message, or <c>null</c> for all players. If you don't need to broadcast to all players, specifying player IDs is recommended to reduce latency.</param>
- public void BroadcastModMessage<TMessage>(TMessage message, string messageType, string fromModID, string[] toModIDs, long[] toPlayerIDs)
+ public void BroadcastModMessage<TMessage>(TMessage message, string messageType, string fromModID, string[]? toModIDs, long[]? toPlayerIDs)
{
// validate input
if (message == null)
@@ -488,13 +486,13 @@ namespace StardewModdingAPI.Framework
/// <summary>Read the metadata context for a player.</summary>
/// <param name="reader">The stream reader.</param>
- private RemoteContextModel ReadContext(BinaryReader reader)
+ private RemoteContextModel? ReadContext(BinaryReader reader)
{
string data = reader.ReadString();
RemoteContextModel model = this.JsonHelper.Deserialize<RemoteContextModel>(data);
return model.ApiVersion != null
? model
- : null; // no data available for unmodded players
+ : null; // no data available for vanilla players
}
/// <summary>Receive a mod message sent from another player's mods.</summary>
@@ -515,12 +513,15 @@ namespace StardewModdingAPI.Framework
// forward to other players
if (Context.IsMainPlayer && playerIDs.Any(p => p != Game1.player.UniqueMultiplayerID))
{
- ModMessageModel newModel = new(model);
foreach (long playerID in playerIDs)
{
- if (playerID != Game1.player.UniqueMultiplayerID && playerID != model.FromPlayerID && this.Peers.TryGetValue(playerID, out MultiplayerPeer peer))
+ if (playerID != Game1.player.UniqueMultiplayerID && playerID != model.FromPlayerID && this.Peers.TryGetValue(playerID, out MultiplayerPeer? peer))
{
- newModel.ToPlayerIDs = new[] { peer.PlayerID };
+ ModMessageModel newModel = new(model)
+ {
+ ToPlayerIDs = new[] { peer.PlayerID }
+ };
+
this.Monitor.VerboseLog($" Forwarding message to player {peer.PlayerID}.");
peer.SendMessage(new OutgoingMessage((byte)MessageType.ModMessage, peer.PlayerID, this.JsonHelper.Serialize(newModel, Formatting.None)));
}
@@ -546,22 +547,20 @@ namespace StardewModdingAPI.Framework
/// <summary>Get the fields to include in a context sync message sent to other players.</summary>
private object[] GetContextSyncMessageFields()
{
- RemoteContextModel model = new()
- {
- IsHost = Context.IsWorldReady && Context.IsMainPlayer,
- Platform = Constants.TargetPlatform,
- ApiVersion = Constants.ApiVersion,
- GameVersion = Constants.GameVersion,
- Mods = this.ModRegistry
+ RemoteContextModel model = new(
+ isHost: Context.IsWorldReady && Context.IsMainPlayer,
+ platform: Constants.TargetPlatform,
+ apiVersion: Constants.ApiVersion,
+ gameVersion: Constants.GameVersion,
+ mods: this.ModRegistry
.GetAll()
- .Select(mod => new RemoteContextModModel
- {
- ID = mod.Manifest.UniqueID,
- Name = mod.Manifest.Name,
- Version = mod.Manifest.Version
- })
+ .Select(mod => new RemoteContextModModel(
+ id: mod.Manifest.UniqueID,
+ name: mod.Manifest.Name,
+ version: mod.Manifest.Version
+ ))
.ToArray()
- };
+ );
return new object[] { this.JsonHelper.Serialize(model, Formatting.None) };
}
@@ -573,21 +572,19 @@ namespace StardewModdingAPI.Framework
if (!peer.HasSmapi)
return new object[] { "{}" };
- RemoteContextModel model = new()
- {
- IsHost = peer.IsHost,
- Platform = peer.Platform.Value,
- ApiVersion = peer.ApiVersion,
- GameVersion = peer.GameVersion,
- Mods = peer.Mods
- .Select(mod => new RemoteContextModModel
- {
- ID = mod.ID,
- Name = mod.Name,
- Version = mod.Version
- })
+ RemoteContextModel model = new(
+ isHost: peer.IsHost,
+ platform: peer.Platform.Value,
+ apiVersion: peer.ApiVersion,
+ gameVersion: peer.GameVersion,
+ mods: peer.Mods
+ .Select(mod => new RemoteContextModModel(
+ id: mod.ID,
+ name: mod.Name,
+ version: mod.Version
+ ))
.ToArray()
- };
+ );
return new object[] { this.JsonHelper.Serialize(model, Formatting.None) };
}