Changes

expand and update
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>''&apos;&#123;&#123;expression&#125;&#125;&apos; is a &#123;&#123;net type&#125;&#125; field; consider using the &#123;&#123;property name&#125;&#125; 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 &apos;&#123;&#123;expression&#125;&#125;&apos; from &#123;&#123;net type&#125;&#125; to &#123;&#123;other type&#125;&#125;, but &#123;&#123;net type&#125;&#125; 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]]
translators
8,437

edits