diff options
author | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-11-04 22:41:31 -0500 |
---|---|---|
committer | Jesse Plamondon-Willard <github@jplamondonw.com> | 2018-11-04 22:41:31 -0500 |
commit | 222265816d803e8e145c0a500568412d03dd49da (patch) | |
tree | e9538299c484b3a488c92bb4d435cfea339efc3d /src | |
parent | bfb40202793f2f7f2c9c73272f01a477b23edfa2 (diff) | |
download | SMAPI-222265816d803e8e145c0a500568412d03dd49da.tar.gz SMAPI-222265816d803e8e145c0a500568412d03dd49da.tar.bz2 SMAPI-222265816d803e8e145c0a500568412d03dd49da.zip |
add ContextReceived event (#480)
Diffstat (limited to 'src')
-rw-r--r-- | src/SMAPI/Events/ContextReceivedEventArgs.cs | 25 | ||||
-rw-r--r-- | src/SMAPI/Events/IMultiplayerEvents.cs | 3 | ||||
-rw-r--r-- | src/SMAPI/Framework/Events/EventManager.cs | 4 | ||||
-rw-r--r-- | src/SMAPI/Framework/Events/ModMultiplayerEvents.cs | 7 | ||||
-rw-r--r-- | src/SMAPI/Framework/SMultiplayer.cs | 50 | ||||
-rw-r--r-- | src/SMAPI/StardewModdingAPI.csproj | 1 |
6 files changed, 75 insertions, 15 deletions
diff --git a/src/SMAPI/Events/ContextReceivedEventArgs.cs b/src/SMAPI/Events/ContextReceivedEventArgs.cs new file mode 100644 index 00000000..c715cf1c --- /dev/null +++ b/src/SMAPI/Events/ContextReceivedEventArgs.cs @@ -0,0 +1,25 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// <summary>Event arguments for an <see cref="IMultiplayerEvents.ContextReceived"/> event.</summary> + public class ContextReceivedEventArgs : EventArgs + { + /********* + ** Accessors + *********/ + /// <summary>The player whose metadata was received.</summary> + public IMultiplayerPeer Peer { get; } + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="peer">The player to whom a connection is being established.</param> + internal ContextReceivedEventArgs(IMultiplayerPeer peer) + { + this.Peer = peer; + } + } +} diff --git a/src/SMAPI/Events/IMultiplayerEvents.cs b/src/SMAPI/Events/IMultiplayerEvents.cs index a6ac6fd3..91e0789c 100644 --- a/src/SMAPI/Events/IMultiplayerEvents.cs +++ b/src/SMAPI/Events/IMultiplayerEvents.cs @@ -5,6 +5,9 @@ namespace StardewModdingAPI.Events /// <summary>Events raised for multiplayer messages and connections.</summary> public interface IMultiplayerEvents { + /// <summary>Raised after the mod context for a player is received. This happens before the game approves the connection, so the player does not yet exist in the game. This is the earliest point where messages can be sent to the player via SMAPI.</summary> + event EventHandler<ContextReceivedEventArgs> ContextReceived; + /// <summary>Raised after a mod message is received over the network.</summary> event EventHandler<ModMessageReceivedEventArgs> ModMessageReceived; } diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 519cf48a..63ac17ee 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -101,6 +101,9 @@ namespace StardewModdingAPI.Framework.Events /**** ** Multiplayer ****/ + /// <summary>Raised after the mod context for a player is received. This happens before the game approves the connection, so the player does not yet exist in the game. This is the earliest point where messages can be sent to the player via SMAPI.</summary> + public readonly ManagedEvent<ContextReceivedEventArgs> ContextReceived; + /// <summary>Raised after a mod message is received over the network.</summary> public readonly ManagedEvent<ModMessageReceivedEventArgs> ModMessageReceived; @@ -380,6 +383,7 @@ namespace StardewModdingAPI.Framework.Events this.CursorMoved = ManageEventOf<CursorMovedEventArgs>(nameof(IModEvents.Input), nameof(IInputEvents.CursorMoved)); this.MouseWheelScrolled = ManageEventOf<MouseWheelScrolledEventArgs>(nameof(IModEvents.Input), nameof(IInputEvents.MouseWheelScrolled)); + this.ContextReceived = ManageEventOf<ContextReceivedEventArgs>(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.ContextReceived)); this.ModMessageReceived = ManageEventOf<ModMessageReceivedEventArgs>(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.ModMessageReceived)); this.InventoryChanged = ManageEventOf<InventoryChangedEventArgs>(nameof(IModEvents.Player), nameof(IPlayerEvents.InventoryChanged)); diff --git a/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs b/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs index a830a54a..432a92d3 100644 --- a/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs +++ b/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs @@ -16,6 +16,13 @@ namespace StardewModdingAPI.Framework.Events remove => this.EventManager.ModMessageReceived.Remove(value); } + /// <summary>Raised after the mod context for a player is received. This happens before the game approves the connection, so the player does not yet exist in the game. This is the earliest point where messages can be sent to the player via SMAPI.</summary> + public event EventHandler<ContextReceivedEventArgs> ContextReceived + { + add => this.EventManager.ContextReceived.Add(value); + remove => this.EventManager.ContextReceived.Remove(value); + } + /********* ** Public methods diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs index 70f1a89a..9f649639 100644 --- a/src/SMAPI/Framework/SMultiplayer.cs +++ b/src/SMAPI/Framework/SMultiplayer.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using Lidgren.Network; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Networking; using StardewModdingAPI.Framework.Reflection; @@ -186,7 +188,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"Rejected mod context from farmhand {message.FarmerID}: already received context for that player.", LogLevel.Error); return; } - this.Peers[message.FarmerID] = newPeer; + this.AddPeer(newPeer, canBeHost: false, raiseEvent: false); // reply with own context this.VerboseLog(" Replying with host context..."); @@ -209,20 +211,23 @@ namespace StardewModdingAPI.Framework otherPeer.SendMessage(new OutgoingMessage((byte)MessageType.ModContext, newPeer.PlayerID, fields)); } } + + // raise event + this.EventManager.ContextReceived.Raise(new ContextReceivedEventArgs(newPeer)); } break; // handle player intro case (byte)MessageType.PlayerIntroduction: + // store peer if new + if (!this.Peers.ContainsKey(message.FarmerID)) { - // get peer - if (!this.Peers.TryGetValue(message.FarmerID, out MultiplayerPeer peer)) - { - this.Monitor.Log($"Received connection for vanilla player {message.FarmerID}.", LogLevel.Trace); - this.Peers[message.FarmerID] = peer = MultiplayerPeer.ForConnectionToFarmhand(message.FarmerID, null, server, rawMessage.SenderConnection); - } - + this.Monitor.Log($"Received connection for vanilla player {message.FarmerID}.", LogLevel.Trace); + MultiplayerPeer peer = MultiplayerPeer.ForConnectionToFarmhand(message.FarmerID, null, server, rawMessage.SenderConnection); + this.AddPeer(peer, canBeHost: false); } + + resume(); break; // handle mod message @@ -262,9 +267,7 @@ namespace StardewModdingAPI.Framework 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); return; } - this.Peers[message.FarmerID] = peer; - if (peer.IsHost) - this.HostPeer = peer; + this.AddPeer(peer, canBeHost: true); } break; @@ -275,7 +278,7 @@ 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.Peers[message.FarmerID] = MultiplayerPeer.ForConnectionToHost(message.FarmerID, null, client, isHost: true); + this.AddPeer(MultiplayerPeer.ForConnectionToHost(message.FarmerID, null, client, isHost: true), canBeHost: false); } resume(); break; @@ -289,10 +292,11 @@ namespace StardewModdingAPI.Framework { peer = MultiplayerPeer.ForConnectionToHost(message.FarmerID, null, client, isHost: this.HostPeer == null); this.Monitor.Log($"Received connection for vanilla {(peer.IsHost ? "host" : "farmhand")} {message.FarmerID}.", LogLevel.Trace); - this.Peers[message.FarmerID] = peer; - if (peer.IsHost) - this.HostPeer = peer; + this.AddPeer(peer, canBeHost: true); } + + resume(); + break; } // handle mod message @@ -390,6 +394,22 @@ namespace StardewModdingAPI.Framework /********* ** Private methods *********/ + /// <summary>Save a received peer.</summary> + /// <param name="peer">The peer to add.</param> + /// <param name="canBeHost">Whether to track the peer as the host if applicable.</param> + /// <param name="raiseEvent">Whether to raise the <see cref="Events.EventManager.ContextReceived"/> event.</param> + private void AddPeer(MultiplayerPeer peer, bool canBeHost, bool raiseEvent = true) + { + // store + this.Peers[peer.PlayerID] = peer; + if (canBeHost && peer.IsHost) + this.HostPeer = peer; + + // raise event + if (raiseEvent) + this.EventManager.ContextReceived.Raise(new ContextReceivedEventArgs(peer)); + } + /// <summary>Read the metadata context for a player.</summary> /// <param name="reader">The stream reader.</param> private RemoteContextModel ReadContext(BinaryReader reader) diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index dfe55eb9..09ecddcd 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -85,6 +85,7 @@ <Compile Include="Events\ButtonReleasedEventArgs.cs" /> <Compile Include="Events\ChangeType.cs" /> <Compile Include="Events\ContentEvents.cs" /> + <Compile Include="Events\ContextReceivedEventArgs.cs" /> <Compile Include="Events\ControlEvents.cs" /> <Compile Include="Events\CursorMovedEventArgs.cs" /> <Compile Include="Events\DayEndingEventArgs.cs" /> |