From 270d436a176904ab39fc0ce97da2027dd6ac1114 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 18 Dec 2018 20:15:39 -0500 Subject: remove shell code in Windows installer to reduce antivirus false positives --- src/SMAPI.Installer/InteractiveInstaller.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index d5866c74..95aed4ca 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; @@ -13,6 +12,9 @@ using StardewModdingAPI.Internal.ConsoleWriting; using StardewModdingAPI.Toolkit; using StardewModdingAPI.Toolkit.Framework.ModScanning; using StardewModdingAPI.Toolkit.Utilities; +#if !SMAPI_FOR_WINDOWS +using System.Diagnostics; +#endif namespace StardewModdingApi.Installer { @@ -461,6 +463,8 @@ namespace StardewModdingApi.Installer // mark file executable // (MSBuild doesn't keep permission flags for files zipped in a build task.) + // (Note: exclude from Windows build because antivirus apps can flag the process start code as suspicious.) +#if !SMAPI_FOR_WINDOWS new Process { StartInfo = new ProcessStartInfo @@ -470,6 +474,7 @@ namespace StardewModdingApi.Installer CreateNoWindow = true } }.Start(); +#endif } // create mods directory (if needed) -- cgit From 7294cb3cc5aeed2849827b192c54db2059fe6a5f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 22 Dec 2018 16:08:52 -0500 Subject: add world_clear console command --- docs/release-notes.md | 1 + .../Framework/Commands/World/ClearCommand.cs | 246 +++++++++++++++++++++ .../StardewModdingAPI.Mods.ConsoleCommands.csproj | 1 + 3 files changed, 248 insertions(+) create mode 100644 src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index 41a6cd83..ca47a687 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,7 @@ # Release notes ## Upcoming release * For players: + * Added `world_clear` console command to remove spawned or placed entities. * Tweaked installer to reduce antivirus false positives. ## 2.9.3 diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs new file mode 100644 index 00000000..9b5f07de --- /dev/null +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using StardewValley; +using StardewValley.Locations; +using StardewValley.Objects; +using StardewValley.TerrainFeatures; +using SObject = StardewValley.Object; + +namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World +{ + /// A command which clears in-game objects. + internal class ClearCommand : TrainerCommand + { + /********* + ** Properties + *********/ + /// The valid types that can be cleared. + private readonly string[] ValidTypes = { "debris", "fruit-trees", "grass", "trees", "everything" }; + + /// The resource clump IDs to consider debris. + private readonly int[] DebrisClumps = { ResourceClump.stumpIndex, ResourceClump.hollowLogIndex, ResourceClump.meteoriteIndex, ResourceClump.boulderIndex }; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + public ClearCommand() + : base( + name: "world_clear", + description: "Clears in-game entities in a given location.\n\n" + + "Usage: world_clear \n" + + "- location: the location name for which to clear objects (like Farm), or 'current' for the current location.\n" + + " - object type: the type of object clear. You can specify 'debris' (stones/twigs/weeds and dead crops), 'grass', and 'trees' / 'fruit-trees'. You can also specify 'everything', which includes things not removed by the other types (like furniture or resource clumps)." + ) + { } + + /// Handle the command. + /// Writes messages to the console and log file. + /// The command name. + /// The command arguments. + public override void Handle(IMonitor monitor, string command, ArgumentParser args) + { + // check context + if (!Context.IsWorldReady) + { + monitor.Log("You need to load a save to use this command.", LogLevel.Error); + return; + } + + // parse arguments + if (!args.TryGet(0, "location", out string locationName, required: true)) + return; + if (!args.TryGet(1, "object type", out string type, required: true, oneOf: this.ValidTypes)) + return; + + // get target location + GameLocation location = Game1.locations.FirstOrDefault(p => p.Name != null && p.Name.Equals(locationName, StringComparison.InvariantCultureIgnoreCase)); + if (location == null && locationName == "current") + location = Game1.currentLocation; + if (location == null) + { + string[] locationNames = (from loc in Game1.locations where !string.IsNullOrWhiteSpace(loc.Name) orderby loc.Name select loc.Name).ToArray(); + monitor.Log($"Could not find a location with that name. Must be one of [{string.Join(", ", locationNames)}].", LogLevel.Error); + return; + } + + // apply + switch (type) + { + case "debris": + { + int removed = 0; + foreach (var pair in location.terrainFeatures.Pairs.ToArray()) + { + TerrainFeature feature = pair.Value; + if (feature is HoeDirt dirt && dirt.crop?.dead == true) + { + dirt.crop = null; + removed++; + } + } + + removed += + this.RemoveObjects(location, obj => obj.Name.ToLower().Contains("weed") || obj.Name == "Twig" || obj.Name == "Stone") + + this.RemoveResourceClumps(location, clump => this.DebrisClumps.Contains(clump.parentSheetIndex.Value)); + + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + + case "fruit-trees": + { + int removed = this.RemoveTerrainFeatures(location, feature => feature is FruitTree); + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + + case "grass": + { + int removed = this.RemoveTerrainFeatures(location, feature => feature is Grass); + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + + case "trees": + { + int removed = this.RemoveTerrainFeatures(location, feature => feature is Tree); + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + + case "everything": + { + int removed = + this.RemoveFurniture(location, p => true) + + this.RemoveObjects(location, p => true) + + this.RemoveTerrainFeatures(location, p => true) + + this.RemoveLargeTerrainFeatures(location, p => true) + + this.RemoveResourceClumps(location, p => true); + monitor.Log($"Done! Removed {removed} entities from {location.Name}.", LogLevel.Info); + break; + } + + default: + monitor.Log($"Unknown type '{type}'. Must be one [{string.Join(", ", this.ValidTypes)}].", LogLevel.Error); + break; + } + } + + + /********* + ** Private methods + *********/ + /// Remove objects from a location matching a lambda. + /// The location to search. + /// Whether an entity should be removed. + /// Returns the number of removed entities. + private int RemoveObjects(GameLocation location, Func shouldRemove) + { + int removed = 0; + + foreach (var pair in location.Objects.Pairs.ToArray()) + { + if (shouldRemove(pair.Value)) + { + location.Objects.Remove(pair.Key); + removed++; + } + } + + return removed; + } + + /// Remove terrain features from a location matching a lambda. + /// The location to search. + /// Whether an entity should be removed. + /// Returns the number of removed entities. + private int RemoveTerrainFeatures(GameLocation location, Func shouldRemove) + { + int removed = 0; + + foreach (var pair in location.terrainFeatures.Pairs.ToArray()) + { + if (shouldRemove(pair.Value)) + { + location.terrainFeatures.Remove(pair.Key); + removed++; + } + } + + return removed; + } + + /// Remove large terrain features from a location matching a lambda. + /// The location to search. + /// Whether an entity should be removed. + /// Returns the number of removed entities. + private int RemoveLargeTerrainFeatures(GameLocation location, Func shouldRemove) + { + int removed = 0; + + foreach (LargeTerrainFeature feature in location.largeTerrainFeatures.ToArray()) + { + if (shouldRemove(feature)) + { + location.largeTerrainFeatures.Remove(feature); + removed++; + } + } + + return removed; + } + + /// Remove resource clumps from a location matching a lambda. + /// The location to search. + /// Whether an entity should be removed. + /// Returns the number of removed entities. + private int RemoveResourceClumps(GameLocation location, Func shouldRemove) + { + int removed = 0; + + // get resource clumps + IList resourceClumps = + (location as Farm)?.resourceClumps + ?? (IList)(location as Woods)?.stumps + ?? new List(); + + // remove matching clumps + foreach (var clump in resourceClumps.ToArray()) + { + if (shouldRemove(clump)) + { + resourceClumps.Remove(clump); + removed++; + } + } + + return removed; + } + + /// Remove furniture from a location matching a lambda. + /// The location to search. + /// Whether an entity should be removed. + /// Returns the number of removed entities. + private int RemoveFurniture(GameLocation location, Func shouldRemove) + { + int removed = 0; + + if (location is DecoratableLocation decoratableLocation) + { + foreach (Furniture furniture in decoratableLocation.furniture.ToArray()) + { + if (shouldRemove(furniture)) + { + decoratableLocation.furniture.Remove(furniture); + removed++; + } + } + } + + return removed; + } + } +} diff --git a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj index d1f16e41..a3237a3d 100644 --- a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj +++ b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj @@ -62,6 +62,7 @@ + -- cgit From 4b325f61b370b24403fa10616178dceefa773420 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 23 Dec 2018 16:51:38 -0500 Subject: allow Read/WriteSaveFile as soon as the save is loaded --- docs/release-notes.md | 3 +++ src/SMAPI/Framework/ModHelpers/DataHelper.cs | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index ca47a687..eacf0955 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -4,6 +4,9 @@ * Added `world_clear` console command to remove spawned or placed entities. * Tweaked installer to reduce antivirus false positives. +* For modders: + * You can now use `ReadSaveData` or `WriteSaveData` immediately after the save is loaded, before the in-game world is initialised. + ## 2.9.3 * For players: * Fixed errors hovering items in some cases with SMAPI 2.9.2. diff --git a/src/SMAPI/Framework/ModHelpers/DataHelper.cs b/src/SMAPI/Framework/ModHelpers/DataHelper.cs index e5100aed..242b8ab1 100644 --- a/src/SMAPI/Framework/ModHelpers/DataHelper.cs +++ b/src/SMAPI/Framework/ModHelpers/DataHelper.cs @@ -77,9 +77,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The player hasn't loaded a save file yet or isn't the main player. public TModel ReadSaveData(string key) where TModel : class { - if (!Context.IsSaveLoaded) + if (!Game1.hasLoadedGame) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.ReadSaveData)} when a save file isn't loaded."); - if (!Context.IsMainPlayer) + if (!Game1.IsMasterGame) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.ReadSaveData)} because this isn't the main player. (Save files are stored on the main player's computer.)"); return Game1.CustomData.TryGetValue(this.GetSaveFileKey(key), out string value) @@ -94,9 +94,9 @@ namespace StardewModdingAPI.Framework.ModHelpers /// The player hasn't loaded a save file yet or isn't the main player. public void WriteSaveData(string key, TModel data) where TModel : class { - if (!Context.IsSaveLoaded) + if (!Game1.hasLoadedGame) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.WriteSaveData)} when a save file isn't loaded."); - if (!Context.IsMainPlayer) + if (!Game1.IsMasterGame) throw new InvalidOperationException($"Can't use {nameof(IMod.Helper)}.{nameof(IModHelper.Data)}.{nameof(this.ReadSaveData)} because this isn't the main player. (Save files are stored on the main player's computer.)"); string internalKey = this.GetSaveFileKey(key); -- cgit From 041bd2d6ba726eeea88afed3be307343a6f9286b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 23 Dec 2018 19:26:02 -0500 Subject: add Specialised.SavePreloaded event --- docs/release-notes.md | 3 ++- src/SMAPI/Events/IGameLoopEvents.cs | 2 +- src/SMAPI/Events/ISpecialisedEvents.cs | 3 +++ src/SMAPI/Events/SavePreloadedEventArgs.cs | 7 +++++++ src/SMAPI/Framework/Events/EventManager.cs | 6 +++++- src/SMAPI/Framework/Events/ModGameLoopEvents.cs | 2 +- src/SMAPI/Framework/Events/ModSpecialisedEvents.cs | 7 +++++++ src/SMAPI/Framework/SGame.cs | 23 ++++++++++++++++++---- src/SMAPI/StardewModdingAPI.csproj | 1 + 9 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 src/SMAPI/Events/SavePreloadedEventArgs.cs (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index eacf0955..3daca07f 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,7 +5,8 @@ * Tweaked installer to reduce antivirus false positives. * For modders: - * You can now use `ReadSaveData` or `WriteSaveData` immediately after the save is loaded, before the in-game world is initialised. + * Added `Specialised.SavePreloaded` event, which is raised immediately after a save is loaded but before the in-game world is fully initialised. + * You can now use read/write save data as soon as the save is loaded (instead of once the world is initialised). ## 2.9.3 * For players: diff --git a/src/SMAPI/Events/IGameLoopEvents.cs b/src/SMAPI/Events/IGameLoopEvents.cs index e1900f79..ea79aa74 100644 --- a/src/SMAPI/Events/IGameLoopEvents.cs +++ b/src/SMAPI/Events/IGameLoopEvents.cs @@ -26,7 +26,7 @@ namespace StardewModdingAPI.Events /// Raised after the game finishes writing data to the save file (except the initial save creation). event EventHandler Saved; - /// Raised after the player loads a save slot. + /// Raised after the player loads a save slot and the world is initialised. event EventHandler SaveLoaded; /// Raised after the game begins a new day (including when the player loads a save). diff --git a/src/SMAPI/Events/ISpecialisedEvents.cs b/src/SMAPI/Events/ISpecialisedEvents.cs index 928cd05d..2a19113c 100644 --- a/src/SMAPI/Events/ISpecialisedEvents.cs +++ b/src/SMAPI/Events/ISpecialisedEvents.cs @@ -5,6 +5,9 @@ namespace StardewModdingAPI.Events /// Events serving specialised edge cases that shouldn't be used by most mods. public interface ISpecialisedEvents { + /// Raised immediately after the player loads a save slot, but before the world is fully initialised. The save and game data are available at this point, but some in-game content (like location maps) haven't been initialised yet. + event EventHandler SavePreloaded; + /// Raised before the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console. event EventHandler UnvalidatedUpdateTicking; diff --git a/src/SMAPI/Events/SavePreloadedEventArgs.cs b/src/SMAPI/Events/SavePreloadedEventArgs.cs new file mode 100644 index 00000000..03990f5a --- /dev/null +++ b/src/SMAPI/Events/SavePreloadedEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SavePreloadedEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 0ad85adf..bd862046 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -70,7 +70,7 @@ namespace StardewModdingAPI.Framework.Events /// Raised after the game finishes writing data to the save file (except the initial save creation). public readonly ManagedEvent Saved; - /// Raised after the player loads a save slot. + /// Raised after the player loads a save slot and the world is initialised. public readonly ManagedEvent SaveLoaded; /// Raised after the game begins a new day, including when loading a save. @@ -151,6 +151,9 @@ namespace StardewModdingAPI.Framework.Events /**** ** Specialised ****/ + /// Raised immediately after the player loads a save slot, but before the world is fully initialised. + public readonly ManagedEvent SavePreloaded; + /// Raised before the game performs its overall update tick (≈60 times per second). See notes on . public readonly ManagedEvent UnvalidatedUpdateTicking; @@ -408,6 +411,7 @@ namespace StardewModdingAPI.Framework.Events this.ObjectListChanged = ManageEventOf(nameof(IModEvents.World), nameof(IWorldEvents.ObjectListChanged)); this.TerrainFeatureListChanged = ManageEventOf(nameof(IModEvents.World), nameof(IWorldEvents.TerrainFeatureListChanged)); + this.SavePreloaded = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.SavePreloaded)); this.UnvalidatedUpdateTicking = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.UnvalidatedUpdateTicking)); this.UnvalidatedUpdateTicked = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.UnvalidatedUpdateTicked)); diff --git a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs index a5beac99..3a764ab0 100644 --- a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs +++ b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs @@ -58,7 +58,7 @@ namespace StardewModdingAPI.Framework.Events remove => this.EventManager.Saved.Remove(value); } - /// Raised after the player loads a save slot. + /// Raised after the player loads a save slot and the world is initialised. public event EventHandler SaveLoaded { add => this.EventManager.SaveLoaded.Add(value); diff --git a/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs b/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs index 17c32bb8..83e349cf 100644 --- a/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs +++ b/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs @@ -9,6 +9,13 @@ namespace StardewModdingAPI.Framework.Events /********* ** Accessors *********/ + /// Raised immediately after the player loads a save slot, but before the world is fully initialised. The save and game data are available at this point, but some in-game content (like location maps) haven't been initialised yet. + public event EventHandler SavePreloaded + { + add => this.EventManager.SavePreloaded.Add(value); + remove => this.EventManager.SavePreloaded.Remove(value); + } + /// Raised before the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console. public event EventHandler UnvalidatedUpdateTicking { diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index d515d3ad..befd9cef 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -69,8 +69,11 @@ namespace StardewModdingAPI.Framework /// Skipping a few frames ensures the game finishes initialising the world before mods try to change it. private readonly Countdown AfterLoadTimer = new Countdown(5); + /// Whether was raised for this session. + private bool RaisedPreloadedEvent; + /// Whether the after-load events were raised for this session. - private bool RaisedAfterLoadEvent; + private bool RaisedLoadedEvent; /// Whether the game is saving and SMAPI has already raised . private bool IsBetweenSaveEvents; @@ -217,6 +220,7 @@ namespace StardewModdingAPI.Framework private void OnReturnedToTitle() { this.Monitor.Log("Context: returned to title", LogLevel.Trace); + this.RaisedPreloadedEvent = false; this.Multiplayer.CleanupOnMultiplayerExit(); this.Events.ReturnedToTitle.RaiseEmpty(); #if !SMAPI_3_0_STRICT @@ -466,7 +470,7 @@ namespace StardewModdingAPI.Framework *********/ if (wasWorldReady && !Context.IsWorldReady) this.OnReturnedToTitle(); - else if (!this.RaisedAfterLoadEvent && Context.IsWorldReady) + else if (!this.RaisedLoadedEvent && Context.IsWorldReady) { // print context string context = $"Context: loaded saved game '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}."; @@ -480,7 +484,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log(context, LogLevel.Trace); // raise events - this.RaisedAfterLoadEvent = true; + this.RaisedLoadedEvent = true; this.Events.SaveLoaded.RaiseEmpty(); this.Events.DayStarted.RaiseEmpty(); #if !SMAPI_3_0_STRICT @@ -824,8 +828,19 @@ namespace StardewModdingAPI.Framework ** Game update *********/ this.TicksElapsed++; + + // game launched if (this.TicksElapsed == 1) this.Events.GameLaunched.Raise(new GameLaunchedEventArgs()); + + // preloaded + if (Context.IsSaveLoaded && !this.RaisedPreloadedEvent) + { + this.RaisedPreloadedEvent = true; + this.Events.SavePreloaded.RaiseEmpty(); + } + + // update tick this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); this.Events.UpdateTicking.Raise(new UpdateTickingEventArgs(this.TicksElapsed)); try @@ -1639,7 +1654,7 @@ namespace StardewModdingAPI.Framework { Context.IsWorldReady = false; this.AfterLoadTimer.Reset(); - this.RaisedAfterLoadEvent = false; + this.RaisedLoadedEvent = false; } #if !SMAPI_3_0_STRICT diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 9b00e777..36fa7e0b 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -150,6 +150,7 @@ + -- cgit From 6ad52d607c49b16c6933060375086830edd9a1f9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 24 Dec 2018 17:28:58 -0500 Subject: add Specialised.LoadStageChanged event --- docs/release-notes.md | 2 +- src/SMAPI/Enums/LoadStage.cs | 36 +++++++ src/SMAPI/Events/ISpecialisedEvents.cs | 4 +- src/SMAPI/Events/LoadStageChangedEventArgs.cs | 31 ++++++ src/SMAPI/Events/SavePreloadedEventArgs.cs | 7 -- src/SMAPI/Framework/Events/EventManager.cs | 6 +- src/SMAPI/Framework/Events/ModSpecialisedEvents.cs | 8 +- src/SMAPI/Framework/SCore.cs | 13 +-- src/SMAPI/Framework/SGame.cs | 89 +++++++++++------ src/SMAPI/Patches/LoadForNewGamePatch.cs | 109 +++++++++++++++++++++ src/SMAPI/StardewModdingAPI.csproj | 4 +- 11 files changed, 255 insertions(+), 54 deletions(-) create mode 100644 src/SMAPI/Enums/LoadStage.cs create mode 100644 src/SMAPI/Events/LoadStageChangedEventArgs.cs delete mode 100644 src/SMAPI/Events/SavePreloadedEventArgs.cs create mode 100644 src/SMAPI/Patches/LoadForNewGamePatch.cs (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index 3daca07f..15747488 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,7 +5,7 @@ * Tweaked installer to reduce antivirus false positives. * For modders: - * Added `Specialised.SavePreloaded` event, which is raised immediately after a save is loaded but before the in-game world is fully initialised. + * Added `Specialised.LoadStageChanged` for mods which need to do something at a specific point in the game's save loading process. * You can now use read/write save data as soon as the save is loaded (instead of once the world is initialised). ## 2.9.3 diff --git a/src/SMAPI/Enums/LoadStage.cs b/src/SMAPI/Enums/LoadStage.cs new file mode 100644 index 00000000..6ff7de4f --- /dev/null +++ b/src/SMAPI/Enums/LoadStage.cs @@ -0,0 +1,36 @@ +namespace StardewModdingAPI.Enums +{ + /// A low-level stage in the game's loading process. + public enum LoadStage + { + /// A save is not loaded or loading. + None, + + /// The game is creating a new save slot, and has initialised the basic save info. + CreatedBasicInfo, + + /// The game is creating a new save slot, and has initialised the in-game locations. + CreatedLocations, + + /// The game is creating a new save slot, and has created the physical save files. + CreatedSaveFile, + + /// The game is loading a save slot, and has read the raw save data into . Not applicable when connecting to a multiplayer host. This is equivalent to value 20. + SaveParsed, + + /// The game is loading a save slot, and has applied the basic save info (including player data). Not applicable when connecting to a multiplayer host. Note that some basic info (like daily luck) is not initialised at this point. This is equivalent to value 36. + SaveLoadedBasicInfo, + + /// The game is loading a save slot, and has applied the in-game location data. Not applicable when connecting to a multiplayer host. This is equivalent to value 50. + SaveLoadedLocations, + + /// The final metadata has been loaded from the save file. This happens before the game applies problem fixes, checks for achievements, starts music, etc. Not applicable when connecting to a multiplayer host. + Preloaded, + + /// The save is fully loaded, but the world may not be fully initialised yet. + Loaded, + + /// The save is fully loaded, the world has been initialised, and is now true. + Ready + } +} diff --git a/src/SMAPI/Events/ISpecialisedEvents.cs b/src/SMAPI/Events/ISpecialisedEvents.cs index 2a19113c..ecb109e6 100644 --- a/src/SMAPI/Events/ISpecialisedEvents.cs +++ b/src/SMAPI/Events/ISpecialisedEvents.cs @@ -5,8 +5,8 @@ namespace StardewModdingAPI.Events /// Events serving specialised edge cases that shouldn't be used by most mods. public interface ISpecialisedEvents { - /// Raised immediately after the player loads a save slot, but before the world is fully initialised. The save and game data are available at this point, but some in-game content (like location maps) haven't been initialised yet. - event EventHandler SavePreloaded; + /// Raised when the low-level stage in the game's loading process has changed. This is an advanced event for mods which need to run code at specific points in the loading process. The available stages or when they happen might change without warning in future versions (e.g. due to changes in the game's load process), so mods using this event are more likely to break or have bugs. Most mods should use instead. + event EventHandler LoadStageChanged; /// Raised before the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console. event EventHandler UnvalidatedUpdateTicking; diff --git a/src/SMAPI/Events/LoadStageChangedEventArgs.cs b/src/SMAPI/Events/LoadStageChangedEventArgs.cs new file mode 100644 index 00000000..e837a5f1 --- /dev/null +++ b/src/SMAPI/Events/LoadStageChangedEventArgs.cs @@ -0,0 +1,31 @@ +using System; +using StardewModdingAPI.Enums; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class LoadStageChangedEventArgs : EventArgs + { + /********* + ** Accessors + *********/ + /// The previous load stage. + public LoadStage OldStage { get; } + + /// The new load stage. + public LoadStage NewStage { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The previous load stage. + /// The new load stage. + public LoadStageChangedEventArgs(LoadStage old, LoadStage current) + { + this.OldStage = old; + this.NewStage = current; + } + } +} diff --git a/src/SMAPI/Events/SavePreloadedEventArgs.cs b/src/SMAPI/Events/SavePreloadedEventArgs.cs deleted file mode 100644 index 03990f5a..00000000 --- a/src/SMAPI/Events/SavePreloadedEventArgs.cs +++ /dev/null @@ -1,7 +0,0 @@ -using System; - -namespace StardewModdingAPI.Events -{ - /// Event arguments for an event. - public class SavePreloadedEventArgs : EventArgs { } -} diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index bd862046..b7f00f52 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -151,8 +151,8 @@ namespace StardewModdingAPI.Framework.Events /**** ** Specialised ****/ - /// Raised immediately after the player loads a save slot, but before the world is fully initialised. - public readonly ManagedEvent SavePreloaded; + /// Raised when the low-level stage in the game's loading process has changed. See notes on . + public readonly ManagedEvent LoadStageChanged; /// Raised before the game performs its overall update tick (≈60 times per second). See notes on . public readonly ManagedEvent UnvalidatedUpdateTicking; @@ -411,7 +411,7 @@ namespace StardewModdingAPI.Framework.Events this.ObjectListChanged = ManageEventOf(nameof(IModEvents.World), nameof(IWorldEvents.ObjectListChanged)); this.TerrainFeatureListChanged = ManageEventOf(nameof(IModEvents.World), nameof(IWorldEvents.TerrainFeatureListChanged)); - this.SavePreloaded = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.SavePreloaded)); + this.LoadStageChanged = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.LoadStageChanged)); this.UnvalidatedUpdateTicking = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.UnvalidatedUpdateTicking)); this.UnvalidatedUpdateTicked = ManageEventOf(nameof(IModEvents.Specialised), nameof(ISpecialisedEvents.UnvalidatedUpdateTicked)); diff --git a/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs b/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs index 83e349cf..7c3e9dee 100644 --- a/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs +++ b/src/SMAPI/Framework/Events/ModSpecialisedEvents.cs @@ -9,11 +9,11 @@ namespace StardewModdingAPI.Framework.Events /********* ** Accessors *********/ - /// Raised immediately after the player loads a save slot, but before the world is fully initialised. The save and game data are available at this point, but some in-game content (like location maps) haven't been initialised yet. - public event EventHandler SavePreloaded + /// Raised when the low-level stage in the game's loading process has changed. This is an advanced event for mods which need to run code at specific points in the loading process. The available stages or when they happen might change without warning in future versions (e.g. due to changes in the game's load process), so mods using this event are more likely to break or have bugs. Most mods should use instead. + public event EventHandler LoadStageChanged { - add => this.EventManager.SavePreloaded.Add(value); - remove => this.EventManager.SavePreloaded.Remove(value); + add => this.EventManager.LoadStageChanged.Add(value); + remove => this.EventManager.LoadStageChanged.Remove(value); } /// Raised before the game state is updated (≈60 times per second), regardless of normal SMAPI validation. This event is not thread-safe and may be invoked while game logic is running asynchronously. Changes to game state in this method may crash the game or corrupt an in-progress save. Do not use this event unless you're fully aware of the context in which your code will be run. Mods using this event will trigger a stability warning in the SMAPI console. diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 679838ba..00801b72 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -181,12 +181,6 @@ namespace StardewModdingAPI.Framework return; } #endif - - // apply game patches - new GamePatcher(this.Monitor).Apply( - new DialogueErrorPatch(this.MonitorForGame, this.Reflection), - new ObjectErrorPatch() - ); } /// Launch SMAPI. @@ -237,6 +231,13 @@ namespace StardewModdingAPI.Framework this.GameInstance = new SGame(this.Monitor, this.MonitorForGame, this.Reflection, this.EventManager, this.Toolkit.JsonHelper, this.ModRegistry, SCore.DeprecationManager, this.OnLocaleChanged, this.InitialiseAfterGameStart, this.Dispose); StardewValley.Program.gamePtr = this.GameInstance; + // apply game patches + new GamePatcher(this.Monitor).Apply( + new DialogueErrorPatch(this.MonitorForGame, this.Reflection), + new ObjectErrorPatch(), + new LoadForNewGamePatch(this.Reflection, this.GameInstance.OnLoadStageChanged) + ); + // add exit handler new Thread(() => { diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index befd9cef..cb62de2a 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -69,11 +69,8 @@ namespace StardewModdingAPI.Framework /// Skipping a few frames ensures the game finishes initialising the world before mods try to change it. private readonly Countdown AfterLoadTimer = new Countdown(5); - /// Whether was raised for this session. - private bool RaisedPreloadedEvent; - - /// Whether the after-load events were raised for this session. - private bool RaisedLoadedEvent; + /// The current stage in the game's loading process. + private LoadStage LoadStage = LoadStage.None; /// Whether the game is saving and SMAPI has already raised . private bool IsBetweenSaveEvents; @@ -216,16 +213,33 @@ namespace StardewModdingAPI.Framework this.Events.ModMessageReceived.RaiseForMods(new ModMessageReceivedEventArgs(message), mod => mod != null && modIDs.Contains(mod.Manifest.UniqueID)); } - /// A callback raised when the player quits a save and returns to the title screen. - private void OnReturnedToTitle() + /// A callback invoked when the game's low-level load stage changes. + /// The new load stage. + internal void OnLoadStageChanged(LoadStage newStage) { - this.Monitor.Log("Context: returned to title", LogLevel.Trace); - this.RaisedPreloadedEvent = false; - this.Multiplayer.CleanupOnMultiplayerExit(); - this.Events.ReturnedToTitle.RaiseEmpty(); + // nothing to do + if (newStage == this.LoadStage) + return; + + // update data + LoadStage oldStage = this.LoadStage; + this.LoadStage = newStage; + if (newStage == LoadStage.None) + { + this.Monitor.Log("Context: returned to title", LogLevel.Trace); + this.Multiplayer.CleanupOnMultiplayerExit(); + } + this.Monitor.VerboseLog($"Context: load stage changed to {newStage}"); + + // raise events + this.Events.LoadStageChanged.Raise(new LoadStageChangedEventArgs(oldStage, newStage)); + if (newStage == LoadStage.None) + { + this.Events.ReturnedToTitle.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_AfterReturnToTitle.Raise(); + this.Events.Legacy_AfterReturnToTitle.Raise(); #endif + } } /// Constructor a content manager to read XNB files. @@ -284,7 +298,29 @@ namespace StardewModdingAPI.Framework { this.Monitor.Log("Game loader synchronising...", LogLevel.Trace); while (Game1.currentLoader?.MoveNext() == true) - ; + { + // raise load stage changed + switch (Game1.currentLoader.Current) + { + case 20: + this.OnLoadStageChanged(LoadStage.SaveParsed); + break; + + case 36: + this.OnLoadStageChanged(LoadStage.SaveLoadedBasicInfo); + break; + + case 50: + this.OnLoadStageChanged(LoadStage.SaveLoadedLocations); + break; + + default: + if (Game1.gameMode == Game1.playingGameMode) + this.OnLoadStageChanged(LoadStage.Preloaded); + break; + } + } + Game1.currentLoader = null; this.Monitor.Log("Game loader done.", LogLevel.Trace); } @@ -411,6 +447,7 @@ namespace StardewModdingAPI.Framework // raise after-create this.IsBetweenCreateEvents = false; this.Monitor.Log($"Context: after save creation, starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}.", LogLevel.Trace); + this.OnLoadStageChanged(LoadStage.CreatedSaveFile); this.Events.SaveCreated.RaiseEmpty(); #if !SMAPI_3_0_STRICT this.Events.Legacy_AfterCreateSave.Raise(); @@ -434,7 +471,10 @@ namespace StardewModdingAPI.Framework *********/ bool wasWorldReady = Context.IsWorldReady; if ((Context.IsWorldReady && !Context.IsSaveLoaded) || Game1.exitToTitle) - this.MarkWorldNotReady(); + { + Context.IsWorldReady = false; + this.AfterLoadTimer.Reset(); + } else if (Context.IsSaveLoaded && this.AfterLoadTimer.Current > 0 && Game1.currentLocation != null) { if (Game1.dayOfMonth != 0) // wait until new-game intro finishes (world not fully initialised yet) @@ -469,8 +509,8 @@ namespace StardewModdingAPI.Framework ** Load / return-to-title events *********/ if (wasWorldReady && !Context.IsWorldReady) - this.OnReturnedToTitle(); - else if (!this.RaisedLoadedEvent && Context.IsWorldReady) + this.OnLoadStageChanged(LoadStage.None); + else if (Context.IsWorldReady && this.LoadStage != LoadStage.Ready) { // print context string context = $"Context: loaded saved game '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}."; @@ -484,7 +524,7 @@ namespace StardewModdingAPI.Framework this.Monitor.Log(context, LogLevel.Trace); // raise events - this.RaisedLoadedEvent = true; + this.OnLoadStageChanged(LoadStage.Ready); this.Events.SaveLoaded.RaiseEmpty(); this.Events.DayStarted.RaiseEmpty(); #if !SMAPI_3_0_STRICT @@ -834,11 +874,8 @@ namespace StardewModdingAPI.Framework this.Events.GameLaunched.Raise(new GameLaunchedEventArgs()); // preloaded - if (Context.IsSaveLoaded && !this.RaisedPreloadedEvent) - { - this.RaisedPreloadedEvent = true; - this.Events.SavePreloaded.RaiseEmpty(); - } + if (Context.IsSaveLoaded && this.LoadStage != LoadStage.Loaded && this.LoadStage != LoadStage.Ready) + this.OnLoadStageChanged(LoadStage.Loaded); // update tick this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); @@ -1649,14 +1686,6 @@ namespace StardewModdingAPI.Framework /**** ** Methods ****/ - /// Perform any cleanup needed when a save is unloaded. - private void MarkWorldNotReady() - { - Context.IsWorldReady = false; - this.AfterLoadTimer.Reset(); - this.RaisedLoadedEvent = false; - } - #if !SMAPI_3_0_STRICT /// Raise the if there are any listeners. /// Whether to create a new sprite batch. diff --git a/src/SMAPI/Patches/LoadForNewGamePatch.cs b/src/SMAPI/Patches/LoadForNewGamePatch.cs new file mode 100644 index 00000000..9e788e84 --- /dev/null +++ b/src/SMAPI/Patches/LoadForNewGamePatch.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.Reflection; +using Harmony; +using StardewModdingAPI.Enums; +using StardewModdingAPI.Framework.Patching; +using StardewModdingAPI.Framework.Reflection; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Patches +{ + /// A Harmony patch for which notifies SMAPI for save creation load stages. + /// This patch hooks into , checks if TitleMenu.transitioningCharacterCreationMenu is true (which means the player is creating a new save file), then raises after the location list is cleared twice (the second clear happens right before locations are created), and when the method ends. + internal class LoadForNewGamePatch : IHarmonyPatch + { + /********* + ** Accessors + *********/ + /// Simplifies access to private code. + private static Reflector Reflection; + + /// A callback to invoke when the load stage changes. + private static Action OnStageChanged; + + /// Whether was called as part of save creation. + private static bool IsCreating; + + /// The number of times that has been cleared since started. + private static int TimesLocationsCleared = 0; + + + /********* + ** Accessors + *********/ + /// A unique name for this patch. + public string Name => $"{nameof(LoadForNewGamePatch)}"; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// Simplifies access to private code. + /// A callback to invoke when the load stage changes. + public LoadForNewGamePatch(Reflector reflection, Action onStageChanged) + { + LoadForNewGamePatch.Reflection = reflection; + LoadForNewGamePatch.OnStageChanged = onStageChanged; + } + + /// Apply the Harmony patch. + /// The Harmony instance. + public void Apply(HarmonyInstance harmony) + { + MethodInfo method = AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)); + MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Prefix)); + MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(LoadForNewGamePatch.Postfix)); + + harmony.Patch(method, new HarmonyMethod(prefix), new HarmonyMethod(postfix)); + } + + + /********* + ** Private methods + *********/ + /// The method to call instead of . + /// Returns whether to execute the original method. + /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. + private static bool Prefix() + { + LoadForNewGamePatch.IsCreating = Game1.activeClickableMenu is TitleMenu menu && LoadForNewGamePatch.Reflection.GetField(menu, "transitioningCharacterCreationMenu").GetValue(); + LoadForNewGamePatch.TimesLocationsCleared = 0; + if (LoadForNewGamePatch.IsCreating) + { + // raise CreatedBasicInfo after locations are cleared twice + ObservableCollection locations = (ObservableCollection)Game1.locations; + locations.CollectionChanged += LoadForNewGamePatch.OnLocationListChanged; + } + + return true; + } + + /// The method to call instead after . + /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. + private static void Postfix() + { + if (LoadForNewGamePatch.IsCreating) + { + // clean up + ObservableCollection locations = (ObservableCollection) Game1.locations; + locations.CollectionChanged -= LoadForNewGamePatch.OnLocationListChanged; + + // raise stage changed + LoadForNewGamePatch.OnStageChanged(LoadStage.CreatedLocations); + } + } + + /// Raised when changes. + /// The event sender. + /// The event arguments. + private static void OnLocationListChanged(object sender, NotifyCollectionChangedEventArgs e) + { + if (++LoadForNewGamePatch.TimesLocationsCleared == 2) + LoadForNewGamePatch.OnStageChanged(LoadStage.CreatedBasicInfo); + } + } +} diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 36fa7e0b..fdb0c6c7 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -76,6 +76,7 @@ Properties\GlobalAssemblyInfo.cs + @@ -123,6 +124,7 @@ + @@ -150,7 +152,6 @@ - @@ -327,6 +328,7 @@ + -- cgit From 8e0573d7d9f18792a19e741660b6a090cca1fb38 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 25 Dec 2018 15:10:22 -0500 Subject: add GameLoop.OneSecondUpdateTicking/Ticked --- docs/release-notes.md | 1 + src/SMAPI/Events/IGameLoopEvents.cs | 6 ++++ src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs | 32 ++++++++++++++++++++++ .../Events/OneSecondUpdateTickingEventArgs.cs | 32 ++++++++++++++++++++++ src/SMAPI/Framework/Events/EventManager.cs | 8 ++++++ src/SMAPI/Framework/Events/ModGameLoopEvents.cs | 14 ++++++++++ src/SMAPI/Framework/SGame.cs | 5 ++++ src/SMAPI/StardewModdingAPI.csproj | 2 ++ 8 files changed, 100 insertions(+) create mode 100644 src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs create mode 100644 src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index 15747488..5293f1c1 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,6 +5,7 @@ * Tweaked installer to reduce antivirus false positives. * For modders: + * Added `GameLoop.OneSecondUpdateTicking/Ticked` events. * Added `Specialised.LoadStageChanged` for mods which need to do something at a specific point in the game's save loading process. * You can now use read/write save data as soon as the save is loaded (instead of once the world is initialised). diff --git a/src/SMAPI/Events/IGameLoopEvents.cs b/src/SMAPI/Events/IGameLoopEvents.cs index ea79aa74..6fb56c8b 100644 --- a/src/SMAPI/Events/IGameLoopEvents.cs +++ b/src/SMAPI/Events/IGameLoopEvents.cs @@ -14,6 +14,12 @@ namespace StardewModdingAPI.Events /// Raised after the game state is updated (≈60 times per second). event EventHandler UpdateTicked; + /// Raised once per second before the game state is updated. + event EventHandler OneSecondUpdateTicking; + + /// Raised once per second after the game state is updated. + event EventHandler OneSecondUpdateTicked; + /// Raised before the game creates a new save file. event EventHandler SaveCreating; diff --git a/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs b/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs new file mode 100644 index 00000000..d330502a --- /dev/null +++ b/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs @@ -0,0 +1,32 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class OneSecondUpdateTickedEventArgs : EventArgs + { + /********* + ** Accessors + *********/ + /// The number of ticks elapsed since the game started, including the current tick. + public uint Ticks { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The number of ticks elapsed since the game started, including the current tick. + internal OneSecondUpdateTickedEventArgs(uint ticks) + { + this.Ticks = ticks; + } + + /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). + /// The factor to check. + public bool IsMultipleOf(uint number) + { + return this.Ticks % number == 0; + } + } +} diff --git a/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs b/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs new file mode 100644 index 00000000..cdd9f4cc --- /dev/null +++ b/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs @@ -0,0 +1,32 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class OneSecondUpdateTickingEventArgs : EventArgs + { + /********* + ** Accessors + *********/ + /// The number of ticks elapsed since the game started, including the current tick. + public uint Ticks { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The number of ticks elapsed since the game started, including the current tick. + internal OneSecondUpdateTickingEventArgs(uint ticks) + { + this.Ticks = ticks; + } + + /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). + /// The factor to check. + public bool IsMultipleOf(uint number) + { + return this.Ticks % number == 0; + } + } +} diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index b7f00f52..13244601 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -58,6 +58,12 @@ namespace StardewModdingAPI.Framework.Events /// Raised after the game performs its overall update tick (≈60 times per second). public readonly ManagedEvent UpdateTicked; + /// Raised once per second before the game performs its overall update tick. + public readonly ManagedEvent OneSecondUpdateTicking; + + /// Raised once per second after the game performs its overall update tick. + public readonly ManagedEvent OneSecondUpdateTicked; + /// Raised before the game creates the save file. public readonly ManagedEvent SaveCreating; @@ -380,6 +386,8 @@ namespace StardewModdingAPI.Framework.Events this.GameLaunched = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.GameLaunched)); this.UpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicking)); this.UpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.UpdateTicked)); + this.OneSecondUpdateTicking = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicking)); + this.OneSecondUpdateTicked = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.OneSecondUpdateTicked)); this.SaveCreating = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.SaveCreating)); this.SaveCreated = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.SaveCreated)); this.Saving = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.Saving)); diff --git a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs index 3a764ab0..0177c22e 100644 --- a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs +++ b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs @@ -30,6 +30,20 @@ namespace StardewModdingAPI.Framework.Events remove => this.EventManager.UpdateTicked.Remove(value); } + /// Raised once per second before the game state is updated. + public event EventHandler OneSecondUpdateTicking + { + add => this.EventManager.OneSecondUpdateTicking.Add(value); + remove => this.EventManager.OneSecondUpdateTicking.Remove(value); + } + + /// Raised once per second after the game state is updated. + public event EventHandler OneSecondUpdateTicked + { + add => this.EventManager.OneSecondUpdateTicked.Add(value); + remove => this.EventManager.OneSecondUpdateTicked.Remove(value); + } + /// Raised before the game creates a new save file. public event EventHandler SaveCreating { diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index cb62de2a..8abe4d16 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -878,8 +878,11 @@ namespace StardewModdingAPI.Framework this.OnLoadStageChanged(LoadStage.Loaded); // update tick + bool isOneSecond = this.TicksElapsed % 60 == 0; this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); this.Events.UpdateTicking.Raise(new UpdateTickingEventArgs(this.TicksElapsed)); + if (isOneSecond) + this.Events.OneSecondUpdateTicking.Raise(new OneSecondUpdateTickingEventArgs(this.TicksElapsed)); try { this.Input.UpdateSuppression(); @@ -891,6 +894,8 @@ namespace StardewModdingAPI.Framework } this.Events.UnvalidatedUpdateTicked.Raise(new UnvalidatedUpdateTickedEventArgs(this.TicksElapsed)); this.Events.UpdateTicked.Raise(new UpdateTickedEventArgs(this.TicksElapsed)); + if (isOneSecond) + this.Events.OneSecondUpdateTicked.Raise(new OneSecondUpdateTickedEventArgs(this.TicksElapsed)); /********* ** Update events diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index fdb0c6c7..5540f277 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -135,6 +135,8 @@ + + -- cgit From 382b5fe914894b87e44462060ca7ae8415c9533e Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 25 Dec 2018 15:12:58 -0500 Subject: minor performance optimisation --- docs/release-notes.md | 1 + src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs | 10 +- .../Events/OneSecondUpdateTickingEventArgs.cs | 10 +- .../Events/UnvalidatedUpdateTickedEventArgs.cs | 13 +- .../Events/UnvalidatedUpdateTickingEventArgs.cs | 13 +- src/SMAPI/Events/UpdateTickedEventArgs.cs | 13 +- src/SMAPI/Events/UpdateTickingEventArgs.cs | 13 +- src/SMAPI/Framework/Events/ManagedEvent.cs | 2 + src/SMAPI/Framework/SGame.cs | 294 +++++++++++---------- 9 files changed, 167 insertions(+), 202 deletions(-) (limited to 'src') diff --git a/docs/release-notes.md b/docs/release-notes.md index 5293f1c1..3913862b 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,6 +2,7 @@ ## Upcoming release * For players: * Added `world_clear` console command to remove spawned or placed entities. + * Minor performance improvement. * Tweaked installer to reduce antivirus false positives. * For modders: diff --git a/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs b/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs index d330502a..dadbb71a 100644 --- a/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs +++ b/src/SMAPI/Events/OneSecondUpdateTickedEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,19 +10,12 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal OneSecondUpdateTickedEventArgs(uint ticks) - { - this.Ticks = ticks; - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs b/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs index cdd9f4cc..e9bb46c6 100644 --- a/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs +++ b/src/SMAPI/Events/OneSecondUpdateTickingEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,19 +10,12 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal OneSecondUpdateTickingEventArgs(uint ticks) - { - this.Ticks = ticks; - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Events/UnvalidatedUpdateTickedEventArgs.cs b/src/SMAPI/Events/UnvalidatedUpdateTickedEventArgs.cs index 95ae59d8..d15e9531 100644 --- a/src/SMAPI/Events/UnvalidatedUpdateTickedEventArgs.cs +++ b/src/SMAPI/Events/UnvalidatedUpdateTickedEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,23 +10,15 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /// Whether is a multiple of 60, which happens approximately once per second. - public bool IsOneSecond { get; } + public bool IsOneSecond => Game1.ticks % 60 == 0; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal UnvalidatedUpdateTickedEventArgs(uint ticks) - { - this.Ticks = ticks; - this.IsOneSecond = this.IsMultipleOf(60); - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Events/UnvalidatedUpdateTickingEventArgs.cs b/src/SMAPI/Events/UnvalidatedUpdateTickingEventArgs.cs index 4ed781e0..577f0776 100644 --- a/src/SMAPI/Events/UnvalidatedUpdateTickingEventArgs.cs +++ b/src/SMAPI/Events/UnvalidatedUpdateTickingEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,23 +10,15 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /// Whether is a multiple of 60, which happens approximately once per second. - public bool IsOneSecond { get; } + public bool IsOneSecond => Game1.ticks % 60 == 0; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal UnvalidatedUpdateTickingEventArgs(uint ticks) - { - this.Ticks = ticks; - this.IsOneSecond = this.IsMultipleOf(60); - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Events/UpdateTickedEventArgs.cs b/src/SMAPI/Events/UpdateTickedEventArgs.cs index 3466b731..aa710b44 100644 --- a/src/SMAPI/Events/UpdateTickedEventArgs.cs +++ b/src/SMAPI/Events/UpdateTickedEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,23 +10,15 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /// Whether is a multiple of 60, which happens approximately once per second. - public bool IsOneSecond { get; } + public bool IsOneSecond => Game1.ticks % 60 == 0; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal UpdateTickedEventArgs(uint ticks) - { - this.Ticks = ticks; - this.IsOneSecond = this.IsMultipleOf(60); - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Events/UpdateTickingEventArgs.cs b/src/SMAPI/Events/UpdateTickingEventArgs.cs index d4913268..cacf5a54 100644 --- a/src/SMAPI/Events/UpdateTickingEventArgs.cs +++ b/src/SMAPI/Events/UpdateTickingEventArgs.cs @@ -1,4 +1,5 @@ using System; +using StardewValley; namespace StardewModdingAPI.Events { @@ -9,23 +10,15 @@ namespace StardewModdingAPI.Events ** Accessors *********/ /// The number of ticks elapsed since the game started, including the current tick. - public uint Ticks { get; } + public uint Ticks => (uint)Game1.ticks; /// Whether is a multiple of 60, which happens approximately once per second. - public bool IsOneSecond { get; } + public bool IsOneSecond => Game1.ticks % 60 == 0; /********* ** Public methods *********/ - /// Construct an instance. - /// The number of ticks elapsed since the game started, including the current tick. - internal UpdateTickingEventArgs(uint ticks) - { - this.Ticks = ticks; - this.IsOneSecond = this.IsMultipleOf(60); - } - /// Get whether is a multiple of the given . This is mainly useful if you want to run logic intermittently (e.g. e.IsMultipleOf(30) for every half-second). /// The factor to check. public bool IsMultipleOf(uint number) diff --git a/src/SMAPI/Framework/Events/ManagedEvent.cs b/src/SMAPI/Framework/Events/ManagedEvent.cs index 65f6e38e..ebd79e6c 100644 --- a/src/SMAPI/Framework/Events/ManagedEvent.cs +++ b/src/SMAPI/Framework/Events/ManagedEvent.cs @@ -93,6 +93,7 @@ namespace StardewModdingAPI.Framework.Events } } +#if !SMAPI_3_0_STRICT /// An event wrapper which intercepts and logs errors in handler code. internal class ManagedEvent : ManagedEventBase { @@ -156,4 +157,5 @@ namespace StardewModdingAPI.Framework.Events } } } +#endif } diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index 8abe4d16..957fd1d6 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -96,15 +96,9 @@ namespace StardewModdingAPI.Framework /// Monitors the entire game state for changes. private WatcherCore Watchers; - /// An index incremented on every tick and reset every 60th tick (0–59). - private int CurrentUpdateTick; - /// Whether post-game-startup initialisation has been performed. private bool IsInitialised; - /// The number of update ticks which have already executed. - private uint TicksElapsed; - /// Whether the next content manager requested by the game will be for . private bool NextContentManagerIsMain; @@ -271,6 +265,8 @@ namespace StardewModdingAPI.Framework /// A snapshot of the game timing state. protected override void Update(GameTime gameTime) { + var events = this.Events; + try { this.DeprecationManager.PrintQueued(); @@ -342,11 +338,11 @@ namespace StardewModdingAPI.Framework // update tick are neglible and not worth the complications of bypassing Game1.Update. if (Game1._newDayTask != null || Game1.gameMode == Game1.loadingMode) { - this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); + events.UnvalidatedUpdateTicking.RaiseEmpty(); base.Update(gameTime); - this.Events.UnvalidatedUpdateTicked.Raise(new UnvalidatedUpdateTickedEventArgs(this.TicksElapsed)); + events.UnvalidatedUpdateTicked.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_UnvalidatedUpdateTick.Raise(); + events.Legacy_UnvalidatedUpdateTick.Raise(); #endif return; } @@ -416,9 +412,9 @@ namespace StardewModdingAPI.Framework { this.IsBetweenCreateEvents = true; this.Monitor.Log("Context: before save creation.", LogLevel.Trace); - this.Events.SaveCreating.RaiseEmpty(); + events.SaveCreating.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_BeforeCreateSave.Raise(); + events.Legacy_BeforeCreateSave.Raise(); #endif } @@ -427,18 +423,18 @@ namespace StardewModdingAPI.Framework { this.IsBetweenSaveEvents = true; this.Monitor.Log("Context: before save.", LogLevel.Trace); - this.Events.Saving.RaiseEmpty(); + events.Saving.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_BeforeSave.Raise(); + events.Legacy_BeforeSave.Raise(); #endif } // suppress non-save events - this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); + events.UnvalidatedUpdateTicking.RaiseEmpty(); base.Update(gameTime); - this.Events.UnvalidatedUpdateTicked.Raise(new UnvalidatedUpdateTickedEventArgs(this.TicksElapsed)); + events.UnvalidatedUpdateTicked.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_UnvalidatedUpdateTick.Raise(); + events.Legacy_UnvalidatedUpdateTick.Raise(); #endif return; } @@ -448,9 +444,9 @@ namespace StardewModdingAPI.Framework this.IsBetweenCreateEvents = false; this.Monitor.Log($"Context: after save creation, starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}.", LogLevel.Trace); this.OnLoadStageChanged(LoadStage.CreatedSaveFile); - this.Events.SaveCreated.RaiseEmpty(); + events.SaveCreated.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_AfterCreateSave.Raise(); + events.Legacy_AfterCreateSave.Raise(); #endif } if (this.IsBetweenSaveEvents) @@ -458,11 +454,11 @@ namespace StardewModdingAPI.Framework // raise after-save this.IsBetweenSaveEvents = false; this.Monitor.Log($"Context: after save, starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}.", LogLevel.Trace); - this.Events.Saved.RaiseEmpty(); - this.Events.DayStarted.RaiseEmpty(); + events.Saved.RaiseEmpty(); + events.DayStarted.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_AfterSave.Raise(); - this.Events.Legacy_AfterDayStarted.Raise(); + events.Legacy_AfterSave.Raise(); + events.Legacy_AfterDayStarted.Raise(); #endif } @@ -499,7 +495,7 @@ namespace StardewModdingAPI.Framework this.OnLocaleChanged(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_LocaleChanged.Raise(new EventArgsValueChanged(was.ToString(), now.ToString())); + events.Legacy_LocaleChanged.Raise(new EventArgsValueChanged(was.ToString(), now.ToString())); #endif this.Watchers.LocaleWatcher.Reset(); @@ -525,11 +521,11 @@ namespace StardewModdingAPI.Framework // raise events this.OnLoadStageChanged(LoadStage.Ready); - this.Events.SaveLoaded.RaiseEmpty(); - this.Events.DayStarted.RaiseEmpty(); + events.SaveLoaded.RaiseEmpty(); + events.DayStarted.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_AfterLoad.Raise(); - this.Events.Legacy_AfterDayStarted.Raise(); + events.Legacy_AfterLoad.Raise(); + events.Legacy_AfterDayStarted.Raise(); #endif } @@ -548,9 +544,9 @@ namespace StardewModdingAPI.Framework Point oldSize = this.Watchers.WindowSizeWatcher.PreviousValue; Point newSize = this.Watchers.WindowSizeWatcher.CurrentValue; - this.Events.WindowResized.Raise(new WindowResizedEventArgs(oldSize, newSize)); + events.WindowResized.Raise(new WindowResizedEventArgs(oldSize, newSize)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_Resize.Raise(); + events.Legacy_Resize.Raise(); #endif this.Watchers.WindowSizeWatcher.Reset(); } @@ -569,23 +565,33 @@ namespace StardewModdingAPI.Framework // raise cursor moved event if (this.Watchers.CursorWatcher.IsChanged) { - ICursorPosition was = this.Watchers.CursorWatcher.PreviousValue; - ICursorPosition now = this.Watchers.CursorWatcher.CurrentValue; - this.Watchers.CursorWatcher.Reset(); + if (events.CursorMoved.HasListeners()) + { + ICursorPosition was = this.Watchers.CursorWatcher.PreviousValue; + ICursorPosition now = this.Watchers.CursorWatcher.CurrentValue; + this.Watchers.CursorWatcher.Reset(); - this.Events.CursorMoved.Raise(new CursorMovedEventArgs(was, now)); + events.CursorMoved.Raise(new CursorMovedEventArgs(was, now)); + } + else + this.Watchers.CursorWatcher.Reset(); } // raise mouse wheel scrolled if (this.Watchers.MouseWheelScrollWatcher.IsChanged) { - int was = this.Watchers.MouseWheelScrollWatcher.PreviousValue; - int now = this.Watchers.MouseWheelScrollWatcher.CurrentValue; - this.Watchers.MouseWheelScrollWatcher.Reset(); + if (events.MouseWheelScrolled.HasListeners() || this.Monitor.IsVerbose) + { + int was = this.Watchers.MouseWheelScrollWatcher.PreviousValue; + int now = this.Watchers.MouseWheelScrollWatcher.CurrentValue; + this.Watchers.MouseWheelScrollWatcher.Reset(); - if (this.Monitor.IsVerbose) - this.Monitor.Log($"Events: mouse wheel scrolled to {now}.", LogLevel.Trace); - this.Events.MouseWheelScrolled.Raise(new MouseWheelScrolledEventArgs(cursor, was, now)); + if (this.Monitor.IsVerbose) + this.Monitor.Log($"Events: mouse wheel scrolled to {now}.", LogLevel.Trace); + events.MouseWheelScrolled.Raise(new MouseWheelScrolledEventArgs(cursor, was, now)); + } + else + this.Watchers.MouseWheelScrollWatcher.Reset(); } // raise input button events @@ -599,22 +605,22 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) this.Monitor.Log($"Events: button {button} pressed.", LogLevel.Trace); - this.Events.ButtonPressed.Raise(new ButtonPressedEventArgs(button, cursor, inputState)); + events.ButtonPressed.Raise(new ButtonPressedEventArgs(button, cursor, inputState)); #if !SMAPI_3_0_STRICT // legacy events - this.Events.Legacy_ButtonPressed.Raise(new EventArgsInput(button, cursor, inputState.SuppressButtons)); + events.Legacy_ButtonPressed.Raise(new EventArgsInput(button, cursor, inputState.SuppressButtons)); if (button.TryGetKeyboard(out Keys key)) { if (key != Keys.None) - this.Events.Legacy_KeyPressed.Raise(new EventArgsKeyPressed(key)); + events.Legacy_KeyPressed.Raise(new EventArgsKeyPressed(key)); } else if (button.TryGetController(out Buttons controllerButton)) { if (controllerButton == Buttons.LeftTrigger || controllerButton == Buttons.RightTrigger) - this.Events.Legacy_ControllerTriggerPressed.Raise(new EventArgsControllerTriggerPressed(PlayerIndex.One, controllerButton, controllerButton == Buttons.LeftTrigger ? inputState.RealController.Triggers.Left : inputState.RealController.Triggers.Right)); + events.Legacy_ControllerTriggerPressed.Raise(new EventArgsControllerTriggerPressed(PlayerIndex.One, controllerButton, controllerButton == Buttons.LeftTrigger ? inputState.RealController.Triggers.Left : inputState.RealController.Triggers.Right)); else - this.Events.Legacy_ControllerButtonPressed.Raise(new EventArgsControllerButtonPressed(PlayerIndex.One, controllerButton)); + events.Legacy_ControllerButtonPressed.Raise(new EventArgsControllerButtonPressed(PlayerIndex.One, controllerButton)); } #endif } @@ -623,22 +629,22 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) this.Monitor.Log($"Events: button {button} released.", LogLevel.Trace); - this.Events.ButtonReleased.Raise(new ButtonReleasedEventArgs(button, cursor, inputState)); + events.ButtonReleased.Raise(new ButtonReleasedEventArgs(button, cursor, inputState)); #if !SMAPI_3_0_STRICT // legacy events - this.Events.Legacy_ButtonReleased.Raise(new EventArgsInput(button, cursor, inputState.SuppressButtons)); + events.Legacy_ButtonReleased.Raise(new EventArgsInput(button, cursor, inputState.SuppressButtons)); if (button.TryGetKeyboard(out Keys key)) { if (key != Keys.None) - this.Events.Legacy_KeyReleased.Raise(new EventArgsKeyPressed(key)); + events.Legacy_KeyReleased.Raise(new EventArgsKeyPressed(key)); } else if (button.TryGetController(out Buttons controllerButton)) { if (controllerButton == Buttons.LeftTrigger || controllerButton == Buttons.RightTrigger) - this.Events.Legacy_ControllerTriggerReleased.Raise(new EventArgsControllerTriggerReleased(PlayerIndex.One, controllerButton, controllerButton == Buttons.LeftTrigger ? inputState.RealController.Triggers.Left : inputState.RealController.Triggers.Right)); + events.Legacy_ControllerTriggerReleased.Raise(new EventArgsControllerTriggerReleased(PlayerIndex.One, controllerButton, controllerButton == Buttons.LeftTrigger ? inputState.RealController.Triggers.Left : inputState.RealController.Triggers.Right)); else - this.Events.Legacy_ControllerButtonReleased.Raise(new EventArgsControllerButtonReleased(PlayerIndex.One, controllerButton)); + events.Legacy_ControllerButtonReleased.Raise(new EventArgsControllerButtonReleased(PlayerIndex.One, controllerButton)); } #endif } @@ -647,9 +653,9 @@ namespace StardewModdingAPI.Framework #if !SMAPI_3_0_STRICT // raise legacy state-changed events if (inputState.RealKeyboard != previousInputState.RealKeyboard) - this.Events.Legacy_KeyboardChanged.Raise(new EventArgsKeyboardStateChanged(previousInputState.RealKeyboard, inputState.RealKeyboard)); + events.Legacy_KeyboardChanged.Raise(new EventArgsKeyboardStateChanged(previousInputState.RealKeyboard, inputState.RealKeyboard)); if (inputState.RealMouse != previousInputState.RealMouse) - this.Events.Legacy_MouseChanged.Raise(new EventArgsMouseStateChanged(previousInputState.RealMouse, inputState.RealMouse, new Point((int)previousInputState.CursorPosition.ScreenPixels.X, (int)previousInputState.CursorPosition.ScreenPixels.Y), new Point((int)inputState.CursorPosition.ScreenPixels.X, (int)inputState.CursorPosition.ScreenPixels.Y))); + events.Legacy_MouseChanged.Raise(new EventArgsMouseStateChanged(previousInputState.RealMouse, inputState.RealMouse, new Point((int)previousInputState.CursorPosition.ScreenPixels.X, (int)previousInputState.CursorPosition.ScreenPixels.Y), new Point((int)inputState.CursorPosition.ScreenPixels.X, (int)inputState.CursorPosition.ScreenPixels.Y))); #endif } } @@ -667,12 +673,12 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"Context: menu changed from {was?.GetType().FullName ?? "none"} to {now?.GetType().FullName ?? "none"}.", LogLevel.Trace); // raise menu events - this.Events.MenuChanged.Raise(new MenuChangedEventArgs(was, now)); + events.MenuChanged.Raise(new MenuChangedEventArgs(was, now)); #if !SMAPI_3_0_STRICT if (now != null) - this.Events.Legacy_MenuChanged.Raise(new EventArgsClickableMenuChanged(was, now)); + events.Legacy_MenuChanged.Raise(new EventArgsClickableMenuChanged(was, now)); else - this.Events.Legacy_MenuClosed.Raise(new EventArgsClickableMenuClosed(was)); + events.Legacy_MenuClosed.Raise(new EventArgsClickableMenuClosed(was)); #endif } @@ -700,9 +706,9 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"Context: location list changed (added {addedText}; removed {removedText}).", LogLevel.Trace); } - this.Events.LocationListChanged.Raise(new LocationListChangedEventArgs(added, removed)); + events.LocationListChanged.Raise(new LocationListChangedEventArgs(added, removed)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_LocationsChanged.Raise(new EventArgsLocationsChanged(added, removed)); + events.Legacy_LocationsChanged.Raise(new EventArgsLocationsChanged(added, removed)); #endif } @@ -719,9 +725,9 @@ namespace StardewModdingAPI.Framework Building[] removed = watcher.BuildingsWatcher.Removed.ToArray(); watcher.BuildingsWatcher.Reset(); - this.Events.BuildingListChanged.Raise(new BuildingListChangedEventArgs(location, added, removed)); + events.BuildingListChanged.Raise(new BuildingListChangedEventArgs(location, added, removed)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_BuildingsChanged.Raise(new EventArgsLocationBuildingsChanged(location, added, removed)); + events.Legacy_BuildingsChanged.Raise(new EventArgsLocationBuildingsChanged(location, added, removed)); #endif } @@ -733,7 +739,7 @@ namespace StardewModdingAPI.Framework Debris[] removed = watcher.DebrisWatcher.Removed.ToArray(); watcher.DebrisWatcher.Reset(); - this.Events.DebrisListChanged.Raise(new DebrisListChangedEventArgs(location, added, removed)); + events.DebrisListChanged.Raise(new DebrisListChangedEventArgs(location, added, removed)); } // large terrain features changed @@ -744,7 +750,7 @@ namespace StardewModdingAPI.Framework LargeTerrainFeature[] removed = watcher.LargeTerrainFeaturesWatcher.Removed.ToArray(); watcher.LargeTerrainFeaturesWatcher.Reset(); - this.Events.LargeTerrainFeatureListChanged.Raise(new LargeTerrainFeatureListChangedEventArgs(location, added, removed)); + events.LargeTerrainFeatureListChanged.Raise(new LargeTerrainFeatureListChangedEventArgs(location, added, removed)); } // NPCs changed @@ -755,7 +761,7 @@ namespace StardewModdingAPI.Framework NPC[] removed = watcher.NpcsWatcher.Removed.ToArray(); watcher.NpcsWatcher.Reset(); - this.Events.NpcListChanged.Raise(new NpcListChangedEventArgs(location, added, removed)); + events.NpcListChanged.Raise(new NpcListChangedEventArgs(location, added, removed)); } // objects changed @@ -766,9 +772,9 @@ namespace StardewModdingAPI.Framework KeyValuePair[] removed = watcher.ObjectsWatcher.Removed.ToArray(); watcher.ObjectsWatcher.Reset(); - this.Events.ObjectListChanged.Raise(new ObjectListChangedEventArgs(location, added, removed)); + events.ObjectListChanged.Raise(new ObjectListChangedEventArgs(location, added, removed)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_ObjectsChanged.Raise(new EventArgsLocationObjectsChanged(location, added, removed)); + events.Legacy_ObjectsChanged.Raise(new EventArgsLocationObjectsChanged(location, added, removed)); #endif } @@ -780,7 +786,7 @@ namespace StardewModdingAPI.Framework KeyValuePair[] removed = watcher.TerrainFeaturesWatcher.Removed.ToArray(); watcher.TerrainFeaturesWatcher.Reset(); - this.Events.TerrainFeatureListChanged.Raise(new TerrainFeatureListChangedEventArgs(location, added, removed)); + events.TerrainFeatureListChanged.Raise(new TerrainFeatureListChangedEventArgs(location, added, removed)); } } } @@ -798,9 +804,9 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) this.Monitor.Log($"Events: time changed from {was} to {now}.", LogLevel.Trace); - this.Events.TimeChanged.Raise(new TimeChangedEventArgs(was, now)); + events.TimeChanged.Raise(new TimeChangedEventArgs(was, now)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_TimeOfDayChanged.Raise(new EventArgsIntChanged(was, now)); + events.Legacy_TimeOfDayChanged.Raise(new EventArgsIntChanged(was, now)); #endif } else @@ -818,9 +824,9 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"Context: set location to {newLocation.Name}.", LogLevel.Trace); GameLocation oldLocation = playerTracker.LocationWatcher.PreviousValue; - this.Events.Warped.Raise(new WarpedEventArgs(playerTracker.Player, oldLocation, newLocation)); + events.Warped.Raise(new WarpedEventArgs(playerTracker.Player, oldLocation, newLocation)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_PlayerWarped.Raise(new EventArgsPlayerWarped(oldLocation, newLocation)); + events.Legacy_PlayerWarped.Raise(new EventArgsPlayerWarped(oldLocation, newLocation)); #endif } @@ -830,9 +836,9 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) this.Monitor.Log($"Events: player skill '{pair.Key}' changed from {pair.Value.PreviousValue} to {pair.Value.CurrentValue}.", LogLevel.Trace); - this.Events.LevelChanged.Raise(new LevelChangedEventArgs(playerTracker.Player, pair.Key, pair.Value.PreviousValue, pair.Value.CurrentValue)); + events.LevelChanged.Raise(new LevelChangedEventArgs(playerTracker.Player, pair.Key, pair.Value.PreviousValue, pair.Value.CurrentValue)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_LeveledUp.Raise(new EventArgsLevelUp((EventArgsLevelUp.LevelType)pair.Key, pair.Value.CurrentValue)); + events.Legacy_LeveledUp.Raise(new EventArgsLevelUp((EventArgsLevelUp.LevelType)pair.Key, pair.Value.CurrentValue)); #endif } @@ -842,9 +848,9 @@ namespace StardewModdingAPI.Framework { if (this.Monitor.IsVerbose) this.Monitor.Log("Events: player inventory changed.", LogLevel.Trace); - this.Events.InventoryChanged.Raise(new InventoryChangedEventArgs(playerTracker.Player, changedItems)); + events.InventoryChanged.Raise(new InventoryChangedEventArgs(playerTracker.Player, changedItems)); #if !SMAPI_3_0_STRICT - this.Events.Legacy_InventoryChanged.Raise(new EventArgsInventoryChanged(Game1.player.Items, changedItems)); + events.Legacy_InventoryChanged.Raise(new EventArgsInventoryChanged(Game1.player.Items, changedItems)); #endif } @@ -854,7 +860,7 @@ namespace StardewModdingAPI.Framework if (this.Monitor.IsVerbose) this.Monitor.Log($"Context: mine level changed to {mineLevel}.", LogLevel.Trace); #if !SMAPI_3_0_STRICT - this.Events.Legacy_MineLevelChanged.Raise(new EventArgsMineLevelChanged(playerTracker.MineLevelWatcher.PreviousValue, mineLevel)); + events.Legacy_MineLevelChanged.Raise(new EventArgsMineLevelChanged(playerTracker.MineLevelWatcher.PreviousValue, mineLevel)); #endif } } @@ -867,22 +873,21 @@ namespace StardewModdingAPI.Framework /********* ** Game update *********/ - this.TicksElapsed++; - // game launched - if (this.TicksElapsed == 1) - this.Events.GameLaunched.Raise(new GameLaunchedEventArgs()); + bool isFirstTick = Game1.ticks == 0; + if (isFirstTick) + events.GameLaunched.Raise(new GameLaunchedEventArgs()); // preloaded if (Context.IsSaveLoaded && this.LoadStage != LoadStage.Loaded && this.LoadStage != LoadStage.Ready) this.OnLoadStageChanged(LoadStage.Loaded); // update tick - bool isOneSecond = this.TicksElapsed % 60 == 0; - this.Events.UnvalidatedUpdateTicking.Raise(new UnvalidatedUpdateTickingEventArgs(this.TicksElapsed)); - this.Events.UpdateTicking.Raise(new UpdateTickingEventArgs(this.TicksElapsed)); + bool isOneSecond = Game1.ticks % 60 == 0; + events.UnvalidatedUpdateTicking.RaiseEmpty(); + events.UpdateTicking.RaiseEmpty(); if (isOneSecond) - this.Events.OneSecondUpdateTicking.Raise(new OneSecondUpdateTickingEventArgs(this.TicksElapsed)); + events.OneSecondUpdateTicking.RaiseEmpty(); try { this.Input.UpdateSuppression(); @@ -892,35 +897,32 @@ namespace StardewModdingAPI.Framework { this.MonitorForGame.Log($"An error occured in the base update loop: {ex.GetLogSummary()}", LogLevel.Error); } - this.Events.UnvalidatedUpdateTicked.Raise(new UnvalidatedUpdateTickedEventArgs(this.TicksElapsed)); - this.Events.UpdateTicked.Raise(new UpdateTickedEventArgs(this.TicksElapsed)); + events.UnvalidatedUpdateTicked.RaiseEmpty(); + events.UpdateTicked.RaiseEmpty(); if (isOneSecond) - this.Events.OneSecondUpdateTicked.Raise(new OneSecondUpdateTickedEventArgs(this.TicksElapsed)); + events.OneSecondUpdateTicked.RaiseEmpty(); /********* ** Update events *********/ #if !SMAPI_3_0_STRICT - this.Events.Legacy_UnvalidatedUpdateTick.Raise(); - if (this.TicksElapsed == 1) - this.Events.Legacy_FirstUpdateTick.Raise(); - this.Events.Legacy_UpdateTick.Raise(); - if (this.CurrentUpdateTick % 2 == 0) - this.Events.Legacy_SecondUpdateTick.Raise(); - if (this.CurrentUpdateTick % 4 == 0) - this.Events.Legacy_FourthUpdateTick.Raise(); - if (this.CurrentUpdateTick % 8 == 0) - this.Events.Legacy_EighthUpdateTick.Raise(); - if (this.CurrentUpdateTick % 15 == 0) - this.Events.Legacy_QuarterSecondTick.Raise(); - if (this.CurrentUpdateTick % 30 == 0) - this.Events.Legacy_HalfSecondTick.Raise(); - if (this.CurrentUpdateTick % 60 == 0) - this.Events.Legacy_OneSecondTick.Raise(); + events.Legacy_UnvalidatedUpdateTick.Raise(); + if (isFirstTick) + events.Legacy_FirstUpdateTick.Raise(); + events.Legacy_UpdateTick.Raise(); + if (Game1.ticks % 2 == 0) + events.Legacy_SecondUpdateTick.Raise(); + if (Game1.ticks % 4 == 0) + events.Legacy_FourthUpdateTick.Raise(); + if (Game1.ticks % 8 == 0) + events.Legacy_EighthUpdateTick.Raise(); + if (Game1.ticks % 15 == 0) + events.Legacy_QuarterSecondTick.Raise(); + if (Game1.ticks % 30 == 0) + events.Legacy_HalfSecondTick.Raise(); + if (Game1.ticks % 60 == 0) + events.Legacy_OneSecondTick.Raise(); #endif - this.CurrentUpdateTick += 1; - if (this.CurrentUpdateTick >= 60) - this.CurrentUpdateTick = 0; this.UpdateCrashTimer.Reset(); } @@ -988,10 +990,10 @@ namespace StardewModdingAPI.Framework [SuppressMessage("SMAPI.CommonErrors", "AvoidImplicitNetFieldCast", Justification = "copied from game code as-is")] private void DrawImpl(GameTime gameTime) { + var events = this.Events; + if (Game1._newDayTask != null) - { this.GraphicsDevice.Clear(this.bgColor); - } else { if ((double)Game1.options.zoomLevel != 1.0) @@ -1003,17 +1005,17 @@ namespace StardewModdingAPI.Framework if (activeClickableMenu != null) { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); try { - this.Events.RenderingActiveMenu.RaiseEmpty(); + events.RenderingActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderGuiEvent.Raise(); + events.Legacy_OnPreRenderGuiEvent.Raise(); #endif activeClickableMenu.draw(Game1.spriteBatch); - this.Events.RenderedActiveMenu.RaiseEmpty(); + events.RenderedActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderGuiEvent.Raise(); + events.Legacy_OnPostRenderGuiEvent.Raise(); #endif } catch (Exception ex) @@ -1021,9 +1023,9 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"The {activeClickableMenu.GetType().FullName} menu crashed while drawing itself during save. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error); activeClickableMenu.exitThisMenu(); } - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderEvent.Raise(); + events.Legacy_OnPostRenderEvent.Raise(); #endif Game1.spriteBatch.End(); @@ -1043,18 +1045,18 @@ namespace StardewModdingAPI.Framework { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); try { Game1.activeClickableMenu.drawBackground(Game1.spriteBatch); - this.Events.RenderingActiveMenu.RaiseEmpty(); + events.RenderingActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderGuiEvent.Raise(); + events.Legacy_OnPreRenderGuiEvent.Raise(); #endif Game1.activeClickableMenu.draw(Game1.spriteBatch); - this.Events.RenderedActiveMenu.RaiseEmpty(); + events.RenderedActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderGuiEvent.Raise(); + events.Legacy_OnPostRenderGuiEvent.Raise(); #endif } catch (Exception ex) @@ -1062,9 +1064,9 @@ namespace StardewModdingAPI.Framework this.Monitor.Log($"The {Game1.activeClickableMenu.GetType().FullName} menu crashed while drawing itself. SMAPI will force it to exit to avoid crashing the game.\n{ex.GetLogSummary()}", LogLevel.Error); Game1.activeClickableMenu.exitThisMenu(); } - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderEvent.Raise(); + events.Legacy_OnPostRenderEvent.Raise(); #endif Game1.spriteBatch.End(); this.drawOverlays(Game1.spriteBatch); @@ -1085,13 +1087,13 @@ namespace StardewModdingAPI.Framework else if (Game1.gameMode == (byte)11) { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.content.LoadString("Strings\\StringsFromCSFiles:Game1.cs.3685"), new Vector2(16f, 16f), Color.HotPink); Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.content.LoadString("Strings\\StringsFromCSFiles:Game1.cs.3686"), new Vector2(16f, 32f), new Color(0, (int)byte.MaxValue, 0)); Game1.spriteBatch.DrawString(Game1.dialogueFont, Game1.parseText(Game1.errorMessage, Game1.dialogueFont, Game1.graphics.GraphicsDevice.Viewport.Width), new Vector2(16f, 48f), Color.White); - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderEvent.Raise(); + events.Legacy_OnPostRenderEvent.Raise(); #endif Game1.spriteBatch.End(); } @@ -1119,19 +1121,19 @@ namespace StardewModdingAPI.Framework else if (Game1.showingEndOfNightStuff) { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); if (Game1.activeClickableMenu != null) { try { - this.Events.RenderingActiveMenu.RaiseEmpty(); + events.RenderingActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderGuiEvent.Raise(); + events.Legacy_OnPreRenderGuiEvent.Raise(); #endif Game1.activeClickableMenu.draw(Game1.spriteBatch); - this.Events.RenderedActiveMenu.RaiseEmpty(); + events.RenderedActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderGuiEvent.Raise(); + events.Legacy_OnPostRenderGuiEvent.Raise(); #endif } catch (Exception ex) @@ -1140,7 +1142,7 @@ namespace StardewModdingAPI.Framework Game1.activeClickableMenu.exitThisMenu(); } } - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); Game1.spriteBatch.End(); this.drawOverlays(Game1.spriteBatch); if ((double)Game1.options.zoomLevel == 1.0) @@ -1154,7 +1156,7 @@ namespace StardewModdingAPI.Framework else if (Game1.gameMode == (byte)6 || Game1.gameMode == (byte)3 && Game1.currentLocation == null) { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); string str1 = ""; for (int index = 0; (double)index < gameTime.TotalGameTime.TotalMilliseconds % 999.0 / 333.0; ++index) str1 += "."; @@ -1166,7 +1168,7 @@ namespace StardewModdingAPI.Framework int x = 64; int y = Game1.graphics.GraphicsDevice.Viewport.GetTitleSafeArea().Bottom - height; SpriteText.drawString(Game1.spriteBatch, s, x, y, 999999, widthOfString, height, 1f, 0.88f, false, 0, str3, -1); - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); Game1.spriteBatch.End(); this.drawOverlays(Game1.spriteBatch); if ((double)Game1.options.zoomLevel != 1.0) @@ -1195,7 +1197,7 @@ namespace StardewModdingAPI.Framework { Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); if (++batchOpens == 1) - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); } else { @@ -1205,7 +1207,7 @@ namespace StardewModdingAPI.Framework this.GraphicsDevice.Clear(Color.White * 0.0f); Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.NonPremultiplied, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); if (++batchOpens == 1) - this.Events.Rendering.RaiseEmpty(); + events.Rendering.RaiseEmpty(); Game1.spriteBatch.Draw(Game1.staminaRect, Game1.lightmap.Bounds, Game1.currentLocation.Name.StartsWith("UndergroundMine") ? Game1.mine.getLightingColor(gameTime) : (Game1.ambientLight.Equals(Color.White) || Game1.isRaining && (bool)((NetFieldBase)Game1.currentLocation.isOutdoors) ? Game1.outdoorLight : Game1.ambientLight)); for (int index = 0; index < Game1.currentLightSources.Count; ++index) { @@ -1220,10 +1222,10 @@ namespace StardewModdingAPI.Framework this.GraphicsDevice.Clear(this.bgColor); Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); if (++batchOpens == 1) - this.Events.Rendering.RaiseEmpty(); - this.Events.RenderingWorld.RaiseEmpty(); + events.Rendering.RaiseEmpty(); + events.RenderingWorld.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderEvent.Raise(); + events.Legacy_OnPreRenderEvent.Raise(); #endif if (Game1.background != null) Game1.background.draw(Game1.spriteBatch); @@ -1480,7 +1482,7 @@ namespace StardewModdingAPI.Framework Game1.spriteBatch.End(); } Game1.spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, (DepthStencilState)null, (RasterizerState)null); - this.Events.RenderedWorld.RaiseEmpty(); + events.RenderedWorld.RaiseEmpty(); if (Game1.drawGrid) { int num1 = -Game1.viewport.X % 64; @@ -1536,14 +1538,14 @@ namespace StardewModdingAPI.Framework this.drawBillboard(); if ((Game1.displayHUD || Game1.eventUp) && (Game1.currentBillboard == 0 && Game1.gameMode == (byte)3) && (!Game1.freezeControls && !Game1.panMode && !Game1.HostPaused)) { - this.Events.RenderingHud.RaiseEmpty(); + events.RenderingHud.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderHudEvent.Raise(); + events.Legacy_OnPreRenderHudEvent.Raise(); #endif this.drawHUD(); - this.Events.RenderedHud.RaiseEmpty(); + events.RenderedHud.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderHudEvent.Raise(); + events.Legacy_OnPostRenderHudEvent.Raise(); #endif } else if (Game1.activeClickableMenu == null && Game1.farmEvent == null) @@ -1652,14 +1654,14 @@ namespace StardewModdingAPI.Framework { try { - this.Events.RenderingActiveMenu.RaiseEmpty(); + events.RenderingActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPreRenderGuiEvent.Raise(); + events.Legacy_OnPreRenderGuiEvent.Raise(); #endif Game1.activeClickableMenu.draw(Game1.spriteBatch); - this.Events.RenderedActiveMenu.RaiseEmpty(); + events.RenderedActiveMenu.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderGuiEvent.Raise(); + events.Legacy_OnPostRenderGuiEvent.Raise(); #endif } catch (Exception ex) @@ -1676,9 +1678,9 @@ namespace StardewModdingAPI.Framework SpriteText.drawStringWithScrollBackground(Game1.spriteBatch, s, 96, 32, "", 1f, -1); } - this.Events.Rendered.RaiseEmpty(); + events.Rendered.RaiseEmpty(); #if !SMAPI_3_0_STRICT - this.Events.Legacy_OnPostRenderEvent.Raise(); + events.Legacy_OnPostRenderEvent.Raise(); #endif Game1.spriteBatch.End(); this.drawOverlays(Game1.spriteBatch); -- cgit From 51e65fc8a090996b0bb2f0f4697376135b233654 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 27 Dec 2018 02:40:57 -0500 Subject: enable latest C# features --- src/SMAPI.Installer/StardewModdingAPI.Installer.csproj | 1 + .../SMAPI.ModBuildConfig.Analyzer.Tests.csproj | 1 + .../StardewModdingAPI.ModBuildConfig.Analyzer.csproj | 1 + src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj | 1 + .../StardewModdingAPI.Mods.ConsoleCommands.csproj | 1 + src/SMAPI.Mods.SaveBackup/StardewModdingAPI.Mods.SaveBackup.csproj | 1 + src/SMAPI.Tests/StardewModdingAPI.Tests.csproj | 1 + src/SMAPI.Web/StardewModdingAPI.Web.csproj | 1 + src/SMAPI.sln.DotSettings | 1 + src/SMAPI/StardewModdingAPI.csproj | 1 + .../StardewModdingAPI.Toolkit.CoreInterfaces.csproj | 1 + src/StardewModdingAPI.Toolkit/StardewModdingAPI.Toolkit.csproj | 1 + 12 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj index 8000e4e7..083044fb 100644 --- a/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj +++ b/src/SMAPI.Installer/StardewModdingAPI.Installer.csproj @@ -12,6 +12,7 @@ v4.5 512 true + latest x86 diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/SMAPI.ModBuildConfig.Analyzer.Tests.csproj b/src/SMAPI.ModBuildConfig.Analyzer.Tests/SMAPI.ModBuildConfig.Analyzer.Tests.csproj index 4d93df73..26065ec2 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/SMAPI.ModBuildConfig.Analyzer.Tests.csproj +++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/SMAPI.ModBuildConfig.Analyzer.Tests.csproj @@ -2,6 +2,7 @@ netcoreapp2.0 + latest diff --git a/src/SMAPI.ModBuildConfig.Analyzer/StardewModdingAPI.ModBuildConfig.Analyzer.csproj b/src/SMAPI.ModBuildConfig.Analyzer/StardewModdingAPI.ModBuildConfig.Analyzer.csproj index 9d3f6d5b..9d646e8f 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer/StardewModdingAPI.ModBuildConfig.Analyzer.csproj +++ b/src/SMAPI.ModBuildConfig.Analyzer/StardewModdingAPI.ModBuildConfig.Analyzer.csproj @@ -5,6 +5,7 @@ false false bin + latest diff --git a/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj b/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj index f068b480..9118b043 100644 --- a/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj +++ b/src/SMAPI.ModBuildConfig/StardewModdingAPI.ModBuildConfig.csproj @@ -11,6 +11,7 @@ StardewModdingAPI.ModBuildConfig v4.5 512 + latest true diff --git a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj index a3237a3d..2c958dbc 100644 --- a/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj +++ b/src/SMAPI.Mods.ConsoleCommands/StardewModdingAPI.Mods.ConsoleCommands.csproj @@ -11,6 +11,7 @@ ConsoleCommands v4.5 512 + latest true diff --git a/src/SMAPI.Mods.SaveBackup/StardewModdingAPI.Mods.SaveBackup.csproj b/src/SMAPI.Mods.SaveBackup/StardewModdingAPI.Mods.SaveBackup.csproj index fafa4d25..56b6b7f4 100644 --- a/src/SMAPI.Mods.SaveBackup/StardewModdingAPI.Mods.SaveBackup.csproj +++ b/src/SMAPI.Mods.SaveBackup/StardewModdingAPI.Mods.SaveBackup.csproj @@ -11,6 +11,7 @@ SaveBackup v4.5 512 + latest true diff --git a/src/SMAPI.Tests/StardewModdingAPI.Tests.csproj b/src/SMAPI.Tests/StardewModdingAPI.Tests.csproj index 4ec1a3de..83bd92af 100644 --- a/src/SMAPI.Tests/StardewModdingAPI.Tests.csproj +++ b/src/SMAPI.Tests/StardewModdingAPI.Tests.csproj @@ -11,6 +11,7 @@ StardewModdingAPI.Tests v4.5 512 + latest true diff --git a/src/SMAPI.Web/StardewModdingAPI.Web.csproj b/src/SMAPI.Web/StardewModdingAPI.Web.csproj index 9d1990d9..32fdf135 100644 --- a/src/SMAPI.Web/StardewModdingAPI.Web.csproj +++ b/src/SMAPI.Web/StardewModdingAPI.Web.csproj @@ -3,6 +3,7 @@ netcoreapp2.0 false + latest diff --git a/src/SMAPI.sln.DotSettings b/src/SMAPI.sln.DotSettings index 68d7c72b..5f67fd9e 100644 --- a/src/SMAPI.sln.DotSettings +++ b/src/SMAPI.sln.DotSettings @@ -18,6 +18,7 @@ True True True + True True True True diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 5540f277..6692bc02 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -27,6 +27,7 @@ 1.0.0.%2a false true + latest true diff --git a/src/StardewModdingAPI.Toolkit.CoreInterfaces/StardewModdingAPI.Toolkit.CoreInterfaces.csproj b/src/StardewModdingAPI.Toolkit.CoreInterfaces/StardewModdingAPI.Toolkit.CoreInterfaces.csproj index 525931e5..67adbd67 100644 --- a/src/StardewModdingAPI.Toolkit.CoreInterfaces/StardewModdingAPI.Toolkit.CoreInterfaces.csproj +++ b/src/StardewModdingAPI.Toolkit.CoreInterfaces/StardewModdingAPI.Toolkit.CoreInterfaces.csproj @@ -6,6 +6,7 @@ false ..\..\bin\$(Configuration)\SMAPI.Toolkit.CoreInterfaces ..\..\bin\$(Configuration)\SMAPI.Toolkit.CoreInterfaces\$(TargetFramework)\StardewModdingAPI.Toolkit.CoreInterfaces.xml + latest diff --git a/src/StardewModdingAPI.Toolkit/StardewModdingAPI.Toolkit.csproj b/src/StardewModdingAPI.Toolkit/StardewModdingAPI.Toolkit.csproj index 3fa28d19..351b36b6 100644 --- a/src/StardewModdingAPI.Toolkit/StardewModdingAPI.Toolkit.csproj +++ b/src/StardewModdingAPI.Toolkit/StardewModdingAPI.Toolkit.csproj @@ -5,6 +5,7 @@ false ..\..\bin\$(Configuration)\SMAPI.Toolkit ..\..\bin\$(Configuration)\SMAPI.Toolkit\$(TargetFramework)\StardewModdingAPI.Toolkit.xml + latest -- cgit From c4a82418ac8b09a6965052f5c9173928457fba52 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 27 Dec 2018 12:39:10 -0500 Subject: tweak comment header convention --- src/SMAPI.Installer/InteractiveInstaller.cs | 2 +- src/SMAPI.Installer/Program.cs | 2 +- src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs | 2 +- src/SMAPI.Internal/EnvironmentUtility.cs | 2 +- src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs | 2 +- .../ObsoleteFieldAnalyzerTests.cs | 2 +- src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs | 2 +- src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs | 2 +- src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs | 2 +- src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs | 2 +- .../Framework/Commands/Player/AddCommand.cs | 2 +- .../Framework/Commands/Player/ListItemTypesCommand.cs | 2 +- .../Framework/Commands/Player/ListItemsCommand.cs | 2 +- .../Framework/Commands/Player/SetHealthCommand.cs | 2 +- .../Framework/Commands/Player/SetMoneyCommand.cs | 2 +- .../Framework/Commands/Player/SetStaminaCommand.cs | 2 +- .../Framework/Commands/World/ClearCommand.cs | 2 +- .../Framework/Commands/World/FreezeTimeCommand.cs | 2 +- .../Framework/Commands/World/SetSeasonCommand.cs | 2 +- src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs | 2 +- src/SMAPI.Mods.ConsoleCommands/ModEntry.cs | 2 +- src/SMAPI.Mods.SaveBackup/ModEntry.cs | 2 +- src/SMAPI.Tests/Sample.cs | 6 +++--- src/SMAPI.Tests/Utilities/SDateTests.cs | 2 +- src/SMAPI.Web/Controllers/IndexController.cs | 2 +- src/SMAPI.Web/Controllers/LogParserController.cs | 2 +- src/SMAPI.Web/Controllers/ModsApiController.cs | 2 +- src/SMAPI.Web/Controllers/ModsController.cs | 2 +- src/SMAPI.Web/Framework/AllowLargePostsAttribute.cs | 2 +- src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs | 2 +- src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs | 2 +- src/SMAPI.Web/Framework/Clients/GitHub/GitHubClient.cs | 2 +- src/SMAPI.Web/Framework/Clients/ModDrop/ModDropClient.cs | 2 +- src/SMAPI.Web/Framework/Clients/Nexus/NexusWebScrapeClient.cs | 2 +- src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs | 2 +- src/SMAPI.Web/Framework/LogParsing/LogParser.cs | 2 +- src/SMAPI.Web/Framework/ModRepositories/ChucklefishRepository.cs | 2 +- src/SMAPI.Web/Framework/ModRepositories/GitHubRepository.cs | 2 +- src/SMAPI.Web/Framework/ModRepositories/ModDropRepository.cs | 2 +- src/SMAPI.Web/Framework/ModRepositories/NexusRepository.cs | 2 +- .../Framework/RewriteRules/ConditionalRedirectToHttpsRule.cs | 2 +- src/SMAPI.Web/Framework/RewriteRules/RedirectToUrlRule.cs | 2 +- src/SMAPI.Web/ViewModels/LogParserModel.cs | 2 +- src/SMAPI/Constants.cs | 2 +- src/SMAPI/Events/ButtonPressedEventArgs.cs | 2 +- src/SMAPI/Events/ButtonReleasedEventArgs.cs | 2 +- src/SMAPI/Events/ContentEvents.cs | 2 +- src/SMAPI/Events/ControlEvents.cs | 2 +- src/SMAPI/Events/EventArgsInput.cs | 2 +- src/SMAPI/Events/GameEvents.cs | 2 +- src/SMAPI/Events/GraphicsEvents.cs | 2 +- src/SMAPI/Events/InputEvents.cs | 2 +- src/SMAPI/Events/LocationEvents.cs | 2 +- src/SMAPI/Events/MenuEvents.cs | 2 +- src/SMAPI/Events/MineEvents.cs | 2 +- src/SMAPI/Events/ModMessageReceivedEventArgs.cs | 2 +- src/SMAPI/Events/MultiplayerEvents.cs | 2 +- src/SMAPI/Events/PlayerEvents.cs | 2 +- src/SMAPI/Events/SaveEvents.cs | 2 +- src/SMAPI/Events/SpecialisedEvents.cs | 2 +- src/SMAPI/Events/TimeEvents.cs | 2 +- src/SMAPI/Framework/CommandManager.cs | 2 +- src/SMAPI/Framework/Content/AssetData.cs | 2 +- src/SMAPI/Framework/Content/AssetDataForImage.cs | 2 +- src/SMAPI/Framework/Content/AssetInfo.cs | 2 +- src/SMAPI/Framework/Content/ContentCache.cs | 2 +- src/SMAPI/Framework/ContentCoordinator.cs | 2 +- src/SMAPI/Framework/ContentManagers/BaseContentManager.cs | 2 +- src/SMAPI/Framework/ContentManagers/GameContentManager.cs | 2 +- src/SMAPI/Framework/ContentManagers/ModContentManager.cs | 2 +- src/SMAPI/Framework/ContentPack.cs | 2 +- src/SMAPI/Framework/DeprecationManager.cs | 2 +- src/SMAPI/Framework/Events/ManagedEvent.cs | 4 ++-- src/SMAPI/Framework/Events/ManagedEventBase.cs | 2 +- src/SMAPI/Framework/Events/ModEventsBase.cs | 2 +- src/SMAPI/Framework/Input/GamePadStateBuilder.cs | 2 +- src/SMAPI/Framework/Logging/ConsoleInterceptionManager.cs | 2 +- src/SMAPI/Framework/Logging/LogFileManager.cs | 2 +- src/SMAPI/Framework/ModHelpers/CommandHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/ContentHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/ContentPackHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/DataHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/ModRegistryHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/MultiplayerHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/ReflectionHelper.cs | 2 +- src/SMAPI/Framework/ModHelpers/TranslationHelper.cs | 2 +- src/SMAPI/Framework/ModLoading/AssemblyDefinitionResolver.cs | 2 +- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 2 +- src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs | 2 +- src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs | 2 +- src/SMAPI/Framework/ModLoading/Finders/MethodFinder.cs | 2 +- src/SMAPI/Framework/ModLoading/Finders/PropertyFinder.cs | 2 +- .../ModLoading/Finders/ReferenceToMemberWithUnexpectedTypeFinder.cs | 2 +- .../Framework/ModLoading/Finders/ReferenceToMissingMemberFinder.cs | 2 +- src/SMAPI/Framework/ModLoading/RewriteHelper.cs | 2 +- src/SMAPI/Framework/ModLoading/Rewriters/FieldReplaceRewriter.cs | 2 +- src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs | 2 +- src/SMAPI/Framework/ModLoading/Rewriters/MethodParentRewriter.cs | 2 +- .../Framework/ModLoading/Rewriters/StaticFieldToConstantRewriter.cs | 2 +- src/SMAPI/Framework/ModLoading/Rewriters/TypeReferenceRewriter.cs | 2 +- src/SMAPI/Framework/ModRegistry.cs | 2 +- src/SMAPI/Framework/Monitor.cs | 2 +- src/SMAPI/Framework/Networking/MultiplayerPeer.cs | 2 +- src/SMAPI/Framework/Networking/SGalaxyNetClient.cs | 2 +- src/SMAPI/Framework/Networking/SGalaxyNetServer.cs | 2 +- src/SMAPI/Framework/Networking/SLidgrenClient.cs | 2 +- src/SMAPI/Framework/Networking/SLidgrenServer.cs | 2 +- src/SMAPI/Framework/Patching/GamePatcher.cs | 2 +- src/SMAPI/Framework/Reflection/InterfaceProxyBuilder.cs | 2 +- src/SMAPI/Framework/Reflection/InterfaceProxyFactory.cs | 2 +- src/SMAPI/Framework/Reflection/ReflectedField.cs | 2 +- src/SMAPI/Framework/Reflection/ReflectedMethod.cs | 2 +- src/SMAPI/Framework/Reflection/ReflectedProperty.cs | 2 +- src/SMAPI/Framework/Reflection/Reflector.cs | 2 +- src/SMAPI/Framework/SCore.cs | 2 +- src/SMAPI/Framework/SGame.cs | 2 +- src/SMAPI/Framework/SModHooks.cs | 2 +- src/SMAPI/Framework/SMultiplayer.cs | 2 +- .../Framework/StateTracking/FieldWatchers/BaseDisposableWatcher.cs | 2 +- .../Framework/StateTracking/FieldWatchers/ComparableListWatcher.cs | 2 +- .../Framework/StateTracking/FieldWatchers/ComparableWatcher.cs | 2 +- .../Framework/StateTracking/FieldWatchers/NetCollectionWatcher.cs | 2 +- .../Framework/StateTracking/FieldWatchers/NetDictionaryWatcher.cs | 2 +- src/SMAPI/Framework/StateTracking/FieldWatchers/NetValueWatcher.cs | 2 +- .../StateTracking/FieldWatchers/ObservableCollectionWatcher.cs | 2 +- src/SMAPI/Framework/StateTracking/LocationTracker.cs | 2 +- src/SMAPI/Framework/StateTracking/PlayerTracker.cs | 2 +- src/SMAPI/Framework/StateTracking/WorldLocationsTracker.cs | 2 +- src/SMAPI/Framework/WatcherCore.cs | 2 +- src/SMAPI/Metadata/CoreAssetPropagator.cs | 2 +- src/SMAPI/Metadata/InstructionMetadata.cs | 2 +- src/SMAPI/Program.cs | 2 +- src/SMAPI/SemanticVersion.cs | 2 +- src/SMAPI/Translation.cs | 2 +- src/SMAPI/Utilities/SDate.cs | 2 +- .../Framework/Clients/WebApi/WebApiClient.cs | 2 +- src/StardewModdingAPI.Toolkit/Framework/Clients/Wiki/WikiClient.cs | 2 +- src/StardewModdingAPI.Toolkit/Framework/ModData/ModDatabase.cs | 2 +- src/StardewModdingAPI.Toolkit/Framework/ModScanning/ModScanner.cs | 2 +- src/StardewModdingAPI.Toolkit/ModToolkit.cs | 2 +- src/StardewModdingAPI.Toolkit/SemanticVersion.cs | 2 +- src/StardewModdingAPI.Toolkit/Utilities/PathUtilities.cs | 2 +- 142 files changed, 145 insertions(+), 145 deletions(-) (limited to 'src') diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 95aed4ca..7148b1d9 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -22,7 +22,7 @@ namespace StardewModdingApi.Installer internal class InteractiveInstaller { /********* - ** Properties + ** Fields *********/ /// The absolute path to the directory containing the files to copy into the game folder. private readonly string BundlePath; diff --git a/src/SMAPI.Installer/Program.cs b/src/SMAPI.Installer/Program.cs index 0ca5aea0..3c4d8593 100644 --- a/src/SMAPI.Installer/Program.cs +++ b/src/SMAPI.Installer/Program.cs @@ -12,7 +12,7 @@ namespace StardewModdingApi.Installer internal class Program { /********* - ** Properties + ** Fields *********/ /// The absolute path of the installer folder. [SuppressMessage("ReSharper", "AssignNullToNotNullAttribute", Justification = "The assembly location is never null in this context.")] diff --git a/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs b/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs index c04cf0e7..cdc729e2 100644 --- a/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs +++ b/src/SMAPI.Internal/ConsoleWriting/ColorfulConsoleWriter.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Internal.ConsoleWriting internal class ColorfulConsoleWriter { /********* - ** Properties + ** Fields *********/ /// The console text color for each log level. private readonly IDictionary Colors; diff --git a/src/SMAPI.Internal/EnvironmentUtility.cs b/src/SMAPI.Internal/EnvironmentUtility.cs index a3581898..c4e4678a 100644 --- a/src/SMAPI.Internal/EnvironmentUtility.cs +++ b/src/SMAPI.Internal/EnvironmentUtility.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.Internal internal static class EnvironmentUtility { /********* - ** Properties + ** Fields *********/ /// Get the OS name from the system uname command. /// The buffer to fill with the resulting string. diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs index 6f8c8b9b..85a77d15 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs +++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/NetFieldAnalyzerTests.cs @@ -11,7 +11,7 @@ namespace SMAPI.ModBuildConfig.Analyzer.Tests public class NetFieldAnalyzerTests : DiagnosticVerifier { /********* - ** Properties + ** Fields *********/ /// Sample C# mod code, with a {{test-code}} placeholder for the code in the Entry method to test. const string SampleProgram = @" diff --git a/src/SMAPI.ModBuildConfig.Analyzer.Tests/ObsoleteFieldAnalyzerTests.cs b/src/SMAPI.ModBuildConfig.Analyzer.Tests/ObsoleteFieldAnalyzerTests.cs index 102a80d1..fa9235a3 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer.Tests/ObsoleteFieldAnalyzerTests.cs +++ b/src/SMAPI.ModBuildConfig.Analyzer.Tests/ObsoleteFieldAnalyzerTests.cs @@ -11,7 +11,7 @@ namespace SMAPI.ModBuildConfig.Analyzer.Tests public class ObsoleteFieldAnalyzerTests : DiagnosticVerifier { /********* - ** Properties + ** Fields *********/ /// Sample C# mod code, with a {{test-code}} placeholder for the code in the Entry method to test. const string SampleProgram = @" diff --git a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs index e6766e61..f2608348 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs +++ b/src/SMAPI.ModBuildConfig.Analyzer/NetFieldAnalyzer.cs @@ -14,7 +14,7 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer public class NetFieldAnalyzer : DiagnosticAnalyzer { /********* - ** Properties + ** Fields *********/ /// The namespace for Stardew Valley's Netcode types. private const string NetcodeNamespace = "Netcode"; diff --git a/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs b/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs index 3d353e52..f1a3ef75 100644 --- a/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs +++ b/src/SMAPI.ModBuildConfig.Analyzer/ObsoleteFieldAnalyzer.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.ModBuildConfig.Analyzer public class ObsoleteFieldAnalyzer : DiagnosticAnalyzer { /********* - ** Properties + ** Fields *********/ /// Maps obsolete fields/properties to their non-obsolete equivalent. private readonly IDictionary ReplacedFields = new Dictionary diff --git a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs index 7ff66695..e03683d0 100644 --- a/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs +++ b/src/SMAPI.ModBuildConfig/Framework/ModFileManager.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.ModBuildConfig.Framework internal class ModFileManager { /********* - ** Properties + ** Fields *********/ /// The name of the manifest file. private readonly string ManifestFileName = "manifest.json"; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs index 3ad1e168..10007b42 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/ArgumentParser.cs @@ -9,7 +9,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands internal class ArgumentParser : IReadOnlyList { /********* - ** Properties + ** Fields *********/ /// The command name for errors. private readonly string CommandName; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs index 37f4719e..263e126c 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/AddCommand.cs @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class AddCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Provides methods for searching and constructing items. private readonly ItemRepository Items = new ItemRepository(); diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs index 34f1760c..a835455e 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemTypesCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class ListItemTypesCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Provides methods for searching and constructing items. private readonly ItemRepository Items = new ItemRepository(); diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs index 942a50b8..5b52e9a2 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/ListItemsCommand.cs @@ -9,7 +9,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class ListItemsCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Provides methods for searching and constructing items. private readonly ItemRepository Items = new ItemRepository(); diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs index 2e8f6630..1abb82b5 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetHealthCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class SetHealthCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Whether to keep the player's health at its maximum. private bool InfiniteHealth; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs index 3fc504b1..ad11cc66 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetMoneyCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class SetMoneyCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Whether to keep the player's money at a set value. private bool InfiniteMoney; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs index 866c3d22..009cb1de 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/Player/SetStaminaCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.Player internal class SetStaminaCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// Whether to keep the player's stamina at its maximum. private bool InfiniteStamina; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs index 9b5f07de..c769b622 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/ClearCommand.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World internal class ClearCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// The valid types that can be cleared. private readonly string[] ValidTypes = { "debris", "fruit-trees", "grass", "trees", "everything" }; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs index 2627b714..6a7ab162 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/FreezeTimeCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World internal class FreezeTimeCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// The time of day at which to freeze time. internal static int FrozenTime; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs index b5db9c0d..0615afe7 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/Commands/World/SetSeasonCommand.cs @@ -7,7 +7,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework.Commands.World internal class SetSeasonCommand : TrainerCommand { /********* - ** Properties + ** Fields *********/ /// The valid season names. private readonly string[] ValidSeasons = { "winter", "spring", "summer", "fall" }; diff --git a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs index f4a38403..fc631826 100644 --- a/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs +++ b/src/SMAPI.Mods.ConsoleCommands/Framework/ItemRepository.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands.Framework internal class ItemRepository { /********* - ** Properties + ** Fields *********/ /// The custom ID offset for items don't have a unique ID in the game. private readonly int CustomIDOffset = 1000; diff --git a/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs b/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs index 30951064..77dace26 100644 --- a/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs +++ b/src/SMAPI.Mods.ConsoleCommands/ModEntry.cs @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Mods.ConsoleCommands public class ModEntry : Mod { /********* - ** Properties + ** Fields *********/ /// The commands to handle. private ITrainerCommand[] Commands; diff --git a/src/SMAPI.Mods.SaveBackup/ModEntry.cs b/src/SMAPI.Mods.SaveBackup/ModEntry.cs index 4d56789a..56a86cd9 100644 --- a/src/SMAPI.Mods.SaveBackup/ModEntry.cs +++ b/src/SMAPI.Mods.SaveBackup/ModEntry.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.Mods.SaveBackup public class ModEntry : Mod { /********* - ** Properties + ** Fields *********/ /// The number of backups to keep. private readonly int BackupsToKeep = 10; diff --git a/src/SMAPI.Tests/Sample.cs b/src/SMAPI.Tests/Sample.cs index 99835d92..6cd27707 100644 --- a/src/SMAPI.Tests/Sample.cs +++ b/src/SMAPI.Tests/Sample.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace StardewModdingAPI.Tests { @@ -6,14 +6,14 @@ namespace StardewModdingAPI.Tests internal static class Sample { /********* - ** Properties + ** Fields *********/ /// A random number generator. private static readonly Random Random = new Random(); /********* - ** Properties + ** Accessors *********/ /// Get a sample string. public static string String() diff --git a/src/SMAPI.Tests/Utilities/SDateTests.cs b/src/SMAPI.Tests/Utilities/SDateTests.cs index b89d8857..1f31168e 100644 --- a/src/SMAPI.Tests/Utilities/SDateTests.cs +++ b/src/SMAPI.Tests/Utilities/SDateTests.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Tests.Utilities internal class SDateTests { /********* - ** Properties + ** Fields *********/ /// All valid seasons. private static readonly string[] ValidSeasons = { "spring", "summer", "fall", "winter" }; diff --git a/src/SMAPI.Web/Controllers/IndexController.cs b/src/SMAPI.Web/Controllers/IndexController.cs index d7be664d..7b3b3e80 100644 --- a/src/SMAPI.Web/Controllers/IndexController.cs +++ b/src/SMAPI.Web/Controllers/IndexController.cs @@ -20,7 +20,7 @@ namespace StardewModdingAPI.Web.Controllers internal class IndexController : Controller { /********* - ** Properties + ** Fields *********/ /// The site config settings. private readonly SiteConfig SiteConfig; diff --git a/src/SMAPI.Web/Controllers/LogParserController.cs b/src/SMAPI.Web/Controllers/LogParserController.cs index 17f8d3aa..21e4a56f 100644 --- a/src/SMAPI.Web/Controllers/LogParserController.cs +++ b/src/SMAPI.Web/Controllers/LogParserController.cs @@ -19,7 +19,7 @@ namespace StardewModdingAPI.Web.Controllers internal class LogParserController : Controller { /********* - ** Properties + ** Fields *********/ /// The site config settings. private readonly SiteConfig Config; diff --git a/src/SMAPI.Web/Controllers/ModsApiController.cs b/src/SMAPI.Web/Controllers/ModsApiController.cs index 12d349e0..7e6f592c 100644 --- a/src/SMAPI.Web/Controllers/ModsApiController.cs +++ b/src/SMAPI.Web/Controllers/ModsApiController.cs @@ -28,7 +28,7 @@ namespace StardewModdingAPI.Web.Controllers internal class ModsApiController : Controller { /********* - ** Properties + ** Fields *********/ /// The mod repositories which provide mod metadata. private readonly IDictionary Repositories; diff --git a/src/SMAPI.Web/Controllers/ModsController.cs b/src/SMAPI.Web/Controllers/ModsController.cs index 57aa9da9..1ac0aff2 100644 --- a/src/SMAPI.Web/Controllers/ModsController.cs +++ b/src/SMAPI.Web/Controllers/ModsController.cs @@ -16,7 +16,7 @@ namespace StardewModdingAPI.Web.Controllers internal class ModsController : Controller { /********* - ** Properties + ** Fields *********/ /// The cache in which to store mod metadata. private readonly IMemoryCache Cache; diff --git a/src/SMAPI.Web/Framework/AllowLargePostsAttribute.cs b/src/SMAPI.Web/Framework/AllowLargePostsAttribute.cs index 68ead3c2..5dc0feb6 100644 --- a/src/SMAPI.Web/Framework/AllowLargePostsAttribute.cs +++ b/src/SMAPI.Web/Framework/AllowLargePostsAttribute.cs @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Web.Framework public class AllowLargePostsAttribute : Attribute, IAuthorizationFilter, IOrderedFilter { /********* - ** Properties + ** Fields *********/ /// The underlying form options. private readonly FormOptions FormOptions; diff --git a/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs b/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs index b39a3b61..fe27fe2f 100644 --- a/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs +++ b/src/SMAPI.Web/Framework/BeanstalkEnvPropsConfigProvider.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.Web.Framework internal class BeanstalkEnvPropsConfigProvider : ConfigurationProvider, IConfigurationSource { /********* - ** Properties + ** Fields *********/ /// The absolute path to the container configuration file on an Amazon EC2 instance. private const string ContainerConfigPath = @"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration"; diff --git a/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs index 029553ce..2753e33a 100644 --- a/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs +++ b/src/SMAPI.Web/Framework/Clients/Chucklefish/ChucklefishClient.cs @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.Chucklefish internal class ChucklefishClient : IChucklefishClient { /********* - ** Properties + ** Fields *********/ /// The URL for a mod page excluding the base URL, where {0} is the mod ID. private readonly string ModPageUrlFormat; diff --git a/src/SMAPI.Web/Framework/Clients/GitHub/GitHubClient.cs b/src/SMAPI.Web/Framework/Clients/GitHub/GitHubClient.cs index 2cfc6903..22950db9 100644 --- a/src/SMAPI.Web/Framework/Clients/GitHub/GitHubClient.cs +++ b/src/SMAPI.Web/Framework/Clients/GitHub/GitHubClient.cs @@ -10,7 +10,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.GitHub internal class GitHubClient : IGitHubClient { /********* - ** Properties + ** Fields *********/ /// The URL for a GitHub API query for the latest stable release, excluding the base URL, where {0} is the organisation and project name. private readonly string StableReleaseUrlFormat; diff --git a/src/SMAPI.Web/Framework/Clients/ModDrop/ModDropClient.cs b/src/SMAPI.Web/Framework/Clients/ModDrop/ModDropClient.cs index 19b0b24d..5ad2d2f8 100644 --- a/src/SMAPI.Web/Framework/Clients/ModDrop/ModDropClient.cs +++ b/src/SMAPI.Web/Framework/Clients/ModDrop/ModDropClient.cs @@ -9,7 +9,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.ModDrop internal class ModDropClient : IModDropClient { /********* - ** Properties + ** Fields *********/ /// The underlying HTTP client. private readonly IClient Client; diff --git a/src/SMAPI.Web/Framework/Clients/Nexus/NexusWebScrapeClient.cs b/src/SMAPI.Web/Framework/Clients/Nexus/NexusWebScrapeClient.cs index 1b3fa195..e83a6041 100644 --- a/src/SMAPI.Web/Framework/Clients/Nexus/NexusWebScrapeClient.cs +++ b/src/SMAPI.Web/Framework/Clients/Nexus/NexusWebScrapeClient.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.Nexus internal class NexusWebScrapeClient : INexusClient { /********* - ** Properties + ** Fields *********/ /// The URL for a Nexus mod page for the user, excluding the base URL, where {0} is the mod ID. private readonly string ModUrlFormat; diff --git a/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs b/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs index ef83a91e..12c3e83f 100644 --- a/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs +++ b/src/SMAPI.Web/Framework/Clients/Pastebin/PastebinClient.cs @@ -14,7 +14,7 @@ namespace StardewModdingAPI.Web.Framework.Clients.Pastebin internal class PastebinClient : IPastebinClient { /********* - ** Properties + ** Fields *********/ /// The underlying HTTP client. private readonly IClient Client; diff --git a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs index f9b5ba76..6f848469 100644 --- a/src/SMAPI.Web/Framework/LogParsing/LogParser.cs +++ b/src/SMAPI.Web/Framework/LogParsing/LogParser.cs @@ -12,7 +12,7 @@ namespace StardewModdingAPI.Web.Framework.LogParsing public class LogParser { /********* - ** Properties + ** Fields *********/ /// A regex pattern matching the start of a SMAPI message. private readonly Regex MessageHeaderPattern = new Regex(@"^\[(?