Line 5: |
Line 5: |
| This page explains how to update your SMAPI mod code for compatibility with Stardew Valley 1.3. | | This page explains how to update your SMAPI mod code for compatibility with Stardew Valley 1.3. |
| | | |
− | ==SMAPI mods==
| + | ==Overview== |
− | ===Overview===
| |
| At a high level, here's how to update a SMAPI mod: | | At a high level, here's how to update a SMAPI mod: |
| # Update the [https://www.nuget.org/packages/Pathoschild.Stardew.ModBuildConfig mod build NuGet package] to 2.1-beta. (You may need to enable the 'include prerelease' checkbox to see the beta.)<br />''This adds support for Stardew Valley 1.3, and adds code analysis which will report common problems in Stardew Valley 1.3 as compiler warnings.'' | | # Update the [https://www.nuget.org/packages/Pathoschild.Stardew.ModBuildConfig mod build NuGet package] to 2.1-beta. (You may need to enable the 'include prerelease' checkbox to see the beta.)<br />''This adds support for Stardew Valley 1.3, and adds code analysis which will report common problems in Stardew Valley 1.3 as compiler warnings.'' |
| + | # '''Restart Visual Studio''' to fully install the package. |
| # Rebuild your solution. | | # Rebuild your solution. |
| # Fix any compiler errors and warnings you see in the ''Error List'' pane in Visual Studio (or equivalent for other editors). | | # Fix any compiler errors and warnings you see in the ''Error List'' pane in Visual Studio (or equivalent for other editors). |
Line 18: |
Line 18: |
| If you need help updating your code, feel free to ask questions [[Modding:Community#Discord|on the Stardew Valley Discord]]. | | If you need help updating your code, feel free to ask questions [[Modding:Community#Discord|on the Stardew Valley Discord]]. |
| | | |
− | ===Net types=== | + | ==Major changes== |
− | Stardew Valley 1.3 uses net types (like <tt>NetBool</tt> and <tt>NetInt</tt>) to handle multiplayer sync. These types can implicitly convert to their equivalent normal values (like <code>bool x = new NetBool()</code>), but their conversion rules are unintuitive and error-prone. For example, <code>item?.category == null && item?.category != null</code> can both be true at once, and <code>building.indoors != null</code> will be true for a null value in some cases. With the mod build config package installed, rebuild the project and look for warnings in the Error List pane like this: | + | ===Net fields=== |
− | <blockquote>'''{{expression}}' is a {{net type}} field; consider using the {{property name}} property instead. See https://smapi.io/buildmsg/smapi002 for details.''</blockquote>
| + | A 'net type' is any of several new classes which Stardew Valley 1.3 uses to sync data between players, named for the <code>Net</code> prefix in their name. A net type can represent a simple value like <tt>NetBool</tt>, or complex values like <tt>NetFieldDictionary</tt>. Many existing fields have been converted to net types (called 'net fields'), each wrapping the underlying value: |
− | <blockquote>''This implicitly converts '{{expression}}' from {{net type}} to {{other type}}, but {{net type}} has unintuitive implicit conversion rules. Consider comparing against the actual value instead to avoid bugs. See https://smapi.io/buildmsg/smapi001 for details.''</blockquote>
| + | : <source lang="C#"> |
| + | NetString str = new NetString("bar"); |
| + | if (str.Value == "bar") // true |
| + | </source> |
| + | |
| + | Impact on mods: |
| + | * The game will regularly collect all the net fields reachable from <tt>Game1.netWorldState</tt> and sync them with other players. That means that many mod changes will be synchronised automatically in multiplayer. |
| + | * Net fields can implicitly convert to their equivalent normal values (like <code>bool x = new NetBool(true)</code>), but their conversion rules can be counterintuitive and error-prone. For example, <code>item?.category == null && item?.category != null</code> can both be true at once. '''Always avoid implicit casts to minimise bugs.''' |
| | | |
| Suggested fix: | | Suggested fix: |
| + | * With the latest mod build package installed, rebuild your project. The package will detect net field references you need to update, and show an appropriate warning. See [[#Fix common warnings|''fix common warnings'']] below. |
| + | |
| + | ===<tt>Game1.player.friendships</tt>=== |
| + | This field is always null in Stardew Valley 1.3. Use the new <tt>Game1.player.friendshipData</tt> field instead, which wraps the raw data with a model. |
| + | |
| + | ===Texture constructor arguments=== |
| + | Many constructors which previously accepted <tt>Texture2D texture</tt> arguments now take a <tt>string textureName</tt> argument instead. It's usually better to use SMAPI's content API to override textures instead. You can change the cached texture after the object is constructed (may need [[Modding:SMAPI APIs#Reflection|reflection]]), but don't change the texture name to avoid multiplayer sync issues. |
| + | |
| + | ==Fix common compiler warnings== |
| + | Make sure you check your Error List pane in Visual Studio (or equivalent in other IDEs) and fix any warnings. Here are some common ones: |
| + | |
| + | ===Mismatch between the processor architecture...=== |
| + | Sample warning: "''There was a mismatch between the processor architecture of the project being built "{0}" and the processor architecture of the reference "{1}". This mismatch may cause runtime failures.''" |
| + | |
| + | That warning is normal. The error is saying that your build is set to 'Any CPU', but Stardew Valley is x86-only so it'll only work in x86 anyway. You can either ignore it, or [https://msdn.microsoft.com/en-us/library/ms185328.aspx change your platform target] to x86. |
| + | |
| + | ===This implicitly converts...=== |
| + | Sample warning: "''This implicitly converts '{0}' from {1} to {2}, but {1} has unintuitive implicit conversion rules. Consider comparing against the actual value instead to avoid bugs. See https://smapi.io/buildmsg/avoid-implicit-net-field-cast for details.''" |
| + | |
| + | Your code is referencing a [[#Net fields|net field]], which can cause subtle bugs. The field you're referencing has an equivalent non-net property, like <tt>monster.Health</tt> (<tt>int</tt>) instead of <tt>monster.health</tt> (<tt>NetBool</tt>). Change your code to use the suggested property instead. |
| + | |
| + | ===FieldName is a Net* field...=== |
| + | Sample warning: "'''{0}' is a {1} field; consider using the {2} property instead. See https://smapi.io/buildmsg/avoid-net-field for details.''" |
| + | |
| + | Your code is referencing a [[#Net fields|net field]], which can cause subtle bugs. You should access the underlying value instead: |
| <ul> | | <ul> |
− | <li>Some net fields have an equivalent non-net property, like <tt>monster.Health</tt> (<tt>int</tt>) instead of <tt>monster.health</tt> (<tt>NetBool</tt>). The mod build package will add a [https://smapi.io/buildmsg/smapi002 SMAPI002 warning] which says which property to use instead.</li>
| |
| <li>For a reference type (i.e. one that can contain <tt>null</tt>), you can use the <tt>.Value</tt> property (or <tt>.FieldDict</tt> for a <tt>NetDictionary</tt>): | | <li>For a reference type (i.e. one that can contain <tt>null</tt>), you can use the <tt>.Value</tt> property (or <tt>.FieldDict</tt> for a <tt>NetDictionary</tt>): |
| <source lang="c#"> | | <source lang="c#"> |
Line 33: |
Line 64: |
| Or convert the value before comparison: | | Or convert the value before comparison: |
| <source lang="c#"> | | <source lang="c#"> |
− | GameLocation indoors = building.indoors; | + | GameLocation indoors = building.indoors.Value; |
| if(indoors == null) | | if(indoors == null) |
| // ... | | // ... |
| </source></li> | | </source></li> |
− | <li>For a value type (i.e. one that can't contain <tt>null</tt>), check if the object is null (if applicable) and compare with <tt>.Value</tt>: | + | <li>For a value type (i.e. one that can't contain <tt>null</tt>), check if the parent is null (if needed) and compare with <tt>.Value</tt>: |
| <source lang="c#"> | | <source lang="c#"> |
| if (item != null && item.category.Value == 0) | | if (item != null && item.category.Value == 0) |
Line 43: |
Line 74: |
| </ul> | | </ul> |
| | | |
− | ===<tt>Game1.player.friendships</tt>=== | + | ===The FieldName field is obsolete...=== |
− | This field is always null in Stardew Valley 1.3. Use the new <tt>Game1.player.friendshipData</tt> field instead, which wraps the raw data with a model.
| + | Sample warning: "''The 'Character.friendships' field is obsolete and should be replaced with 'friendshipData'. See https://smapi.io/buildmsg/smapi003 for details.''" |
− | | |
− | ===Texture constructor arguments===
| |
− | Many constructors which previously accepted <tt>Texture2D texture</tt> arguments now take a <tt>string textureName</tt> argument instead. It's usually better to use SMAPI's content API to override textures instead. You can change the cached texture after the object is constructed (may need [[Modding:SMAPI APIs#Reflection|reflection]]), but don't change the texture name to avoid multiplayer sync issues.
| |
− | | |
− | ===Common compiler warnings===
| |
− | Make sure you check your Error List pane in Visual Studio (or equivalent in other IDEs) and fix any warnings. Here are some common ones:
| |
− | | |
− | * "''There was a mismatch between the processor architecture of the project being built "{0}" and the processor architecture of the reference "{1}". This mismatch may cause runtime failures.''"<br />That warning is normal. The error is saying that your build is set to 'Any CPU', but Stardew Valley is x86-only so it'll only work in x86 anyway. You can either ignore it, or [https://msdn.microsoft.com/en-us/library/ms185328.aspx change your platform target] to x86.
| |
− | | |
− | * "''This implicitly converts '{0}' from {1} to {2}, but {1} has unintuitive implicit conversion rules. Consider comparing against the actual value instead to avoid bugs. See https://smapi.io/buildmsg/smapi001 for details.''"<br />See [[#Net types]].
| |
− | | |
− | * "'''{0}' is a {1} field; consider using the {2} property instead. See https://smapi.io/buildmsg/smapi002 for details.''"<br />See [[#Net types]].
| |
| | | |
− | * "''The '{0}' field is obsolete and should be replaced with '{1}'. See https://smapi.io/buildmsg/smapi003 for details.''"<br />You're referencing a field which should no longer be used. Just use the suggested field name instead to fix it.
| + | You're referencing a field which should no longer be used. Use the suggested field name instead to fix it. |
| | | |
| [[Category:Modding]] | | [[Category:Modding]] |