diff options
-rw-r--r-- | src/SMAPI/Framework/InternalExtensions.cs | 3 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 175 | ||||
-rw-r--r-- | src/SMAPI/Framework/SMultiplayer.cs | 12 |
3 files changed, 115 insertions, 75 deletions
diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index 580651f3..ba9bbcec 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -64,7 +64,8 @@ namespace StardewModdingAPI.Framework /// <param name="event">The event to raise.</param> public static void RaiseEmpty<TEventArgs>(this ManagedEvent<TEventArgs> @event) where TEventArgs : new() { - @event.Raise(Singleton<TEventArgs>.Instance); + if (@event.HasListeners) + @event.Raise(Singleton<TEventArgs>.Instance); } /**** diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index c1e03634..ec21e38a 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -47,6 +47,7 @@ using StardewModdingAPI.Toolkit.Utilities.PathLookups; using StardewModdingAPI.Utilities; using StardewValley; using StardewValley.Menus; +using StardewValley.Objects; using xTile.Display; using LanguageCode = StardewValley.LocalizedContentManager.LanguageCode; using MiniMonoModHotfix = MonoMod.Utils.MiniMonoModHotfix; @@ -808,7 +809,8 @@ namespace StardewModdingAPI.Framework if (verbose) this.Monitor.Log($"Events: window size changed to {state.WindowSize.New}."); - events.WindowResized.Raise(new WindowResizedEventArgs(state.WindowSize.Old, state.WindowSize.New)); + if (events.WindowResized.HasListeners) + events.WindowResized.Raise(new WindowResizedEventArgs(state.WindowSize.Old, state.WindowSize.New)); } /********* @@ -823,7 +825,7 @@ namespace StardewModdingAPI.Framework ICursorPosition cursor = instance.Input.CursorPosition; // raise cursor moved event - if (state.Cursor.IsChanged) + if (state.Cursor.IsChanged && events.CursorMoved.HasListeners) events.CursorMoved.Raise(new CursorMovedEventArgs(state.Cursor.Old!, state.Cursor.New!)); // raise mouse wheel scrolled @@ -831,32 +833,42 @@ namespace StardewModdingAPI.Framework { if (verbose) this.Monitor.Log($"Events: mouse wheel scrolled to {state.MouseWheelScroll.New}."); - events.MouseWheelScrolled.Raise(new MouseWheelScrolledEventArgs(cursor, state.MouseWheelScroll.Old, state.MouseWheelScroll.New)); + + if (events.MouseWheelScrolled.HasListeners) + events.MouseWheelScrolled.Raise(new MouseWheelScrolledEventArgs(cursor, state.MouseWheelScroll.Old, state.MouseWheelScroll.New)); } // raise input button events if (inputState.ButtonStates.Count > 0) { - events.ButtonsChanged.Raise(new ButtonsChangedEventArgs(cursor, inputState)); - - foreach (var pair in inputState.ButtonStates) - { - SButton button = pair.Key; - SButtonState status = pair.Value; + if (events.ButtonsChanged.HasListeners) + events.ButtonsChanged.Raise(new ButtonsChangedEventArgs(cursor, inputState)); - if (status == SButtonState.Pressed) - { - if (verbose) - this.Monitor.Log($"Events: button {button} pressed."); + bool raisePressed = events.ButtonPressed.HasListeners; + bool raiseReleased = events.ButtonReleased.HasListeners; - events.ButtonPressed.Raise(new ButtonPressedEventArgs(button, cursor, inputState)); - } - else if (status == SButtonState.Released) + if (verbose || raisePressed || raiseReleased) + { + foreach ((SButton button, SButtonState status) in inputState.ButtonStates) { - if (verbose) - this.Monitor.Log($"Events: button {button} released."); - - events.ButtonReleased.Raise(new ButtonReleasedEventArgs(button, cursor, inputState)); + switch (status) + { + case SButtonState.Pressed: + if (verbose) + this.Monitor.Log($"Events: button {button} pressed."); + + if (raisePressed) + events.ButtonPressed.Raise(new ButtonPressedEventArgs(button, cursor, inputState)); + break; + + case SButtonState.Released: + if (verbose) + this.Monitor.Log($"Events: button {button} released."); + + if (raiseReleased) + events.ButtonReleased.Raise(new ButtonReleasedEventArgs(button, cursor, inputState)); + break; + } } } } @@ -868,14 +880,15 @@ namespace StardewModdingAPI.Framework *********/ if (state.ActiveMenu.IsChanged) { - var was = state.ActiveMenu.Old; - var now = state.ActiveMenu.New; + IClickableMenu? was = state.ActiveMenu.Old; + IClickableMenu? now = state.ActiveMenu.New; if (verbose) this.Monitor.Log($"Context: menu changed from {was?.GetType().FullName ?? "none"} to {now?.GetType().FullName ?? "none"}."); // raise menu events - events.MenuChanged.Raise(new MenuChangedEventArgs(was, now)); + if (events.MenuChanged.HasListeners) + events.MenuChanged.Raise(new MenuChangedEventArgs(was, now)); } /********* @@ -898,7 +911,8 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText})."); } - events.LocationListChanged.Raise(new LocationListChangedEventArgs(added, removed)); + if (events.LocationListChanged.HasListeners) + events.LocationListChanged.Raise(new LocationListChangedEventArgs(added, removed)); } // raise location contents changed @@ -906,50 +920,47 @@ namespace StardewModdingAPI.Framework { foreach (LocationSnapshot locState in state.Locations.Locations) { - var location = locState.Location; + GameLocation location = locState.Location; // buildings changed - if (locState.Buildings.IsChanged) + if (locState.Buildings.IsChanged && events.BuildingListChanged.HasListeners) events.BuildingListChanged.Raise(new BuildingListChangedEventArgs(location, locState.Buildings.Added, locState.Buildings.Removed)); // debris changed - if (locState.Debris.IsChanged) + if (locState.Debris.IsChanged && events.DebrisListChanged.HasListeners) events.DebrisListChanged.Raise(new DebrisListChangedEventArgs(location, locState.Debris.Added, locState.Debris.Removed)); // large terrain features changed - if (locState.LargeTerrainFeatures.IsChanged) + if (locState.LargeTerrainFeatures.IsChanged && events.LargeTerrainFeatureListChanged.HasListeners) events.LargeTerrainFeatureListChanged.Raise(new LargeTerrainFeatureListChangedEventArgs(location, locState.LargeTerrainFeatures.Added, locState.LargeTerrainFeatures.Removed)); // NPCs changed - if (locState.Npcs.IsChanged) + if (locState.Npcs.IsChanged && events.NpcListChanged.HasListeners) events.NpcListChanged.Raise(new NpcListChangedEventArgs(location, locState.Npcs.Added, locState.Npcs.Removed)); // objects changed - if (locState.Objects.IsChanged) + if (locState.Objects.IsChanged && events.ObjectListChanged.HasListeners) events.ObjectListChanged.Raise(new ObjectListChangedEventArgs(location, locState.Objects.Added, locState.Objects.Removed)); // chest items changed if (events.ChestInventoryChanged.HasListeners) { - foreach (var pair in locState.ChestItems) - { - SnapshotItemListDiff diff = pair.Value; - events.ChestInventoryChanged.Raise(new ChestInventoryChangedEventArgs(pair.Key, location, added: diff.Added, removed: diff.Removed, quantityChanged: diff.QuantityChanged)); - } + foreach ((Chest chest, SnapshotItemListDiff diff) in locState.ChestItems) + events.ChestInventoryChanged.Raise(new ChestInventoryChangedEventArgs(chest, location, added: diff.Added, removed: diff.Removed, quantityChanged: diff.QuantityChanged)); } // terrain features changed - if (locState.TerrainFeatures.IsChanged) + if (locState.TerrainFeatures.IsChanged && events.TerrainFeatureListChanged.HasListeners) events.TerrainFeatureListChanged.Raise(new TerrainFeatureListChangedEventArgs(location, locState.TerrainFeatures.Added, locState.TerrainFeatures.Removed)); // furniture changed - if (locState.Furniture.IsChanged) + if (locState.Furniture.IsChanged && events.FurnitureListChanged.HasListeners) events.FurnitureListChanged.Raise(new FurnitureListChangedEventArgs(location, locState.Furniture.Added, locState.Furniture.Removed)); } } // raise time changed - if (raiseWorldEvents && state.Time.IsChanged) + if (raiseWorldEvents && state.Time.IsChanged && events.TimeChanged.HasListeners) events.TimeChanged.Raise(new TimeChangedEventArgs(state.Time.Old, state.Time.New)); // raise player events @@ -964,29 +975,38 @@ namespace StardewModdingAPI.Framework if (verbose) this.Monitor.Log($"Context: set location to {playerState.Location.New}."); - events.Warped.Raise(new WarpedEventArgs(player, playerState.Location.Old!, playerState.Location.New!)); + if (events.Warped.HasListeners) + events.Warped.Raise(new WarpedEventArgs(player, playerState.Location.Old!, playerState.Location.New!)); } // raise player leveled up a skill - foreach ((SkillType skill, var value) in playerState.Skills) + bool raiseLevelChanged = events.LevelChanged.HasListeners; + if (verbose || raiseLevelChanged) { - if (!value.IsChanged) - continue; + foreach ((SkillType skill, var value) in playerState.Skills) + { + if (!value.IsChanged) + continue; - if (verbose) - this.Monitor.Log($"Events: player skill '{skill}' changed from {value.Old} to {value.New}."); + if (verbose) + this.Monitor.Log($"Events: player skill '{skill}' changed from {value.Old} to {value.New}."); - events.LevelChanged.Raise(new LevelChangedEventArgs(player, skill, value.Old, value.New)); + if (raiseLevelChanged) + events.LevelChanged.Raise(new LevelChangedEventArgs(player, skill, value.Old, value.New)); + } } // raise player inventory changed if (playerState.Inventory.IsChanged) { - SnapshotItemListDiff inventory = playerState.Inventory; - if (verbose) this.Monitor.Log("Events: player inventory changed."); - events.InventoryChanged.Raise(new InventoryChangedEventArgs(player, added: inventory.Added, removed: inventory.Removed, quantityChanged: inventory.QuantityChanged)); + + if (events.InventoryChanged.HasListeners) + { + SnapshotItemListDiff inventory = playerState.Inventory; + events.InventoryChanged.Raise(new InventoryChangedEventArgs(player, added: inventory.Added, removed: inventory.Removed, quantityChanged: inventory.QuantityChanged)); + } } } } @@ -998,7 +1018,9 @@ namespace StardewModdingAPI.Framework if (instance.IsFirstTick && !Context.IsGameLaunched) { Context.IsGameLaunched = true; - events.GameLaunched.Raise(new GameLaunchedEventArgs()); + + if (events.GameLaunched.HasListeners) + events.GameLaunched.Raise(new GameLaunchedEventArgs()); } // preloaded @@ -1124,9 +1146,11 @@ namespace StardewModdingAPI.Framework } // raise events - this.EventManager.LoadStageChanged.Raise(new LoadStageChangedEventArgs(oldStage, newStage)); + EventManager events = this.EventManager; + if (events.LoadStageChanged.HasListeners) + events.LoadStageChanged.Raise(new LoadStageChangedEventArgs(oldStage, newStage)); if (newStage == LoadStage.None) - this.EventManager.ReturnedToTitle.RaiseEmpty(); + events.ReturnedToTitle.RaiseEmpty(); } /// <summary>A callback invoked before <see cref="Game1.newDayAfterFade"/> runs.</summary> @@ -1156,9 +1180,14 @@ namespace StardewModdingAPI.Framework /// <param name="asset">The asset info being requested.</param> private IList<AssetOperationGroup> RequestAssetOperations(IAssetInfo asset) { - List<AssetOperationGroup> operations = new(); - - this.EventManager.AssetRequested.Raise( + // get event + var @event = this.EventManager.AssetRequested; + if (!@event.HasListeners) + return Array.Empty<AssetOperationGroup>(); + + // get operations + List<AssetOperationGroup>? operations = null; + @event.Raise( invoke: (mod, invoke) => { AssetRequestedEventArgs args = new(mod, asset, this.GetOnBehalfOfContentPack); @@ -1167,6 +1196,7 @@ namespace StardewModdingAPI.Framework if (args.LoadOperations.Any() || args.EditOperations.Any()) { + operations ??= new(); operations.Add( new AssetOperationGroup(mod, args.LoadOperations.ToArray(), args.EditOperations.ToArray()) ); @@ -1174,7 +1204,9 @@ namespace StardewModdingAPI.Framework } ); - return operations; + return operations != null + ? operations + : Array.Empty<AssetOperationGroup>(); } /// <summary>Get the mod metadata for a content pack whose ID matches <paramref name="id"/>, if it's a valid content pack for the given <paramref name="mod"/>.</summary> @@ -1226,23 +1258,26 @@ namespace StardewModdingAPI.Framework /// <param name="message">The message to deliver to applicable mods.</param> private void OnModMessageReceived(ModMessageModel message) { - // get mod IDs to notify - HashSet<string> modIDs = new HashSet<string>(message.ToModIDs ?? this.ModRegistry.GetAll().Select(p => p.Manifest.UniqueID), StringComparer.OrdinalIgnoreCase); - if (message.FromPlayerID == Game1.player?.UniqueMultiplayerID) - modIDs.Remove(message.FromModID); // don't send a broadcast back to the sender - - // raise events - ModMessageReceivedEventArgs? args = null; - this.EventManager.ModMessageReceived.Raise( - invoke: (mod, invoke) => - { - if (modIDs.Contains(mod.Manifest.UniqueID)) + if (this.EventManager.ModMessageReceived.HasListeners) + { + // get mod IDs to notify + HashSet<string> modIDs = new(message.ToModIDs ?? this.ModRegistry.GetAll().Select(p => p.Manifest.UniqueID), StringComparer.OrdinalIgnoreCase); + if (message.FromPlayerID == Game1.player?.UniqueMultiplayerID) + modIDs.Remove(message.FromModID); // don't send a broadcast back to the sender + + // raise events + ModMessageReceivedEventArgs? args = null; + this.EventManager.ModMessageReceived.Raise( + invoke: (mod, invoke) => { - args ??= new(message, this.Toolkit.JsonHelper); - invoke(args); + if (modIDs.Contains(mod.Manifest.UniqueID)) + { + args ??= new(message, this.Toolkit.JsonHelper); + invoke(args); + } } - } - ); + ); + } } /// <summary>Constructor a content manager to read game content files.</summary> diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs index 2badcbbf..441a50ef 100644 --- a/src/SMAPI/Framework/SMultiplayer.cs +++ b/src/SMAPI/Framework/SMultiplayer.cs @@ -235,7 +235,8 @@ namespace StardewModdingAPI.Framework } // raise event - this.EventManager.PeerContextReceived.Raise(new PeerContextReceivedEventArgs(newPeer)); + if (this.EventManager.PeerContextReceived.HasListeners) + this.EventManager.PeerContextReceived.Raise(new PeerContextReceivedEventArgs(newPeer)); } break; @@ -259,7 +260,8 @@ namespace StardewModdingAPI.Framework resume(); // raise event - this.EventManager.PeerConnected.Raise(new PeerConnectedEventArgs(this.Peers[message.FarmerID])); + if (this.EventManager.PeerConnected.HasListeners) + this.EventManager.PeerConnected.Raise(new PeerConnectedEventArgs(this.Peers[message.FarmerID])); break; // handle mod message @@ -370,7 +372,9 @@ namespace StardewModdingAPI.Framework { this.Monitor.Log($"Player quit: {playerID}"); this.Peers.Remove(playerID); - this.EventManager.PeerDisconnected.Raise(new PeerDisconnectedEventArgs(peer)); + + if (this.EventManager.PeerDisconnected.HasListeners) + this.EventManager.PeerDisconnected.Raise(new PeerDisconnectedEventArgs(peer)); } } @@ -481,7 +485,7 @@ namespace StardewModdingAPI.Framework this.HostPeer = peer; // raise event - if (raiseEvent) + if (raiseEvent && this.EventManager.PeerContextReceived.HasListeners) this.EventManager.PeerContextReceived.Raise(new PeerContextReceivedEventArgs(peer)); } |