Difference between revisions of "Modding:Modder Guide/APIs/Events"
Pathoschild (talk | contribs) (→Game loop: + note that Context.IsWorldReady is guaranteed to be true in GameLoop.SaveLoaded) |
Pathoschild (talk | contribs) (→World: clarify how events are raised for things already present in a new location) |
||
Line 458: | Line 458: | ||
|name = BuildingListChanged | |name = BuildingListChanged | ||
|desc = Raised after buildings are added/removed in any location. | |desc = Raised after buildings are added/removed in any location. | ||
+ | |||
+ | This event isn't raised for buildings already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added.OfType<BuildableGameLocation>()</tt> → <tt>buildings</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> | ||
Line 479: | Line 481: | ||
|name = DebrisListChanged | |name = DebrisListChanged | ||
|desc = Raised after debris is added/removed in any location (including dropped or spawned floating items). | |desc = Raised after debris is added/removed in any location (including dropped or spawned floating items). | ||
+ | |||
+ | This event isn't raised for debris already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added</tt> → <tt>debris</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> | ||
Line 501: | Line 505: | ||
|name = LargeTerrainFeatureListChanged | |name = LargeTerrainFeatureListChanged | ||
|desc = Raised after large terrain features (like bushes) are added/removed in any location. | |desc = Raised after large terrain features (like bushes) are added/removed in any location. | ||
+ | |||
+ | This event isn't raised for large terrain features already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added</tt> → <tt>largeTerrainFeatures</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> | ||
Line 522: | Line 528: | ||
|name = NpcListChanged | |name = NpcListChanged | ||
|desc = Raised after NPCs are added/removed in any location (including villagers, horses, Junimos, monsters, and pets). | |desc = Raised after NPCs are added/removed in any location (including villagers, horses, Junimos, monsters, and pets). | ||
+ | |||
+ | This event isn't raised for characters already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added</tt> → <tt>characters</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> | ||
Line 543: | Line 551: | ||
|name = ObjectListChanged | |name = ObjectListChanged | ||
|desc = Raised after objects are added/removed in any location (including machines, furniture, fences, etc). For floating items, see <tt>DebrisListChanged</tt>. | |desc = Raised after objects are added/removed in any location (including machines, furniture, fences, etc). For floating items, see <tt>DebrisListChanged</tt>. | ||
+ | |||
+ | This event isn't raised for objects already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added</tt> → <tt>objects</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> | ||
Line 564: | Line 574: | ||
|name = TerrainFeatureListChanged | |name = TerrainFeatureListChanged | ||
|desc = Raised after terrain features are added/removed in any location (including trees, hoed dirt, and flooring). For bushes, see <tt>LargeTerrainFeatureListChanged</tt>. | |desc = Raised after terrain features are added/removed in any location (including trees, hoed dirt, and flooring). For bushes, see <tt>LargeTerrainFeatureListChanged</tt>. | ||
+ | |||
+ | This event isn't raised for terrain features already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<tt>LocationListChanged</tt>]] and check <tt>e.Added</tt> → <tt>terrainFeatures</tt>. | ||
|arg name 1 = <tt>e.Location</tt> | |arg name 1 = <tt>e.Location</tt> |
Revision as of 01:42, 6 September 2019
- Get started
- Game fundamentals
- Test & troubleshoot
- Release
- API reference
- Basic SMAPI APIs:
- Advanced SMAPI APIs:
- Specific guides
SMAPI provides several C# events which let your mod respond when something happens (like when the player places an object) or run code periodically (like once per update tick).
Intro
A C# event is the way that SMAPI notifies mods when something happens. You can add any number of event handlers (methods to call) when an event is raised. Event handlers are usually added in your Entry method, though you can add and remove them anytime.
For example, let's say you want to print a message when each day starts. First you would choose the appropriate event from the list below (GameLoop.DayStarted), then add an event handler, and do something in your method code:
/// <summary>The main entry point for the mod.</summary>
public class ModEntry : Mod
{
/**********
** Public methods
*********/
/// <summary>The mod entry point, called after the mod is first loaded.</summary>
/// <param name="helper">Provides simplified APIs for writing mods.</param>
public override void Entry(IModHelper helper)
{
// event += method to call
helper.Events.GameLoop.DayStarted += this.OnDayStarted;
}
/// <summary>The method called after a new day starts.</summary>
/// <param name="sender">The event sender.</param>
/// <param name="e">The event arguments.</param>
private void OnDayStarted(object sender, DayStartedEventArgs e)
{
this.Monitor.Log("A new day dawns!");
}
}
Tip: you don't need to memorise the method arguments. In Visual Studio, type helper.Events.GameLoop.SaveLoaded +=
and press TAB to auto-create a method. (There doesn't seem to be an equivalent feature in MonoDevelop.)
Events
The available events are documented below.
Display
this.Helper.Events.Display has events linked to UI and drawing to the screen.
event | summary | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
#MenuChanged | Raised after a game menu is opened, closed, or replaced.
Event arguments:
| |||||||||
#Rendering | Raised before the game draws anything to the screen in a draw tick, as soon as the sprite batch is opened. The sprite batch may be closed and reopened multiple times after this event is called, but it's only raised once per draw tick. This event isn't useful for drawing to the screen, since the game will draw over it.
Limitations:
Event arguments:
| |||||||||
#Rendered | Raised after the game draws to the sprite patch in a draw tick, just before the final sprite batch is rendered to the screen. Since the game may open/close the sprite batch multiple times in a draw tick, the sprite batch may not contain everything being drawn and some things may already be rendered to the screen. Content drawn to the sprite batch at this point will be drawn over all vanilla content (including menus, HUD, and cursor).
Limitations:
Event arguments:
| |||||||||
#RenderingWorld | Raised before the game world is drawn to the screen. This event isn't useful for drawing to the screen, since the game will draw over it.
Event arguments:
| |||||||||
#RenderedWorld | Raised after the game world is drawn to the sprite patch, before it's rendered to the screen. Content drawn to the sprite batch at this point will be drawn over the world, but under any active menu, HUD elements, or cursor.
Event arguments:
| |||||||||
#RenderingActiveMenu | When a menu is open (Game1.activeClickableMenu != null), raised before that menu is drawn to the screen. This includes the game's internal menus like the title screen. Content drawn to the sprite batch at this point will appear under the menu.
Event arguments:
| |||||||||
#RenderedActiveMenu | When a menu is open (Game1.activeClickableMenu != null), raised after that menu is drawn to the sprite batch but before it's rendered to the screen. Content drawn to the sprite batch at this point will appear over the menu and menu cursor.
Event arguments:
| |||||||||
#RenderingHud | Raised before drawing the HUD (item toolbar, clock, etc) to the screen. The vanilla HUD may be hidden at this point (e.g. because a menu is open). Content drawn to the sprite batch at this point will appear under the HUD.
Event arguments:
| |||||||||
#RenderedHud | Raised after drawing the HUD (item toolbar, clock, etc) to the sprite batch, but before it's rendered to the screen. The vanilla HUD may be hidden at this point (e.g. because a menu is open). Content drawn to the sprite batch at this point will appear over the HUD.
Event arguments:
| |||||||||
#WindowResized | Raised after the game window is resized.
Event arguments:
|
Game loop
this.Helper.Events.GameLoop has events linked to the game's update loop. The update loop runs roughly ≈60 times/second to run game logic like state changes, action handling, etc. These are often useful, but you should consider semantic events like Input where applicable.
event | summary | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#GameLaunched | Raised after the game is launched, right before the first update tick. This happens once per game session (unrelated to loading saves). All mods are loaded and initialised at this point, so this is a good time to set up mod integrations. | ||||||||||||
#UpdateTicking UpdateTicked |
Raised before/after the game state is updated (≈60 times per second).
Event arguments:
| ||||||||||||
#OneSecondUpdateTicking OneSecondUpdateTicked |
Raised before/after the game state is updated, once per second.
Event arguments:
| ||||||||||||
#SaveCreating SaveCreated |
Raised before/after the game creates the save file (after the new-game intro). The save won't be written until all mods have finished handling this event. This is a somewhat specialised event, since the world isn't fully initialised at this point; in most cases you should use DayStarted, Saving, Saved instead. | ||||||||||||
#Saving Saved |
Raised before/after the game writes data to save file (except the initial save creation). The save won't be written until all mods have finished handling this event. | ||||||||||||
#SaveLoaded | Raised before/after the game reads data from a save file and initialises the world (including when day one starts on a new save). This event is not raised after saving; if you want to do something at the start of each day, see DayStarted instead. Context.IsWorldReady is guaranteed to be true at this point. | ||||||||||||
#DayStarted | Raised after a new in-game day starts. Everything has already been initialised at this point. (To run code before the game sets up the day, see DayEnding instead.) | ||||||||||||
#DayEnding | Raised before the game ends the current day. This happens before it starts setting up the next day and before Saving. | ||||||||||||
#TimeChanged | Raised after the in-game clock time changes, which happens in intervals of ten in-game minutes.
Event arguments:
| ||||||||||||
#ReturnedToTitle | Raised after the game returns to the title screen. |
Input
this.Helper.Events.Input has events raised when the player uses a controller, keyboard, or mouse in some way. They can be used with the input API to access more info or suppress input.
event | summary | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#ButtonPressed ButtonReleased |
Raised after the player pressed/released a keyboard, mouse, or controller button. This includes mouse clicks.
Event arguments:
| |||||||||||||||
#CursorMoved | Raised after the player moves the in-game cursor.
Event arguments:
| |||||||||||||||
#MouseWheelScrolled | Raised after the player scrolls the mouse wheel.
Event arguments:
|
Multiplayer
this.Helper.Events.Multiplayer has events raised for multiplayer messages and connections.
event | summary | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#PeerContextReceived | Raised after the mod context for a player is received. The event is raised for any player (whether host or farmhand), including when the connecting player doesn't have SMAPI installed. This is the earliest point where messages can be sent to the player via SMAPI.
This happens before the game approves the connection, so the player doesn't exist in the game yet. When connecting to the host, contextual fields like Game1.IsMasterGame or Context.IsMultiplayer may not be set yet; you can check e.Peer.IsHost to know whether the current player is a farmhand, since the host context will always be received first. Event arguments:
| |||||||||||||||
#ModMessageReceived | Raised after a mod message is received over the network.
Event arguments:
| |||||||||||||||
#PeerDisconnected | Raised after the connection to a player is severed.
Event arguments:
|
Player
this.Helper.Events.Player has events raised when the player data changes.
Currently these events are only raised for the current player. That will likely change in a future version, so make sure to check e.IsLocalPlayer if you only want to handle the current player.
event | summary | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#InventoryChanged | Raised after items are added or removed from the player inventory.
Event arguments:
| ||||||||||||||||||
#LevelChanged | Raised after a player's skill level changes. When the player levels up normally, this is raised immediately (not when the game notifies the player after they go to bed).
Event arguments:
| ||||||||||||||||||
#Warped | Raised after the current player moves to a new location.
Event arguments:
|
World
this.Helper.Events.World has events raised when the in-game world changes in some way.
event | summary | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#LocationListChanged | Raised after a game location is added or removed (including building interiors).
Event arguments:
| |||||||||||||||
#BuildingListChanged | Raised after buildings are added/removed in any location.
This event isn't raised for buildings already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added.OfType<BuildableGameLocation>() → buildings. Event arguments:
| |||||||||||||||
#DebrisListChanged | Raised after debris is added/removed in any location (including dropped or spawned floating items).
This event isn't raised for debris already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added → debris. Event arguments:
| |||||||||||||||
#LargeTerrainFeatureListChanged | Raised after large terrain features (like bushes) are added/removed in any location.
This event isn't raised for large terrain features already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added → largeTerrainFeatures. Event arguments:
| |||||||||||||||
#NpcListChanged | Raised after NPCs are added/removed in any location (including villagers, horses, Junimos, monsters, and pets).
This event isn't raised for characters already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added → characters. Event arguments:
| |||||||||||||||
#ObjectListChanged | Raised after objects are added/removed in any location (including machines, furniture, fences, etc). For floating items, see DebrisListChanged.
This event isn't raised for objects already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added → objects. Event arguments:
| |||||||||||||||
#TerrainFeatureListChanged | Raised after terrain features are added/removed in any location (including trees, hoed dirt, and flooring). For bushes, see LargeTerrainFeatureListChanged.
This event isn't raised for terrain features already present when a location is added. If you need to handle those too, use LocationListChanged and check e.Added → terrainFeatures. Event arguments:
|
Specialised
this.Helper.Events.Specialised has events for specialised edge cases. These shouldn't be used by most mods.
event | summary | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
#LoadStageChanged | Raised when the low-level stage in the game's loading process has changed, 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 the game loop events instead.
Event arguments:
| ||||||||||||
#UnvalidatedUpdateTicking UnvalidatedUpdateTicked |
Raised before/after the game updates its state (≈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. Using this event will trigger a warning in the SMAPI console.
Event arguments:
|