Line 139: |
Line 139: |
| ! event !! summary | | ! event !! summary |
| |- | | |- |
− | | FirstUpdateTick || '''[SMAPI 2.3+]''' Raised after the game first updates its state. This happens once per game session (unrelated to loading saves). | + | | FirstUpdateTick || Raised after the game first updates its state. This happens once per game session (unrelated to loading saves). |
| |- | | |- |
| | UpdateTick || Raised when the game updates its state (≈60 times per second). | | | UpdateTick || Raised when the game updates its state (≈60 times per second). |
Line 558: |
Line 558: |
| | | |
| ===Reflection=== | | ===Reflection=== |
− | SMAPI provides an API for robustly accessing the game's private fields or methods. You can use it from <tt>helper.Reflection</tt> in your entry method, or <tt>this.Helper.Reflection</tt> elsewhere in your entry class. It consists of three methods: | + | SMAPI provides an API for robustly accessing fields, properties, or methods you otherwise couldn't access, such as private fields. You can use it from <tt>helper.Reflection</tt> in your entry method, or <tt>this.Helper.Reflection</tt> elsewhere in your entry class. |
− | | |
− | * <tt>GetPrivateValue<TValue>(...)</tt> returns the value of a private field.
| |
− | * <tt>GetPrivateField<TValue>(...)</tt> returns an object you can use to get or set a field's value.
| |
− | * <tt>GetPrivateMethod(...)</tt> returns an object you can use to invoke a method.
| |
| | | |
| Here are a few examples of what this lets you do: | | Here are a few examples of what this lets you do: |
Line 568: |
Line 564: |
| <source lang="c#"> | | <source lang="c#"> |
| // did you pet your pet today? | | // did you pet your pet today? |
− | bool wasPet = this.Helper.Reflection.GetPrivateValue<bool>(pet, "wasPetToday"); | + | bool wasPet = this.Helper.Reflection.GetField<bool>(pet, "wasPetToday").GetValue(); |
| | | |
| // what is the spirit forecast today? | | // what is the spirit forecast today? |
| string forecast = this.Helper.Reflection | | string forecast = this.Helper.Reflection |
− | .GetPrivateMethod(new TV(), "getFortuneForecast") | + | .GetMethod(new TV(), "getFortuneForecast") |
| .Invoke<string>(); | | .Invoke<string>(); |
| | | |
| // randomise the mines | | // randomise the mines |
| if(Game1.currentLocation is MineShaft) | | if(Game1.currentLocation is MineShaft) |
− | this.Helper.Reflection.GetPrivateField<Random>(Game1.currentLocation, "mineRandom").SetValue(new Random()); | + | this.Helper.Reflection.GetField<Random>(Game1.currentLocation, "mineRandom").SetValue(new Random()); |
| </source> | | </source> |
| | | |
| This works with static or instance fields/methods, caches the reflection to improve performance, and will throw useful errors automatically when reflection fails. | | This works with static or instance fields/methods, caches the reflection to improve performance, and will throw useful errors automatically when reflection fails. |
| | | |
− | If you need to do more, you can also switch to C#'s underlying reflection API: | + | If you need to do more, you can switch to [https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/reflection C#'s underlying reflection API]: |
| | | |
| <source lang="c#"> | | <source lang="c#"> |
− | FieldInfo field = this.Helper.Reflection.GetPrivateField<string>(…).FieldInfo; | + | FieldInfo field = this.Helper.Reflection.GetField<string>(…).FieldInfo; |
− | MethodInfo method = this.Helper.Reflection.GetPrivateMethod(…).MethodInfo; | + | MethodInfo method = this.Helper.Reflection.GetMethod(…).MethodInfo; |
| </source> | | </source> |
| | | |
Line 812: |
Line 808: |
| | | |
| ==Mod-provided APIs== | | ==Mod-provided APIs== |
− | {{SMAPI upcoming
| + | Mods can provide their own APIs to other mods, even without a dependency or assembly reference. This can be used to integrate mods, provide custom information, or provide new framework APIs beyond those offered by SMAPI itself. |
− | |version = 2.3
| |
− | |content = Mods can provide their own APIs to other mods, even without a dependency or assembly reference. This can be used to integrate mods, provide custom information, or provide new framework APIs beyond those offered by SMAPI itself.
| |
| | | |
| ===Providing an API=== | | ===Providing an API=== |
Line 876: |
Line 870: |
| * You can't call <tt>GetApi</tt> until all mods are initialised and their <tt>Entry</tt> methods called. You can use the <tt>GameEvents.FirstUpdateTick</tt> [[#Events|event]] if you need to access mod APIs early; this is guaranteed to happen after all mods are initialised. | | * You can't call <tt>GetApi</tt> until all mods are initialised and their <tt>Entry</tt> methods called. You can use the <tt>GameEvents.FirstUpdateTick</tt> [[#Events|event]] if you need to access mod APIs early; this is guaranteed to happen after all mods are initialised. |
| * You should always null-check APIs you consume. <tt>GetApi</tt> will return <tt>null</tt> if the API isn't available (e.g. because the mod isn't already installed or doesn't have one), or if an error occurs fetching the API. | | * You should always null-check APIs you consume. <tt>GetApi</tt> will return <tt>null</tt> if the API isn't available (e.g. because the mod isn't already installed or doesn't have one), or if an error occurs fetching the API. |
− | }}
| |
| | | |
| [[Category:Modding]] | | [[Category:Modding]] |