Changes

→‎Small changes: remove list of accessibility modifier changes (very incomplete, too many to reasonably list here)
Line 5: Line 5:     
==Done in Stardew Valley {{version|1.3.27}}==
 
==Done in Stardew Valley {{version|1.3.27}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.3]].''
 +
 
===Bug fixes===
 
===Bug fixes===
 
* ☑ Fix strange null handling with net fields (mostly fixed).
 
* ☑ Fix strange null handling with net fields (mostly fixed).
* ☑ Fix bee houses hardcoded to check <tt>Farm</tt> location, instead of their current location.
+
* ☑ Fix bee houses hardcoded to check <samp>Farm</samp> location, instead of their current location.
 
* ☑ On the load menu, clicking the 'back' button clicks the slot under it.
 
* ☑ On the load menu, clicking the 'back' button clicks the slot under it.
* ☑ <tt>Object.getOne()</tt> doesn't copy the 1.2+ fields: <tt>name</tt>, <tt>DisplayName</tt>, <tt>preserve</tt>, <tt>preservedParentSheetIndex</tt>, and <tt>honeyType</tt>.
+
* ☑ <samp>Object.getOne()</samp> doesn't copy the 1.2+ fields: <samp>name</samp>, <samp>DisplayName</samp>, <samp>preserve</samp>, <samp>preservedParentSheetIndex</samp>, and <samp>honeyType</samp>.
    
===Small changes===
 
===Small changes===
* ☑ Include <tt>Stardew Valley.pdb</tt> in the release, so we get line numbers when a crash happens in game code.
+
* ☑ Include <samp>Stardew Valley.pdb</samp> in the release, so we get line numbers when a crash happens in game code.
* ☑ Add a <tt>SerializableDictionary<string, string> CustomData</tt> property to <tt>SaveData</tt>, for SMAPI mods to safely store data.
+
* ☑ Add a <samp>SerializableDictionary<string, string> CustomData</samp> property to <samp>SaveData</samp>, for SMAPI mods to safely store data.
* ☑ Remove <tt>Farmer</tt> namespace (so we don't need to alias the <tt>Farmer</tt> class anymore).
+
* ☑ Remove <samp>Farmer</samp> namespace (so we don't need to alias the <samp>Farmer</samp> class anymore).
* ☑ Make these <tt>Game1</tt> fields protected instead of private: <tt>_debugStringBuilder</tt>, <tt>_fpsList</tt>, <tt>_fpsStopwatch</tt>, <tt>_fps</tt>, <tt>_newDayTask</tt>, <tt>_bgColor</tt>, <tt>screen</tt>, <tt>lightingBlend</tt>, <tt>drawFarmBuildings</tt>, <tt>drawHUD</tt>, <tt>drawDialogueBox</tt>, <tt>drawOverlays</tt>, and <tt>renderScreenBuffer</tt>. That will let SMAPI override the draw loop without reflection calls.
+
* ☑ Make these <samp>Game1</samp> fields protected instead of private: <samp>_debugStringBuilder</samp>, <samp>_fpsList</samp>, <samp>_fpsStopwatch</samp>, <samp>_fps</samp>, <samp>_newDayTask</samp>, <samp>_bgColor</samp>, <samp>screen</samp>, <samp>lightingBlend</samp>, <samp>drawFarmBuildings</samp>, <samp>drawHUD</samp>, <samp>drawDialogueBox</samp>, <samp>drawOverlays</samp>, and <samp>renderScreenBuffer</samp>. That will let SMAPI override the draw loop without reflection calls.
* ☑ Make <tt>LocalizedContentManager.languageCodeString</tt> public. That will let SMAPI override the draw loop without reflection calls.
+
* ☑ Make <samp>LocalizedContentManager.languageCodeString</samp> public. That will let SMAPI override the draw loop without reflection calls.
* ☑ Remove <tt>LocalizedContentManager.LanguageOverride</tt>; it's unused, and that way SMAPI won't need to handle it.
+
* ☑ Remove <samp>LocalizedContentManager.LanguageOverride</samp>; it's unused, and that way SMAPI won't need to handle it.
* ☑ Replace <tt>ChatBox.enableCheats()</tt> with a property.
+
* ☑ Replace <samp>ChatBox.enableCheats()</samp> with a property.
 
* ☑ Make these methods/properties virtual:
 
* ☑ Make these methods/properties virtual:
** ☑ <tt>Item</tt>:
+
** ☑ <samp>Item</samp>:
*** ☑ <tt>canStackWith</tt>
+
*** ☑ <samp>canStackWith</samp>
*** ☑ <tt>CompareTo</tt>
+
*** ☑ <samp>CompareTo</samp>
 
** ☑ LocalizedContentManager:
 
** ☑ LocalizedContentManager:
*** ☑ <tt>CreateTemporary</tt>
+
*** ☑ <samp>CreateTemporary</samp>
*** ☑ <tt>Load(assetName, language)</tt>
+
*** ☑ <samp>Load(assetName, language)</samp>
*** ☑ <tt>LoadBase</tt>
+
*** ☑ <samp>LoadBase</samp>
*** ☑ <tt>CreateTemporary</tt>
+
*** ☑ <samp>CreateTemporary</samp>
*** ☑ <tt>LoadString</tt>
+
*** ☑ <samp>LoadString</samp>
*** ☑ <tt>LoadBaseString</tt>
+
*** ☑ <samp>LoadBaseString</samp>
** ☑ <tt>Buildings/Building</tt>:
+
** ☑ <samp>Buildings/Building</samp>:
*** ☑ <tt>textureName</tt>
+
*** ☑ <samp>textureName</samp>
*** ☑ <tt>resetTexture</tt>
+
*** ☑ <samp>resetTexture</samp>
*** ☑ <tt>showUpgradeAnimation</tt>
+
*** ☑ <samp>showUpgradeAnimation</samp>
*** ☑ <tt>getNameOfNextUpgrade</tt>
+
*** ☑ <samp>getNameOfNextUpgrade</samp>
*** ☑ <tt>showDestroyedAnimation</tt>
+
*** ☑ <samp>showDestroyedAnimation</samp>
*** ☑ <tt>updateInteriorWarps</tt>
+
*** ☑ <samp>updateInteriorWarps</samp>
*** ☑ <tt>drawInConstruction</tt>
+
*** ☑ <samp>drawInConstruction</samp>
** ☑ <tt>Buildings/Stable</tt>:
+
** ☑ <samp>Buildings/Stable</samp>:
*** ☑ <tt>grabHorse</tt>
+
*** ☑ <samp>grabHorse</samp>
** ☑ <tt>Locations/FarmHouse</tt>:
+
** ☑ <samp>Locations/FarmHouse</samp>:
*** ☑ <tt>showSpouseRoom</tt>
+
*** ☑ <samp>showSpouseRoom</samp>
*** ☑ <tt>loadMapForUpgradeLevel</tt>
+
*** ☑ <samp>loadMapForUpgradeLevel</samp>
*** ☑ <tt>setMapForUpgradeLevel</tt>
+
*** ☑ <samp>setMapForUpgradeLevel</samp>
*** ☑ <tt>loadSpouseRoom</tt>
+
*** ☑ <samp>loadSpouseRoom</samp>
** ☑ <tt>Menus/ChatBox</tt>:
+
** ☑ <samp>Menus/ChatBox</samp>:
*** ☑ <tt>textboxEnter</tt>
+
*** ☑ <samp>textboxEnter</samp>
*** ☑ <tt>runCommand</tt> (and mark it protected)
+
*** ☑ <samp>runCommand</samp> (and mark it protected)
*** ☑ <tt>addInfoMessage</tt>
+
*** ☑ <samp>addInfoMessage</samp>
*** ☑ <tt>globalInfoMessage</tt>
+
*** ☑ <samp>globalInfoMessage</samp>
*** ☑ <tt>addErrorMessage</tt>
+
*** ☑ <samp>addErrorMessage</samp>
*** ☑ <tt>listPlayers</tt>
+
*** ☑ <samp>listPlayers</samp>
*** ☑ <tt>showHelp</tt>
+
*** ☑ <samp>showHelp</samp>
*** ☑ <tt>setText</tt>
+
*** ☑ <samp>setText</samp>
*** ☑ <tt>messageColor</tt> (and mark it protected)
+
*** ☑ <samp>messageColor</samp> (and mark it protected)
*** ☑ <tt>receiveChatMessage</tt>
+
*** ☑ <samp>receiveChatMessage</samp>
*** ☑ <tt>addMessage</tt>
+
*** ☑ <samp>addMessage</samp>
** ☑ <tt>Menus/IClickableMenu</tt>:
+
** ☑ <samp>Menus/IClickableMenu</samp>:
*** ☑ <tt>receiveRightClick</tt> (currently abstract)
+
*** ☑ <samp>receiveRightClick</samp> (currently abstract)
** ☑ <tt>Network/NetAudioCueManager</tt>:
+
** ☑ <samp>Network/NetAudioCueManager</samp>:
*** ☑ <tt>Update</tt>
+
*** ☑ <samp>Update</samp>
** ☑ <tt>Objects/Chest</tt>:
+
** ☑ <samp>Objects/Chest</samp>:
*** ☑ <tt>grabItemFromChest</tt>
+
*** ☑ <samp>grabItemFromChest</samp>
*** ☑ <tt>addItem</tt>
+
*** ☑ <samp>addItem</samp>
*** ☑ <tt>grabItemFromInventory</tt>
+
*** ☑ <samp>grabItemFromInventory</samp>
*** ☑ <tt>isEmpty</tt>
+
*** ☑ <samp>isEmpty</samp>
*** ☑ <tt>clearNulls</tt>
+
*** ☑ <samp>clearNulls</samp>
*** ☑ <tt>draw</tt> (last overload)
+
*** ☑ <samp>draw</samp> (last overload)
** ☑ <tt>Objects/Object:</tt>
+
** ☑ <samp>Objects/Object:</samp>
*** ☑ <tt>cutWeed</tt>
+
*** ☑ <samp>cutWeed</samp>
*** ☑ <tt>isAnimalProduct</tt>
+
*** ☑ <samp>isAnimalProduct</samp>
*** ☑ <tt>canBeShipped</tt>
+
*** ☑ <samp>canBeShipped</samp>
*** ☑ <tt>rot</tt>
+
*** ☑ <samp>rot</samp>
*** ☑ <tt>isForage</tt>
+
*** ☑ <samp>isForage</samp>
*** ☑ <tt>initializeLightSource</tt>
+
*** ☑ <samp>initializeLightSource</samp>
*** ☑ <tt>consumeRecipe</tt>
+
*** ☑ <samp>consumeRecipe</samp>
*** ☑ <tt>performUseAction</tt>
+
*** ☑ <samp>performUseAction</samp>
*** ☑ <tt>grabItemFromAutoGrabber</tt>
+
*** ☑ <samp>grabItemFromAutoGrabber</samp>
*** ☑ <tt>farmerAdjacentAction</tt>
+
*** ☑ <samp>farmerAdjacentAction</samp>
*** ☑ <tt>addWorkingAnimation</tt>
+
*** ☑ <samp>addWorkingAnimation</samp>
*** ☑ <tt>drawAsProp</tt>
+
*** ☑ <samp>drawAsProp</samp>
*** ☑ <tt>sellToStorePrice</tt>
+
*** ☑ <samp>sellToStorePrice</samp>
** ☑ <tt>Projectiles/Projectile</tt>:
+
** ☑ <samp>Projectiles/Projectile</samp>:
*** ☑ <tt>update</tt>
+
*** ☑ <samp>update</samp>
** ☑ <tt>TV</tt>
+
** ☑ <samp>TV</samp>
* ☐ <s>Make <tt>Farmer.friendships</tt> internal to avoid confusion (replaced with <tt>friendshipData</tt>)</s> (would require significant changes to how the class is serialised).
+
* ☐ <s>Make <samp>Farmer.friendships</samp> internal to avoid confusion (replaced with <samp>friendshipData</samp>)</s> (would require significant changes to how the class is serialised).
* ☐ <s>Include <tt>Stardew Valley.xml</tt> in the release (if available), so we get code documentation</s> (no code documentation available).
+
* ☐ <s>Include <samp>Stardew Valley.xml</samp> in the release (if available), so we get code documentation</s> (no code documentation available).
    
===Medium changes===
 
===Medium changes===
* ☑ Add <tt>Game1.hooks</tt> to let SMAPI intercept some core game logic.
+
* ☑ Add <samp>Game1.hooks</samp> to let SMAPI intercept some core game logic.
* ☑ Add <tt>Game1.input</tt>, which centralises <tt>Keyboard.GetState()</tt>, <tt>Mouse.GetState()</tt>, and <tt>GamePad.GetState()</tt>.
+
* ☑ Add <samp>Game1.input</samp>, which centralises <samp>Keyboard.GetState()</samp>, <samp>Mouse.GetState()</samp>, and <samp>GamePad.GetState()</samp>.
* ☑ Add a <tt>GameLocation.IsGreenhouse</tt> property, set it to true for the greenhouse, and use it anywhere the game checks <code>.Name.Equals("Greenhouse")</code>. That will let mods add custom indoor locations where crops can grow.
+
* ☑ Add a <samp>GameLocation.IsGreenhouse</samp> property, set it to true for the greenhouse, and use it anywhere the game checks <code>.Name.Equals("Greenhouse")</code>. That will let mods add custom indoor locations where crops can grow.
* ☑ Change <tt>GameLocation.updateSeasonalTilesheets</tt> to enable custom seasonal tilesheets.
+
* ☑ Change <samp>GameLocation.updateSeasonalTilesheets</samp> to enable custom seasonal tilesheets.
* ☑ Instead of hardcoding non-social NPCs in <tt>new SocialMenu(...)</tt>, add a virtual <tt>npc.CanSocialise</tt> field.
+
* ☑ Instead of hardcoding non-social NPCs in <samp>new SocialMenu(...)</samp>, add a virtual <samp>npc.CanSocialise</samp> field.
* ☑ Integrate SMAPI's <tt>SDate</tt> features into the new <tt>WorldDate</tt> (like comparison operators and <tt>DayOfWeek</tt>).
+
* ☑ Integrate SMAPI's <samp>SDate</samp> features into the new <samp>WorldDate</samp> (like comparison operators and <samp>DayOfWeek</samp>).
* ☑ Add events to <tt>NetList</tt> for item added/removed/replaced (similar to the ones <tt>NetDictionary</tt> has). SMAPI will use them to watch for changes in some collections (like player inventory).
+
* ☑ Add events to <samp>NetList</samp> for item added/removed/replaced (similar to the ones <samp>NetDictionary</samp> has). SMAPI will use them to watch for changes in some collections (like player inventory).
    
===Refactoring===
 
===Refactoring===
* ☑ Change static <tt>Multiplayer</tt> class into a <tt>Game1.multiplayer</tt> field so SMAPI can override it, and make its methods non-static and virtual.
+
* ☑ Change static <samp>Multiplayer</samp> class into a <samp>Game1.multiplayer</samp> field so SMAPI can override it, and make its methods non-static and virtual.
 
* ☑ Use interfaces instead of concrete types to let SMAPI/mods override them:
 
* ☑ Use interfaces instead of concrete types to let SMAPI/mods override them:
** ☑ <tt>Farmer</tt>:
+
** ☑ <samp>Farmer</samp>:
*** ☑ <tt>IList&lt;Buff&gt; buffs</tt>
+
*** ☑ <samp>IList&lt;Buff&gt; buffs</samp>
*** ☑ <tt>IList&lt;OutgoingMessage&gt; messageQueue</tt>
+
*** ☑ <samp>IList&lt;OutgoingMessage&gt; messageQueue</samp>
** ☑ <tt>Game1</tt>:
+
** ☑ <samp>Game1</samp>:
*** ☑ <tt>NetBase&lt;IWorldState&gt; netWorldState</tt> (create interface)
+
*** ☑ <samp>NetBase&lt;IWorldState&gt; netWorldState</samp> (create interface)
*** ☑ <tt>IGameServer GameServer</tt> (create interface)
+
*** ☑ <samp>IGameServer GameServer</samp> (create interface)
*** ☑ <tt>ISoundBank soundBank</tt> (create interface with thin wrapper around <tt>SoundBank</tt>)
+
*** ☑ <samp>ISoundBank soundBank</samp> (create interface with thin wrapper around <samp>SoundBank</samp>)
*** ☑ <tt>IList&lt;GameLocation&gt; locations</tt>
+
*** ☑ <samp>IList&lt;GameLocation&gt; locations</samp>
*** ☑ <tt>IList&lt;Item&gt; itemsToShip</tt>
+
*** ☑ <samp>IList&lt;Item&gt; itemsToShip</samp>
*** ☑ <tt>IList&lt;IClickableMenu&gt; onScreenMenus</tt>
+
*** ☑ <samp>IList&lt;IClickableMenu&gt; onScreenMenus</samp>
*** ☑ <tt>IList&lt;DelayedAction&gt; delayedActions</tt>
+
*** ☑ <samp>IList&lt;DelayedAction&gt; delayedActions</samp>
*** ☑ <tt>IDictionary&lt;int, string&gt; objectInformation</tt>
+
*** ☑ <samp>IDictionary&lt;int, string&gt; objectInformation</samp>
*** ☑ <tt>IDictionary&lt;int, string&gt; bigCraftablesInformation</tt>
+
*** ☑ <samp>IDictionary&lt;int, string&gt; bigCraftablesInformation</samp>
*** ☑ <tt>IDictionary&lt;string, string&gt; NPCGiftTastes</tt>
+
*** ☑ <samp>IDictionary&lt;string, string&gt; NPCGiftTastes</samp>
 
* ☑ [http://community.playstarbound.com/threads/multi-language-open-beta-available.130058/page-27#post-3159274 Use <code>Game1.CreateContentManager</code> consistently].
 
* ☑ [http://community.playstarbound.com/threads/multi-language-open-beta-available.130058/page-27#post-3159274 Use <code>Game1.CreateContentManager</code> consistently].
* ☑ Internal changes to <tt>CoopMenu</tt> so SMAPI can hook into it.
+
* ☑ Internal changes to <samp>CoopMenu</samp> so SMAPI can hook into it.
 
* ☑ Replace <code>obj.getType() == type</code> with <code>obj is type</code> to support mod subclasses in various places.
 
* ☑ Replace <code>obj.getType() == type</code> with <code>obj is type</code> to support mod subclasses in various places.
 
* ☐ <s>Update the bundled Mono to the latest version</s> (declined, too big a change).
 
* ☐ <s>Update the bundled Mono to the latest version</s> (declined, too big a change).
Line 121: Line 123:     
==Done in Stardew Valley {{version|1.3.28}}==
 
==Done in Stardew Valley {{version|1.3.28}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.3]].''
 +
 
===Small changes===
 
===Small changes===
* ☑ When creating honey, set <tt>preservedParentSheetIndex</tt> to the flower's item ID.
+
* ☑ When creating honey, set <samp>preservedParentSheetIndex</samp> to the flower's item ID.
* ☑ Make <tt>LoadGameMenu</tt>'s inner classes <tt>public</tt>.
+
* ☑ Make <samp>LoadGameMenu</samp>'s inner classes <samp>public</samp>.
* ☑ Change <tt>ItemGrabMenu.sourceItem</tt> to <tt>public readonly object context</tt>, and track non-objects too. Suggested values:
+
* ☑ Change <samp>ItemGrabMenu.sourceItem</samp> to <samp>public readonly object context</samp>, and track non-objects too. Suggested values:
** <tt>Chest</tt> instance when opening a chest (like current <tt>sourceItem</tt>);
+
** <samp>Chest</samp> instance when opening a chest (like current <samp>sourceItem</samp>);
** auto-grabber / <tt>Mill</tt> / <tt>JunimoHut</tt> instance when viewing their output;
+
** auto-grabber / <samp>Mill</samp> / <samp>JunimoHut</samp> instance when viewing their output;
** <tt>AdventureGuild</tt> / <tt>LibraryMuseum</tt> / <tt>JunimoNoteMenu</tt> / <tt>FishingRod</tt> instance for their rewards;
+
** <samp>AdventureGuild</samp> / <samp>LibraryMuseum</samp> / <samp>JunimoNoteMenu</samp> / <samp>FishingRod</samp> instance for their rewards;
** <tt>Farm.shippingBin</tt> for the shipping bin;
+
** <samp>Farm.shippingBin</samp> for the shipping bin;
** <tt>Item</tt> instance if opened by a method like <tt>addItemByMenuIfNecessary</tt>;
+
** <samp>Item</samp> instance if opened by a method like <samp>addItemByMenuIfNecessary</samp>;
** <tt>null</tt> if not applicable.
+
** <samp>null</samp> if not applicable.
* ☑ Change <tt>GameLocation.IsGreenhouse</tt> to a <tt>{ get; set; }</tt> property, and set it in the location constructor instead.
+
* ☑ Change <samp>GameLocation.IsGreenhouse</samp> to a <samp>{ get; set; }</samp> property, and set it in the location constructor instead.
* ☑ When logging an exception, use <tt>Console.WriteLine(exception.ToString())</tt> instead of <tt>Console.WriteLine(exception.GetType())</tt> + <tt>Console.WriteLine(exception.Message)</tt> + <tt>Console.WriteLine(exception.StackTrace)</tt>. This will let SMAPI detect exception messages more easily.
+
* ☑ When logging an exception, use <samp>Console.WriteLine(exception.ToString())</samp> instead of <samp>Console.WriteLine(exception.GetType())</samp> + <samp>Console.WriteLine(exception.Message)</samp> + <samp>Console.WriteLine(exception.StackTrace)</samp>. This will let SMAPI detect exception messages more easily.
 
* ☑ Make these methods virtual:
 
* ☑ Make these methods virtual:
** ☑ <tt>Character</tt>:
+
** ☑ <samp>Character</samp>:
*** ☑ <tt>checkForFootstep</tt>
+
*** ☑ <samp>checkForFootstep</samp>
** ☑ <tt>Locations\DecoratableLocation</tt>:
+
** ☑ <samp>Locations\DecoratableLocation</samp>:
*** ☑ <tt>isTileOnWall</tt>
+
*** ☑ <samp>isTileOnWall</samp>
*** ☑ <tt>setFloors</tt>
+
*** ☑ <samp>setFloors</samp>
*** ☑ <tt>setWallpapers</tt>
+
*** ☑ <samp>setWallpapers</samp>
*** ☑ <tt>getFloorAt</tt>
+
*** ☑ <samp>getFloorAt</samp>
*** ☑ <tt>getWallForRoomAt</tt>
+
*** ☑ <samp>getWallForRoomAt</samp>
*** ☑ <tt>setFloor</tt>
+
*** ☑ <samp>setFloor</samp>
*** ☑ <tt>getWalls</tt> (and make it non-static)
+
*** ☑ <samp>getWalls</samp> (and make it non-static)
*** ☑ <tt>getFloors</tt> (and make it non-static)
+
*** ☑ <samp>getFloors</samp> (and make it non-static)
    
==Done in Stardew Valley {{version|1.3.32}}==
 
==Done in Stardew Valley {{version|1.3.32}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.3]].''
 +
 
===Small changes===
 
===Small changes===
 
<ul>
 
<ul>
Line 155: Line 161:  
! changes
 
! changes
 
|-
 
|-
| <tt>Multiplayer</tt>
+
| <samp>Multiplayer</samp>
 
| &#32;
 
| &#32;
* Make field protected: <tt>disconnectingFarmers</tt>.
+
* Make field protected: <samp>disconnectingFarmers</samp>.
 
|-
 
|-
| <tt>Network/NetBufferReadStream</tt>,<br /><tt>Network/NetBufferWriteStream</tt>
+
| <samp>Network/NetBufferReadStream</samp>,<br /><samp>Network/NetBufferWriteStream</samp>
 
| &#32;
 
| &#32;
 
* Make classes public.
 
* Make classes public.
 
|-
 
|-
| <tt>Network/LidgrenServer</tt>
+
| <samp>Network/LidgrenServer</samp>
 
| &#32;
 
| &#32;
* Make fields protected: <tt>peers</tt> and <tt>server</tt>.
+
* Make fields protected: <samp>peers</samp> and <samp>server</samp>.
* Make methods protected virtual: <tt>sendMessage(NetConnection, OutgoingMessage)</tt> and <tt>parseDataMessageFromClient</tt>.
+
* Make methods protected virtual: <samp>sendMessage(NetConnection, OutgoingMessage)</samp> and <samp>parseDataMessageFromClient</samp>.
 
|-
 
|-
| <tt>SDKs/GalaxyNetClient</tt>
+
| <samp>SDKs/GalaxyNetClient</samp>
 
| &#32;
 
| &#32;
* make fields protected: <tt>client</tt>.
+
* make fields protected: <samp>client</samp>.
* make methods protected virtual: <tt>onReceiveConnection</tt>, <tt>onReceiveMessage</tt>, <tt>onReceiveDisconnect</tt>, and <tt>onReceiveError</tt>.
+
* make methods protected virtual: <samp>onReceiveConnection</samp>, <samp>onReceiveMessage</samp>, <samp>onReceiveDisconnect</samp>, and <samp>onReceiveError</samp>.
 
|-
 
|-
| <tt>SDKs/GalaxyNetServer</tt>
+
| <samp>SDKs/GalaxyNetServer</samp>
 
| &#32;
 
| &#32;
 
* make class public.
 
* make class public.
* make fields protected: <tt>server</tt> and <tt>peers</tt>.
+
* make fields protected: <samp>server</samp> and <samp>peers</samp>.
* make methods protected virtual: <tt>onReceiveConnection</tt>, <tt>onReceiveMessage</tt>, <tt>onReceiveDisconnect</tt>, <tt>onReceiveError</tt>, and <tt>sendMessage(GalaxyID, OutgoingMessage)</tt>.
+
* make methods protected virtual: <samp>onReceiveConnection</samp>, <samp>onReceiveMessage</samp>, <samp>onReceiveDisconnect</samp>, <samp>onReceiveError</samp>, and <samp>sendMessage(GalaxyID, OutgoingMessage)</samp>.
 
|}</li>
 
|}</li>
<li>☑ Changes to use <tt>IsGreenhouse</tt>:
+
<li>☑ Changes to use <samp>IsGreenhouse</samp>:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 185: Line 191:  
! changes
 
! changes
 
|- valign="top"
 
|- valign="top"
| <tt>Crop.newDay</tt>
+
| <samp>Crop.newDay</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 194: Line 200:  
</syntaxhighlight>
 
</syntaxhighlight>
 
|- valign="top"
 
|- valign="top"
| <tt>HoeDirt.canPlantThisSeedHere</tt>
+
| <samp>HoeDirt.canPlantThisSeedHere</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 203: Line 209:  
</syntaxhighlight>
 
</syntaxhighlight>
 
|- valign="top"
 
|- valign="top"
| <tt>HoeDirt.plant</tt>
+
| <samp>HoeDirt.plant</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 223: Line 229:     
==Done in Stardew Valley {{version|1.4}}==
 
==Done in Stardew Valley {{version|1.4}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.4]].''
 +
 
===Bug fixes===
 
===Bug fixes===
* When a fence is placed, its <tt>maxHealth</tt> is assigned to the same <tt>NetFloat</tt> instance as <tt>health</tt>. This causes the max health to deteriorate over time until the game is reloaded. (To fix it, <code>this.maxHealth = this.health</code> should become <code>this.maxHealth.Value = this.health.Value</code>.)
+
* When a fence is placed, its <samp>maxHealth</samp> is assigned to the same <samp>NetFloat</samp> instance as <samp>health</samp>. This causes the max health to deteriorate over time until the game is reloaded. (To fix it, <code>this.maxHealth = this.health</code> should become <code>this.maxHealth.Value = this.health.Value</code>.)
 
* Fix crash when wearing the [[Jukebox Ring]] (only obtainable via mods) in the mines.
 
* Fix crash when wearing the [[Jukebox Ring]] (only obtainable via mods) in the mines.
* Fix <tt>MineShaft</tt> checking character count instead of monster count, which causes issues like ladders not spawning if a horse is present.
+
* Fix <samp>MineShaft</samp> checking character count instead of monster count, which causes issues like ladders not spawning if a horse is present.
    
===Small changes===
 
===Small changes===
 
<ul>
 
<ul>
 
<li>☑ Add the game version to the save file. (That enables game/mod migrations when loading a save from an older game version.)</li>
 
<li>☑ Add the game version to the save file. (That enables game/mod migrations when loading a save from an older game version.)</li>
<li>☑ Change <tt>Utility.getAllCharacters(List&lt;T&gt;)</tt> to also return the list, to simplify usage.</li>
+
<li>☑ Change <samp>Utility.getAllCharacters(List&lt;T&gt;)</samp> to also return the list, to simplify usage.</li>
 
<li>☑ Tweak accessibility modifiers:
 
<li>☑ Tweak accessibility modifiers:
 
{| class="wikitable"
 
{| class="wikitable"
Line 238: Line 246:  
! changes
 
! changes
 
|-
 
|-
| <tt>InteriorDoor</tt><br /><tt>InteriorDoorDictionary</tt>
+
| <samp>InteriorDoor</samp><br /><samp>InteriorDoorDictionary</samp>
 
| &#32;
 
| &#32;
 
* make classes public.
 
* make classes public.
 
|-
 
|-
| <tt>NPC</tt>
+
| <samp>NPC</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>scheduleTimeToTry</tt>, <tt>NO_TRY</tt>.
+
* make fields public: <samp>scheduleTimeToTry</samp>, <samp>NO_TRY</samp>.
* make methods public: <tt>getTextureName</tt> (also it probably doesn't need to handle the rival anymore).
+
* make methods public: <samp>getTextureName</samp> (also it probably doesn't need to handle the rival anymore).
 
|-
 
|-
| <tt>Locations/GameLocation</tt>
+
| <samp>Locations/GameLocation</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>interiorDoors</tt>.
+
* make fields public: <samp>interiorDoors</samp>.
* make methods public: <tt>reloadMap</tt>, <tt>updateWarps</tt>.
+
* make methods public: <samp>reloadMap</samp>, <samp>updateWarps</samp>.
 
|-
 
|-
| <tt>Menus/GameMenu</tt>
+
| <samp>Menus/GameMenu</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>tabs</tt>, <tt>pages</tt>.
+
* make fields public: <samp>tabs</samp>, <samp>pages</samp>.
 
|-
 
|-
| <tt>Menus/ShopMenu</tt>
+
| <samp>Menus/ShopMenu</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>forSale</tt>, <tt>categoriesToSellHere</tt>, <tt>itemPriceAndStock</tt>, <tt>hoverPrice</tt>, <tt>heldItem</tt>, <tt>hoveredItem</tt>, <tt>currency</tt>, <tt>currentItemIndex</tt>.
+
* make fields public: <samp>forSale</samp>, <samp>categoriesToSellHere</samp>, <samp>itemPriceAndStock</samp>, <samp>hoverPrice</samp>, <samp>heldItem</samp>, <samp>hoveredItem</samp>, <samp>currency</samp>, <samp>currentItemIndex</samp>.
 
|-
 
|-
| <tt>Menus/TitleMenu</tt>
+
| <samp>Menus/TitleMenu</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>birds</tt>, <tt>cloudsTexture</tt>, <tt>titleButtonsTexture</tt>.
+
* make fields public: <samp>birds</samp>, <samp>cloudsTexture</samp>, <samp>titleButtonsTexture</samp>.
 
|-
 
|-
| <tt>Minigames/AbigailGame</tt>
+
| <samp>Minigames/AbigailGame</samp>
 
| &#32;
 
| &#32;
 
* make class public;
 
* make class public;
* make fields public: <tt>storeItems</tt>, <tt>abigailPortraitDuration</tt>, <tt>quit</tt>, <tt>died</tt>, <tt>targetMonster</tt>;
+
* make fields public: <samp>storeItems</samp>, <samp>abigailPortraitDuration</samp>, <samp>quit</samp>, <samp>died</samp>, <samp>targetMonster</samp>;
* make all <tt>CowboyMonster</tt>, <tt>Dracula</tt>, and <tt>Outlaw</tt> fields public.
+
* make all <samp>CowboyMonster</samp>, <samp>Dracula</samp>, and <samp>Outlaw</samp> fields public.
 
|-
 
|-
| <tt>Objects/Fence</tt>
+
| <samp>Objects/Fence</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>fenceTexture</tt>.
+
* make fields public: <samp>fenceTexture</samp>.
 
|-
 
|-
| <tt>SDKs/GalaxyNetClient</tt>
+
| <samp>SDKs/GalaxyNetClient</samp>
 
| &#32;
 
| &#32;
* make field protected: <tt>client</tt>.
+
* make field protected: <samp>client</samp>.
 
|-
 
|-
| <tt>TerrainFeatures/Bush</tt>
+
| <samp>TerrainFeatures/Bush</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>texture</tt>.
+
* make fields public: <samp>texture</samp>.
 
|-
 
|-
| <tt>TerrainFeatures/Tree</tt>
+
| <samp>TerrainFeatures/Tree</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>texture</tt>.
+
* make fields public: <samp>texture</samp>.
 
|}</li>
 
|}</li>
<li>☑ Changes to use <tt>IsGreenhouse</tt>:
+
<li>☑ Changes to use <samp>IsGreenhouse</samp>:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
Line 292: Line 300:  
! changes
 
! changes
 
|- valign="top"
 
|- valign="top"
| <tt>FruitTree.dayUpdate</tt>
+
| <samp>FruitTree.dayUpdate</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 315: Line 323:  
</syntaxhighlight>
 
</syntaxhighlight>
 
|- valign="top"
 
|- valign="top"
| <tt>FruitTree.performUseAction</tt>
+
| <samp>FruitTree.performUseAction</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 324: Line 332:  
</syntaxhighlight>
 
</syntaxhighlight>
 
|- valign="top"
 
|- valign="top"
| <tt>Tree.dayUpdate</tt>
+
| <samp>Tree.dayUpdate</samp>
 
| <syntaxhighlight lang="c#">
 
| <syntaxhighlight lang="c#">
 
// from:
 
// from:
Line 340: Line 348:  
! methods
 
! methods
 
|-
 
|-
| <tt>Game1</tt>
+
| <samp>Game1</samp>
| <tt>_draw</tt>, <tt>drawHUD</tt>, <tt>drawMouseCursor</tt>, <tt>drawOverlays</tt>, <tt>drawWeather</tt>, <tt>renderScreenBuffer</tt>
+
| <samp>_draw</samp>, <samp>drawHUD</samp>, <samp>drawMouseCursor</samp>, <samp>drawOverlays</samp>, <samp>drawWeather</samp>, <samp>renderScreenBuffer</samp>
 
|}</li>
 
|}</li>
 
<li>☑ Remove unused content files:
 
<li>☑ Remove unused content files:
* <tt>Characters/schedules/beforePathfinding/*</tt>;
+
* <samp>Characters/schedules/beforePathfinding/*</samp>;
* <tt>Characters/schedules/newSchedules/*</tt>;
+
* <samp>Characters/schedules/newSchedules/*</samp>;
* <tt>Characters/schedules/spring/*</tt>.
+
* <samp>Characters/schedules/spring/*</samp>.
 
</li>
 
</li>
 
<li>☑ Remove unused code:
 
<li>☑ Remove unused code:
* <tt>TerrainFeatures/DiggableWall</tt>;
+
* <samp>TerrainFeatures/DiggableWall</samp>;
* <tt>TerrainFeatures/TerrainFeatureFactory</tt>.
+
* <samp>TerrainFeatures/TerrainFeatureFactory</samp>.
 
</li>
 
</li>
<li>☑ In <tt>GameLocation.loadObjects</tt>, split the door-finding logic into a separate <tt>updateDoors</tt> method for reuse.</li>
+
<li>☑ In <samp>GameLocation.loadObjects</samp>, split the door-finding logic into a separate <samp>updateDoors</samp> method for reuse.</li>
<li>☑ In <tt>Farmhouse.loadSpouseRoom</tt>, avoid <tt>dictionary.Add</tt> to fix a common crash when a mod has already added that property there.</li>
+
<li>☑ In <samp>Farmhouse.loadSpouseRoom</samp>, avoid <samp>dictionary.Add</samp> to fix a common crash when a mod has already added that property there.</li>
<li>☑ Remove confusing content folder fallback logic in <tt>Game1.Initialize</tt>, where the game looks for a hardcoded Windows path (and usually crashes with a confusing error) if the XACT folder isn't found.</li>
+
<li>☑ Remove confusing content folder fallback logic in <samp>Game1.Initialize</samp>, where the game looks for a hardcoded Windows path (and usually crashes with a confusing error) if the XACT folder isn't found.</li>
 
<li>☑ Load NPC schedules data through a helper function so it's easier to track down schedule load issues.</li>
 
<li>☑ Load NPC schedules data through a helper function so it's easier to track down schedule load issues.</li>
 
</ul>
 
</ul>
Line 361: Line 369:  
* ☑ Change the beehouse logic to allow honey from any hoed-dirt flower, instead of the vanilla subset.
 
* ☑ Change the beehouse logic to allow honey from any hoed-dirt flower, instead of the vanilla subset.
 
* ☑ Fix reharvestable crops always dropping the min number of items, instead of a random number between the min and max values. (Stardew Valley 1.4 also adjusts the crop data so the end result for vanilla crops matches the 1.3.36 behavior.)
 
* ☑ Fix reharvestable crops always dropping the min number of items, instead of a random number between the min and max values. (Stardew Valley 1.4 also adjusts the crop data so the end result for vanilla crops matches the 1.3.36 behavior.)
* ☑ Add an <tt>ICue</tt> interface and change references to <tt>Cue</tt>. That would let SMAPI/mods take control of sounds and music, which is hard to do currently.
+
* ☑ Add an <samp>ICue</samp> interface and change references to <samp>Cue</samp>. That would let SMAPI/mods take control of sounds and music, which is hard to do currently.
 
* ☑ Some XNB files have a separate display name field, but only in non-English. Using display names consistently regardless of language would let mods rename things without breaking keys:
 
* ☑ Some XNB files have a separate display name field, but only in non-English. Using display names consistently regardless of language would let mods rename things without breaking keys:
** ☑ <tt>Data\BigCraftablesInformation</tt>
+
** ☑ <samp>Data\BigCraftablesInformation</samp>
** ☑ <tt>Data\ObjectInformation</tt>
+
** ☑ <samp>Data\ObjectInformation</samp>
* ☑ Consolidate <tt>Crop.harvest</tt> logic so it's consistent between scythe and hand harvesting.
+
* ☑ Consolidate <samp>Crop.harvest</samp> logic so it's consistent between scythe and hand harvesting.
* ☑ Move the <tt>Data\*</tt> loading logic out of the <tt>FarmAnimal</tt> and <tt>NPC</tt> constructors into <tt>reloadData()</tt> methods (so animal/NPC data can be refreshed when the asset changes).
+
* ☑ Move the <samp>Data\*</samp> loading logic out of the <samp>FarmAnimal</samp> and <samp>NPC</samp> constructors into <samp>reloadData()</samp> methods (so animal/NPC data can be refreshed when the asset changes).
 
* ☑ Reload farm animal & NPC data when the save is loaded, to fix inconsistency bugs and simplify mod changes to fields like an NPC's default location.
 
* ☑ Reload farm animal & NPC data when the save is loaded, to fix inconsistency bugs and simplify mod changes to fields like an NPC's default location.
    
==Done in Stardew Valley {{version|1.4.4}}==
 
==Done in Stardew Valley {{version|1.4.4}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.4]].''
 +
 
===Bug fixes===
 
===Bug fixes===
* ☑ <tt>TrashBear.updateItemWanted</tt> is hardcoded to assume <tt>Data\CookingRecipes</tt> field 2 is an item ID, but it can actually be an item ID and count like <tt>272 5</tt> (e.g. see <tt>CraftingRecipe</tt> constructor). That means it crashes if it randomly chooses a recipe with multiple outputs.
+
* ☑ <samp>TrashBear.updateItemWanted</samp> is hardcoded to assume <samp>Data\CookingRecipes</samp> field 2 is an item ID, but it can actually be an item ID and count like <samp>272 5</samp> (e.g. see <samp>CraftingRecipe</samp> constructor). That means it crashes if it randomly chooses a recipe with multiple outputs.
    
==Done in Stardew Valley {{version|1.5}}==
 
==Done in Stardew Valley {{version|1.5}}==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.5]].''
 +
 
===Bug fixes===
 
===Bug fixes===
* ☑ The game handles <tt>this.Window.ClientSizeChanged</tt> unsafely in <tt>Game1</tt>, so the resize logic can run in the middle of a draw/update cycle and [https://smapi.io/log/f29188142be44430a00c802eea75812f cause ObjectDisposedException crashes]. For most players the crash is rare (if they avoid resizing the window while it's loading something), but a minority of players report constant crashes. Proposed fix: when the window resize event is called, set a flag and perform the resize logic on the next update tick instead.
+
* ☑ The game handles <samp>this.Window.ClientSizeChanged</samp> unsafely in <samp>Game1</samp>, so the resize logic can run in the middle of a draw/update cycle and [https://smapi.io/log/f29188142be44430a00c802eea75812f cause ObjectDisposedException crashes]. For most players the crash is rare (if they avoid resizing the window while it's loading something), but a minority of players report constant crashes. Proposed fix: when the window resize event is called, set a flag and perform the resize logic on the next update tick instead.
* ☑ <tt>ItemGrabMenu</tt> exits immediately if it's opened for a chest in another location, unless it's given a null source chest.
+
* ☑ <samp>ItemGrabMenu</samp> exits immediately if it's opened for a chest in another location, unless it's given a null source chest.
* ☑ <tt>Game1.warpFarmer</tt> moves the player when they warp from any location marked <tt>IsGreenhouse</tt> to the farm; it should check <tt>Name == "Greenhouse"</tt> instead to allow for custom greenhouse locations.
+
* ☑ <samp>Game1.warpFarmer</samp> moves the player when they warp from any location marked <samp>IsGreenhouse</samp> to the farm; it should check <samp>Name == "Greenhouse"</samp> instead to allow for custom greenhouse locations.
    
===Small changes===
 
===Small changes===
 
* ☑ Add <code>chest.GetCapacity()</code> method to simplify modded chest sizes.
 
* ☑ Add <code>chest.GetCapacity()</code> method to simplify modded chest sizes.
* ☑ Add a <tt>modData</tt> dictionary field on <tt>Building</tt>, <tt>Character</tt>, <tt>GameLocation</tt>, <tt>Item</tt>, and <tt>TerrainFeature</tt> to store arbitrary mod data that's read/written to the save file and synchronized in multiplayer.
+
* ☑ Add a <samp>modData</samp> dictionary field on <samp>Building</samp>, <samp>Character</samp>, <samp>GameLocation</samp>, <samp>Item</samp>, and <samp>TerrainFeature</samp> to store arbitrary mod data that's read/written to the save file and synchronized in multiplayer.
 
* ☑ In festival maps, allow adding NPC spawns by editing the festival data file instead of patching the characters tilesheet (which is conflict-prone).
 
* ☑ In festival maps, allow adding NPC spawns by editing the festival data file instead of patching the characters tilesheet (which is conflict-prone).
 
* ☑ Add a utility method like <code>Utility.ModifyTime(0600, 70) == 0710</code> to simplify common time math in mod (and game) code.
 
* ☑ Add a utility method like <code>Utility.ModifyTime(0600, 70) == 0710</code> to simplify common time math in mod (and game) code.
* ☑ Tweak accessibility modifiers (all modifiers listed in wishlist done).
+
* ☑ Change the <samp>WarpGreenhouse</samp> action to use the farm warp position, instead of a hardcoded position.
* ☑ Change the <tt>WarpGreenhouse</tt> action to use the farm warp position, instead of a hardcoded position.
   
<ul>
 
<ul>
 
<li>☑ Tweak accessibility modifiers:
 
<li>☑ Tweak accessibility modifiers:
Line 393: Line 404:  
! changes
 
! changes
 
|-
 
|-
| <tt>FarmAnimals\FarmAnimal</tt>
+
| <samp>FarmAnimals\FarmAnimal</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>isEating</tt>.
+
* make fields public: <samp>isEating</samp>.
 
|-
 
|-
| <tt>Monsters\Bat</tt>
+
| <samp>Monsters\Bat</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>cursedDoll</tt>, <tt>hauntedSkull</tt>.
+
* make fields public: <samp>cursedDoll</samp>, <samp>hauntedSkull</samp>.
 
|-
 
|-
| <tt>Menus\CollectionsPage</tt>
+
| <samp>Menus\CollectionsPage</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>currentPage</tt>, <tt>currentTab</tt>, <tt>secretNotesData</tt>, <tt>secretNoteImageTexture</tt>.
+
* make fields public: <samp>currentPage</samp>, <samp>currentTab</samp>, <samp>secretNotesData</samp>, <samp>secretNoteImageTexture</samp>.
 
|-
 
|-
| <tt>Menus\CraftingPage</tt>
+
| <samp>Menus\CraftingPage</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>pagesOfCraftingRecipes</tt>, <tt>_materialContainers</tt>.
+
* make fields public: <samp>pagesOfCraftingRecipes</samp>, <samp>_materialContainers</samp>.
 
|-
 
|-
| <tt>Menus\DialogueBox</tt>
+
| <samp>Menus\DialogueBox</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>dialogues</tt>, <tt>characterDialoguesBrokenUp</tt>, <tt>responses</tt>, <tt>selectedResponse</tt>, <tt>characterDialogue</tt>, <tt>dialogueContinuedOnNextPage</tt>, <tt>dialogueFinished</tt>.
+
* make fields public: <samp>dialogues</samp>, <samp>characterDialoguesBrokenUp</samp>, <samp>responses</samp>, <samp>selectedResponse</samp>, <samp>characterDialogue</samp>, <samp>dialogueContinuedOnNextPage</samp>, <samp>dialogueFinished</samp>.
 
|-
 
|-
| <tt>Menus\LetterViewerMenu</tt>
+
| <samp>Menus\LetterViewerMenu</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>cookingOrCrafting</tt>, <tt>learnedRecipe</tt>, <tt>mailMessage</tt>, <tt>moneyIncluded</tt>, <tt>scale</tt>, <tt>whichBG</tt>.
+
* make fields public: <samp>cookingOrCrafting</samp>, <samp>learnedRecipe</samp>, <samp>mailMessage</samp>, <samp>moneyIncluded</samp>, <samp>scale</samp>, <samp>whichBG</samp>.
* make methods public and virtual: <tt>getTextColor</tt>.
+
* make methods public and virtual: <samp>getTextColor</samp>.
 
|-
 
|-
| <tt>TerrainFeatures\Grass</tt>
+
| <samp>TerrainFeatures\Grass</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>texture</tt>.
+
* make fields public: <samp>texture</samp>.
* make methods public: <tt>textureName</tt>.
+
* make methods public: <samp>textureName</samp>.
 
|-
 
|-
| <tt>AnimatedSprite</tt>
+
| <samp>AnimatedSprite</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>spriteTexture</tt>, <tt>loadedTexture</tt>, <tt>endOfAnimationFunction</tt>.
+
* make fields public: <samp>spriteTexture</samp>, <samp>loadedTexture</samp>, <samp>endOfAnimationFunction</samp>.
 
|-
 
|-
| <tt>CraftingRecipe</tt>
+
| <samp>CraftingRecipe</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>recipeList</tt>, <tt>itemToProduce</tt>, <tt>description</tt>;
+
* make fields public: <samp>recipeList</samp>, <samp>itemToProduce</samp>, <samp>description</samp>;
* make methods virtual: <tt>createItem</tt>, <tt>doesFarmerHaveIngredientsInInventory</tt>, <tt>drawMenuView</tt>, <tt>drawRecipeDescription</tt>, <tt>getCraftableCount</tt>, <tt>getCraftCountText</tt>, <tt>getNumberOfIngredients</tt>.
+
* make methods virtual: <samp>createItem</samp>, <samp>doesFarmerHaveIngredientsInInventory</samp>, <samp>drawMenuView</samp>, <samp>drawRecipeDescription</samp>, <samp>getCraftableCount</samp>, <samp>getCraftCountText</samp>, <samp>getNumberOfIngredients</samp>.
 
|-
 
|-
| <tt>GameLocation</tt>
+
| <samp>GameLocation</samp>
 
| &#32;
 
| &#32;
* make fields public: <tt>critters</tt>.
+
* make fields public: <samp>critters</samp>.
 
|-
 
|-
| <tt>HUDMessage</tt>
+
| <samp>HUDMessage</samp>
 
| &#32;
 
| &#32;
* make methods virtual: <tt>draw</tt>, <tt>update</tt>.
+
* make methods virtual: <samp>draw</samp>, <samp>update</samp>.
 
|}</li>
 
|}</li>
 
</ul>
 
</ul>
Line 445: Line 456:  
* ☑ Add support for specifying NPC gift tastes using item context tags instead of IDs.
 
* ☑ Add support for specifying NPC gift tastes using item context tags instead of IDs.
 
* ☑ Add missing mod NPCs to the game for farmhands too, so they can be summoned in festivals.
 
* ☑ Add missing mod NPCs to the game for farmhands too, so they can be summoned in festivals.
* ☑ Map tilesheets exist in both <tt>Content</tt> and <tt>Content/Maps</tt>, but only the latter are used. Deleting the ones under <tt>Content</tt> would reduce confusion.
+
* ☑ Map tilesheets exist in both <samp>Content</samp> and <samp>Content/Maps</samp>, but only the latter are used. Deleting the ones under <samp>Content</samp> would reduce confusion.
 
* ☑ Get the farmhouse and greenhouse locations from a map property, instead of static values in code. That would let map modders easily move it.
 
* ☑ Get the farmhouse and greenhouse locations from a map property, instead of static values in code. That would let map modders easily move it.
    
==Done in Stardew Valley {{version|1.5.5}}==
 
==Done in Stardew Valley {{version|1.5.5}}==
 +
''See also [[Modding:Migrate to Stardew Valley 1.5.5]].''
 +
 
===Bug fixes===
 
===Bug fixes===
* ☑ <tt>Object.getOne</tt> doesn't copy the <tt>owner</tt> field, so it's not set correctly for most placed items.
+
* ☑ <samp>Object.getOne</samp> doesn't copy the <samp>owner</samp> field, so it's not set correctly for most placed items.
* ☑ In <tt>HoeDirt.seasonUpdate</tt>, change <code>!this.isGreenhouseDirt.Value && base.currentLocation is not IslandLocation</code> to <code>!base.currentLocation.SeedsIgnoreSeasonsHere()</code> so fertilizer doesn't disappear in other locations that ignore seasons.
+
* ☑ In <samp>HoeDirt.seasonUpdate</samp>, change <code>!this.isGreenhouseDirt.Value && base.currentLocation is not IslandLocation</code> to <code>!base.currentLocation.SeedsIgnoreSeasonsHere()</code> so fertilizer doesn't disappear in other locations that ignore seasons.
 
* ☑ Fix rain not watering tilled dirt outside the farm.
 
* ☑ Fix rain not watering tilled dirt outside the farm.
* ☑ Fix some sprites not rendered correctly at large Y tile coordinates (e.g. mailbox after Y=255).
+
* ☑ Fix some sprites not rendered correctly at large Y tile coordinates (e.g. mailbox after Y=155).
 +
* ☑ Fix warp tower on the island ignoring <samp>WarpTotemEntry</samp> farm property.
 +
* ☑ Fix fishing menu crashing if the [[Fishing#Bar Size|bobber bar]] is too big due to stacking every fishing buff.
 +
* ☑ Fix [[The Farm#Grandpa's Shrine|farm shrine]] player interactions checking tile indexes instead of the <samp>GrandpaShrineLocation</samp> [[Modding:Maps|map property]].
 +
* ☑ Fix tile-based seat interactions having higher priority than action property checks.
    
===Small changes===
 
===Small changes===
* ☑ Add a <s><tt>Data/LocationNames</tt> asset or</s> <tt>Data/Festivals/*</tt> field instead of hardcoding specific festival location names in <tt>performTenMinuteClockUpdate</tt> (search for <tt>Game1.cs.2634</tt>).
+
* ☑ Add a <s><samp>Data/LocationNames</samp> asset or</s> <samp>Data/Festivals/*</samp> field instead of hardcoding specific festival location names in <samp>performTenMinuteClockUpdate</samp> (search for <samp>Game1.cs.2634</samp>).
* ☑ Remove unused <tt>BloomComponent</tt>, <tt>BloomSettings</tt>, and all code which references them (this is broken and never enabled).
+
* ☑ Add a <samp>TouchAction Warp</samp> tile property which is identical <samp>TouchAction MagicWarp</samp>, but without the sound/visual effects (see [[.
* ☑ Make the game assembly name (i.e. <tt>Stardew Valley.exe</tt> on Windows and <tt>StardewValley.exe</tt> on Linux/macOS) consistent to simplify crossplatform modding.
+
* ☑ Add map properties <code>IsFarm T</code> and <code>IsGreenhouse T</code> to set the location's <samp>IsFarm</samp> and <samp>IsGreenhouse</samp> properties in <code>GameLocation.loadMap</code> (similar to the existing <code>Outdoors T</code>).
 +
* ☑ Remove unused <samp>BloomComponent</samp>, <samp>BloomSettings</samp>, and all code which references them (this is broken and never enabled).
 +
* ☑ Make the game assembly name (i.e. <samp>Stardew Valley.exe</samp> on Windows and <samp>StardewValley.exe</samp> on Linux/macOS) consistent to simplify crossplatform modding.
 +
* ☑ Remove caching on the farmhouse <samp>KitchenStandingLocation</samp> property to simplify editing it.
 +
* ☑ Include <samp>Stardew Valley.xml</samp> in the release build so we get code documentation.
 +
<ul>
 +
<li>☑ NPCs check the player spouse or NPC relationships with a substring match. That causes issues for mods; e.g. [[Jas]] will show marriage dialogue for a custom Jasper NPC. More specifically:
 +
{| class="wikitable"
 +
|-
 +
! method
 +
! proposed change
 +
|-
 +
| <samp>NPC.loadCurrentDialogue</samp>
 +
| <pre>old: Game1.player.spouse.Contains(base.Name)
 +
new: Game1.player.spouse == base.Name</pre>
 +
|-
 +
| <samp>NPC.performTenMinuteUpdate</samp>
 +
| <pre>old: !dispositions[base.Name].Split('/')[9].Contains(c.Name)
 +
new: !dispositions[base.Name].Split('/')[9].Split(' ').Contains(c.Name)</pre>
 +
|-
 +
| <samp>NPC.tryToReceiveActiveObject</samp>
 +
| <pre>old: !who.spouse.Contains(base.Name)
 +
new: who.spouse != base.Name</pre>
 +
|}
 +
</li>
 +
<li>☑ Make methods virtual:
 +
{| class="wikitable"
 +
|-
 +
! class
 +
! methods
 +
|-
 +
| <samp>BedFurniture</samp>
 +
| <samp>GetBedSpot</samp>
 +
|-
 +
| <samp>Boots</samp>
 +
| <samp>loadDisplayFields</samp>, <samp>onEquip</samp>, <samp>onUnequip</samp>
 +
|-
 +
| <samp>Clothing</samp>
 +
| <samp>Dye</samp>, <samp>GetOtherData</samp>, <samp>LoadData</samp>
 +
|-
 +
| <samp>Crop</samp>
 +
| <samp>draw</samp>, <samp>drawInMenu</samp>, <samp>drawWithOffset</samp>, <samp>getRandomWildCropForSeason</samp>, <samp>getSourceRect</samp>, <samp>growCompletely</samp>, <samp>harvest</samp>, <samp>hitWithHoe</samp>, <samp>InferSeedIndex</samp>, <samp>isWildSeedCrop</samp>, <samp>newDay</samp>, <samp>ResetCropYield</samp>, <samp>ResetPhaseDays</samp>, <samp>updateDrawMath</samp>
 +
|-
 +
| <samp>Fence</samp>
 +
| <samp>CanRepairWithThisItem</samp>, <samp>GetRepairHealthAdjustment</samp>, <samp>loadFenceTexture</samp>, <samp>repair</samp>, <samp>toggleGate</samp>
 +
|-
 +
| <samp>FishTankFurniture</samp>
 +
| <samp>GetCapacityForCategory</samp>
 +
|-
 +
| <samp>Furniture</samp>
 +
| <samp>addLights</samp>, <samp>drawAtNonTileSpot</samp>, <samp>getDefaultBoundingBoxForType</samp>, <samp>getDefaultSourceRectForType</samp>, <samp>GetModifiedWallTilePosition</samp>, <samp>getScaleSize</samp>, <samp>GetSittingDirection</samp>, <samp>GetSittingPosition</samp>, <samp>getTilesWide</samp>, <samp>getTilesHigh</samp>, <samp>HasSittingFarmers</samp>, <samp>isGroundFurniture</samp>, <samp>IsSeatHere</samp>, <samp>IsSittingHere</samp>, <samp>loadDescription</samp>, <samp>lightSourceIdentifier</samp>, <samp>OnAdded</samp>, <samp>removeLights</samp>, <samp>rotate</samp>, <samp>setFireplace</samp>, <samp>updateDrawPosition</samp>, <samp>updateRotation</samp>
 +
|-
 +
| <samp>FruitTree</samp>
 +
| <samp>shake</samp>
 +
|-
 +
| <samp>MeleeWeapon</samp>
 +
| <samp>defaultKnockBackForThisType</samp>, <samp>DoDamage</samp>, <samp>getItemLevel</samp>, <samp>isScythe</samp>, <samp>RecalculateAppliedForges</samp>, <samp>drawDuringUse</samp>
 +
|-
 +
| <samp>Object</samp>
 +
| <samp>countsForShippedCollection</samp>, <samp>getPriceAfterMultipliers</samp>, <samp>getScale</samp>, <samp>isSapling</samp>
 +
|-
 +
| <samp>StorageFurniture</samp>
 +
| <samp>ShowShopMenu</samp>, <samp>SortItems</samp>
 +
|}
 +
</li>
    
===Medium changes===
 
===Medium changes===
* ☑ Get the spouse room offset from <s><tt>Data/NPCDispositions</tt></s> a new <tt>Data/spouseRooms</tt> asset, instead of hardcoding it in <tt>FarmHouse.loadSpouseRoom</tt>.
+
* ☑ Move hardcoded scarecrow logic from <samp>Farm.addCrows</samp> into new <samp>Object.IsScarecrow()</samp> and <samp>Object.GetRadiusForScarecrow()</samp> methods.
* ☑ Call <tt>Game1.hooks.OnGameLocation_CheckAction</tt> from overridden <tt>checkAction</tt> methods too, not only the base one.
+
* ☑ Get the spouse room offset from <s><samp>Data/NPCDispositions</samp></s> a new <samp>Data/spouseRooms</samp> asset, instead of hardcoding it in <samp>FarmHouse.loadSpouseRoom</samp>.
 +
* ☑ Call <samp>Game1.hooks.OnGameLocation_CheckAction</samp> from overridden <samp>checkAction</samp> methods too, not only the base one.
    
===Refactoring===
 
===Refactoring===
 +
* ☑ The farmhouse walls are hardcoded in <code>FarmHouse.getWalls</code>; moving those into a content file would make custom renovations and layouts much easier.
 
* ☑ Make the game framework (i.e. XNA Framework on Windows and MonoGame on Linux/macOS) consistent to simplify crossplatform modding.
 
* ☑ Make the game framework (i.e. XNA Framework on Windows and MonoGame on Linux/macOS) consistent to simplify crossplatform modding.
 +
 +
==Done in Stardew Valley {{version|1.5.6}}==
 +
===Bug fixes===
 +
* ☑ Fix crash in <samp>GameLocation.getTileIndexAt(Point p, string layer)</samp> if the layer is missing (which currently affects custom spouse rooms due to 1.5.5 adding a new layer).
 +
* ☑ Fix [[Modding:Custom languages|custom language]] time format's <samp>HOURS_24_00</samp> incorrectly wrapping at 12.
 +
* ☑ Fix custom spouse room stand positions ignored due to <samp>ApplyMapOverride</samp> creating layer with wrong size.
 +
 +
===Small changes===
 +
* ☑ Fix <samp>Stardew Valley.dll</samp> no longer having a unique build number in the version after Stardew Valley 1.5.5.
 +
 +
==Done in Stardew Valley {{version|1.6}} (upcoming)==
 +
: ''See also [[Modding:Migrate to Stardew Valley 1.6]] for the full list of modding changes in 1.6.''
 +
 +
===Small changes===
 +
* ☑ Change all remaining <code>internal class</code> and <code>private class</code> to <code>public class</code> to simplify mod access.
 +
* ☑ Change <code>Utility.isMale(name)</code> to check the NPC info instead of a hardcoded switch, so it works with custom NPCs.
 +
* ☑ Change <samp>IslandLocation.DrawParallaxHorizon</samp> to support custom sunset times that aren't on the hour, by using <samp>Utility.CalculateMinutesBetweenTimes</samp> instead of calculating the time manually.
 +
* ☑ Remove <samp>Woods.stumps</samp> and use the new <samp>location.resourceClumps</samp> field instead.
 +
* ☑ Tweak accessibility modifiers. <small>(Stardew Valley 1.6 marks a large number of methods <samp>virtual</samp> and <samp>public</samp>/<samp>protected</samp>, too many to list here.)</small>
 +
 +
===Medium changes===
 +
* ☑ Some XNB files have a separate display name field, but only in non-English. Using display names consistently regardless of language would let mods rename things without breaking keys:
 +
** ☑ <samp>Data\Boots</samp>
 +
** ☑ <samp>Data\Bundles</samp>
 +
** ☑ <samp>Data\CraftingRecipes</samp>
 +
** ☑ <samp>Data\CookingRecipes</samp>
 +
** ☑ <samp>Data\Furniture</samp>
 +
** ☑ <samp>Data\Weapons</samp>
 +
* ☑ Remove hardcoded logic that ignores display names when playing in English (e.g. for NPC gift taste dialogues). That causes a bug where renamed NPCs still show their internal name in some places.
 +
 +
===Refactoring===
 +
* ☑ Add unique item keys and allow custom spritesheets per item. This would eliminate the current complexities with adding custom items to Stardew Valley, make code much more readable, simplify troubleshooting mod errors, and make it possible to support any item type in cases like sending mail. See the [https://gist.github.com/Pathoschild/92d1fcb7c2ffeb7e1461c242cdb025e2 detailed proposal doc].
 +
* ☑ Move shop inventories into a data asset so mods can easily change them (e.g. <code>"<shop id>": "item_id quantity_available [required_mail_flag]/..."</code>).
    
[[Category:Modding]]
 
[[Category:Modding]]
translators
8,445

edits