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.cs86
1 files changed, 57 insertions, 29 deletions
diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs
index 2f89fce9..5956b63f 100644
--- a/src/SMAPI/Framework/SMultiplayer.cs
+++ b/src/SMAPI/Framework/SMultiplayer.cs
@@ -56,10 +56,10 @@ namespace StardewModdingAPI.Framework
private readonly bool LogNetworkTraffic;
/// <summary>The backing field for <see cref="Peers"/>.</summary>
- private readonly PerScreen<IDictionary<long, MultiplayerPeer>> PeersImpl = new(() => new Dictionary<long, MultiplayerPeer>());
+ private readonly PerScreen<IDictionary<long, MultiplayerPeer>> PeersImpl = new PerScreen<IDictionary<long, MultiplayerPeer>>(() => 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 PerScreen<MultiplayerPeer>();
/*********
@@ -196,7 +196,13 @@ namespace StardewModdingAPI.Framework
this.Monitor.Log($"Received context for farmhand {message.FarmerID} running {(model != null ? $"SMAPI {model.ApiVersion} with {model.Mods.Length} mods" : "vanilla")}.", LogLevel.Trace);
// store peer
- MultiplayerPeer newPeer = new MultiplayerPeer(message.FarmerID, model, sendMessage, isHost: false);
+ MultiplayerPeer newPeer = new MultiplayerPeer(
+ playerID: message.FarmerID,
+ screenID: this.GetScreenId(message.FarmerID),
+ model: model,
+ sendMessage: sendMessage,
+ isHost: false
+ );
if (this.Peers.ContainsKey(message.FarmerID))
{
this.Monitor.Log($"Received mod context from farmhand {message.FarmerID}, but the game didn't see them disconnect. This may indicate issues with the network connection.", LogLevel.Info);
@@ -238,7 +244,13 @@ namespace StardewModdingAPI.Framework
if (!this.Peers.ContainsKey(message.FarmerID))
{
this.Monitor.Log($"Received connection for vanilla player {message.FarmerID}.", LogLevel.Trace);
- MultiplayerPeer peer = new MultiplayerPeer(message.FarmerID, null, sendMessage, isHost: false);
+ MultiplayerPeer peer = new MultiplayerPeer(
+ playerID: message.FarmerID,
+ screenID: this.GetScreenId(message.FarmerID),
+ model: null,
+ sendMessage: sendMessage,
+ isHost: false
+ );
this.AddPeer(peer, canBeHost: false);
}
@@ -280,7 +292,13 @@ namespace StardewModdingAPI.Framework
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")}.", LogLevel.Trace);
// store peer
- MultiplayerPeer peer = new MultiplayerPeer(message.FarmerID, model, sendMessage, isHost: model?.IsHost ?? this.HostPeer == null);
+ MultiplayerPeer peer = new MultiplayerPeer(
+ playerID: message.FarmerID,
+ screenID: this.GetScreenId(message.FarmerID),
+ model: model,
+ sendMessage: sendMessage,
+ isHost: model?.IsHost ?? this.HostPeer == null
+ );
if (peer.IsHost && this.HostPeer != null)
{
this.Monitor.Log($"Rejected mod context from host player {peer.PlayerID}: already received host data from {(peer.PlayerID == this.HostPeer.PlayerID ? "that player" : $"player {peer.PlayerID}")}.", LogLevel.Error);
@@ -297,7 +315,14 @@ namespace StardewModdingAPI.Framework
if (!this.Peers.ContainsKey(message.FarmerID) && this.HostPeer == null)
{
this.Monitor.Log($"Received connection for vanilla host {message.FarmerID}.", LogLevel.Trace);
- this.AddPeer(new MultiplayerPeer(message.FarmerID, null, sendMessage, isHost: true), canBeHost: false);
+ var peer = new MultiplayerPeer(
+ playerID: message.FarmerID,
+ screenID: this.GetScreenId(message.FarmerID),
+ model: null,
+ sendMessage: sendMessage,
+ isHost: true
+ );
+ this.AddPeer(peer, canBeHost: false);
}
resume();
break;
@@ -309,7 +334,13 @@ namespace StardewModdingAPI.Framework
// store peer
if (!this.Peers.TryGetValue(message.FarmerID, out MultiplayerPeer peer))
{
- peer = new MultiplayerPeer(message.FarmerID, null, sendMessage, isHost: this.HostPeer == null);
+ peer = new MultiplayerPeer(
+ playerID: message.FarmerID,
+ screenID: this.GetScreenId(message.FarmerID),
+ model: null,
+ sendMessage: sendMessage,
+ isHost: this.HostPeer == null
+ );
this.Monitor.Log($"Received connection for vanilla {(peer.IsHost ? "host" : "farmhand")} {message.FarmerID}.", LogLevel.Trace);
this.AddPeer(peer, canBeHost: true);
}
@@ -361,34 +392,24 @@ namespace StardewModdingAPI.Framework
if (string.IsNullOrWhiteSpace(fromModID))
throw new ArgumentNullException(nameof(fromModID));
- // get target players
- long curPlayerId = Game1.player.UniqueMultiplayerID;
- bool sendToSelf = false;
- List<MultiplayerPeer> sendToPeers = new List<MultiplayerPeer>();
- if (toPlayerIDs == null)
- {
- sendToSelf = true;
- sendToPeers.AddRange(this.Peers.Values);
- }
- else
+ // get valid peers
+ var sendToPeers = this.Peers.Values.Where(p => p.HasSmapi).ToList();
+ bool sendToSelf = true;
+
+ // filter by player ID
+ if (toPlayerIDs != null)
{
- foreach (long id in toPlayerIDs.Distinct())
- {
- if (id == curPlayerId)
- sendToSelf = true;
- else if (this.Peers.TryGetValue(id, out MultiplayerPeer peer) && peer.HasSmapi)
- sendToPeers.Add(peer);
- }
+ var ids = new HashSet<long>(toPlayerIDs);
+ sendToPeers.RemoveAll(peer => !ids.Contains(peer.PlayerID));
+ sendToSelf = ids.Contains(Game1.player.UniqueMultiplayerID);
}
// filter by mod ID
if (toModIDs != null)
{
- HashSet<string> sendToMods = new HashSet<string>(toModIDs, StringComparer.OrdinalIgnoreCase);
- if (sendToSelf && toModIDs.All(id => this.ModRegistry.Get(id) == null))
- sendToSelf = false;
-
- sendToPeers.RemoveAll(peer => peer.Mods.All(mod => !sendToMods.Contains(mod.ID)));
+ var ids = new HashSet<string>(toModIDs, StringComparer.OrdinalIgnoreCase);
+ sendToPeers.RemoveAll(peer => peer.Mods.All(mod => !ids.Contains(mod.ID)));
+ sendToSelf = sendToSelf && toModIDs.Any(id => this.ModRegistry.Get(id) != null);
}
// validate recipients
@@ -505,6 +526,13 @@ namespace StardewModdingAPI.Framework
}
}
+ /// <summary>Get the screen ID for a given player ID, if the player is local.</summary>
+ /// <param name="playerId">The player ID to check.</param>
+ private int? GetScreenId(long playerId)
+ {
+ return SGameRunner.Instance.GetScreenId(playerId);
+ }
+
/// <summary>Get all connected player IDs, including the current player.</summary>
private IEnumerable<long> GetKnownPlayerIDs()
{