From 14fab29370310a762a000c50b23075326b4e95da Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 6 Oct 2018 00:25:48 -0400 Subject: add save and day-started events for 3.0 (#310) --- src/SMAPI/Events/DayStartedEventArgs.cs | 7 +++++ src/SMAPI/Events/IGameLoopEvents.cs | 18 +++++++++++ src/SMAPI/Events/SaveCreatedEventArgs.cs | 7 +++++ src/SMAPI/Events/SaveCreatingEventArgs.cs | 7 +++++ src/SMAPI/Events/SaveLoadedEventArgs.cs | 7 +++++ src/SMAPI/Events/SavedEventArgs.cs | 7 +++++ src/SMAPI/Events/SavingEventArgs.cs | 7 +++++ src/SMAPI/Framework/Events/EventManager.cs | 24 ++++++++++++++ src/SMAPI/Framework/Events/ModGameLoopEvents.cs | 42 +++++++++++++++++++++++++ src/SMAPI/Framework/InternalExtensions.cs | 12 +++++++ src/SMAPI/Framework/SGame.cs | 9 ++++++ src/SMAPI/Framework/Singleton.cs | 10 ++++++ src/SMAPI/StardewModdingAPI.csproj | 7 +++++ 13 files changed, 164 insertions(+) create mode 100644 src/SMAPI/Events/DayStartedEventArgs.cs create mode 100644 src/SMAPI/Events/SaveCreatedEventArgs.cs create mode 100644 src/SMAPI/Events/SaveCreatingEventArgs.cs create mode 100644 src/SMAPI/Events/SaveLoadedEventArgs.cs create mode 100644 src/SMAPI/Events/SavedEventArgs.cs create mode 100644 src/SMAPI/Events/SavingEventArgs.cs create mode 100644 src/SMAPI/Framework/Singleton.cs (limited to 'src/SMAPI') diff --git a/src/SMAPI/Events/DayStartedEventArgs.cs b/src/SMAPI/Events/DayStartedEventArgs.cs new file mode 100644 index 00000000..45823628 --- /dev/null +++ b/src/SMAPI/Events/DayStartedEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class DayStartedEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Events/IGameLoopEvents.cs b/src/SMAPI/Events/IGameLoopEvents.cs index 8ab86c9e..165aa0ce 100644 --- a/src/SMAPI/Events/IGameLoopEvents.cs +++ b/src/SMAPI/Events/IGameLoopEvents.cs @@ -13,5 +13,23 @@ namespace StardewModdingAPI.Events /// Raised after the game state is updated (≈60 times per second). event EventHandler UpdateTicked; + + /// Raised before the game creates a new save file. + event EventHandler SaveCreating; + + /// Raised after the game finishes creating the save file. + event EventHandler SaveCreated; + + /// Raised before the game begins writes data to the save file (except the initial save creation). + event EventHandler Saving; + + /// 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. + event EventHandler SaveLoaded; + + /// Raised after the game begins a new day (including when the player loads a save). + event EventHandler DayStarted; } } diff --git a/src/SMAPI/Events/SaveCreatedEventArgs.cs b/src/SMAPI/Events/SaveCreatedEventArgs.cs new file mode 100644 index 00000000..5ae22531 --- /dev/null +++ b/src/SMAPI/Events/SaveCreatedEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SaveCreatedEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Events/SaveCreatingEventArgs.cs b/src/SMAPI/Events/SaveCreatingEventArgs.cs new file mode 100644 index 00000000..3c83f421 --- /dev/null +++ b/src/SMAPI/Events/SaveCreatingEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SaveCreatingEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Events/SaveLoadedEventArgs.cs b/src/SMAPI/Events/SaveLoadedEventArgs.cs new file mode 100644 index 00000000..f8aaa7f7 --- /dev/null +++ b/src/SMAPI/Events/SaveLoadedEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SaveLoadedEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Events/SavedEventArgs.cs b/src/SMAPI/Events/SavedEventArgs.cs new file mode 100644 index 00000000..a4e90729 --- /dev/null +++ b/src/SMAPI/Events/SavedEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SavedEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Events/SavingEventArgs.cs b/src/SMAPI/Events/SavingEventArgs.cs new file mode 100644 index 00000000..f323ca9e --- /dev/null +++ b/src/SMAPI/Events/SavingEventArgs.cs @@ -0,0 +1,7 @@ +using System; + +namespace StardewModdingAPI.Events +{ + /// Event arguments for an event. + public class SavingEventArgs : EventArgs { } +} diff --git a/src/SMAPI/Framework/Events/EventManager.cs b/src/SMAPI/Framework/Events/EventManager.cs index 1435976a..023c45de 100644 --- a/src/SMAPI/Framework/Events/EventManager.cs +++ b/src/SMAPI/Framework/Events/EventManager.cs @@ -23,6 +23,24 @@ namespace StardewModdingAPI.Framework.Events /// Raised after the game performs its overall update tick (≈60 times per second). public readonly ManagedEvent UpdateTicked; + /// Raised before the game creates the save file. + public readonly ManagedEvent SaveCreating; + + /// Raised after the game finishes creating the save file. + public readonly ManagedEvent SaveCreated; + + /// Raised before the game begins writes data to the save file (except the initial save creation). + public readonly ManagedEvent Saving; + + /// 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. + public readonly ManagedEvent SaveLoaded; + + /// Raised after the game begins a new day, including when loading a save. + public readonly ManagedEvent DayStarted; + /**** ** Input ****/ @@ -267,6 +285,12 @@ 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.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)); + this.Saved = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.Saved)); + this.SaveLoaded = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.SaveLoaded)); + this.DayStarted = ManageEventOf(nameof(IModEvents.GameLoop), nameof(IGameLoopEvents.DayStarted)); this.ButtonPressed = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.ButtonPressed)); this.ButtonReleased = ManageEventOf(nameof(IModEvents.Input), nameof(IInputEvents.ButtonReleased)); diff --git a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs index 781597ef..cf7e54aa 100644 --- a/src/SMAPI/Framework/Events/ModGameLoopEvents.cs +++ b/src/SMAPI/Framework/Events/ModGameLoopEvents.cs @@ -30,6 +30,48 @@ namespace StardewModdingAPI.Framework.Events remove => this.EventManager.UpdateTicked.Remove(value); } + /// Raised before the game creates a new save file. + public event EventHandler SaveCreating + { + add => this.EventManager.SaveCreating.Add(value); + remove => this.EventManager.SaveCreating.Remove(value); + } + + /// Raised after the game finishes creating the save file. + public event EventHandler SaveCreated + { + add => this.EventManager.SaveCreated.Add(value); + remove => this.EventManager.SaveCreated.Remove(value); + } + + /// Raised before the game begins writes data to the save file. + public event EventHandler Saving + { + add => this.EventManager.Saving.Add(value); + remove => this.EventManager.Saving.Remove(value); + } + + /// Raised after the game finishes writing data to the save file. + public event EventHandler Saved + { + add => this.EventManager.Saved.Add(value); + remove => this.EventManager.Saved.Remove(value); + } + + /// Raised after the player loads a save slot. + public event EventHandler SaveLoaded + { + add => this.EventManager.SaveLoaded.Add(value); + remove => this.EventManager.SaveLoaded.Remove(value); + } + + /// Raised after the game begins a new day (including when the player loads a save). + public event EventHandler DayStarted + { + add => this.EventManager.DayStarted.Add(value); + remove => this.EventManager.DayStarted.Remove(value); + } + /********* ** Public methods diff --git a/src/SMAPI/Framework/InternalExtensions.cs b/src/SMAPI/Framework/InternalExtensions.cs index ff3925fb..b51ff6a8 100644 --- a/src/SMAPI/Framework/InternalExtensions.cs +++ b/src/SMAPI/Framework/InternalExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Reflection; using Microsoft.Xna.Framework.Graphics; +using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Reflection; using StardewValley; @@ -39,6 +40,17 @@ namespace StardewModdingAPI.Framework metadata.Monitor.Log(message, level); } + /**** + ** ManagedEvent + ****/ + /// Raise the event and notify all handlers. + /// The empty event arguments type to construct. + /// The event to raise. + public static void RaiseEmpty(this ManagedEvent @event) where TEventArgs : new() + { + @event.Raise(Singleton.Instance); + } + /**** ** Exceptions ****/ diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index a432e844..ef851afc 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -323,6 +323,7 @@ namespace StardewModdingAPI.Framework { this.IsBetweenCreateEvents = true; this.Monitor.Log("Context: before save creation.", LogLevel.Trace); + this.Events.SaveCreating.RaiseEmpty(); this.Events.Legacy_BeforeCreateSave.Raise(); } @@ -331,6 +332,7 @@ namespace StardewModdingAPI.Framework { this.IsBetweenSaveEvents = true; this.Monitor.Log("Context: before save.", LogLevel.Trace); + this.Events.Saving.RaiseEmpty(); this.Events.Legacy_BeforeSave.Raise(); } @@ -344,6 +346,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.Events.SaveCreated.RaiseEmpty(); this.Events.Legacy_AfterCreateSave.Raise(); } if (this.IsBetweenSaveEvents) @@ -351,6 +354,9 @@ 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(); + this.Events.Legacy_AfterSave.Raise(); this.Events.Legacy_AfterDayStarted.Raise(); } @@ -410,6 +416,9 @@ namespace StardewModdingAPI.Framework // raise events this.RaisedAfterLoadEvent = true; + this.Events.SaveLoaded.RaiseEmpty(); + this.Events.DayStarted.RaiseEmpty(); + this.Events.Legacy_AfterLoad.Raise(); this.Events.Legacy_AfterDayStarted.Raise(); } diff --git a/src/SMAPI/Framework/Singleton.cs b/src/SMAPI/Framework/Singleton.cs new file mode 100644 index 00000000..399a8bf0 --- /dev/null +++ b/src/SMAPI/Framework/Singleton.cs @@ -0,0 +1,10 @@ +namespace StardewModdingAPI.Framework +{ + /// Provides singleton instances of a given type. + /// The instance type. + internal static class Singleton where T : new() + { + /// The singleton instance. + public static T Instance { get; } = new T(); + } +} diff --git a/src/SMAPI/StardewModdingAPI.csproj b/src/SMAPI/StardewModdingAPI.csproj index 5ddee30c..4c8f2ffa 100644 --- a/src/SMAPI/StardewModdingAPI.csproj +++ b/src/SMAPI/StardewModdingAPI.csproj @@ -79,6 +79,12 @@ Properties\GlobalAssemblyInfo.cs + + + + + + @@ -125,6 +131,7 @@ + -- cgit