Line 32: |
Line 32: |
| * [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record record structs]; | | * [https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/record record structs]; |
| * and support for ARM64 on macOS. | | * and support for ARM64 on macOS. |
| + | |
| + | ===Hash set fields=== |
| + | For C# mod authors, the game now uses [https://www.bytehide.com/blog/hashset-csharp hash sets] for many list fields which expect unique values. That allows much more efficient O(1) read/write, prevents duplicate values, and simplifies common logic. |
| + | |
| + | This affects: |
| + | {| class="wikitable" |
| + | |- |
| + | ! type |
| + | ! fields |
| + | |- |
| + | | <samp>Farmer</samp> |
| + | | <samp>achievements</samp><br /><samp>dialogueQuestionsAnswered</samp><br /><samp>eventsSeen</samp><br /><samp>mailbox</samp><br /><samp>mailForTomorrow</samp><br /><samp>mailReceived</samp><br /><samp>professions</samp><br /><samp>secretNotesSeen</samp><br /><samp>songsHeard</samp> |
| + | |- |
| + | | <samp>FarmerTeam</samp> |
| + | | <samp>broadcastedMail</samp> |
| + | |} |
| + | |
| + | Usage is very similar, and many list methods like <samp>Contains</samp> work the same way with hash sets. Here are the main differences: |
| + | <ul> |
| + | <li>Hash sets aren't ordered. For example, there's no guarantee that the first value when you enumerate it was the earliest one added.</li> |
| + | <li><p>Hash sets can't be indexed. For example, you can no longer use <code>list[0]</code> to get the first value. You can still enumerate them, but in most cases you should use methods like <samp>Add</samp> or <samp>Contains</samp> instead.</p> |
| + | |
| + | To remove multiple matching values from the set, you can use <samp>RemoveWhere</samp> instead: |
| + | <syntaxhighlight lang="c#"> |
| + | // old code |
| + | for (int i = Game1.player.mailbox.Count - 1; i >= 0; i--) |
| + | { |
| + | if (Game1.player.mailbox[i].StartsWith("Example.ModId_")) |
| + | Game1.player.mailbox.RemoveAt(i); |
| + | } |
| + | |
| + | // new code |
| + | Game1.player.mailbox.RemoveWhere(id => id.StartsWith("Example.ModId_")); |
| + | </syntaxhighlight> |
| + | |
| + | The game also adds a <samp>Peek()</samp> extension in the <samp>StardewValley.Extensions</samp> namespace to get the first value that would be enumerated. This is equivalent to the previous <samp>list[0]</samp>, except that the order may change when a value is added or removed. |
| + | </li> |
| + | <li>You no longer need to check before adding a value, since the hash set will ignore duplicates.</li> |
| + | <li>The <samp>Add</samp> or <samp>Remove</samp> values return whether a value was added/removed, which lets you check at the same time. For example: |
| + | <syntaxhighlight lang="c#"> |
| + | if (Game1.player.mailReceived.Add("BackpackTip")) // returns true if it wasn't in the set yet |
| + | Game1.addMailForTomorrow("pierreBackpack"); |
| + | </syntaxhighlight> |
| + | </li> |
| + | </ul> |
| | | |
| ==What's new for items== | | ==What's new for items== |