summaryrefslogtreecommitdiff
path: root/src/SMAPI/Events
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Events')
-rw-r--r--src/SMAPI/Events/ChangeType.cs15
-rw-r--r--src/SMAPI/Events/ContentEvents.cs29
-rw-r--r--src/SMAPI/Events/ControlEvents.cs112
-rw-r--r--src/SMAPI/Events/EventArgsClickableMenuChanged.cs31
-rw-r--r--src/SMAPI/Events/EventArgsClickableMenuClosed.cs26
-rw-r--r--src/SMAPI/Events/EventArgsControllerButtonPressed.cs32
-rw-r--r--src/SMAPI/Events/EventArgsControllerButtonReleased.cs32
-rw-r--r--src/SMAPI/Events/EventArgsControllerTriggerPressed.cs37
-rw-r--r--src/SMAPI/Events/EventArgsControllerTriggerReleased.cs37
-rw-r--r--src/SMAPI/Events/EventArgsCurrentLocationChanged.cs31
-rw-r--r--src/SMAPI/Events/EventArgsGameLocationsChanged.cs27
-rw-r--r--src/SMAPI/Events/EventArgsInput.cs124
-rw-r--r--src/SMAPI/Events/EventArgsIntChanged.cs29
-rw-r--r--src/SMAPI/Events/EventArgsInventoryChanged.cs41
-rw-r--r--src/SMAPI/Events/EventArgsKeyPressed.cs26
-rw-r--r--src/SMAPI/Events/EventArgsKeyboardStateChanged.cs31
-rw-r--r--src/SMAPI/Events/EventArgsLevelUp.cs52
-rw-r--r--src/SMAPI/Events/EventArgsLocationObjectsChanged.cs28
-rw-r--r--src/SMAPI/Events/EventArgsMineLevelChanged.cs30
-rw-r--r--src/SMAPI/Events/EventArgsMouseStateChanged.cs42
-rw-r--r--src/SMAPI/Events/EventArgsValueChanged.cs31
-rw-r--r--src/SMAPI/Events/GameEvents.cs96
-rw-r--r--src/SMAPI/Events/GraphicsEvents.cs116
-rw-r--r--src/SMAPI/Events/InputEvents.cs43
-rw-r--r--src/SMAPI/Events/ItemStackChange.cs20
-rw-r--r--src/SMAPI/Events/LocationEvents.cs54
-rw-r--r--src/SMAPI/Events/MenuEvents.cs40
-rw-r--r--src/SMAPI/Events/MineEvents.cs28
-rw-r--r--src/SMAPI/Events/PlayerEvents.cs43
-rw-r--r--src/SMAPI/Events/SaveEvents.cs56
-rw-r--r--src/SMAPI/Events/TimeEvents.cs37
31 files changed, 1376 insertions, 0 deletions
diff --git a/src/SMAPI/Events/ChangeType.cs b/src/SMAPI/Events/ChangeType.cs
new file mode 100644
index 00000000..4b207f08
--- /dev/null
+++ b/src/SMAPI/Events/ChangeType.cs
@@ -0,0 +1,15 @@
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Indicates how an inventory item changed.</summary>
+ public enum ChangeType
+ {
+ /// <summary>The entire stack was removed.</summary>
+ Removed,
+
+ /// <summary>The entire stack was added.</summary>
+ Added,
+
+ /// <summary>The stack size changed.</summary>
+ StackChange
+ }
+} \ No newline at end of file
diff --git a/src/SMAPI/Events/ContentEvents.cs b/src/SMAPI/Events/ContentEvents.cs
new file mode 100644
index 00000000..4b4e2ad0
--- /dev/null
+++ b/src/SMAPI/Events/ContentEvents.cs
@@ -0,0 +1,29 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the game loads content.</summary>
+ public static class ContentEvents
+ {
+
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after the content language changes.</summary>
+ public static event EventHandler<EventArgsValueChanged<string>> AfterLocaleChanged;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise an <see cref="AfterLocaleChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="oldLocale">The previous locale.</param>
+ /// <param name="newLocale">The current locale.</param>
+ internal static void InvokeAfterLocaleChanged(IMonitor monitor, string oldLocale, string newLocale)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ContentEvents)}.{nameof(ContentEvents.AfterLocaleChanged)}", ContentEvents.AfterLocaleChanged?.GetInvocationList(), null, new EventArgsValueChanged<string>(oldLocale, newLocale));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/ControlEvents.cs b/src/SMAPI/Events/ControlEvents.cs
new file mode 100644
index 00000000..80d0f547
--- /dev/null
+++ b/src/SMAPI/Events/ControlEvents.cs
@@ -0,0 +1,112 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the player uses a controller, keyboard, or mouse.</summary>
+ public static class ControlEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised when the <see cref="KeyboardState"/> changes. That happens when the player presses or releases a key.</summary>
+ public static event EventHandler<EventArgsKeyboardStateChanged> KeyboardChanged;
+
+ /// <summary>Raised when the player presses a keyboard key.</summary>
+ public static event EventHandler<EventArgsKeyPressed> KeyPressed;
+
+ /// <summary>Raised when the player releases a keyboard key.</summary>
+ public static event EventHandler<EventArgsKeyPressed> KeyReleased;
+
+ /// <summary>Raised when the <see cref="MouseState"/> changes. That happens when the player moves the mouse, scrolls the mouse wheel, or presses/releases a button.</summary>
+ public static event EventHandler<EventArgsMouseStateChanged> MouseChanged;
+
+ /// <summary>The player pressed a controller button. This event isn't raised for trigger buttons.</summary>
+ public static event EventHandler<EventArgsControllerButtonPressed> ControllerButtonPressed;
+
+ /// <summary>The player released a controller button. This event isn't raised for trigger buttons.</summary>
+ public static event EventHandler<EventArgsControllerButtonReleased> ControllerButtonReleased;
+
+ /// <summary>The player pressed a controller trigger button.</summary>
+ public static event EventHandler<EventArgsControllerTriggerPressed> ControllerTriggerPressed;
+
+ /// <summary>The player released a controller trigger button.</summary>
+ public static event EventHandler<EventArgsControllerTriggerReleased> ControllerTriggerReleased;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="KeyboardChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorState">The previous keyboard state.</param>
+ /// <param name="newState">The current keyboard state.</param>
+ internal static void InvokeKeyboardChanged(IMonitor monitor, KeyboardState priorState, KeyboardState newState)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.KeyboardChanged)}", ControlEvents.KeyboardChanged?.GetInvocationList(), null, new EventArgsKeyboardStateChanged(priorState, newState));
+ }
+
+ /// <summary>Raise a <see cref="MouseChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorState">The previous mouse state.</param>
+ /// <param name="newState">The current mouse state.</param>
+ /// <param name="priorPosition">The previous mouse position on the screen adjusted for the zoom level.</param>
+ /// <param name="newPosition">The current mouse position on the screen adjusted for the zoom level.</param>
+ internal static void InvokeMouseChanged(IMonitor monitor, MouseState priorState, MouseState newState, Point priorPosition, Point newPosition)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.MouseChanged)}", ControlEvents.MouseChanged?.GetInvocationList(), null, new EventArgsMouseStateChanged(priorState, newState, priorPosition, newPosition));
+ }
+
+ /// <summary>Raise a <see cref="KeyPressed"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="key">The keyboard button that was pressed.</param>
+ internal static void InvokeKeyPressed(IMonitor monitor, Keys key)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.KeyPressed)}", ControlEvents.KeyPressed?.GetInvocationList(), null, new EventArgsKeyPressed(key));
+ }
+
+ /// <summary>Raise a <see cref="KeyReleased"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="key">The keyboard button that was released.</param>
+ internal static void InvokeKeyReleased(IMonitor monitor, Keys key)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.KeyReleased)}", ControlEvents.KeyReleased?.GetInvocationList(), null, new EventArgsKeyPressed(key));
+ }
+
+ /// <summary>Raise a <see cref="ControllerButtonPressed"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The controller button that was pressed.</param>
+ internal static void InvokeButtonPressed(IMonitor monitor, Buttons button)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.ControllerButtonPressed)}", ControlEvents.ControllerButtonPressed?.GetInvocationList(), null, new EventArgsControllerButtonPressed(PlayerIndex.One, button));
+ }
+
+ /// <summary>Raise a <see cref="ControllerButtonReleased"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The controller button that was released.</param>
+ internal static void InvokeButtonReleased(IMonitor monitor, Buttons button)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.ControllerButtonReleased)}", ControlEvents.ControllerButtonReleased?.GetInvocationList(), null, new EventArgsControllerButtonReleased(PlayerIndex.One, button));
+ }
+
+ /// <summary>Raise a <see cref="ControllerTriggerPressed"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The trigger button that was pressed.</param>
+ /// <param name="value">The current trigger value.</param>
+ internal static void InvokeTriggerPressed(IMonitor monitor, Buttons button, float value)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.ControllerTriggerPressed)}", ControlEvents.ControllerTriggerPressed?.GetInvocationList(), null, new EventArgsControllerTriggerPressed(PlayerIndex.One, button, value));
+ }
+
+ /// <summary>Raise a <see cref="ControllerTriggerReleased"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The trigger button that was pressed.</param>
+ /// <param name="value">The current trigger value.</param>
+ internal static void InvokeTriggerReleased(IMonitor monitor, Buttons button, float value)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(ControlEvents)}.{nameof(ControlEvents.ControllerTriggerReleased)}", ControlEvents.ControllerTriggerReleased?.GetInvocationList(), null, new EventArgsControllerTriggerReleased(PlayerIndex.One, button, value));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsClickableMenuChanged.cs b/src/SMAPI/Events/EventArgsClickableMenuChanged.cs
new file mode 100644
index 00000000..2a2aa163
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsClickableMenuChanged.cs
@@ -0,0 +1,31 @@
+using System;
+using StardewValley.Menus;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="MenuEvents.MenuChanged"/> event.</summary>
+ public class EventArgsClickableMenuChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous menu.</summary>
+ public IClickableMenu NewMenu { get; }
+
+ /// <summary>The current menu.</summary>
+ public IClickableMenu PriorMenu { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorMenu">The previous menu.</param>
+ /// <param name="newMenu">The current menu.</param>
+ public EventArgsClickableMenuChanged(IClickableMenu priorMenu, IClickableMenu newMenu)
+ {
+ this.NewMenu = newMenu;
+ this.PriorMenu = priorMenu;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsClickableMenuClosed.cs b/src/SMAPI/Events/EventArgsClickableMenuClosed.cs
new file mode 100644
index 00000000..5e6585f0
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsClickableMenuClosed.cs
@@ -0,0 +1,26 @@
+using System;
+using StardewValley.Menus;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="MenuEvents.MenuClosed"/> event.</summary>
+ public class EventArgsClickableMenuClosed : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The menu that was closed.</summary>
+ public IClickableMenu PriorMenu { get; }
+
+
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorMenu">The menu that was closed.</param>
+ public EventArgsClickableMenuClosed(IClickableMenu priorMenu)
+ {
+ this.PriorMenu = priorMenu;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsControllerButtonPressed.cs b/src/SMAPI/Events/EventArgsControllerButtonPressed.cs
new file mode 100644
index 00000000..3243b80b
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsControllerButtonPressed.cs
@@ -0,0 +1,32 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.ControllerButtonPressed"/> event.</summary>
+ public class EventArgsControllerButtonPressed : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player who pressed the button.</summary>
+ public PlayerIndex PlayerIndex { get; }
+
+ /// <summary>The controller button that was pressed.</summary>
+ public Buttons ButtonPressed { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="playerIndex">The player who pressed the button.</param>
+ /// <param name="button">The controller button that was pressed.</param>
+ public EventArgsControllerButtonPressed(PlayerIndex playerIndex, Buttons button)
+ {
+ this.PlayerIndex = playerIndex;
+ this.ButtonPressed = button;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsControllerButtonReleased.cs b/src/SMAPI/Events/EventArgsControllerButtonReleased.cs
new file mode 100644
index 00000000..e05a080b
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsControllerButtonReleased.cs
@@ -0,0 +1,32 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.ControllerButtonReleased"/> event.</summary>
+ public class EventArgsControllerButtonReleased : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player who pressed the button.</summary>
+ public PlayerIndex PlayerIndex { get; }
+
+ /// <summary>The controller button that was pressed.</summary>
+ public Buttons ButtonReleased { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="playerIndex">The player who pressed the button.</param>
+ /// <param name="button">The controller button that was released.</param>
+ public EventArgsControllerButtonReleased(PlayerIndex playerIndex, Buttons button)
+ {
+ this.PlayerIndex = playerIndex;
+ this.ButtonReleased = button;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsControllerTriggerPressed.cs b/src/SMAPI/Events/EventArgsControllerTriggerPressed.cs
new file mode 100644
index 00000000..a2087733
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsControllerTriggerPressed.cs
@@ -0,0 +1,37 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.ControllerTriggerPressed"/> event.</summary>
+ public class EventArgsControllerTriggerPressed : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player who pressed the button.</summary>
+ public PlayerIndex PlayerIndex { get; }
+
+ /// <summary>The controller button that was pressed.</summary>
+ public Buttons ButtonPressed { get; }
+
+ /// <summary>The current trigger value.</summary>
+ public float Value { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="playerIndex">The player who pressed the trigger button.</param>
+ /// <param name="button">The trigger button that was pressed.</param>
+ /// <param name="value">The current trigger value.</param>
+ public EventArgsControllerTriggerPressed(PlayerIndex playerIndex, Buttons button, float value)
+ {
+ this.PlayerIndex = playerIndex;
+ this.ButtonPressed = button;
+ this.Value = value;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsControllerTriggerReleased.cs b/src/SMAPI/Events/EventArgsControllerTriggerReleased.cs
new file mode 100644
index 00000000..d2eecbec
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsControllerTriggerReleased.cs
@@ -0,0 +1,37 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.ControllerTriggerReleased"/> event.</summary>
+ public class EventArgsControllerTriggerReleased : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player who pressed the button.</summary>
+ public PlayerIndex PlayerIndex { get; }
+
+ /// <summary>The controller button that was released.</summary>
+ public Buttons ButtonReleased { get; }
+
+ /// <summary>The current trigger value.</summary>
+ public float Value { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="playerIndex">The player who pressed the trigger button.</param>
+ /// <param name="button">The trigger button that was released.</param>
+ /// <param name="value">The current trigger value.</param>
+ public EventArgsControllerTriggerReleased(PlayerIndex playerIndex, Buttons button, float value)
+ {
+ this.PlayerIndex = playerIndex;
+ this.ButtonReleased = button;
+ this.Value = value;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsCurrentLocationChanged.cs b/src/SMAPI/Events/EventArgsCurrentLocationChanged.cs
new file mode 100644
index 00000000..25d3ebf3
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsCurrentLocationChanged.cs
@@ -0,0 +1,31 @@
+using System;
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="LocationEvents.CurrentLocationChanged"/> event.</summary>
+ public class EventArgsCurrentLocationChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player's current location.</summary>
+ public GameLocation NewLocation { get; }
+
+ /// <summary>The player's previous location.</summary>
+ public GameLocation PriorLocation { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorLocation">The player's previous location.</param>
+ /// <param name="newLocation">The player's current location.</param>
+ public EventArgsCurrentLocationChanged(GameLocation priorLocation, GameLocation newLocation)
+ {
+ this.NewLocation = newLocation;
+ this.PriorLocation = priorLocation;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsGameLocationsChanged.cs b/src/SMAPI/Events/EventArgsGameLocationsChanged.cs
new file mode 100644
index 00000000..fb8c821e
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsGameLocationsChanged.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="LocationEvents.LocationsChanged"/> event.</summary>
+ public class EventArgsGameLocationsChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The current list of game locations.</summary>
+ public List<GameLocation> NewLocations { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="newLocations">The current list of game locations.</param>
+ public EventArgsGameLocationsChanged(List<GameLocation> newLocations)
+ {
+ this.NewLocations = newLocations;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsInput.cs b/src/SMAPI/Events/EventArgsInput.cs
new file mode 100644
index 00000000..66cb19f2
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsInput.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Linq;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+using StardewModdingAPI.Utilities;
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments when a button is pressed or released.</summary>
+ public class EventArgsInput : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The button on the controller, keyboard, or mouse.</summary>
+ public SButton Button { get; }
+
+ /// <summary>The current cursor position.</summary>
+ public ICursorPosition Cursor { get; set; }
+
+ /// <summary>Whether the input is considered a 'click' by the game for enabling action.</summary>
+ public bool IsClick { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="button">The button on the controller, keyboard, or mouse.</param>
+ /// <param name="cursor">The cursor position.</param>
+ /// <param name="isClick">Whether the input is considered a 'click' by the game for enabling action.</param>
+ public EventArgsInput(SButton button, ICursorPosition cursor, bool isClick)
+ {
+ this.Button = button;
+ this.Cursor = cursor;
+ this.IsClick = isClick;
+ }
+
+ /// <summary>Prevent the game from handling the vurrent button press. This doesn't prevent other mods from receiving the event.</summary>
+ public void SuppressButton()
+ {
+ this.SuppressButton(this.Button);
+ }
+
+ /// <summary>Prevent the game from handling a button press. This doesn't prevent other mods from receiving the event.</summary>
+ /// <param name="button">The button to suppress.</param>
+ public void SuppressButton(SButton button)
+ {
+ // keyboard
+ if (this.Button.TryGetKeyboard(out Keys key))
+ Game1.oldKBState = new KeyboardState(Game1.oldKBState.GetPressedKeys().Except(new[] { key }).ToArray());
+
+ // controller
+ else if (this.Button.TryGetController(out Buttons controllerButton))
+ {
+ var newState = GamePad.GetState(PlayerIndex.One);
+ var thumbsticks = Game1.oldPadState.ThumbSticks;
+ var triggers = Game1.oldPadState.Triggers;
+ var buttons = Game1.oldPadState.Buttons;
+ var dpad = Game1.oldPadState.DPad;
+
+ switch (controllerButton)
+ {
+ // d-pad
+ case Buttons.DPadDown:
+ dpad = new GamePadDPad(dpad.Up, newState.DPad.Down, dpad.Left, dpad.Right);
+ break;
+ case Buttons.DPadLeft:
+ dpad = new GamePadDPad(dpad.Up, dpad.Down, newState.DPad.Left, dpad.Right);
+ break;
+ case Buttons.DPadRight:
+ dpad = new GamePadDPad(dpad.Up, dpad.Down, dpad.Left, newState.DPad.Right);
+ break;
+ case Buttons.DPadUp:
+ dpad = new GamePadDPad(newState.DPad.Up, dpad.Down, dpad.Left, dpad.Right);
+ break;
+
+ // trigger
+ case Buttons.LeftTrigger:
+ triggers = new GamePadTriggers(newState.Triggers.Left, triggers.Right);
+ break;
+ case Buttons.RightTrigger:
+ triggers = new GamePadTriggers(triggers.Left, newState.Triggers.Right);
+ break;
+
+ // thumbstick
+ case Buttons.LeftThumbstickDown:
+ case Buttons.LeftThumbstickLeft:
+ case Buttons.LeftThumbstickRight:
+ case Buttons.LeftThumbstickUp:
+ thumbsticks = new GamePadThumbSticks(newState.ThumbSticks.Left, thumbsticks.Right);
+ break;
+ case Buttons.RightThumbstickDown:
+ case Buttons.RightThumbstickLeft:
+ case Buttons.RightThumbstickRight:
+ case Buttons.RightThumbstickUp:
+ thumbsticks = new GamePadThumbSticks(newState.ThumbSticks.Right, thumbsticks.Left);
+ break;
+
+ // buttons
+ default:
+ var mask =
+ (buttons.A == ButtonState.Pressed ? Buttons.A : 0)
+ | (buttons.B == ButtonState.Pressed ? Buttons.B : 0)
+ | (buttons.Back == ButtonState.Pressed ? Buttons.Back : 0)
+ | (buttons.BigButton == ButtonState.Pressed ? Buttons.BigButton : 0)
+ | (buttons.LeftShoulder == ButtonState.Pressed ? Buttons.LeftShoulder : 0)
+ | (buttons.LeftStick == ButtonState.Pressed ? Buttons.LeftStick : 0)
+ | (buttons.RightShoulder == ButtonState.Pressed ? Buttons.RightShoulder : 0)
+ | (buttons.RightStick == ButtonState.Pressed ? Buttons.RightStick : 0)
+ | (buttons.Start == ButtonState.Pressed ? Buttons.Start : 0)
+ | (buttons.X == ButtonState.Pressed ? Buttons.X : 0)
+ | (buttons.Y == ButtonState.Pressed ? Buttons.Y : 0);
+ mask = mask ^ controllerButton;
+ buttons = new GamePadButtons(mask);
+ break;
+ }
+
+ Game1.oldPadState = new GamePadState(thumbsticks, triggers, buttons, dpad);
+ }
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsIntChanged.cs b/src/SMAPI/Events/EventArgsIntChanged.cs
new file mode 100644
index 00000000..0c742d12
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsIntChanged.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for an integer field that changed value.</summary>
+ public class EventArgsIntChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous value.</summary>
+ public int PriorInt { get; }
+
+ /// <summary>The current value.</summary>
+ public int NewInt { get; }
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorInt">The previous value.</param>
+ /// <param name="newInt">The current value.</param>
+ public EventArgsIntChanged(int priorInt, int newInt)
+ {
+ this.PriorInt = priorInt;
+ this.NewInt = newInt;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsInventoryChanged.cs b/src/SMAPI/Events/EventArgsInventoryChanged.cs
new file mode 100644
index 00000000..1ee02842
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsInventoryChanged.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="PlayerEvents.InventoryChanged"/> event.</summary>
+ public class EventArgsInventoryChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player's inventory.</summary>
+ public List<Item> Inventory { get; }
+
+ /// <summary>The added items.</summary>
+ public List<ItemStackChange> Added { get; }
+
+ /// <summary>The removed items.</summary>
+ public List<ItemStackChange> Removed { get; }
+
+ /// <summary>The items whose stack sizes changed.</summary>
+ public List<ItemStackChange> QuantityChanged { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="inventory">The player's inventory.</param>
+ /// <param name="changedItems">The inventory changes.</param>
+ public EventArgsInventoryChanged(List<Item> inventory, List<ItemStackChange> changedItems)
+ {
+ this.Inventory = inventory;
+ this.Added = changedItems.Where(n => n.ChangeType == ChangeType.Added).ToList();
+ this.Removed = changedItems.Where(n => n.ChangeType == ChangeType.Removed).ToList();
+ this.QuantityChanged = changedItems.Where(n => n.ChangeType == ChangeType.StackChange).ToList();
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsKeyPressed.cs b/src/SMAPI/Events/EventArgsKeyPressed.cs
new file mode 100644
index 00000000..d9d81e10
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsKeyPressed.cs
@@ -0,0 +1,26 @@
+using System;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.KeyboardChanged"/> event.</summary>
+ public class EventArgsKeyPressed : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The keyboard button that was pressed.</summary>
+ public Keys KeyPressed { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="key">The keyboard button that was pressed.</param>
+ public EventArgsKeyPressed(Keys key)
+ {
+ this.KeyPressed = key;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsKeyboardStateChanged.cs b/src/SMAPI/Events/EventArgsKeyboardStateChanged.cs
new file mode 100644
index 00000000..14e397ce
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsKeyboardStateChanged.cs
@@ -0,0 +1,31 @@
+using System;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.KeyboardChanged"/> event.</summary>
+ public class EventArgsKeyboardStateChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous keyboard state.</summary>
+ public KeyboardState NewState { get; }
+
+ /// <summary>The current keyboard state.</summary>
+ public KeyboardState PriorState { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorState">The previous keyboard state.</param>
+ /// <param name="newState">The current keyboard state.</param>
+ public EventArgsKeyboardStateChanged(KeyboardState priorState, KeyboardState newState)
+ {
+ this.PriorState = priorState;
+ this.NewState = newState;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsLevelUp.cs b/src/SMAPI/Events/EventArgsLevelUp.cs
new file mode 100644
index 00000000..fe6696d4
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsLevelUp.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="PlayerEvents.LeveledUp"/> event.</summary>
+ public class EventArgsLevelUp : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The player skill that leveled up.</summary>
+ public LevelType Type { get; }
+
+ /// <summary>The new skill level.</summary>
+ public int NewLevel { get; }
+
+ /// <summary>The player skill types.</summary>
+ public enum LevelType
+ {
+ /// <summary>The combat skill.</summary>
+ Combat,
+
+ /// <summary>The farming skill.</summary>
+ Farming,
+
+ /// <summary>The fishing skill.</summary>
+ Fishing,
+
+ /// <summary>The foraging skill.</summary>
+ Foraging,
+
+ /// <summary>The mining skill.</summary>
+ Mining,
+
+ /// <summary>The luck skill.</summary>
+ Luck
+ }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="type">The player skill that leveled up.</param>
+ /// <param name="newLevel">The new skill level.</param>
+ public EventArgsLevelUp(LevelType type, int newLevel)
+ {
+ this.Type = type;
+ this.NewLevel = newLevel;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsLocationObjectsChanged.cs b/src/SMAPI/Events/EventArgsLocationObjectsChanged.cs
new file mode 100644
index 00000000..058999e9
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsLocationObjectsChanged.cs
@@ -0,0 +1,28 @@
+using System;
+using Microsoft.Xna.Framework;
+using StardewValley;
+using Object = StardewValley.Object;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="LocationEvents.LocationObjectsChanged"/> event.</summary>
+ public class EventArgsLocationObjectsChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The current list of objects in the current location.</summary>
+ public SerializableDictionary<Vector2, Object> NewObjects { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="newObjects">The current list of objects in the current location.</param>
+ public EventArgsLocationObjectsChanged(SerializableDictionary<Vector2, Object> newObjects)
+ {
+ this.NewObjects = newObjects;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsMineLevelChanged.cs b/src/SMAPI/Events/EventArgsMineLevelChanged.cs
new file mode 100644
index 00000000..c82fed35
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsMineLevelChanged.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="MineEvents.MineLevelChanged"/> event.</summary>
+ public class EventArgsMineLevelChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous mine level.</summary>
+ public int PreviousMineLevel { get; }
+
+ /// <summary>The current mine level.</summary>
+ public int CurrentMineLevel { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="previousMineLevel">The previous mine level.</param>
+ /// <param name="currentMineLevel">The current mine level.</param>
+ public EventArgsMineLevelChanged(int previousMineLevel, int currentMineLevel)
+ {
+ this.PreviousMineLevel = previousMineLevel;
+ this.CurrentMineLevel = currentMineLevel;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsMouseStateChanged.cs b/src/SMAPI/Events/EventArgsMouseStateChanged.cs
new file mode 100644
index 00000000..57298164
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsMouseStateChanged.cs
@@ -0,0 +1,42 @@
+using System;
+using Microsoft.Xna.Framework;
+using Microsoft.Xna.Framework.Input;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a <see cref="ControlEvents.MouseChanged"/> event.</summary>
+ public class EventArgsMouseStateChanged : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous mouse state.</summary>
+ public MouseState PriorState { get; }
+
+ /// <summary>The current mouse state.</summary>
+ public MouseState NewState { get; }
+
+ /// <summary>The previous mouse position on the screen adjusted for the zoom level.</summary>
+ public Point PriorPosition { get; }
+
+ /// <summary>The current mouse position on the screen adjusted for the zoom level.</summary>
+ public Point NewPosition { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorState">The previous mouse state.</param>
+ /// <param name="newState">The current mouse state.</param>
+ /// <param name="priorPosition">The previous mouse position on the screen adjusted for the zoom level.</param>
+ /// <param name="newPosition">The current mouse position on the screen adjusted for the zoom level.</param>
+ public EventArgsMouseStateChanged(MouseState priorState, MouseState newState, Point priorPosition, Point newPosition)
+ {
+ this.PriorState = priorState;
+ this.NewState = newState;
+ this.PriorPosition = priorPosition;
+ this.NewPosition = newPosition;
+ }
+ }
+}
diff --git a/src/SMAPI/Events/EventArgsValueChanged.cs b/src/SMAPI/Events/EventArgsValueChanged.cs
new file mode 100644
index 00000000..1d25af49
--- /dev/null
+++ b/src/SMAPI/Events/EventArgsValueChanged.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Event arguments for a field that changed value.</summary>
+ /// <typeparam name="T">The value type.</typeparam>
+ public class EventArgsValueChanged<T> : EventArgs
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The previous value.</summary>
+ public T PriorValue { get; }
+
+ /// <summary>The current value.</summary>
+ public T NewValue { get; }
+
+
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Construct an instance.</summary>
+ /// <param name="priorValue">The previous value.</param>
+ /// <param name="newValue">The current value.</param>
+ public EventArgsValueChanged(T priorValue, T newValue)
+ {
+ this.PriorValue = priorValue;
+ this.NewValue = newValue;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/SMAPI/Events/GameEvents.cs b/src/SMAPI/Events/GameEvents.cs
new file mode 100644
index 00000000..b477376e
--- /dev/null
+++ b/src/SMAPI/Events/GameEvents.cs
@@ -0,0 +1,96 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the game changes state.</summary>
+ public static class GameEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised during launch after configuring XNA or MonoGame. The game window hasn't been opened by this point. Called after <see cref="Microsoft.Xna.Framework.Game.Initialize"/>.</summary>
+ internal static event EventHandler InitializeInternal;
+
+ /// <summary>Raised when the game updates its state (≈60 times per second).</summary>
+ public static event EventHandler UpdateTick;
+
+ /// <summary>Raised every other tick (≈30 times per second).</summary>
+ public static event EventHandler SecondUpdateTick;
+
+ /// <summary>Raised every fourth tick (≈15 times per second).</summary>
+ public static event EventHandler FourthUpdateTick;
+
+ /// <summary>Raised every eighth tick (≈8 times per second).</summary>
+ public static event EventHandler EighthUpdateTick;
+
+ /// <summary>Raised every 15th tick (≈4 times per second).</summary>
+ public static event EventHandler QuarterSecondTick;
+
+ /// <summary>Raised every 30th tick (≈twice per second).</summary>
+ public static event EventHandler HalfSecondTick;
+
+ /// <summary>Raised every 60th tick (≈once per second).</summary>
+ public static event EventHandler OneSecondTick;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise an <see cref="InitializeInternal"/> event.</summary>
+ /// <param name="monitor">Encapsulates logging and monitoring.</param>
+ internal static void InvokeInitialize(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.InitializeInternal)}", GameEvents.InitializeInternal?.GetInvocationList());
+ }
+
+ /// <summary>Raise an <see cref="UpdateTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates logging and monitoring.</param>
+ internal static void InvokeUpdateTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.UpdateTick)}", GameEvents.UpdateTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="SecondUpdateTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeSecondUpdateTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.SecondUpdateTick)}", GameEvents.SecondUpdateTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="FourthUpdateTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeFourthUpdateTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.FourthUpdateTick)}", GameEvents.FourthUpdateTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="EighthUpdateTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeEighthUpdateTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.EighthUpdateTick)}", GameEvents.EighthUpdateTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="QuarterSecondTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeQuarterSecondTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.QuarterSecondTick)}", GameEvents.QuarterSecondTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="HalfSecondTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeHalfSecondTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.HalfSecondTick)}", GameEvents.HalfSecondTick?.GetInvocationList());
+ }
+
+ /// <summary>Raise a <see cref="OneSecondTick"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOneSecondTick(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GameEvents)}.{nameof(GameEvents.OneSecondTick)}", GameEvents.OneSecondTick?.GetInvocationList());
+ }
+ }
+}
diff --git a/src/SMAPI/Events/GraphicsEvents.cs b/src/SMAPI/Events/GraphicsEvents.cs
new file mode 100644
index 00000000..fff51bed
--- /dev/null
+++ b/src/SMAPI/Events/GraphicsEvents.cs
@@ -0,0 +1,116 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised during the game's draw loop, when the game is rendering content to the window.</summary>
+ public static class GraphicsEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /****
+ ** Generic events
+ ****/
+ /// <summary>Raised after the game window is resized.</summary>
+ public static event EventHandler Resize;
+
+ /****
+ ** Main render events
+ ****/
+ /// <summary>Raised before drawing the world to the screen.</summary>
+ public static event EventHandler OnPreRenderEvent;
+
+ /// <summary>Raised after drawing the world to the screen.</summary>
+ public static event EventHandler OnPostRenderEvent;
+
+ /****
+ ** HUD events
+ ****/
+ /// <summary>Raised before drawing the HUD (item toolbar, clock, etc) to the screen. The HUD is available at this point, but not necessarily visible. (For example, the event is raised even if a menu is open.)</summary>
+ public static event EventHandler OnPreRenderHudEvent;
+
+ /// <summary>Raised after drawing the HUD (item toolbar, clock, etc) to the screen. The HUD is available at this point, but not necessarily visible. (For example, the event is raised even if a menu is open.)</summary>
+ public static event EventHandler OnPostRenderHudEvent;
+
+ /****
+ ** GUI events
+ ****/
+ /// <summary>Raised before drawing a menu to the screen during a draw loop. This includes the game's internal menus like the title screen.</summary>
+ public static event EventHandler OnPreRenderGuiEvent;
+
+ /// <summary>Raised after drawing a menu to the screen during a draw loop. This includes the game's internal menus like the title screen.</summary>
+ public static event EventHandler OnPostRenderGuiEvent;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /****
+ ** Generic events
+ ****/
+ /// <summary>Raise a <see cref="Resize"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeResize(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.Resize)}", GraphicsEvents.Resize?.GetInvocationList());
+ }
+
+ /****
+ ** Main render events
+ ****/
+ /// <summary>Raise an <see cref="OnPreRenderEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPreRenderEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPreRenderEvent)}", GraphicsEvents.OnPreRenderEvent?.GetInvocationList());
+ }
+
+ /// <summary>Raise an <see cref="OnPostRenderEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPostRenderEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPostRenderEvent)}", GraphicsEvents.OnPostRenderEvent?.GetInvocationList());
+ }
+
+ /// <summary>Get whether there are any post-render event listeners.</summary>
+ internal static bool HasPostRenderListeners()
+ {
+ return GraphicsEvents.OnPostRenderEvent != null;
+ }
+
+ /****
+ ** GUI events
+ ****/
+ /// <summary>Raise an <see cref="OnPreRenderGuiEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPreRenderGuiEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPreRenderGuiEvent)}", GraphicsEvents.OnPreRenderGuiEvent?.GetInvocationList());
+ }
+
+ /// <summary>Raise an <see cref="OnPostRenderGuiEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPostRenderGuiEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPostRenderGuiEvent)}", GraphicsEvents.OnPostRenderGuiEvent?.GetInvocationList());
+ }
+
+ /****
+ ** HUD events
+ ****/
+ /// <summary>Raise an <see cref="OnPreRenderHudEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPreRenderHudEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPreRenderHudEvent)}", GraphicsEvents.OnPreRenderHudEvent?.GetInvocationList());
+ }
+
+ /// <summary>Raise an <see cref="OnPostRenderHudEvent"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeOnPostRenderHudEvent(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(GraphicsEvents)}.{nameof(GraphicsEvents.OnPostRenderHudEvent)}", GraphicsEvents.OnPostRenderHudEvent?.GetInvocationList());
+ }
+ }
+}
diff --git a/src/SMAPI/Events/InputEvents.cs b/src/SMAPI/Events/InputEvents.cs
new file mode 100644
index 00000000..c31eb698
--- /dev/null
+++ b/src/SMAPI/Events/InputEvents.cs
@@ -0,0 +1,43 @@
+using System;
+using StardewModdingAPI.Framework;
+using StardewModdingAPI.Utilities;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the player uses a controller, keyboard, or mouse button.</summary>
+ public static class InputEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised when the player presses a button on the keyboard, controller, or mouse.</summary>
+ public static event EventHandler<EventArgsInput> ButtonPressed;
+
+ /// <summary>Raised when the player releases a keyboard key on the keyboard, controller, or mouse.</summary>
+ public static event EventHandler<EventArgsInput> ButtonReleased;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="ButtonPressed"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The button on the controller, keyboard, or mouse.</param>
+ /// <param name="cursor">The cursor position.</param>
+ /// <param name="isClick">Whether the input is considered a 'click' by the game for enabling action.</param>
+ internal static void InvokeButtonPressed(IMonitor monitor, SButton button, ICursorPosition cursor, bool isClick)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(InputEvents)}.{nameof(InputEvents.ButtonPressed)}", InputEvents.ButtonPressed?.GetInvocationList(), null, new EventArgsInput(button, cursor, isClick));
+ }
+
+ /// <summary>Raise a <see cref="ButtonReleased"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="button">The button on the controller, keyboard, or mouse.</param>
+ /// <param name="cursor">The cursor position.</param>
+ /// <param name="isClick">Whether the input is considered a 'click' by the game for enabling action.</param>
+ internal static void InvokeButtonReleased(IMonitor monitor, SButton button, ICursorPosition cursor, bool isClick)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(InputEvents)}.{nameof(InputEvents.ButtonReleased)}", InputEvents.ButtonReleased?.GetInvocationList(), null, new EventArgsInput(button, cursor, isClick));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/ItemStackChange.cs b/src/SMAPI/Events/ItemStackChange.cs
new file mode 100644
index 00000000..f9ae6df6
--- /dev/null
+++ b/src/SMAPI/Events/ItemStackChange.cs
@@ -0,0 +1,20 @@
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Represents an inventory slot that changed.</summary>
+ public class ItemStackChange
+ {
+ /*********
+ ** Accessors
+ *********/
+ /// <summary>The item in the slot.</summary>
+ public Item Item { get; set; }
+
+ /// <summary>The amount by which the item's stack size changed.</summary>
+ public int StackChange { get; set; }
+
+ /// <summary>How the inventory slot changed.</summary>
+ public ChangeType ChangeType { get; set; }
+ }
+} \ No newline at end of file
diff --git a/src/SMAPI/Events/LocationEvents.cs b/src/SMAPI/Events/LocationEvents.cs
new file mode 100644
index 00000000..b834bc1c
--- /dev/null
+++ b/src/SMAPI/Events/LocationEvents.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using Microsoft.Xna.Framework;
+using StardewModdingAPI.Framework;
+using StardewValley;
+using Object = StardewValley.Object;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the player transitions between game locations, a location is added or removed, or the objects in the current location change.</summary>
+ public static class LocationEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after the player warps to a new location.</summary>
+ public static event EventHandler<EventArgsCurrentLocationChanged> CurrentLocationChanged;
+
+ /// <summary>Raised after a game location is added or removed.</summary>
+ public static event EventHandler<EventArgsGameLocationsChanged> LocationsChanged;
+
+ /// <summary>Raised after the list of objects in the current location changes (e.g. an object is added or removed).</summary>
+ public static event EventHandler<EventArgsLocationObjectsChanged> LocationObjectsChanged;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="CurrentLocationChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorLocation">The player's previous location.</param>
+ /// <param name="newLocation">The player's current location.</param>
+ internal static void InvokeCurrentLocationChanged(IMonitor monitor, GameLocation priorLocation, GameLocation newLocation)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(LocationEvents)}.{nameof(LocationEvents.CurrentLocationChanged)}", LocationEvents.CurrentLocationChanged?.GetInvocationList(), null, new EventArgsCurrentLocationChanged(priorLocation, newLocation));
+ }
+
+ /// <summary>Raise a <see cref="LocationsChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="newLocations">The current list of game locations.</param>
+ internal static void InvokeLocationsChanged(IMonitor monitor, List<GameLocation> newLocations)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(LocationEvents)}.{nameof(LocationEvents.LocationsChanged)}", LocationEvents.LocationsChanged?.GetInvocationList(), null, new EventArgsGameLocationsChanged(newLocations));
+ }
+
+ /// <summary>Raise a <see cref="LocationObjectsChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="newObjects">The current list of objects in the current location.</param>
+ internal static void InvokeOnNewLocationObject(IMonitor monitor, SerializableDictionary<Vector2, Object> newObjects)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(LocationEvents)}.{nameof(LocationEvents.LocationObjectsChanged)}", LocationEvents.LocationObjectsChanged?.GetInvocationList(), null, new EventArgsLocationObjectsChanged(newObjects));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/MenuEvents.cs b/src/SMAPI/Events/MenuEvents.cs
new file mode 100644
index 00000000..bd8d897e
--- /dev/null
+++ b/src/SMAPI/Events/MenuEvents.cs
@@ -0,0 +1,40 @@
+using System;
+using StardewModdingAPI.Framework;
+using StardewValley.Menus;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when a game menu is opened or closed (including internal menus like the title screen).</summary>
+ public static class MenuEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after a game menu is opened or replaced with another menu. This event is not invoked when a menu is closed.</summary>
+ public static event EventHandler<EventArgsClickableMenuChanged> MenuChanged;
+
+ /// <summary>Raised after a game menu is closed.</summary>
+ public static event EventHandler<EventArgsClickableMenuClosed> MenuClosed;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="MenuChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorMenu">The previous menu.</param>
+ /// <param name="newMenu">The current menu.</param>
+ internal static void InvokeMenuChanged(IMonitor monitor, IClickableMenu priorMenu, IClickableMenu newMenu)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(MenuEvents)}.{nameof(MenuEvents.MenuChanged)}", MenuEvents.MenuChanged?.GetInvocationList(), null, new EventArgsClickableMenuChanged(priorMenu, newMenu));
+ }
+
+ /// <summary>Raise a <see cref="MenuClosed"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorMenu">The menu that was closed.</param>
+ internal static void InvokeMenuClosed(IMonitor monitor, IClickableMenu priorMenu)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(MenuEvents)}.{nameof(MenuEvents.MenuClosed)}", MenuEvents.MenuClosed?.GetInvocationList(), null, new EventArgsClickableMenuClosed(priorMenu));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/MineEvents.cs b/src/SMAPI/Events/MineEvents.cs
new file mode 100644
index 00000000..9cf7edac
--- /dev/null
+++ b/src/SMAPI/Events/MineEvents.cs
@@ -0,0 +1,28 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when something happens in the mines.</summary>
+ public static class MineEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after the player warps to a new level of the mine.</summary>
+ public static event EventHandler<EventArgsMineLevelChanged> MineLevelChanged;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="MineLevelChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="previousMineLevel">The previous mine level.</param>
+ /// <param name="currentMineLevel">The current mine level.</param>
+ internal static void InvokeMineLevelChanged(IMonitor monitor, int previousMineLevel, int currentMineLevel)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(MineEvents)}.{nameof(MineEvents.MineLevelChanged)}", MineEvents.MineLevelChanged?.GetInvocationList(), null, new EventArgsMineLevelChanged(previousMineLevel, currentMineLevel));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/PlayerEvents.cs b/src/SMAPI/Events/PlayerEvents.cs
new file mode 100644
index 00000000..5a9a9d5f
--- /dev/null
+++ b/src/SMAPI/Events/PlayerEvents.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using StardewModdingAPI.Framework;
+using StardewValley;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the player data changes.</summary>
+ public static class PlayerEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after the player's inventory changes in any way (added or removed item, sorted, etc).</summary>
+ public static event EventHandler<EventArgsInventoryChanged> InventoryChanged;
+
+ /// <summary> Raised after the player levels up a skill. This happens as soon as they level up, not when the game notifies the player after their character goes to bed.</summary>
+ public static event EventHandler<EventArgsLevelUp> LeveledUp;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise an <see cref="InventoryChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="inventory">The player's inventory.</param>
+ /// <param name="changedItems">The inventory changes.</param>
+ internal static void InvokeInventoryChanged(IMonitor monitor, List<Item> inventory, IEnumerable<ItemStackChange> changedItems)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(PlayerEvents)}.{nameof(PlayerEvents.InventoryChanged)}", PlayerEvents.InventoryChanged?.GetInvocationList(), null, new EventArgsInventoryChanged(inventory, changedItems.ToList()));
+ }
+
+ /// <summary>Rase a <see cref="LeveledUp"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="type">The player skill that leveled up.</param>
+ /// <param name="newLevel">The new skill level.</param>
+ internal static void InvokeLeveledUp(IMonitor monitor, EventArgsLevelUp.LevelType type, int newLevel)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(PlayerEvents)}.{nameof(PlayerEvents.LeveledUp)}", PlayerEvents.LeveledUp?.GetInvocationList(), null, new EventArgsLevelUp(type, newLevel));
+ }
+ }
+}
diff --git a/src/SMAPI/Events/SaveEvents.cs b/src/SMAPI/Events/SaveEvents.cs
new file mode 100644
index 00000000..50e6d729
--- /dev/null
+++ b/src/SMAPI/Events/SaveEvents.cs
@@ -0,0 +1,56 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised before and after the player saves/loads the game.</summary>
+ public static class SaveEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised before the game begins writes data to the save file.</summary>
+ public static event EventHandler BeforeSave;
+
+ /// <summary>Raised after the game finishes writing data to the save file.</summary>
+ public static event EventHandler AfterSave;
+
+ /// <summary>Raised after the player loads a save slot.</summary>
+ public static event EventHandler AfterLoad;
+
+ /// <summary>Raised after the game returns to the title screen.</summary>
+ public static event EventHandler AfterReturnToTitle;
+
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise a <see cref="BeforeSave"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeBeforeSave(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(SaveEvents)}.{nameof(SaveEvents.BeforeSave)}", SaveEvents.BeforeSave?.GetInvocationList(), null, EventArgs.Empty);
+ }
+
+ /// <summary>Raise a <see cref="AfterSave"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeAfterSave(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(SaveEvents)}.{nameof(SaveEvents.AfterSave)}", SaveEvents.AfterSave?.GetInvocationList(), null, EventArgs.Empty);
+ }
+
+ /// <summary>Raise a <see cref="AfterLoad"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeAfterLoad(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(SaveEvents)}.{nameof(SaveEvents.AfterLoad)}", SaveEvents.AfterLoad?.GetInvocationList(), null, EventArgs.Empty);
+ }
+
+ /// <summary>Raise a <see cref="AfterReturnToTitle"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeAfterReturnToTitle(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(SaveEvents)}.{nameof(SaveEvents.AfterReturnToTitle)}", SaveEvents.AfterReturnToTitle?.GetInvocationList(), null, EventArgs.Empty);
+ }
+ }
+}
diff --git a/src/SMAPI/Events/TimeEvents.cs b/src/SMAPI/Events/TimeEvents.cs
new file mode 100644
index 00000000..9aea5e04
--- /dev/null
+++ b/src/SMAPI/Events/TimeEvents.cs
@@ -0,0 +1,37 @@
+using System;
+using StardewModdingAPI.Framework;
+
+namespace StardewModdingAPI.Events
+{
+ /// <summary>Events raised when the in-game date or time changes.</summary>
+ public static class TimeEvents
+ {
+ /*********
+ ** Events
+ *********/
+ /// <summary>Raised after the game begins a new day, including when loading a save.</summary>
+ public static event EventHandler AfterDayStarted;
+
+ /// <summary>Raised after the in-game clock changes.</summary>
+ public static event EventHandler<EventArgsIntChanged> TimeOfDayChanged;
+
+ /*********
+ ** Internal methods
+ *********/
+ /// <summary>Raise an <see cref="AfterDayStarted"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ internal static void InvokeAfterDayStarted(IMonitor monitor)
+ {
+ monitor.SafelyRaisePlainEvent($"{nameof(TimeEvents)}.{nameof(TimeEvents.AfterDayStarted)}", TimeEvents.AfterDayStarted?.GetInvocationList(), null, EventArgs.Empty);
+ }
+
+ /// <summary>Raise a <see cref="TimeOfDayChanged"/> event.</summary>
+ /// <param name="monitor">Encapsulates monitoring and logging.</param>
+ /// <param name="priorTime">The previous time in military time format (e.g. 6:00pm is 1800).</param>
+ /// <param name="newTime">The current time in military time format (e.g. 6:10pm is 1810).</param>
+ internal static void InvokeTimeOfDayChanged(IMonitor monitor, int priorTime, int newTime)
+ {
+ monitor.SafelyRaiseGenericEvent($"{nameof(TimeEvents)}.{nameof(TimeEvents.TimeOfDayChanged)}", TimeEvents.TimeOfDayChanged?.GetInvocationList(), null, new EventArgsIntChanged(priorTime, newTime));
+ }
+ }
+}