Changes

Jump to navigation Jump to search
m
Text replacement - "i.e. " to "''i.e.,'' "
Line 1: Line 1: −
{{stub}}
+
←[[Modding:Index|Index]]
   −
'''This page is for modders. Players: see [[Modding:SMAPI compatibility]] instead.'''
+
{{Modder compatibility header}}
 +
For updating Content Patcher or XNB mods, see [[Modding:Migrate XNB changes to Stardew Valley 1.3|''Migrate XNB changes to Stardew Valley 1.3'']].
   −
This page explains the most common changes needed in mods 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===
+
===Single player===
At a high level, you can update a mod for Stardew Valley 1.3 '''single player''' like this:
+
At a high level, here's how to update a SMAPI mod:
# Update to [https://www.nuget.org/packages/Pathoschild.Stardew.ModBuildConfig Pathoschild.Stardew.ModBuildConfig 2.1]. This includes 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 build 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).
# See below for specific changes which may affect your mod.
+
# See below for help with specific changes and warnings.
 
# Test all mod features to make sure they work.
 
# Test all mod features to make sure they work.
  −
Updating for multiplayer will depend on how your mod works. Consider using SMAPI's <tt>Context.IsSinglePlayer</tt> and <tt>Context.IsMainPlayer</tt> flags in your logic to avoid conflicts.
      
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===
+
===Multiplayer===
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:
+
The instructions for single player apply for multiplayer too. Stardew Valley 1.3 automatically synchronises most world changes to other players (see ''[[Modding:Modder Guide/Game Fundamentals#Net fields|net fields]]''), so many mods will work in multiplayer too. Some mods may need further changes, but that can only be decided case-by-case.
<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>
     −
Suggested fix:
+
There are three common approaches to multiplayer compatibility:
<ul>
+
* Let anyone install the mod. If your mod makes changes to the world, make sure it'll work fine if different players have different versions or configuration, or only some of the players have it installed.
<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>
+
* Only let the main player install the mod, which avoids complications from other players changing the same data. To do this, check SMAPI's <code>Context.IsMainPlayer</code> in your code.
<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>):
+
* Only enable in single-player mode. This eliminates all multiplayer and sync complications, though players may be disappointed. To do this, check SMAPI's <code>Context.IsMultiplayer</code> in your code.
<source lang="c#">
  −
if (building.indoors.Value == null)
  −
</source>
     −
Or convert the value before comparison:
+
Common issues:
<source lang="c#">
+
* If your mod adds custom buildings or items, the game may crash trying to sync them to other players.
GameLocation indoors = building.indoors;
  −
if(indoors == null)
  −
  // ...
  −
</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>:
  −
<source lang="c#">
  −
if (item != null && item.category.Value == 0)
  −
</source></li>
  −
</ul>
     −
===<tt>Game1.player.friendships</tt>===
+
==Major changes==
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.
+
===⚠ Net fields===
 +
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 <samp>NetBool</samp>, or complex values like <samp>NetFieldDictionary</samp>. Many existing fields have been converted to net types (called 'net fields'), each wrapping the underlying value:
 +
: <syntaxhighlight lang="C#">
 +
NetString str = new NetString("bar");
 +
if (str.Value == "bar") // true
 +
</syntaxhighlight>
   −
===Texture constructor arguments===
+
Impact on mods:
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, though you can change the cached texture after the object is constructed (requires reflection in some cases).
+
* The game will regularly collect all the net fields reachable from <samp>Game1.netWorldState</samp> 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.'''
   −
==XNB mods and Content Patcher==
+
Suggested fix:
===XNB mods deprecated===
+
* 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 build warnings|''fix common build warnings'']] below.
XNB mods are no longer recommended. Consider using [https://www.nexusmods.com/stardewvalley/mods/1915 Content Patcher] instead.
  −
 
  −
===Impact in 1.3===
  −
Here are the XNB changes in Stardew Valley 1.3.
     −
Notes:
+
===⚠ Location changes for farmhands===
* I ignored changes to non-English files for simplicity.
+
In multiplayer, if the current player isn't the main player:
* New content files aren't listed, since they won't impact existing mods and to avoid spoiling some surprises.
+
* '''<samp>Game1.locations</samp> does not contain the actual list of locations'''. It contains a set of locations generated locally, which don't match the actual in-game locations. This also affects related functionality like <samp>Utility.getAllCharacters()</samp>, which searches the in-game locations. There's no fix for this yet. You can use SMAPI's <samp>helper.Multiplayer.GetActiveLocations()</samp> to get the list of locations currently being sync'd from the host, but there's currently no way to fetch all locations. That means SMAPI mods installed by a non-main player have no way to fetch all NPCs, locations, objects, etc.
* XNB mods are disproportionately affected, since they replace the entire file. Content Patcher packs are typically unaffected unless they replace the entire file (in which case see the XNB mod column).
+
* <samp>Game1.currentLocation</samp> is always an active location, but may be null when the player transition between locations. Make sure any references to that field can handle it being null.
* I don't know what changed in affected map files (if anything), only that the files are different.
     −
Shorthand:
+
===Game1.player.friendships is obsolete===
* 'broken' means removing new content or potentially important changes, or potentially causing significant display bugs. This is a broad category — the game may work fine without it or crash, depending how it uses that specific content.
+
The <samp>Game1.player.friendships</samp> field is always null in Stardew Valley 1.3. Use the new <samp>Game1.player.friendshipData</samp> field instead, which wraps the raw data with a more useful model and more data.
* 'mostly unaffected' means mods will only be affected if they edit specific entries or fields.
  −
* Blank means zero expected impact.
      +
To convert old code:
 
{| class="wikitable"
 
{| class="wikitable"
 +
! old field
 +
! new equivalent
 
|-
 
|-
! content file
+
| <code>Game1.player.friendships[name][0]</code>
! changes
+
| <code>Game1.player.friendshipData[name].Points</code>
! XNB
  −
! Content Patcher
   
|-
 
|-
| <tt>Characters/Dialogue/Abigail</tt>
+
| <code>Game1.player.friendships[name][1]</code>
| new content
+
| <code>Game1.player.friendshipData[name].GiftsThisWeek</code>
| '''✘ broken'''
  −
|
   
|-
 
|-
| <tt>Characters/Dialogue/Alex</tt>
+
| <code>Game1.player.friendships[name][2]</code>
| new content
+
| <code>Game1.player.friendshipData[name].TalkedToToday</code> (0 → false, 1 → true)
| '''✘ broken'''
  −
   
|-
 
|-
| <tt>Characters/Dialogue/Abigail</tt>
+
| <code>Game1.player.friendships[name][3]</code>
| new content
+
| <code>Game1.player.friendshipData[name].GiftsToday</code> (0 → false, 1 → true)
| '''✘ broken'''
+
 
|
+
|}
 +
 
 +
===Texture constructor arguments===
 +
Many constructors which previously accepted <samp>Texture2D texture</samp> arguments now take a <samp>string textureName</samp> 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:Modder Guide/APIs|reflection]]), but don't change the texture name to avoid multiplayer sync issues.
 +
 
 +
===Reserved key bindings===
 +
Mods won't receive input sent to the chatbox, and they won't receive the toggle-chatbox key ({{key|T}} by default).
 +
 
 +
===Reflection===
 +
If you use reflection to access private game code, double-check that the fields/properties/methods you're accessing still match. In particular, watch out for these changes:
 +
* fields/properties changing return type;
 +
* fields replaced by properties.
 +
 
 +
===Overlay objects===
 +
Stardew Valley 1.3 adds an <samp>overlayObjects</samp> field to <samp>GameLocation</samp> instances. These have two special properties:
 +
* They're not synced to other players, so each player has their own overlay objects. (That's used for special quest items, so other players can't take your item.)
 +
* They're positioned on top of the normal object layer. (If there was already an object where the item is placed, the previous object will be hidden until you pick up the overlay object instead of being deleted.)
 +
 
 +
===SMAPI deprecated APIs removed===
 +
Since nearly all SMAPI mods broke in Stardew Valley 1.2, SMAPI 2.6 also drops support for deprecated APIs:
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <tt>Characters/Dialogue/Clint</tt>
+
! since
| new content
+
! interfaces
| '''✘ broken'''
+
! replacement
   
|-
 
|-
| <tt>Characters/Dialogue/Demetrius</tt>
+
| 2.3
| new content
+
| <samp>IReflectionHelper.GetPrivateField</samp><br /><samp>IReflectionHelper.GetPrivateMethod</samp><br /><samp>IReflectionHelper.GetPrivateProperty</samp>
| '''✘ broken'''
+
| renamed to <samp>GetField</samp>, <samp>GetMethod</samp>, and <samp>GetProperty</samp> respectively; their return values have also been renamed (<samp>IPrivateField</samp> → <samp>IReflectedField</samp>, <samp>IPrivateProperty</samp> → <samp>IReflectedProperty</samp>, and <samp>IPrivateMethod</samp> → <samp>IReflectedMethod</samp>).
   
|-
 
|-
| <tt>Characters/Dialogue/Elliott</tt>
+
| 2.3
| new content
+
| <samp>IReflectionHelper.GetPrivateValue</samp>
| '''✘ broken'''
+
| use <samp>GetPrivateField(...).GetValue()</samp> instead.
|
+
|}
 +
 
 +
===SMAPI event changes===
 +
Some SMAPI events were rewritten so they make sense in multiplayer. These also use a new architecture under the hood, so they provide much more useful event data (''e.g.,'' added/removed instead of just current values). The following events have breaking changes:
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <tt>Characters/Dialogue/Emily</tt>
+
! old event
| new content
+
!
| '''✘ broken'''
+
! new event
+
! migration notes
 
|-
 
|-
| <tt>Characters/Dialogue/Evelyn</tt>
+
| <samp>LocationEvents.CurrentLocationChanged</samp>
| new content
+
| &rarr;
| '''✘ broken'''
+
| <samp>PlayerEvents.Warped</samp>
|
+
| &#32;
 +
* Change <samp>EventArgsCurrentLocationChanged</samp> to <samp>EventArgsPlayerWarped</samp>.
 
|-
 
|-
| <tt>Characters/Dialogue/George</tt>
+
| <samp>LocationEvents.LocationsChanged</samp>
| new content
+
|  
| '''✘ broken'''
+
| ''(same name)''
+
| &#32;
 +
* Change <samp>EventArgsGameLocationsChanged</samp> to <samp>EventArgsLocationsChanged</samp>.
 +
* The event is now raised when ''any'' location is added/removed (including building interiors), not just the main world locations in <samp>Game1.locations</samp>. If you need to handle only main world locations, you can check <code>if (Game1.locations.Contains(e.NewLocation))</code>.
 +
* The event data previously contained the current list of locations; it now contains the locations added or removed since the last tick. If you previously used <samp>e.NewLocations</samp>, you can replace it with <samp>Game1.locations</samp>.
 
|-
 
|-
| <tt>Characters/Dialogue/Gus</tt>
+
| <samp>LocationEvents.LocationObjectsChanged</samp>
| new content
+
|
| '''✘ broken'''
+
| <samp>LocationEvents.ObjectsChanged</samp>
+
| &#32;
|-
+
* The event is now raised when objects are added/removed to ''any'' location (including building interiors), not just the current player's location. If you need to handle only the current player's location, you can check <code>if (e.Location == Game1.player.currentLocation)</code>.
| <tt>Characters/Dialogue/Haley</tt>
+
* The event data previously contained the current location's list of objects; it now contains the location, and the objects added/removed in it since the last tick. If you previously used <samp>e.NewObjects</samp>, you can use <samp>e.Location.netObjects.FieldDict</samp> instead.
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Harvey</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Krobus</tt>
  −
| small text change
  −
| ✘ minor issues
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/Dialogue/Leah</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Lewis</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Linus</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/`<br />`MarriageDialogueSebastian</tt>
  −
| small text change
  −
| ✘ minor issues
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/Dialogue/Maru</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Pam</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Penny</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Pierre</tt>
  −
| new content + small text change
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/Dialogue/Robin</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Sam</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Sebastian</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Dialogue/Shane</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Characters/Farmer/hats</tt>
  −
| new sprites at bottom
  −
| '''✘ broken'''
  −
| ✘ impacts new-hat packs
  −
|-
  −
| <tt>Characters/Governor</tt>
  −
| new sprites at bottom
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/Pam</tt>
  −
| new sprites at bottom
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/Penny</tt>
  −
| new sprites in empty slot
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Characters/schedules/Abigail</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Alex</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Caroline</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Clint</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Demetrius</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Elliott</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Emily</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Evelyn</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/George</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Gus</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Haley</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Harvey</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Jas</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Jodi</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Leah</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Lewis</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Linus</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Marnie</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Maru</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Penny</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Pierre</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Robin</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Sam</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Sebastian</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Shane</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Vincent</tt>
  −
| format change
  −
| '''✘ broken'''
  −
|  '''✘ broken'''
  −
|-
  −
| <tt>Characters/schedules/Willy</tt>
  −
| format change
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>Data/BigCraftablesInformation</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Blueprints</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/CraftingRecipies</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Crops</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Events/ArchaeologyHouse</tt>
  −
| minor change
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/Beach</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/BusStop</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Events/Farm</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/FarmHouse</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/Forest</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Events/HaleyHouse</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Events/Mountain</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/Saloon</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Events/SeedShop</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/Town</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/WizardHouse</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Events/Woods</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/ExtraDialogue</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Festivals/fall27</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Festivals/spring13</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Festivals/spring24</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Festivals/summer11</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Festivals/summer28</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Festivals/winter8</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/Fish</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Furniture</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Monsters</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/NPCGiftTastes</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/ObjectInformation</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/Quests</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/animationDescriptions</tt>
  −
| changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Data/hats</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Data/mail</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>LooseSprites/ControllerMaps</tt>
  −
| cosmetic changes
  −
| ✘ minor issues
  −
| ✘ minor issues
  −
|-
  −
| <tt>LooseSprites/Cursors</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>LooseSprites/chatBox</tt>
  −
| significantly changed
  −
| '''✘ broken'''
  −
| '''✘ broken'''
  −
|-
  −
| <tt>LooseSprites/letterBG</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>LooseSprites/map</tt>
  −
| cosmetic changes
  −
| ✘ minor issues
  −
  −
|-
  −
| <tt>Maps/Farm</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/FarmHouse</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/FarmHouse1</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/FarmHouse1_marriage</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/FarmHouse2</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/FarmHouse2_marriage</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Farm_Combat</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Farm_Fishing</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Farm_Foraging</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Farm_Mining</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Railroad</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/Sewer</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/sewerTiles</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Maps/Town</tt>
  −
| unknown changes
  −
| '''✘ broken?'''
  −
| '''✘ broken?'''
  −
|-
  −
| <tt>Maps/fall_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Maps/paths</tt>
  −
| new content
  −
| ✘ minor issues
  −
  −
|-
  −
| <tt>Maps/spring_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Maps/springobjects</tt>
  −
| new content + cosmetic changes
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Maps/summer_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Maps/winter_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Portraits/MrQi</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>SewerTiles</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>Strings/Characters</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Strings/Events</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Strings/Locations</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Strings/Objects</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Strings/StringsFromCSFiles</tt>
  −
| new content
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>Strings/UI</tt>
  −
| new content + changes
  −
| '''✘ broken'''
  −
  −
|-
  −
| <tt>TileSheets/Craftables</tt>
  −
| new content + significant changes<br /><small>([https://i.imgur.com/a2MRcqD.png replaced sprites in red, edited in orange])</small>
  −
| '''✘ broken'''
  −
| '''✘ possibly broken'''
  −
|-
  −
| <tt>TileSheets/crops</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>TileSheets/furniture</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>fall_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>paths</tt>
  −
| new content
  −
| ✘ minor issues
  −
  −
|-
  −
| <tt>spring_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
  −
|-
  −
| <tt>winter_town</tt>
  −
| new content
  −
| '''✘ broken'''
  −
| ✓ mostly unaffected
   
|}
 
|}
 +
 +
===Beneficial changes===
 +
Stardew Valley 1.3 includes several changes which benefit modders. These aren't disruptive, but worth noting for use. Some of the most relevant are...
 +
* Many more methods and properties are now virtual.
 +
* <samp>Game1.WorldDate</samp> is a new field which provides a more useful way to check the date. This combines the day, season, and year with useful logic like day-of-week and date comparisons. This incorporates many of the features from SMAPI's <samp>SDate</samp> class.
 +
* Many type checks now allow subclasses (like <code>item.GetType() == typeof(Axe)</code> &rarr; <code>item is Axe</code>).
 +
* Any <samp>GameLocation</samp> can now set <samp>IsGreenhouse = true</samp>, and crops will grow there all year.
 +
* Any <samp>NPC</samp> can now set <samp>IsSocial</samp> to determine whether they appear in the social menu.
 +
* Bee houses now find nearby flowers in any location, not only when placed on the farm.
 +
* Custom map tilesheets no longer need hacks to avoid the game's seasonal logic. Tilesheets which don't start with a season name and underscore won't be seasonalised.
 +
* Several changes to support upcoming SMAPI features and fixes.
 +
 +
==Fix common build 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 Net{1} to {2}, but Net{1} has unintuitive implicit conversion rules. Consider comparing against the actual value instead to avoid bugs. See https://smapi.io/package/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 <samp>monster.Health</samp> (<samp>int</samp>) instead of <samp>monster.health</samp> (<samp>NetBool</samp>). Change your code to use the suggested property instead.
 +
 +
===FieldName is a Net* field...===
 +
Sample warning: "'''{0}' is a Net{1} field; consider using the {2} property instead. See https://smapi.io/package/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>
 +
<li>For a reference type (''i.e.,'' one that can contain <samp>null</samp>), you can use the <samp>.Value</samp> property (or <samp>.FieldDict</samp> for a <samp>NetDictionary</samp>):
 +
<syntaxhighlight lang="c#">
 +
if (building.indoors.Value == null)
 +
</syntaxhighlight>
 +
 +
Or convert the value before comparison:
 +
<syntaxhighlight lang="c#">
 +
GameLocation indoors = building.indoors.Value;
 +
if(indoors == null)
 +
  // ...
 +
</syntaxhighlight></li>
 +
<li>For a value type (''i.e.,'' one that can't contain <samp>null</samp>), check if the parent is null (if needed) and compare with <samp>.Value</samp>:
 +
<syntaxhighlight lang="c#">
 +
if (item != null && item.category.Value == 0)
 +
</syntaxhighlight></li>
 +
</ul>
 +
 +
===The FieldName field is obsolete...===
 +
Sample warning: "''The 'Character.friendships' field is obsolete and should be replaced with 'friendshipData'. See https://smapi.io/package/avoid-obsolete-field for details.''"
 +
 +
You're referencing a field which should no longer be used. Use the suggested field name instead to fix it.
 +
 +
===An instance of analyzer ... cannot be created===
 +
Update to the latest [https://visualstudio.microsoft.com/vs/community/ Visual Studio]; the NuGet package uses a recent feature that isn't available in older versions.
 +
 +
==FAQs==
 +
===How do I test my code in multiplayer?===
 +
You can test mods in multiplayer on the same computer, by launching two instances of the game:
 +
 +
# Prepare player one:
 +
## Launch SMAPI like usual.
 +
## From the title screen: click ''co-op'', then ''host''.
 +
## Start a new save slot (unless you've already created one). Make sure to set 'starting cabins' to at least one (you'll need one cabin per extra player).
 +
# Prepare player two:
 +
## Launch SMAPI again. (This will automatically create a separate log file.)
 +
## From the title screen: click ''co-op'', then ''join LAN game''.
 +
## Leave the 'Enter IP...' box empty and click OK.
 +
 +
===Why not use implicit net field conversion?===
 +
The migration guide suggests [[#Net fields|avoiding net field implicit conversion]]. This may be the most tedious part of the migration for many mods, and the code compiles fine without doing that, so it's tempting to just skip this step. That's not recommended. Although net field conversions will work fine in most cases, their conversion rules can cause strange bugs in unexpected places. It's better to avoid it altogether, rather than learn all the different cases where they'll cause problems. If you really want, you can [https://smapi.io/package/code-warnings disable the build warnings] and decide for yourself when to use the implicit conversion.
    
[[Category:Modding]]
 
[[Category:Modding]]
105,662

edits

Navigation menu