Changes

Jump to navigation Jump to search
→‎Net types: rewrite for new code analysis warnings
Line 10: Line 10:     
===Net types===
 
===Net types===
Stardew Valley 1.3 uses a new set of C# types to synchronise data between players. For example, a crop's <tt>bool dead</tt> field is now <tt>NetBool dead</tt>. The game will intermittently get the value of all reachable net fields, and send them to the other players. A ''net type'' means a network-synchronised type (like <tt>NetBool</tt>), and a ''net field'' is a field with such a type (like <tt>Crop.dead</tt>).
+
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:
 +
<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>
 +
<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>
   −
Usage notes:
+
Suggested fix:
 
<ul>
 
<ul>
<li>Many net fields have a standard property to access them. Use those when possible to simplify your code and avoid net field gotchas:
+
<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>):
 
<source lang="c#">
 
<source lang="c#">
Game1.player.name // NetString
+
if (building.indoors.Value == null)
Game1.player.Name // string
   
</source>
 
</source>
</li>
+
 
<li>You can implicitly cast net types to their standard equivalent:
+
Or convert the value before comparison:
 
<source lang="c#">
 
<source lang="c#">
NetBool a = crop.dead;
+
GameLocation indoors = building.indoors;
bool b = crop.dead;
+
if(indoors == null)
 
+
  // ...
if (a == b) // true
   
</source></li>
 
</source></li>
<li>You may need to access the value explicitly in some cases. Here's how:
+
<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>:
{| class="wikitable"
  −
|-
  −
! net type
  −
! syntax
  −
|-
  −
| <tt>NetDictionary</tt>
  −
| <tt>netField.FieldDict</tt>
  −
|-
  −
| ''most net types''
  −
| <tt>netField.Value</tt>
  −
|}</li>
  −
<li>'''Do not''' reassign net fields. (Many are readonly to prevent that, but not all.) Instead, set the new value:
   
<source lang="c#">
 
<source lang="c#">
// either of these will work
+
if (item != null && item.category.Value == 0)
crop.dead.Value = true;
  −
crop.dead.Set(true);
   
</source></li>
 
</source></li>
<li>Quirk: when using [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators null-conditional operators] with [https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/value-types value-type] net fields (like <tt>NetBool</tt> and <tt>NetInt</tt>), '''missing values will be equal to both null and <tt>default(T)</tt>''':
  −
<source lang="c#">
  −
Item item = null;
  −
if (item?.category == null && item?.category == 0) // both true
  −
</source>
  −
  −
When comparing to the default value, check for null first to avoid that issue:
  −
<source lang="c#">
  −
Item item = null;
  −
if (item != null && item.category == 0)
  −
</source>
  −
  −
</li>
   
</ul>
 
</ul>
  
translators
8,403

edits

Navigation menu