summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-11-04 22:41:31 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-11-04 22:41:31 -0500
commit222265816d803e8e145c0a500568412d03dd49da (patch)
treee9538299c484b3a488c92bb4d435cfea339efc3d /src/SMAPI/Framework
parentbfb40202793f2f7f2c9c73272f01a477b23edfa2 (diff)
downloadSMAPI-222265816d803e8e145c0a500568412d03dd49da.tar.gz
SMAPI-222265816d803e8e145c0a500568412d03dd49da.tar.bz2
SMAPI-222265816d803e8e145c0a500568412d03dd49da.zip
add ContextReceived event (#480)
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/Events/EventManager.cs4
-rw-r--r--src/SMAPI/Framework/Events/ModMultiplayerEvents.cs7
-rw-r--r--src/SMAPI/Framework/SMultiplayer.cs50
3 files changed, 46 insertions, 15 deletions
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)