“模组:制作指南/APIs/Events”的版本间的差异

来自Stardew Valley Wiki
跳到导航 跳到搜索
 
(未显示7个用户的23个中间版本)
第1行: 第1行:
 
{{../../header}}
 
{{../../header}}
  
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).
+
{{翻译}}
 +
 
 +
SMAPI 提供了几个 C #事件,这些事件使模组在某些事情发生时(例如,玩家放置一个对象时)做出响应,或者定期运行代码(例如,每个更新周期一次)
  
 
==常见问题==
 
==常见问题==
===什么是事件 events ?===
+
===什么是事件(events) ?===
 
 事件使你可以在发生某些事情时运行代码。可以在引发“事件”(发生的情况)时添加任意数量的“事件处理程序”(调用方法)。 可以将事件和处理程序视为“when...then”语句:
 
 事件使你可以在发生某些事情时运行代码。可以在引发“事件”(发生的情况)时添加任意数量的“事件处理程序”(调用方法)。 可以将事件和处理程序视为“when...then”语句:
 
<pre>
 
<pre>
第11行: 第13行:
 
</pre>
 
</pre>
  
See [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/ ''Events'' in the C# programming guide] for more info.
+
有关详细信息,请参阅[https://learn.microsoft.com/zh-cn/dotnet/csharp/programming-guide/events/ C# 编程指南中的事件] 中的“事件”。
  
 
===如何使用它们?===
 
===如何使用它们?===
 通常将事件处理程序添加到 <tt>Entry</tt> 方法中,可以随时添加和删除它们。例如,在每天开始时打印一条消息。首先,从下面的列表中选择适当的事件 (<tt>[[#GameLoop.DayStarted|GameLoop.DayStarted]]</tt>), 然后添加一个事件处理程序,并在方法代码中执行以下操作:
+
 通常将事件处理程序添加到 <samp>Entry</samp> 方法中,可以随时添加和删除它们。例如,在每天开始时打印一条消息。首先,从下面的列表中选择适当的事件 (<samp>[[#GameLoop.DayStarted|GameLoop.DayStarted]]</samp>), 然后添加一个事件处理程序,并在方法代码中执行以下操作:
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
 
/// <summary>模组的主要入口点。</summary>
 
/// <summary>模组的主要入口点。</summary>
第48行: 第50行:
 
 每次游戏计时(游戏更新其状态并呈现到屏幕时)都会引发事件,每秒60次。 一个事件可能会引发多次(例如,如果玩家同时按下两个键),但是大多数事件不会每秒引发60次(例如,玩家不太可能每秒按下60个按钮)
 
 每次游戏计时(游戏更新其状态并呈现到屏幕时)都会引发事件,每秒60次。 一个事件可能会引发多次(例如,如果玩家同时按下两个键),但是大多数事件不会每秒引发60次(例如,玩家不太可能每秒按下60个按钮)
  
 事件处理程序是“同步”运行的:游戏暂停时模组的代码不会运行,因此没有更改冲突的风险。由于代码运行非常迅速,因此除非你的代码异常缓慢,否则玩家不会注意到任何延迟。就是说,当使用诸如 <tt>UpdateTicked</tt> 或者 <tt>Rendered</tt> 应该缓存繁重的操作(例如加载资源),而不是在每个刻度中重复执行这些操作,以免影响性能。
+
 事件处理程序是“同步”运行的:游戏暂停时模组的代码不会运行,因此没有更改冲突的风险。由于代码运行非常迅速,因此除非你的代码异常缓慢,否则玩家不会注意到任何延迟。就是说,当使用诸如 <samp>UpdateTicked</samp> 或者 <samp>Rendered</samp> 应该缓存繁重的操作(例如加载资源),而不是在每个刻度中重复执行这些操作,以免影响性能。
  
===What if a mod changes what the event was raised for?===
+
=== 如果模组更改了事件的发起?===
Events are raised based on a snapshot of the game state. That's usually ''but not necessarily'' the current game state.
+
事件根据游戏状态的快照引发,这通常是“但不一定”是当前游戏状态
  
For example, consider this case:
+
例如,考虑这种情况:
# The <tt>GameMenu</tt> opens.
+
# 菜单 <samp>GameMenu</samp> 打开了
# SMAPI raises the <tt>MenuChanged</tt> event, which mods A and B listen to.
+
# SMAPI 引发 <samp>MenuChanged</samp> 事件,并且模组 A B 正在监听
# Mod A receives the event and closes the menu.
+
# 模组 A 接收了事件并关闭了菜单
# Mod B receives the event.
+
# 模组 B 接收了事件
  
Each mod is still handling the <tt>MenuChanged</tt> event for the opened menu, even though the first mod closed it. SMAPI will raise a new <tt>MenuChanged</tt> event for the closed menu on the next tick.
+
每个模组仍在处理菜单打开的 <samp>MenuChanged</samp> 事件,即使第一个模组已将菜单关闭。SMAPI 将在下一个刻度时为关闭的菜单引发一个新的 <samp>MenuChanged</samp> 事件
  
This rarely affects mods, but it's something to keep in mind if you need the current state (e.g. check <tt>Game1.activeClickableMenu</tt> instead of <tt>e.NewMenu</tt>).
+
这很少会影响模组,但是如果你需要当前状态,则需要牢记 ( 例如考虑用 <samp>Game1.activeClickableMenu</samp> 代替 <samp>e.NewMenu</samp>)
  
==Events==
+
== 事件==
The available events are documented below.
+
可用的事件记录在下面
  
===Display===
+
=== 显示===
<tt>this.Helper.Events.Display</tt> has events linked to UI and drawing to the screen.
+
<samp>this.Helper.Events.Display</samp> 具有链接到 UI 并绘制到屏幕的事件
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
! event
+
! 事件
! summary
+
! 描述
 
{{/event
 
{{/event
 
  |group = Display
 
  |group = Display
 
  |name  = MenuChanged
 
  |name  = MenuChanged
  |desc  = Raised after a game menu is opened, closed, or replaced.
+
  |desc  = 在打开、关闭或替换游戏菜单后引发
  
  |arg name 2 = <tt>e.OldMenu</tt>
+
  |arg name 2 = <samp>e.OldMenu</samp>
  |arg type 2 = <tt>IClickableMenu</tt>
+
  |arg type 2 = <samp>IClickableMenu</samp>
  |arg desc 2 = The old menu instance (or <tt>null</tt> if none).
+
  |arg desc 2 = 旧的菜单实例 ( 如果没有,则为 <samp>null</samp>)
  
  |arg name 1 = <tt>e.NewMenu</tt>
+
  |arg name 1 = <samp>e.NewMenu</samp>
  |arg type 1 = <tt>IClickableMenu</tt>
+
  |arg type 1 = <samp>IClickableMenu</samp>
  |arg desc 1 = The new menu instance (or <tt>null</tt> if none).
+
  |arg desc 1 = 新的菜单实例 ( 如果没有,则为 <samp>null</samp> )
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = Display
 
  |group = Display
 
  |name  = Rendering
 
  |name  = Rendering
  |desc  = 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.
+
  |desc  = 打开 sprite batch 同时,在游戏将任何内容绘制到屏幕上之前,触发此事件。在此事件触发后,sprite batch 可能多次关闭并重新打开。 但只在每次draw tick 只会启动一次. 此事件对于在屏幕上绘制没有用, 因为游戏会在这之上覆盖绘制。
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
+
  |arg desc 1 = 开始绘制sprite batch ,添加任何你想绘制的东西到sprite batch 中。
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = Display
 
  |group = Display
 
  |name  = Rendered
 
  |name  = Rendered
  |desc  = 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).
+
  |desc  = 会在游戏的一个draw tick 中对sprite batch 进行绘制后,最后一个sprite batch在屏幕上渲染前启动。因为游戏可能会在一个draw tick中打开/ 关闭sprite batch 多次,sprite batch 可能没有包含正在绘制的所有内容,并且有些内容可能已经渲染在屏幕上了。在这个点上绘制到sprite batch 的内容会覆盖在所有普通内容上(包括菜单,HUD,和光标)。
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
+
  |arg desc 1 = 正在绘制sprite batch 。添加任何你想绘制的东西到sprite batch 中。
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = Display
 
  |group = Display
 
  |name  = RenderingWorld
 
  |name  = RenderingWorld
  |desc  = 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.
+
  |desc  = 在游戏事件绘制到屏幕之前启动。这个事件不对绘制有任何帮助,因为游戏绘制会覆盖它。
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第118行: 第120行:
 
  |desc  = 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.
 
  |desc  = 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.
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第125行: 第127行:
 
  |group = Display
 
  |group = Display
 
  |name  = RenderingActiveMenu
 
  |name  = RenderingActiveMenu
  |desc  = When a menu is open (<tt>Game1.activeClickableMenu != null</tt>), 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.
+
  |desc  = 当一个菜单被打开时 (<samp>Game1.activeClickableMenu != null</samp>), 在将该菜单绘制到屏幕上之前触发。这包括游戏的内部菜单,例如进入游戏时的主菜单。Content drawn to the sprite batch at this point will appear under the menu.
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第134行: 第136行:
 
  |group = Display
 
  |group = Display
 
  |name  = RenderedActiveMenu
 
  |name  = RenderedActiveMenu
  |desc  = When a menu is open (<tt>Game1.activeClickableMenu != null</tt>), 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.
+
  |desc  = When a menu is open (<samp>Game1.activeClickableMenu != null</samp>), 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.
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第143行: 第145行:
 
  |group = Display
 
  |group = Display
 
  |name  = RenderingHud
 
  |name  = RenderingHud
  |desc  = 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.
+
  |desc  = 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.
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第152行: 第154行:
 
  |group = Display
 
  |group = Display
 
  |name  = RenderedHud
 
  |name  = RenderedHud
  |desc  = 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.
+
  |desc  = 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.
  
  |arg name 1 = <tt>e.SpriteBatch</tt>
+
  |arg name 1 = <samp>e.SpriteBatch</samp>
  |arg type 1 = <tt>SpriteBatch</tt>
+
  |arg type 1 = <samp>SpriteBatch</samp>
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
  |arg desc 1 = The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
 
}}
 
}}
第163行: 第165行:
 
  |desc  = Raised after the game window is resized.
 
  |desc  = Raised after the game window is resized.
  
  |arg name 1 = <tt>e.OldSize</tt>
+
  |arg name 1 = <samp>e.OldSize</samp>
  |arg type 1 = <tt>Point</tt>
+
  |arg type 1 = <samp>Point</samp>
  |arg desc 1 = The previous window width (<tt>e.OldSize.X</tt>) and height (<tt>e.OldSize.Y</tt>).
+
  |arg desc 1 = The previous window width (<samp>e.OldSize.X</samp>) and height (<samp>e.OldSize.Y</samp>).
  
  |arg name 2 = <tt>e.NewSize</tt>
+
  |arg name 2 = <samp>e.NewSize</samp>
  |arg type 2 = <tt>Point</tt>
+
  |arg type 2 = <samp>Point</samp>
  |arg desc 2 = The new window width (<tt>e.NewSize.X</tt>) and height (<tt>e.NewSize.Y</tt>).
+
  |arg desc 2 = The new window width (<samp>e.NewSize.X</samp>) and height (<samp>e.NewSize.Y</samp>).
 
}}
 
}}
 
|}
 
|}
  
===Game loop===
+
=== 游戏循环===
<tt>this.Helper.Events.GameLoop</tt> 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 <tt>Input</tt> where applicable.
+
<samp>this.Helper.Events.GameLoop</samp> 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 <samp>Input</samp> where applicable.
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第188行: 第190行:
 
  |group = GameLoop
 
  |group = GameLoop
 
  |name  = UpdateTicking, UpdateTicked
 
  |name  = UpdateTicking, UpdateTicked
  |desc  = Raised before/after the game state is updated (≈60 times per second).
+
  |desc  = 在游戏状态更新前/ 后启动(大约每秒钟60次)。
  
  |arg name 1 = <tt>e.Ticks</tt>
+
  |arg name 1 = <samp>e.Ticks</samp>
  |arg type 1 = <tt>int</tt>
+
  |arg type 1 = <samp>int</samp>
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
  
  |arg name 2 = <tt>e.IsOneSecond</tt>
+
  |arg name 2 = <samp>e.IsOneSecond</samp>
  |arg type 2 = <tt>bool</tt>
+
  |arg type 2 = <samp>bool</samp>
  |arg desc 2 = Whether <tt>e.TicksElapsed</tt> is a multiple of 60, which happens approximately once per second.
+
  |arg desc 2 = Whether <samp>e.TicksElapsed</samp> is a multiple of 60, which happens approximately once per second.
  
  |arg name 3 = <tt>e.IsMultipleOf(int number)</tt>
+
  |arg name 3 = <samp>e.IsMultipleOf(int number)</samp>
  |arg type 3 = ''method'' returns <tt>bool</tt>
+
  |arg type 3 = ''method'' returns <samp>bool</samp>
  |arg desc 3 = Whether <tt>e.TicksElapsed</tt> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g. <code>e.IsMultipleOf(30)</code> for every half-second).
+
  |arg desc 3 = Whether <samp>e.TicksElapsed</samp> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (''e.g.,'' <code>e.IsMultipleOf(30)</code> for every half-second).
 
}}
 
}}
 
{{/event
 
{{/event
第207行: 第209行:
 
  |desc  = Raised before/after the game state is updated, once per second.
 
  |desc  = Raised before/after the game state is updated, once per second.
  
  |arg name 1 = <tt>e.Ticks</tt>
+
  |arg name 1 = <samp>e.Ticks</samp>
  |arg type 1 = <tt>int</tt>
+
  |arg type 1 = <samp>int</samp>
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
  
  |arg name 3 = <tt>e.IsMultipleOf(int number)</tt>
+
  |arg name 3 = <samp>e.IsMultipleOf(int number)</samp>
  |arg type 3 = ''method'' returns <tt>bool</tt>
+
  |arg type 3 = ''method'' returns <samp>bool</samp>
  |arg desc 3 = Whether <tt>e.TicksElapsed</tt> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g. <code>e.IsMultipleOf(120)</code> for every two seconds).
+
  |arg desc 3 = Whether <samp>e.TicksElapsed</samp> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (''e.g.,'' <code>e.IsMultipleOf(120)</code> for every two seconds).
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = GameLoop
 
  |group = GameLoop
 
  |name  = SaveCreating, SaveCreated
 
  |name  = SaveCreating, SaveCreated
  |desc  = 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 [[#GameLoop.DayStarted|<tt>DayStarted</tt>]], [[#GameLoop.Saving|<tt>Saving</tt>]], [[#GameLoop.Saved|<tt>Saved</tt>]] instead.
+
  |desc  = 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 [[#GameLoop.DayStarted|<samp>DayStarted</samp>]], [[#GameLoop.Saving|<samp>Saving</samp>]], [[#GameLoop.Saved|<samp>Saved</samp>]] instead.
 
}}
 
}}
 
{{/event
 
{{/event
第228行: 第230行:
 
  |group = GameLoop
 
  |group = GameLoop
 
  |name  = SaveLoaded
 
  |name  = SaveLoaded
  |desc  = Raised after loading a save (including the first day after creating a new save), or connecting to a multiplayer world. This happens right before <tt>DayStarted</tt>; at this point the save file is read and <tt>[[Modding:Modder Guide/APIs/Utilities#Context|Context.IsWorldReady]]</tt> is true.
+
  |desc  = Raised after loading a save (including the first day after creating a new save), or connecting to a multiplayer world. This happens right before <samp>DayStarted</samp>; at this point the save file is read and <samp>[[Modding:Modder Guide/APIs/Utilities#Context|Context.IsWorldReady]]</samp> is true.
  
This event isn't raised after saving; if you want to do something at the start of each day, see [[#GameLoop.DayStarted|<tt>DayStarted</tt>]] instead. 
+
This event isn't raised after saving; if you want to do something at the start of each day, see [[#GameLoop.DayStarted|<samp>DayStarted</samp>]] instead. 
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = GameLoop
 
  |group = GameLoop
 
  |name  = DayStarted
 
  |name  = DayStarted
  |desc  = Raised after a new in-game day starts, or after connecting to a multiplayer world. Everything has already been initialised at this point. (To run code before the game sets up the day, see [[#GameLoop.DayEnding|<tt>DayEnding</tt>]] instead.)
+
  |desc  = Raised after a new in-game day starts, or after connecting to a multiplayer world. Everything has already been initialised at this point. (To run code before the game sets up the day, see [[#GameLoop.DayEnding|<samp>DayEnding</samp>]] instead.)
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = GameLoop
 
  |group = GameLoop
 
  |name  = DayEnding
 
  |name  = DayEnding
  |desc  = Raised before the game ends the current day. This happens before it starts setting up the next day and before [[#GameLoop.Saving|<tt>Saving</tt>]].
+
  |desc  = Raised before the game ends the current day. This happens before it starts setting up the next day and before [[#GameLoop.Saving|<samp>Saving</samp>]].
 
}}
 
}}
 
{{/event
 
{{/event
第247行: 第249行:
 
  |desc  = Raised after the in-game clock time changes, which happens in intervals of ten in-game minutes.
 
  |desc  = Raised after the in-game clock time changes, which happens in intervals of ten in-game minutes.
  
  |arg name 1 = <tt>e.OldTime</tt>
+
  |arg name 1 = <samp>e.OldTime</samp>
  |arg type 1 = <tt>int</tt>
+
  |arg type 1 = <samp>int</samp>
 
  |arg desc 1 = The previous time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
 
  |arg desc 1 = The previous time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
  
  |arg name 2 = <tt>e.NewTime</tt>
+
  |arg name 2 = <samp>e.NewTime</samp>
  |arg type 2 = <tt>int</tt>
+
  |arg type 2 = <samp>int</samp>
 
  |arg desc 2 = The current time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
 
  |arg desc 2 = The current time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
 
}}
 
}}
第262行: 第264行:
 
|}
 
|}
  
===Input===
+
=== 输入===
<tt>this.Helper.Events.Input</tt> has events raised when the player uses a controller, keyboard, or mouse in some way. They can be used with the [[../Input|input API]] to access more info or suppress input.
+
<samp>this.Helper.Events.Input</samp> has events raised when the player uses a controller, keyboard, or mouse in some way. They can be used with the [[../Input|input API]] to access more info or suppress input.
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第274行: 第276行:
 
  |desc  = Raised after the player pressed/released any buttons on the keyboard, mouse, or controller. This includes mouse clicks. If the player pressed/released multiple keys at once, this is only raised once.
 
  |desc  = Raised after the player pressed/released any buttons on the keyboard, mouse, or controller. This includes mouse clicks. If the player pressed/released multiple keys at once, this is only raised once.
  
  |arg name 1 = <tt>e.Pressed</tt>
+
  |arg name 1 = <samp>e.Pressed</samp>
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#SButton|<tt>SButton[]</tt>]]
+
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#SButton|<samp>SButton[]</samp>]]
 
  |arg desc 1 = The buttons that were pressed since the previous tick.
 
  |arg desc 1 = The buttons that were pressed since the previous tick.
  
  |arg name 2 = <tt>e.Held</tt>
+
  |arg name 2 = <samp>e.Held</samp>
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#SButton|<tt>SButton[]</tt>]]
+
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#SButton|<samp>SButton[]</samp>]]
 
  |arg desc 2 = The buttons that were held since the previous tick.
 
  |arg desc 2 = The buttons that were held since the previous tick.
  
  |arg name 3 = <tt>e.Released</tt>
+
  |arg name 3 = <samp>e.Released</samp>
  |arg type 3 = [[Modding:Modder Guide/APIs/Input#SButton|<tt>SButton[]</tt>]]
+
  |arg type 3 = [[Modding:Modder Guide/APIs/Input#SButton|<samp>SButton[]</samp>]]
 
  |arg desc 3 = The buttons that were released since the previous tick.
 
  |arg desc 3 = The buttons that were released since the previous tick.
  
  |arg name 4 = <tt>e.Cursor</tt>
+
  |arg name 4 = <samp>e.Cursor</samp>
  |arg type 4 = [[Modding:Modder Guide/APIs/Input#Check cursor position|<tt>ICursorPosition</tt>]]
+
  |arg type 4 = [[Modding:Modder Guide/APIs/Input#Check cursor position|<samp>ICursorPosition</samp>]]
 
  |arg desc 4 = The cursor position and grab tile.
 
  |arg desc 4 = The cursor position and grab tile.
  
第297行: 第299行:
 
  |desc  = Raised after the player pressed/released a keyboard, mouse, or controller button. This includes mouse clicks. If the player pressed/released multiple keys at once, this is raised for each button pressed.
 
  |desc  = Raised after the player pressed/released a keyboard, mouse, or controller button. This includes mouse clicks. If the player pressed/released multiple keys at once, this is raised for each button pressed.
  
  |arg name 1 = <tt>e.Button</tt>
+
  |arg name 1 = <samp>e.Button</samp>
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#SButton|<tt>SButton</tt>]]
+
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#SButton|<samp>SButton</samp>]]
 
  |arg desc 1 = The button pressed or released.
 
  |arg desc 1 = The button pressed or released.
  
  |arg name 2 = <tt>e.Cursor</tt>
+
  |arg name 2 = <samp>e.Cursor</samp>
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#Check cursor position|<tt>ICursorPosition</tt>]]
+
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#Check cursor position|<samp>ICursorPosition</samp>]]
 
  |arg desc 2 = The cursor position and grab tile.
 
  |arg desc 2 = The cursor position and grab tile.
  
  |arg name 3 = <tt>e.IsDown</tt>
+
  |arg name 3 = <samp>e.IsDown</samp>
  |arg type 3 = ''method'' returns <tt>bool</tt>
+
  |arg type 3 = ''method'' returns <samp>bool</samp>
 
  |arg desc 3 = Indicates whether a given button is currently pressed.
 
  |arg desc 3 = Indicates whether a given button is currently pressed.
  
  |arg name 4 = <tt>e.IsSuppressed</tt>
+
  |arg name 4 = <samp>e.IsSuppressed</samp>
  |arg type 4 = ''method'' returns <tt>bool</tt>
+
  |arg type 4 = ''method'' returns <samp>bool</samp>
 
  |arg desc 4 = A method which indicates whether a given button was suppressed by a mod, so the game itself won't see it.
 
  |arg desc 4 = A method which indicates whether a given button was suppressed by a mod, so the game itself won't see it.
  
第320行: 第322行:
 
  |desc  = Raised after the player moves the in-game cursor.
 
  |desc  = Raised after the player moves the in-game cursor.
  
  |arg name 1 = <tt>e.OldPosition</tt>
+
  |arg name 1 = <samp>e.OldPosition</samp>
 
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg desc 1 = The previous cursor position and grab tile.
 
  |arg desc 1 = The previous cursor position and grab tile.
  
  |arg name 2 = <tt>e.NewPosition</tt>
+
  |arg name 2 = <samp>e.NewPosition</samp>
 
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg type 2 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg desc 2 = The current cursor position and grab tile.
 
  |arg desc 2 = The current cursor position and grab tile.
第333行: 第335行:
 
  |desc  = Raised after the player scrolls the mouse wheel.
 
  |desc  = Raised after the player scrolls the mouse wheel.
  
  |arg name 1 = <tt>e.Position</tt>
+
  |arg name 1 = <samp>e.Position</samp>
 
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg type 1 = [[Modding:Modder Guide/APIs/Input#Check cursor position|ICursorPosition]]
 
  |arg desc 1 = The current cursor position and grab tile.
 
  |arg desc 1 = The current cursor position and grab tile.
  
  |arg name 2 = <tt>e.Delta</tt>
+
  |arg name 2 = <samp>e.Delta</samp>
  |arg type 2 = <tt>int</tt>
+
  |arg type 2 = <samp>int</samp>
 
  |arg desc 2 = The amount by which the mouse wheel was scrolled since the last update.
 
  |arg desc 2 = The amount by which the mouse wheel was scrolled since the last update.
  
  |arg name 3 = <tt>e.OldValue</tt><br /><tt>e.NewValue</tt>
+
  |arg name 3 = <samp>e.OldValue</samp><br /><samp>e.NewValue</samp>
  |arg type 3 = <tt>int</tt>
+
  |arg type 3 = <samp>int</samp>
  |arg desc 3 = The previous and current scroll value, cumulative since the game started. Mods should generally use <tt>e.Delta</tt> instead.
+
  |arg desc 3 = The previous and current scroll value, cumulative since the game started. Mods should generally use <samp>e.Delta</samp> instead.
 
}}
 
}}
 
|}
 
|}
  
===Multiplayer===
+
=== 多人===
<tt>this.Helper.Events.Multiplayer</tt> has events raised for multiplayer messages and connections.
+
<samp>this.Helper.Events.Multiplayer</samp> has events raised for multiplayer messages and connections.
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第359行: 第361行:
 
  |desc  = 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.
 
  |desc  = 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 immediately before the game approves the connection, so the player doesn't exist in the game yet. When connecting to the host, contextual fields like <tt>Game1.IsMasterGame</tt> or <tt>Context.IsMultiplayer</tt> may not be set yet; you can check <tt>e.Peer.IsHost</tt> to know whether the current player is a farmhand, since the host context will always be received first. Assuming another mod doesn't block the connection, the connection will be approved on the next tick.
+
This happens immediately before the game approves the connection, so the player doesn't exist in the game yet. When connecting to the host, contextual fields like <samp>Game1.IsMasterGame</samp> or <samp>Context.IsMultiplayer</samp> may not be set yet; you can check <samp>e.Peer.IsHost</samp> to know whether the current player is a farmhand, since the host context will always be received first. Assuming another mod doesn't block the connection, the connection will be approved on the next tick.
  
  |arg name 1 = <tt>e.Peer</tt>
+
  |arg name 1 = <samp>e.Peer</samp>
  |arg type 1 = <tt>IMultiplayerPeer</tt>
+
  |arg type 1 = <samp>IMultiplayerPeer</samp>
 
  |arg desc 1 = The peer whose context was received (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
  |arg desc 1 = The peer whose context was received (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
}}
 
}}
第368行: 第370行:
 
  |group = Multiplayer
 
  |group = Multiplayer
 
  |name  = PeerConnected
 
  |name  = PeerConnected
  |desc  = Raised after a connection from another player is approved by the game. The event is raised for any player (whether host or farmhand), including when the connecting player doesn't have SMAPI installed. This happens after <tt>PeerContextReceived</tt>.
+
  |desc  = Raised after a connection from another player is approved by the game. The event is raised for any player (whether host or farmhand), including when the connecting player doesn't have SMAPI installed. This happens after <samp>PeerContextReceived</samp>.
  
The player is connected to the game at this point, so methods like <tt>Game1.server.kick</tt> will work.
+
The player is connected to the game at this point, so methods like <samp>Game1.server.kick</samp> will work.
  
  |arg name 1 = <tt>e.Peer</tt>
+
  |arg name 1 = <samp>e.Peer</samp>
  |arg type 1 = <tt>IMultiplayerPeer</tt>
+
  |arg type 1 = <samp>IMultiplayerPeer</samp>
 
  |arg desc 1 = The peer who connected (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
  |arg desc 1 = The peer who connected (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
}}
 
}}
第381行: 第383行:
 
  |desc  = Raised after [[Modding:Modder Guide/APIs/Multiplayer#Send messages|a mod message]] is received over the network.
 
  |desc  = Raised after [[Modding:Modder Guide/APIs/Multiplayer#Send messages|a mod message]] is received over the network.
  
  |arg name 1 = <tt>e.FromPlayerID</tt>
+
  |arg name 1 = <samp>e.FromPlayerID</samp>
  |arg type 1 = <tt>long</tt>
+
  |arg type 1 = <samp>long</samp>
 
  |arg desc 1 = The unique ID of the player from whose computer the message was sent.
 
  |arg desc 1 = The unique ID of the player from whose computer the message was sent.
  
  |arg name 2 = <tt>e.FromModID</tt>
+
  |arg name 2 = <samp>e.FromModID</samp>
  |arg type 2 = <tt>string</tt>
+
  |arg type 2 = <samp>string</samp>
 
  |arg desc 2 = The unique ID of the mod which sent the message.
 
  |arg desc 2 = The unique ID of the mod which sent the message.
  
  |arg name 3 = <tt>e.Type</tt>
+
  |arg name 3 = <samp>e.Type</samp>
  |arg type 3 = <tt>string</tt>
+
  |arg type 3 = <samp>string</samp>
  |arg desc 3 = A message type which you can use to decide whether it's the one you want to handle. This isn't necessarily globally unique, so you should also check the <tt>FromModID</tt> field.
+
  |arg desc 3 = A message type which you can use to decide whether it's the one you want to handle. This isn't necessarily globally unique, so you should also check the <samp>FromModID</samp> field.
  
  |arg name 4 = <tt>e.ReadAs&lt;TModel&gt;()</tt>
+
  |arg name 4 = <samp>e.ReadAs&lt;TModel&gt;()</samp>
  |arg type 4 = ''method'' returns <tt>TModel</tt>
+
  |arg type 4 = ''method'' returns <samp>TModel</samp>
 
  |arg desc 4 = Read the underlying message data into the given model type (like <code>e.ReadAs&lt;MyMessageClass&gt;()</code> or <code>e.ReadAs&lt;string&gt;()</code>). This will return a new instance each time.
 
  |arg desc 4 = Read the underlying message data into the given model type (like <code>e.ReadAs&lt;MyMessageClass&gt;()</code> or <code>e.ReadAs&lt;string&gt;()</code>). This will return a new instance each time.
 
}}
 
}}
第402行: 第404行:
 
  |desc  = Raised after the connection to a player is severed.
 
  |desc  = Raised after the connection to a player is severed.
  
  |arg name 1 = <tt>e.Peer</tt>
+
  |arg name 1 = <samp>e.Peer</samp>
  |arg type 1 = <tt>IMultiplayerPeer</tt>
+
  |arg type 1 = <samp>IMultiplayerPeer</samp>
 
  |arg desc 1 = The peer whose connection was severed (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
  |arg desc 1 = The peer whose connection was severed (see [[Modding:Modder Guide/APIs/Multiplayer#Get connected player info|Multiplayer#Get connected player info]]).
 
}}
 
}}
 
|}
 
|}
  
===Player===
+
=== 玩家===
<tt>this.Helper.Events.Player</tt> has events raised when the player data changes.
+
<samp>this.Helper.Events.Player</samp> 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 <tt>e.IsLocalPlayer</tt> if you only want to handle the current player.'''
+
'''Currently these events are only raised for the current player. That will likely change in a future version, so make sure to check <samp>e.IsLocalPlayer</samp> if you only want to handle the current player.'''
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第422行: 第424行:
 
  |desc  = Raised after items are added or removed from the player inventory.
 
  |desc  = Raised after items are added or removed from the player inventory.
  
  |arg name 1 = <tt>e.Player</tt>
+
  |arg name 1 = <samp>e.Player</samp>
  |arg type 1 = <tt>Farmer</tt>
+
  |arg type 1 = <samp>Farmer</samp>
 
  |arg desc 1 = The player whose inventory changed.
 
  |arg desc 1 = The player whose inventory changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;Item&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;Item&gt;</samp>
 
  |arg desc 2 = The added item stacks.
 
  |arg desc 2 = The added item stacks.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;Item&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;Item&gt;</samp>
 
  |arg desc 3 = The removed item stacks.
 
  |arg desc 3 = The removed item stacks.
  
  |arg name 4 = <tt>e.QuantityChanged</tt>
+
  |arg name 4 = <samp>e.QuantityChanged</samp>
  |arg type 4 = <tt>IEnumerable&lt;ItemStackSizeChange&gt;</tt>
+
  |arg type 4 = <samp>IEnumerable&lt;ItemStackSizeChange&gt;</samp>
  |arg desc 4 = The item stacks whose quantity changed. Each <tt>ItemStackSizeChange</tt> instance includes <tt>Item</tt> (the affected item stack), <tt>OldSize</tt> (the previous stack size), and <tt>NewSize</tt> (the new stack size).
+
  |arg desc 4 = The item stacks whose quantity changed. Each <samp>ItemStackSizeChange</samp> instance includes <samp>Item</samp> (the affected item stack), <samp>OldSize</samp> (the previous stack size), and <samp>NewSize</samp> (the new stack size).
  
  |arg name 5 = <tt>e.IsLocalPlayer</tt>
+
  |arg name 5 = <samp>e.IsLocalPlayer</samp>
  |arg type 5 = <tt>bool</tt>
+
  |arg type 5 = <samp>bool</samp>
 
  |arg desc 5 = Whether the affected player is the local one.
 
  |arg desc 5 = Whether the affected player is the local one.
 
}}
 
}}
第445行: 第447行:
 
  |group = Player
 
  |group = Player
 
  |name  = LevelChanged
 
  |name  = LevelChanged
  |desc  = 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).
+
  |desc  = 在一个玩家技能等级发生变化后触发. 当玩家技能等级提升的第一时间立马触发 ( 不是在玩家睡觉后游戏提示时触发).
  
  |arg name 1 = <tt>e.Player</tt>
+
  |arg name 1 = <samp>e.Player</samp>
  |arg type 1 = <tt>Farmer</tt>
+
  |arg type 1 = <samp>Farmer</samp>
  |arg desc 1 = The player whose skill level changed.
+
  |arg desc 1 = 技能等级发生变化的玩家.
  
  |arg name 2 = <tt>e.Skill</tt>
+
  |arg name 2 = <samp>e.Skill</samp>
  |arg type 2 = <tt>SkillType</tt>
+
  |arg type 2 = <samp>SkillType</samp>
  |arg desc 2 = The skill whose level changed. This is a constant like <code>SkillType.Combat</code>, which can be converted to the game's internal skill ID using <code>(int)e.Skill</code>.
+
  |arg desc 2 = 等级发生变化的技能. <code>SkillType.Combat</code> (战斗技能)这种能调用 <code>(int)e.Skill</code> 转化成内部id的技能.
  
  |arg name 3 = <tt>e.OldLevel</tt>
+
  |arg name 3 = <samp>e.OldLevel</samp>
  |arg type 3 = <tt>int</tt>
+
  |arg type 3 = <samp>int</samp>
  |arg desc 3 = The player's previous level for that skill.
+
  |arg desc 3 = 变化之前的技能等级.
  
  |arg name 4 = <tt>e.NewLevel</tt>
+
  |arg name 4 = <samp>e.NewLevel</samp>
  |arg type 4 = <tt>int</tt>
+
  |arg type 4 = <samp>int</samp>
  |arg desc 4 = The player's new level for that skill.
+
  |arg desc 4 = 变化之后的等级.
  
  |arg name 5 = <tt>e.IsLocalPlayer</tt>
+
  |arg name 5 = <samp>e.IsLocalPlayer</samp>
  |arg type 5 = <tt>bool</tt>
+
  |arg type 5 = <samp>bool</samp>
 
  |arg desc 5 = Whether the affected player is the local one.
 
  |arg desc 5 = Whether the affected player is the local one.
 
}}
 
}}
第470行: 第472行:
 
  |group = Player
 
  |group = Player
 
  |name  = Warped
 
  |name  = Warped
  |desc  = Raised after the current player moves to a new location.
+
  |desc  = 当玩家移动到新地点的时候触发(农场到车站,玩家所在矿井层数发生变化也算).
  
  |arg name 1 = <tt>e.Player</tt>
+
  |arg name 1 = <samp>e.Player</samp>
  |arg type 1 = <tt>Farmer</tt>
+
  |arg type 1 = <samp>Farmer</samp>
  |arg desc 1 = The player who warped to a new location.
+
  |arg desc 1 = 地点发生变化的玩家.
  
  |arg name 2 = <tt>e.OldLocation</tt>
+
  |arg name 2 = <samp>e.OldLocation</samp>
  |arg type 2 = <tt>GameLocation</tt>
+
  |arg type 2 = <samp>GameLocation</samp>
  |arg desc 2 = The player's previous location.
+
  |arg desc 2 = 玩家移动之前所在的地点.
  
  |arg name 3 = <tt>e.NewLocation</tt>
+
  |arg name 3 = <samp>e.NewLocation</samp>
  |arg type 3 = <tt>GameLocation</tt>
+
  |arg type 3 = <samp>GameLocation</samp>
  |arg desc 3 = The player's new location.
+
  |arg desc 3 = 玩家移动之后到达的地点.
  
  |arg name 4 = <tt>e.IsLocalPlayer</tt>
+
  |arg name 4 = <samp>e.IsLocalPlayer</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
 
  |arg desc 4 = Whether the affected player is the local one.
 
  |arg desc 4 = Whether the affected player is the local one.
 
}}
 
}}
 
|}
 
|}
  
===World===
+
=== 世界===
<tt>this.Helper.Events.World</tt> has events raised when the in-game world changes in some way.
+
<samp>this.Helper.Events.World</samp> has events raised when the in-game world changes in some way.
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第502行: 第504行:
 
  |desc  = Raised after a game location is added or removed (including building interiors).
 
  |desc  = Raised after a game location is added or removed (including building interiors).
  
  |arg name 1 = <tt>e.Added</tt>
+
  |arg name 1 = <samp>e.Added</samp>
  |arg type 1 = <tt>IEnumerable&lt;GameLocation&gt;</tt>
+
  |arg type 1 = <samp>IEnumerable&lt;GameLocation&gt;</samp>
 
  |arg desc 1 = A list of locations added since the last update tick.
 
  |arg desc 1 = A list of locations added since the last update tick.
  
  |arg name 2 = <tt>e.Removed</tt>
+
  |arg name 2 = <samp>e.Removed</samp>
  |arg type 2 = <tt>IEnumerable&lt;GameLocation&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;GameLocation&gt;</samp>
 
  |arg desc 2 = A list of locations removed since the last update tick.
 
  |arg desc 2 = A list of locations removed since the last update tick.
 
}}
 
}}
第515行: 第517行:
 
  |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>.
+
This event isn't raised for buildings already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<samp>LocationListChanged</samp>]] and check <samp>e.Added.OfType<BuildableGameLocation>()</samp> → <samp>buildings</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;Building&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;Building&gt;</samp>
 
  |arg desc 2 = A list of buildings added since the last update tick.
 
  |arg desc 2 = A list of buildings added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;Building&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;Building&gt;</samp>
 
  |arg desc 3 = A list of buildings removed since the last update tick.
 
  |arg desc 3 = A list of buildings removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
{{/event
 
{{/event
第538行: 第540行:
 
  |desc  = Raised after items are added or removed from a chest's inventory.
 
  |desc  = Raised after items are added or removed from a chest's inventory.
  
  |arg name 1 = <tt>e.Chest</tt>
+
  |arg name 1 = <samp>e.Chest</samp>
  |arg type 1 = <tt>Chest</tt>
+
  |arg type 1 = <samp>Chest</samp>
 
  |arg desc 1 = The chest whose inventory changed.
 
  |arg desc 1 = The chest whose inventory changed.
  
  |arg name 2 = <tt>e.Location</tt>
+
  |arg name 2 = <samp>e.Location</samp>
  |arg type 2 = <tt>Location</tt>
+
  |arg type 2 = <samp>Location</samp>
 
  |arg desc 2 = The location containing the chest.
 
  |arg desc 2 = The location containing the chest.
  
  |arg name 3 = <tt>e.Added</tt>
+
  |arg name 3 = <samp>e.Added</samp>
  |arg type 3 = <tt>IEnumerable&lt;Item&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;Item&gt;</samp>
 
  |arg desc 3 = The added item stacks.
 
  |arg desc 3 = The added item stacks.
  
  |arg name 4 = <tt>e.Removed</tt>
+
  |arg name 4 = <samp>e.Removed</samp>
  |arg type 4 = <tt>IEnumerable&lt;Item&gt;</tt>
+
  |arg type 4 = <samp>IEnumerable&lt;Item&gt;</samp>
 
  |arg desc 4 = The removed item stacks.
 
  |arg desc 4 = The removed item stacks.
  
  |arg name 5 = <tt>e.QuantityChanged</tt>
+
  |arg name 5 = <samp>e.QuantityChanged</samp>
  |arg type 5 = <tt>IEnumerable&lt;ItemStackSizeChange&gt;</tt>
+
  |arg type 5 = <samp>IEnumerable&lt;ItemStackSizeChange&gt;</samp>
  |arg desc 5 = The item stacks whose quantity changed. Each <tt>ItemStackSizeChange</tt> instance includes <tt>Item</tt> (the affected item stack), <tt>OldSize</tt> (the previous stack size), and <tt>NewSize</tt> (the new stack size).
+
  |arg desc 5 = The item stacks whose quantity changed. Each <samp>ItemStackSizeChange</samp> instance includes <samp>Item</samp> (the affected item stack), <samp>OldSize</samp> (the previous stack size), and <samp>NewSize</samp> (the new stack size).
 
}}
 
}}
 
{{/event
 
{{/event
第563行: 第565行:
 
  |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>.
+
This event isn't raised for debris already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<samp>LocationListChanged</samp>]] and check <samp>e.Added</samp> → <samp>debris</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;Debris&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;Debris&gt;</samp>
 
  |arg desc 2 = A list of debris added since the last update tick.
 
  |arg desc 2 = A list of debris added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;Debris&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;Debris&gt;</samp>
 
  |arg desc 3 = A list of debris removed since the last update tick.
 
  |arg desc 3 = A list of debris removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
{{/event
 
{{/event
第586行: 第588行:
 
  |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>.
+
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|<samp>LocationListChanged</samp>]] and check <samp>e.Added</samp> → <samp>largeTerrainFeatures</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;LargeTerrainFeature&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;LargeTerrainFeature&gt;</samp>
 
  |arg desc 2 = A list of large terrain features added since the last update tick.
 
  |arg desc 2 = A list of large terrain features added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;LargeTerrainFeature&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;LargeTerrainFeature&gt;</samp>
 
  |arg desc 3 = A list of large terrain features removed since the last update tick.
 
  |arg desc 3 = A list of large terrain features removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
{{/event
 
{{/event
第609行: 第611行:
 
  |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>.
+
This event isn't raised for characters already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<samp>LocationListChanged</samp>]] and check <samp>e.Added</samp> → <samp>characters</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;NPC&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;NPC&gt;</samp>
 
  |arg desc 2 = A list of NPCs added since the last update tick.
 
  |arg desc 2 = A list of NPCs added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;NPC&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;NPC&gt;</samp>
 
  |arg desc 3 = A list of NPCs removed since the last update tick.
 
  |arg desc 3 = A list of NPCs removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = World
 
  |group = World
 
  |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 <samp>DebrisListChanged</samp>.
  
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>.
+
This event isn't raised for objects already present when a location is added. If you need to handle those too, use [[#World.LocationListChanged|<samp>LocationListChanged</samp>]] and check <samp>e.Added</samp> → <samp>objects</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;KeyValuePair&lt;Vector2, Object&gt;&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;KeyValuePair&lt;Vector2, Object&gt;&gt;</samp>
 
  |arg desc 2 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + object pairs added since the last update tick.
 
  |arg desc 2 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + object pairs added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;KeyValuePair&lt;Vector2, Object&gt;&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;KeyValuePair&lt;Vector2, Object&gt;&gt;</samp>
 
  |arg desc 3 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + object pairs removed since the last update tick.
 
  |arg desc 3 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + object pairs removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
{{/event
 
{{/event
 
  |group = World
 
  |group = World
 
  |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 <samp>LargeTerrainFeatureListChanged</samp>.
  
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>.
+
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|<samp>LocationListChanged</samp>]] and check <samp>e.Added</samp> → <samp>terrainFeatures</samp>.
  
  |arg name 1 = <tt>e.Location</tt>
+
  |arg name 1 = <samp>e.Location</samp>
  |arg type 1 = <tt>GameLocation</tt>
+
  |arg type 1 = <samp>GameLocation</samp>
 
  |arg desc 1 = The location which changed.
 
  |arg desc 1 = The location which changed.
  
  |arg name 2 = <tt>e.Added</tt>
+
  |arg name 2 = <samp>e.Added</samp>
  |arg type 2 = <tt>IEnumerable&lt;KeyValuePair&lt;Vector2, TerrainFeature&gt;&gt;</tt>
+
  |arg type 2 = <samp>IEnumerable&lt;KeyValuePair&lt;Vector2, TerrainFeature&gt;&gt;</samp>
 
  |arg desc 2 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + terrain feature pairs added since the last update tick.
 
  |arg desc 2 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + terrain feature pairs added since the last update tick.
  
  |arg name 3 = <tt>e.Removed</tt>
+
  |arg name 3 = <samp>e.Removed</samp>
  |arg type 3 = <tt>IEnumerable&lt;KeyValuePair&lt;Vector2, TerrainFeature&gt;&gt;</tt>
+
  |arg type 3 = <samp>IEnumerable&lt;KeyValuePair&lt;Vector2, TerrainFeature&gt;&gt;</samp>
 
  |arg desc 3 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + terrain feature pairs removed since the last update tick.
 
  |arg desc 3 = A list of [[Modding:Modder Guide/Game Fundamentals#Tiles|tile coordinate]] + terrain feature pairs removed since the last update tick.
  
  |arg name 4 = <tt>e.IsCurrentLocation</tt>
+
  |arg name 4 = <samp>e.IsCurrentLocation</samp>
  |arg type 4 = <tt>bool</tt>
+
  |arg type 4 = <samp>bool</samp>
  |arg desc 4 = Whether <tt>e.Location</tt> is the location containing the local player.
+
  |arg desc 4 = Whether <samp>e.Location</samp> is the location containing the local player.
 
}}
 
}}
 
|}
 
|}
  
===Specialised===
+
=== 特殊===
<tt>this.Helper.Events.Specialised</tt> has events for specialised edge cases. These shouldn't be used by most mods.
+
<samp>this.Helper.Events.Specialised</samp> 针对特殊情况的事件. 大多数模组不应使用这些功能
  
{| class="wikitable"
+
{|class="wikitable"
 
|-
 
|-
 
! event
 
! event
第685行: 第687行:
 
  |group = Specialised
 
  |group = Specialised
 
  |name  = LoadStageChanged
 
  |name  = LoadStageChanged
  |desc  = 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|game loop events]] instead.
+
  |desc  = 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|game loop events]] instead.
  
  |arg name 1 = <tt>e.NewStage</tt>
+
  |arg name 1 = <samp>e.NewStage</samp>
  |arg type 1 = <tt>LoadStage</tt>
+
  |arg type 1 = <samp>LoadStage</samp>
 
  |arg desc 1 = The new load stage. The possible values are...
 
  |arg desc 1 = The new load stage. The possible values are...
  
第698行: 第700行:
 
** <code>CreatedSaveFile</code>: the game has created the physical save files.
 
** <code>CreatedSaveFile</code>: the game has created the physical save files.
 
* When loading an existing save slot:
 
* When loading an existing save slot:
** <code>SaveParsed</code>: the game has read the raw save data into <tt>StardewValley.SaveGame.loaded</tt>. Not applicable when connecting to a multiplayer host. This is equivalent to <tt>StardewValley.SaveGame.getLoadEnumerator</tt> value 20.
+
** <code>SaveParsed</code>: the game has read the raw save data into <samp>StardewValley.SaveGame.loaded</samp>. Not applicable when connecting to a multiplayer host. This is equivalent to <samp>StardewValley.SaveGame.getLoadEnumerator</samp> value 20.
** <code>SaveLoadedBasicInfo</code>: the game 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 <tt>StardewValley.SaveGame.getLoadEnumerator</tt> value 36.
+
** <code>SaveLoadedBasicInfo</code>: the game 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 <samp>StardewValley.SaveGame.getLoadEnumerator</samp> value 36.
 
** <code>SaveAddedLocations</code>: the game has added the location instances to the game, but hasn't restored their save data yet.
 
** <code>SaveAddedLocations</code>: the game has added the location instances to the game, but hasn't restored their save data yet.
** <code>SaveLoadedLocations</code>: the game has restored the in-game location data. Not applicable when connecting to a multiplayer host. This is equivalent to <tt>StardewValley.SaveGame.getLoadEnumerator</tt> value 50.
+
** <code>SaveLoadedLocations</code>: the game has restored the in-game location data. Not applicable when connecting to a multiplayer host. This is equivalent to <samp>StardewValley.SaveGame.getLoadEnumerator</samp> value 50.
 
* <code>Preloaded</code>: 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.
 
* <code>Preloaded</code>: 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.
 
* <code>Loaded</code>: the save is fully loaded, but the world may not be fully initialised yet.
 
* <code>Loaded</code>: the save is fully loaded, but the world may not be fully initialised yet.
* <code>Ready</code>: the save is fully loaded, the world has been initialised, and [[Modding:Modder Guide/APIs/Utilities#Context|<tt>Context.IsWorldReady</tt>]] is now true.
+
* <code>Ready</code>: the save is fully loaded, the world has been initialised, and [[Modding:Modder Guide/APIs/Utilities#Context|<samp>Context.IsWorldReady</samp>]] is now true.
 
* <code>ReturningToTitle</code>: The game is exiting the loaded save and returning to the title screen. This happens before it returns to title; the stage ''after'' it returns to title is <code>None</code>.
 
* <code>ReturningToTitle</code>: The game is exiting the loaded save and returning to the title screen. This happens before it returns to title; the stage ''after'' it returns to title is <code>None</code>.
  
  |arg name 2 = <tt>e.OldStage</tt>
+
  |arg name 2 = <samp>e.OldStage</samp>
  |arg type 2 = <tt>LoadStage</tt>
+
  |arg type 2 = <samp>LoadStage</samp>
  |arg desc 2 = The previous load stage. See comments for <tt>e.NewStage</tt>.
+
  |arg desc 2 = The previous load stage. See comments for <samp>e.NewStage</samp>.
 
}}
 
}}
 
{{/event
 
{{/event
第717行: 第719行:
  
  
  |arg name 1 = <tt>e.Ticks</tt>
+
  |arg name 1 = <samp>e.Ticks</samp>
  |arg type 1 = <tt>int</tt>
+
  |arg type 1 = <samp>int</samp>
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
 
  |arg desc 1 = The number of ticks elapsed since the game started, including the current tick.
  
  |arg name 2 = <tt>e.IsOneSecond</tt>
+
  |arg name 2 = <samp>e.IsOneSecond</samp>
  |arg type 2 = <tt>bool</tt>
+
  |arg type 2 = <samp>bool</samp>
  |arg desc 2 = Whether <tt>e.TicksElapsed</tt> is a multiple of 60, which happens approximately once per second.
+
  |arg desc 2 = Whether <samp>e.TicksElapsed</samp> is a multiple of 60, which happens approximately once per second.
  
  |arg name 3 = <tt>e.IsMultipleOf(int number)</tt>
+
  |arg name 3 = <samp>e.IsMultipleOf(int number)</samp>
  |arg type 3 = ''method'' returns <tt>bool</tt>
+
  |arg type 3 = ''method'' returns <samp>bool</samp>
  |arg desc 3 = Whether <tt>e.TicksElapsed</tt> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g. <code>e.IsMultipleOf(30)</code> for every half-second).
+
  |arg desc 3 = Whether <samp>e.TicksElapsed</samp> is a multiple of the given number. This is mainly useful if you want to run logic intermittently (''e.g.,'' <code>e.IsMultipleOf(30)</code> for every half-second).
 
}}
 
}}
 
|}
 
|}
  
==Advanced==
+
== 进阶==
===Change monitoring===
+
=== 变化监控===
You may want to handle a change that doesn't have its own event (e.g. an in-game event ends, a letter is added to the mailbox, etc). You can usually do that by handling a general event like [[#GameLoop.UpdateTicked|<tt>UpdateTicked</tt>]], and detecting when the value(s) you're watching changed. For example, here's a complete mod which logs a message when an in-game event ends:
+
You may want to handle a change that doesn't have its own event (''e.g.,'' an in-game event ends, a letter is added to the mailbox, etc). You can usually do that by handling a general event like [[#GameLoop.UpdateTicked|<samp>UpdateTicked</samp>]], and detecting when the value(s) you're watching changed. For example, here's a complete mod which logs a message when an in-game event ends:
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">
 
/// <summary>The main entry point for the mod.</summary>
 
/// <summary>The main entry point for the mod.</summary>
第772行: 第774行:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
===Custom priority===
+
=== 自定义优先级===
 
SMAPI calls event handlers in the same order they're registered by default, so the first event handler registered is the first to receive the event each time. This isn't always predictable, since it depends on mod load order and when each mod registers their handlers. This order is also an implementation detail, so it's not guaranteed.
 
SMAPI calls event handlers in the same order they're registered by default, so the first event handler registered is the first to receive the event each time. This isn't always predictable, since it depends on mod load order and when each mod registers their handlers. This order is also an implementation detail, so it's not guaranteed.
  
If you need more control over the order, you can specify an event priority using the <code>[EventPriority]</code> attribute: <tt>Low</tt> (after most handlers), <tt>Default</tt>, <tt>High</tt> (before most handlers), or a custom value (e.g. <tt>High + 1</tt> is higher priority than <tt>High</tt>). '''You should only do this if strictly needed'''; depending on event handler order between mods is fragile (e.g. the other mod might change its priority too).
+
If you need more control over the order, you can specify an event priority using the <code>[EventPriority]</code> attribute: <samp>Low</samp> (after most handlers), <samp>Default</samp>, <samp>High</samp> (before most handlers), or a custom value (''e.g.,'' <samp>High + 1</samp> is higher priority than <samp>High</samp>). '''You should only do this if strictly needed'''; depending on event handler order between mods is fragile (''e.g.,'' the other mod might change its priority too).
  
 
<syntaxhighlight lang="c#">
 
<syntaxhighlight lang="c#">

2024年5月24日 (五) 09:58的最新版本

制作SMAPI模组 SMAPI mascot.png


模组:目录

Robin building.png
“我这里还有很多事情需要处理。”
— 罗宾

不完整的翻译

本文或部分尚未完全翻译成中文。 欢迎您通过编辑帮助其建设。
最后编辑LEMAT于2024-05-24 09:58:17.

SMAPI 提供了几个 C#事件,这些事件使模组在某些事情发生时(例如,玩家放置一个对象时)做出响应,或者定期运行代码(例如,每个更新周期一次)

常见问题

什么是事件(events) ?

事件使你可以在发生某些事情时运行代码。可以在引发“事件”(发生的情况)时添加任意数量的“事件处理程序”(调用方法)。 可以将事件和处理程序视为“when...then”语句:

存档已加载              <-- 事件
然后运行我的代码        <-- 事件处理程序

有关详细信息,请参阅C# 编程指南中的事件中的“事件”。

如何使用它们?

通常将事件处理程序添加到 Entry 方法中,可以随时添加和删除它们。例如,在每天开始时打印一条消息。首先,从下面的列表中选择适当的事件 (GameLoop.DayStarted), 然后添加一个事件处理程序,并在方法代码中执行以下操作:

/// <summary>模组的主要入口点。</summary>
public class ModEntry : Mod
{
    /**********
    ** 公共方法
    *********/
    /// <summary>模组入口点,加载模组后自动调用</summary>
    /// <param name="helper">提供用于编写模组的简化API</param>
    public override void Entry(IModHelper helper)
    {
        // 事件 += 方法
        helper.Events.GameLoop.DayStarted += this.OnDayStarted;
    }
    
    /**********
    ** 私有方法
    *********/
    /// <summary>在新的一天开始后调用的方法</summary>
    /// <param name="sender">事件对象</param>
    /// <param name="e">事件参数</param>
    private void OnDayStarted(object sender, DayStartedEventArgs e)
    {
       this.Monitor.Log("新的一天到来了!");
    }
}

提示:不需要记住方法参数。在 Visual Studio 中,输入 helper.Events.GameLoop.SaveLoaded += 然后按 TAB 来自动生成方法

事件如何呈现到游戏中?

每次游戏计时(游戏更新其状态并呈现到屏幕时)都会引发事件,每秒60次。 一个事件可能会引发多次(例如,如果玩家同时按下两个键),但是大多数事件不会每秒引发60次(例如,玩家不太可能每秒按下60个按钮)

事件处理程序是“同步”运行的:游戏暂停时模组的代码不会运行,因此没有更改冲突的风险。由于代码运行非常迅速,因此除非你的代码异常缓慢,否则玩家不会注意到任何延迟。就是说,当使用诸如 UpdateTicked 或者 Rendered 应该缓存繁重的操作(例如加载资源),而不是在每个刻度中重复执行这些操作,以免影响性能。

如果模组更改了事件的发起?

事件根据游戏状态的快照引发,这通常是“但不一定”是当前游戏状态

例如,考虑这种情况:

  1. 菜单 GameMenu 打开了
  2. SMAPI 引发 MenuChanged 事件,并且模组 A 和 B 正在监听
  3. 模组 A 接收了事件并关闭了菜单
  4. 模组 B 接收了事件

每个模组仍在处理菜单打开的 MenuChanged 事件,即使第一个模组已将菜单关闭。SMAPI 将在下一个刻度时为关闭的菜单引发一个新的 MenuChanged 事件

这很少会影响模组,但是如果你需要当前状态,则需要牢记 (例如考虑用 Game1.activeClickableMenu 代替 e.NewMenu)

事件

可用的事件记录在下面

显示

this.Helper.Events.Display 具有链接到 UI 并绘制到屏幕的事件

事件 描述
#MenuChanged 在打开、关闭或替换游戏菜单后引发

事件参数:

参数 类型 描述
e.NewMenu IClickableMenu 新的菜单实例 (如果没有,则为 null )
e.OldMenu IClickableMenu 旧的菜单实例 (如果没有,则为 null)
#Rendering 打开 sprite batch 同时,在游戏将任何内容绘制到屏幕上之前,触发此事件。在此事件触发后,sprite batch 可能多次关闭并重新打开。 但只在每次draw tick只会启动一次. 此事件对于在屏幕上绘制没有用, 因为游戏会在这之上覆盖绘制。

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch 开始绘制sprite batch,添加任何你想绘制的东西到sprite batch中。
#Rendered 会在游戏的一个draw tick中对sprite batch进行绘制后,最后一个sprite batch在屏幕上渲染前启动。因为游戏可能会在一个draw tick中打开/关闭sprite batch多次,sprite batch可能没有包含正在绘制的所有内容,并且有些内容可能已经渲染在屏幕上了。在这个点上绘制到sprite batch的内容会覆盖在所有普通内容上(包括菜单,HUD,和光标)。

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch 正在绘制sprite batch。添加任何你想绘制的东西到sprite batch中。
#RenderingWorld 在游戏事件绘制到屏幕之前启动。这个事件不对绘制有任何帮助,因为游戏绘制会覆盖它。

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#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.

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#RenderingActiveMenu 当一个菜单被打开时 (Game1.activeClickableMenu != null), 在将该菜单绘制到屏幕上之前触发。这包括游戏的内部菜单,例如进入游戏时的主菜单。Content drawn to the sprite batch at this point will appear under the menu.

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#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.

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#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.

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#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.

事件参数:

参数 类型 描述
e.SpriteBatch SpriteBatch The sprite batch being drawn. Add anything you want to appear on-screen to this sprite batch.
#WindowResized Raised after the game window is resized.

事件参数:

参数 类型 描述
e.OldSize Point The previous window width (e.OldSize.X) and height (e.OldSize.Y).
e.NewSize Point The new window width (e.NewSize.X) and height (e.NewSize.Y).

游戏循环

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
在游戏状态更新前/后启动(大约每秒钟60次)。

事件参数:

参数 类型 描述
e.Ticks int The number of ticks elapsed since the game started, including the current tick.
e.IsOneSecond bool Whether e.TicksElapsed is a multiple of 60, which happens approximately once per second.
e.IsMultipleOf(int number) method returns bool Whether e.TicksElapsed is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g., e.IsMultipleOf(30) for every half-second).
#OneSecondUpdateTicking
OneSecondUpdateTicked
Raised before/after the game state is updated, once per second.

事件参数:

参数 类型 描述
e.Ticks int The number of ticks elapsed since the game started, including the current tick.
e.IsMultipleOf(int number) method returns bool Whether e.TicksElapsed is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g., e.IsMultipleOf(120) for every two seconds).
#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. This is also raised for farmhands in multiplayer.
#SaveLoaded Raised after loading a save (including the first day after creating a new save), or connecting to a multiplayer world. This happens right before DayStarted; at this point the save file is read and Context.IsWorldReady is true.

This event isn't raised after saving; if you want to do something at the start of each day, see DayStarted instead.

#DayStarted Raised after a new in-game day starts, or after connecting to a multiplayer world. 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.

事件参数:

参数 类型 描述
e.OldTime int The previous time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
e.NewTime int The current time of day in 24-hour notation (like 1600 for 4pm). The clock time resets when the player sleeps, so 2am (before sleeping) is 2600.
#ReturnedToTitle Raised after the game returns to the title screen.

输入

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
#ButtonsChanged Raised after the player pressed/released any buttons on the keyboard, mouse, or controller. This includes mouse clicks. If the player pressed/released multiple keys at once, this is only raised once.

事件参数:

参数 类型 描述
e.Pressed SButton[] The buttons that were pressed since the previous tick.
e.Held SButton[] The buttons that were held since the previous tick.
e.Released SButton[] The buttons that were released since the previous tick.
e.Cursor ICursorPosition The cursor position and grab tile. Note: mods won't receive input sent to the chatbox.
#ButtonPressed
ButtonReleased
Raised after the player pressed/released a keyboard, mouse, or controller button. This includes mouse clicks. If the player pressed/released multiple keys at once, this is raised for each button pressed.

事件参数:

参数 类型 描述
e.Button SButton The button pressed or released.
e.Cursor ICursorPosition The cursor position and grab tile.
e.IsDown method returns bool Indicates whether a given button is currently pressed.
e.IsSuppressed method returns bool A method which indicates whether a given button was suppressed by a mod, so the game itself won't see it. Note: mods won't receive input sent to the chatbox.
#CursorMoved Raised after the player moves the in-game cursor.

事件参数:

参数 类型 描述
e.OldPosition ICursorPosition The previous cursor position and grab tile.
e.NewPosition ICursorPosition The current cursor position and grab tile.
#MouseWheelScrolled Raised after the player scrolls the mouse wheel.

事件参数:

参数 类型 描述
e.Position ICursorPosition The current cursor position and grab tile.
e.Delta int The amount by which the mouse wheel was scrolled since the last update.
e.OldValue
e.NewValue
int The previous and current scroll value, cumulative since the game started. Mods should generally use e.Delta instead.

多人

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 immediately 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. Assuming another mod doesn't block the connection, the connection will be approved on the next tick.

事件参数:

参数 类型 描述
e.Peer IMultiplayerPeer The peer whose context was received (see Multiplayer#Get connected player info).
#PeerConnected Raised after a connection from another player is approved by the game. The event is raised for any player (whether host or farmhand), including when the connecting player doesn't have SMAPI installed. This happens after PeerContextReceived.

The player is connected to the game at this point, so methods like Game1.server.kick will work.

事件参数:

参数 类型 描述
e.Peer IMultiplayerPeer The peer who connected (see Multiplayer#Get connected player info).
#ModMessageReceived Raised after a mod message is received over the network.

事件参数:

参数 类型 描述
e.FromPlayerID long The unique ID of the player from whose computer the message was sent.
e.FromModID string The unique ID of the mod which sent the message.
e.Type string A message type which you can use to decide whether it's the one you want to handle. This isn't necessarily globally unique, so you should also check the FromModID field.
e.ReadAs<TModel>() method returns TModel Read the underlying message data into the given model type (like e.ReadAs<MyMessageClass>() or e.ReadAs<string>()). This will return a new instance each time.
#PeerDisconnected Raised after the connection to a player is severed.

事件参数:

参数 类型 描述
e.Peer IMultiplayerPeer The peer whose connection was severed (see Multiplayer#Get connected player info).

玩家

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.

事件参数:

参数 类型 描述
e.Player Farmer The player whose inventory changed.
e.Added IEnumerable<Item> The added item stacks.
e.Removed IEnumerable<Item> The removed item stacks.
e.QuantityChanged IEnumerable<ItemStackSizeChange> The item stacks whose quantity changed. Each ItemStackSizeChange instance includes Item (the affected item stack), OldSize (the previous stack size), and NewSize (the new stack size).
e.IsLocalPlayer bool Whether the affected player is the local one.
#LevelChanged 在一个玩家技能等级发生变化后触发. 当玩家技能等级提升的第一时间立马触发 (不是在玩家睡觉后游戏提示时触发).

事件参数:

参数 类型 描述
e.Player Farmer 技能等级发生变化的玩家.
e.Skill SkillType 等级发生变化的技能. 像 SkillType.Combat (战斗技能)这种能调用 (int)e.Skill 转化成内部id的技能.
e.OldLevel int 变化之前的技能等级.
e.NewLevel int 变化之后的等级.
e.IsLocalPlayer bool Whether the affected player is the local one.
#Warped 当玩家移动到新地点的时候触发(农场到车站,玩家所在矿井层数发生变化也算).

事件参数:

参数 类型 描述
e.Player Farmer 地点发生变化的玩家.
e.OldLocation GameLocation 玩家移动之前所在的地点.
e.NewLocation GameLocation 玩家移动之后到达的地点.
e.IsLocalPlayer bool Whether the affected player is the local one.

世界

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).

事件参数:

参数 类型 描述
e.Added IEnumerable<GameLocation> A list of locations added since the last update tick.
e.Removed IEnumerable<GameLocation> A list of locations removed since the last update tick.
#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.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<Building> A list of buildings added since the last update tick.
e.Removed IEnumerable<Building> A list of buildings removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.
#ChestInventoryChanged Raised after items are added or removed from a chest's inventory.

事件参数:

参数 类型 描述
e.Chest Chest The chest whose inventory changed.
e.Location Location The location containing the chest.
e.Added IEnumerable<Item> The added item stacks.
e.Removed IEnumerable<Item> The removed item stacks.
e.QuantityChanged IEnumerable<ItemStackSizeChange> The item stacks whose quantity changed. Each ItemStackSizeChange instance includes Item (the affected item stack), OldSize (the previous stack size), and NewSize (the new stack size).
#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.Addeddebris.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<Debris> A list of debris added since the last update tick.
e.Removed IEnumerable<Debris> A list of debris removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.
#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.AddedlargeTerrainFeatures.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<LargeTerrainFeature> A list of large terrain features added since the last update tick.
e.Removed IEnumerable<LargeTerrainFeature> A list of large terrain features removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.
#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.Addedcharacters.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<NPC> A list of NPCs added since the last update tick.
e.Removed IEnumerable<NPC> A list of NPCs removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.
#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.Addedobjects.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<KeyValuePair<Vector2, Object>> A list of tile coordinate + object pairs added since the last update tick.
e.Removed IEnumerable<KeyValuePair<Vector2, Object>> A list of tile coordinate + object pairs removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.
#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.AddedterrainFeatures.

事件参数:

参数 类型 描述
e.Location GameLocation The location which changed.
e.Added IEnumerable<KeyValuePair<Vector2, TerrainFeature>> A list of tile coordinate + terrain feature pairs added since the last update tick.
e.Removed IEnumerable<KeyValuePair<Vector2, TerrainFeature>> A list of tile coordinate + terrain feature pairs removed since the last update tick.
e.IsCurrentLocation bool Whether e.Location is the location containing the local player.

特殊

this.Helper.Events.Specialised 针对特殊情况的事件. 大多数模组不应使用这些功能

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.

事件参数:

参数 类型 描述
e.NewStage LoadStage The new load stage. The possible values are...
  • None: a save is not loaded or loading. (For example, the player is on the title screen.)
  • When creating a new save slot:
    • CreatedBasicInfo: the game has initialised the basic save info.
    • CreatedInitialLocations: the game has added the location instances, but hasn't fully initialized them yet.
    • CreatedLocations: the game has initialised the in-game locations.
    • CreatedSaveFile: the game has created the physical save files.
  • When loading an existing save slot:
    • SaveParsed: the game has read the raw save data into StardewValley.SaveGame.loaded. Not applicable when connecting to a multiplayer host. This is equivalent to StardewValley.SaveGame.getLoadEnumerator value 20.
    • SaveLoadedBasicInfo: the game 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 StardewValley.SaveGame.getLoadEnumerator value 36.
    • SaveAddedLocations: the game has added the location instances to the game, but hasn't restored their save data yet.
    • SaveLoadedLocations: the game has restored the in-game location data. Not applicable when connecting to a multiplayer host. This is equivalent to StardewValley.SaveGame.getLoadEnumerator value 50.
  • Preloaded: 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.
  • Loaded: the save is fully loaded, but the world may not be fully initialised yet.
  • Ready: the save is fully loaded, the world has been initialised, and Context.IsWorldReady is now true.
  • ReturningToTitle: The game is exiting the loaded save and returning to the title screen. This happens before it returns to title; the stage after it returns to title is None.
e.OldStage LoadStage The previous load stage. See comments for e.NewStage.
#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.

事件参数:

参数 类型 描述
e.Ticks int The number of ticks elapsed since the game started, including the current tick.
e.IsOneSecond bool Whether e.TicksElapsed is a multiple of 60, which happens approximately once per second.
e.IsMultipleOf(int number) method returns bool Whether e.TicksElapsed is a multiple of the given number. This is mainly useful if you want to run logic intermittently (e.g., e.IsMultipleOf(30) for every half-second).

进阶

变化监控

You may want to handle a change that doesn't have its own event (e.g., an in-game event ends, a letter is added to the mailbox, etc). You can usually do that by handling a general event like UpdateTicked, and detecting when the value(s) you're watching changed. For example, here's a complete mod which logs a message when an in-game event ends:

/// <summary>The main entry point for the mod.</summary>
public class ModEntry : Mod
{
    /*********
    ** Fields
    *********/
    /// <summary>The in-game event detected on the last update tick.</summary>
    private Event LastEvent;


    /*********
    ** 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)
    {
        helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked;
    }


    /*********
    ** Private methods
    *********/
    /// <summary>The method invoked when the game updates its state.</summary>
    /// <param name="sender">The event sender.</param>
    /// <param name="e">The event arguments.</param>
    private void OnUpdateTicked(object sender, EventArgs e)
    {
        if (this.LastEvent != null && Game1.CurrentEvent == null)
            this.Monitor.Log($"Event {this.LastEvent.id} just ended!");

        this.LastEvent = Game1.CurrentEvent;
    }
}

自定义优先级

SMAPI calls event handlers in the same order they're registered by default, so the first event handler registered is the first to receive the event each time. This isn't always predictable, since it depends on mod load order and when each mod registers their handlers. This order is also an implementation detail, so it's not guaranteed.

If you need more control over the order, you can specify an event priority using the [EventPriority] attribute: Low (after most handlers), Default, High (before most handlers), or a custom value (e.g., High + 1 is higher priority than High). You should only do this if strictly needed; depending on event handler order between mods is fragile (e.g., the other mod might change its priority too).

/// <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)
    {
        helper.Events.GameLoop.UpdateTicked += this.OnUpdateTicked;
    }


    /*********
    ** Private methods
    *********/
    /// <summary>The method invoked when the game updates its state.</summary>
    /// <param name="sender">The event sender.</param>
    /// <param name="e">The event arguments.</param>
    [EventPriority(EventPriority.High)]
    private void OnUpdateTicked(object sender, EventArgs e)
    {
        this.Monitor.Log("Update!");
    }
}