summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Events
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2018-11-04 23:18:55 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2018-11-04 23:18:55 -0500
commite8276166c3e8d1a0b3a976ef29a00f8e1569cc72 (patch)
treea78c44e929ff1de70d20b012385c418aea7e78a6 /src/SMAPI/Framework/Events
parent688ee69ee64e03aee7a693e6c15092daf229ac5e (diff)
parentb4a5b3829f0f738e5b7e05048068eaec9d2d01d1 (diff)
downloadSMAPI-e8276166c3e8d1a0b3a976ef29a00f8e1569cc72.tar.gz
SMAPI-e8276166c3e8d1a0b3a976ef29a00f8e1569cc72.tar.bz2
SMAPI-e8276166c3e8d1a0b3a976ef29a00f8e1569cc72.zip
Merge branch 'add-multiplayer-sync' into develop
Diffstat (limited to 'src/SMAPI/Framework/Events')
-rw-r--r--src/SMAPI/Framework/Events/EventManager.cs16
-rw-r--r--src/SMAPI/Framework/Events/ManagedEvent.cs24
-rw-r--r--src/SMAPI/Framework/Events/ManagedEventBase.cs12
-rw-r--r--src/SMAPI/Framework/Events/ModEvents.cs4
-rw-r--r--src/SMAPI/Framework/Events/ModMultiplayerEvents.cs43
5 files changed, 98 insertions, 1 deletions
diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs
index 31b0346a..b9d1c453 100644
--- a/src/SMAPI/Framework/Events/EventManager.cs
+++ b/src/SMAPI/Framework/Events/EventManager.cs
@@ -99,6 +99,18 @@ namespace StardewModdingAPI.Framework.Events
public readonly ManagedEvent<MouseWheelScrolledEventArgs> MouseWheelScrolled;
/****
+ ** Multiplayer
+ ****/
+ /// <summary>Raised after the mod context for a peer is received. This happens before the game approves the connection, so the player doesn't yet exist in the game. This is the earliest point where messages can be sent to the peer via SMAPI.</summary>
+ public readonly ManagedEvent<PeerContextReceivedEventArgs> PeerContextReceived;
+
+ /// <summary>Raised after a mod message is received over the network.</summary>
+ public readonly ManagedEvent<ModMessageReceivedEventArgs> ModMessageReceived;
+
+ /// <summary>Raised after the connection with a peer is severed.</summary>
+ public readonly ManagedEvent<PeerDisconnectedEventArgs> PeerDisconnected;
+
+ /****
** Player
****/
/// <summary>Raised after items are added or removed to a player's inventory.</summary>
@@ -374,6 +386,10 @@ 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.PeerContextReceived = ManageEventOf<PeerContextReceivedEventArgs>(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.PeerContextReceived));
+ this.ModMessageReceived = ManageEventOf<ModMessageReceivedEventArgs>(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.ModMessageReceived));
+ this.PeerDisconnected = ManageEventOf<PeerDisconnectedEventArgs>(nameof(IModEvents.Multiplayer), nameof(IMultiplayerEvents.PeerDisconnected));
+
this.InventoryChanged = ManageEventOf<InventoryChangedEventArgs>(nameof(IModEvents.Player), nameof(IPlayerEvents.InventoryChanged));
this.LevelChanged = ManageEventOf<LevelChangedEventArgs>(nameof(IModEvents.Player), nameof(IPlayerEvents.LevelChanged));
this.Warped = ManageEventOf<WarpedEventArgs>(nameof(IModEvents.Player), nameof(IPlayerEvents.Warped));
diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs
index c1ebf6c7..65f6e38e 100644
--- a/src/SMAPI/Framework/Events/ManagedEvent.cs
+++ b/src/SMAPI/Framework/Events/ManagedEvent.cs
@@ -67,6 +67,30 @@ namespace StardewModdingAPI.Framework.Events
}
}
}
+
+ /// <summary>Raise the event and notify all handlers.</summary>
+ /// <param name="args">The event arguments to pass.</param>
+ /// <param name="match">A lambda which returns true if the event should be raised for the given mod.</param>
+ public void RaiseForMods(TEventArgs args, Func<IModMetadata, bool> match)
+ {
+ if (this.Event == null)
+ return;
+
+ foreach (EventHandler<TEventArgs> handler in this.CachedInvocationList)
+ {
+ if (match(this.GetSourceMod(handler)))
+ {
+ try
+ {
+ handler.Invoke(null, args);
+ }
+ catch (Exception ex)
+ {
+ this.LogError(handler, ex);
+ }
+ }
+ }
+ }
}
/// <summary>An event wrapper which intercepts and logs errors in handler code.</summary>
diff --git a/src/SMAPI/Framework/Events/ManagedEventBase.cs b/src/SMAPI/Framework/Events/ManagedEventBase.cs
index f3a278dc..defd903a 100644
--- a/src/SMAPI/Framework/Events/ManagedEventBase.cs
+++ b/src/SMAPI/Framework/Events/ManagedEventBase.cs
@@ -69,12 +69,22 @@ namespace StardewModdingAPI.Framework.Events
this.SourceMods.Remove(handler);
}
+ /// <summary>Get the mod which registered the given event handler, if available.</summary>
+ /// <param name="handler">The event handler.</param>
+ protected IModMetadata GetSourceMod(TEventHandler handler)
+ {
+ return this.SourceMods.TryGetValue(handler, out IModMetadata mod)
+ ? mod
+ : null;
+ }
+
/// <summary>Log an exception from an event handler.</summary>
/// <param name="handler">The event handler instance.</param>
/// <param name="ex">The exception that was raised.</param>
protected void LogError(TEventHandler handler, Exception ex)
{
- if (this.SourceMods.TryGetValue(handler, out IModMetadata mod))
+ IModMetadata mod = this.GetSourceMod(handler);
+ if (mod != null)
mod.LogAsMod($"This mod failed in the {this.EventName} event. Technical details: \n{ex.GetLogSummary()}", LogLevel.Error);
else
this.Monitor.Log($"A mod failed in the {this.EventName} event. Technical details: \n{ex.GetLogSummary()}", LogLevel.Error);
diff --git a/src/SMAPI/Framework/Events/ModEvents.cs b/src/SMAPI/Framework/Events/ModEvents.cs
index 7a318e8b..8ad3936c 100644
--- a/src/SMAPI/Framework/Events/ModEvents.cs
+++ b/src/SMAPI/Framework/Events/ModEvents.cs
@@ -17,6 +17,9 @@ namespace StardewModdingAPI.Framework.Events
/// <summary>Events raised when the player provides input using a controller, keyboard, or mouse.</summary>
public IInputEvents Input { get; }
+ /// <summary>Events raised for multiplayer messages and connections.</summary>
+ public IMultiplayerEvents Multiplayer { get; }
+
/// <summary>Events raised when the player data changes.</summary>
public IPlayerEvents Player { get; }
@@ -38,6 +41,7 @@ namespace StardewModdingAPI.Framework.Events
this.Display = new ModDisplayEvents(mod, eventManager);
this.GameLoop = new ModGameLoopEvents(mod, eventManager);
this.Input = new ModInputEvents(mod, eventManager);
+ this.Multiplayer = new ModMultiplayerEvents(mod, eventManager);
this.Player = new ModPlayerEvents(mod, eventManager);
this.World = new ModWorldEvents(mod, eventManager);
this.Specialised = new ModSpecialisedEvents(mod, eventManager);
diff --git a/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs b/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs
new file mode 100644
index 00000000..152c4e0c
--- /dev/null
+++ b/src/SMAPI/Framework/Events/ModMultiplayerEvents.cs
@@ -0,0 +1,43 @@
+using System;
+using StardewModdingAPI.Events;
+
+namespace StardewModdingAPI.Framework.Events
+{
+ /// <summary>Events raised for multiplayer messages and connections.</summary>
+ internal class ModMultiplayerEvents : ModEventsBase, IMultiplayerEvents
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Raised after the mod context for a peer is received. This happens before the game approves the connection, so the player doesn't yet exist in the game. This is the earliest point where messages can be sent to the peer via SMAPI.</summary>
+ public event EventHandler<PeerContextReceivedEventArgs> PeerContextReceived
+ {
+ add => this.EventManager.PeerContextReceived.Add(value);
+ remove => this.EventManager.PeerContextReceived.Remove(value);
+ }
+
+ /// <summary>Raised after a mod message is received over the network.</summary>
+ public event EventHandler<ModMessageReceivedEventArgs> ModMessageReceived
+ {
+ add => this.EventManager.ModMessageReceived.Add(value);
+ remove => this.EventManager.ModMessageReceived.Remove(value);
+ }
+
+ /// <summary>Raised after the connection with a peer is severed.</summary>
+ public event EventHandler<PeerDisconnectedEventArgs> PeerDisconnected
+ {
+ add => this.EventManager.PeerDisconnected.Add(value);
+ remove => this.EventManager.PeerDisconnected.Remove(value);
+ }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="mod">The mod which uses this instance.</param>
+ /// <param name="eventManager">The underlying event manager.</param>
+ internal ModMultiplayerEvents(IModMetadata mod, EventManager eventManager)
+ : base(mod, eventManager) { }
+ }
+}