Skip to content

Instantly share code, notes, and snippets.

@Pathoschild
Last active Oct 23, 2021
Embed
What would you like to do?
Stardew Valley item key proposal

Custom items are a common goal for new mod authors, but they're one of the hardest things to do because the game uses the item spritesheet index as the ID. That means IDs need to fit within the spritesheet's max size, and mods can't avoid conflicts with other mods without complex workarounds like Json Assets and Dynamic Game Assets (which add their own problems and limitations).

This proposal solves that by giving each item a string UniqueKey, and allowing custom spritesheets per item. That also avoids needing to check item types in most code, since there's no longer any possible ID overlap.

Goals

This proposal aims to...

  • minimize changes needed in the game code where possible;
  • maximize compatibility with existing content packs where possible;
  • allow item keys anywhere that currently uses the parent sheet index;
  • let mods add items without Harmony or complex frameworks;
  • let mods add any number of custom items without key or sprite index conflicts.

Changes to C# code

Item class

The Item class has two new fields:

name type description
ParentSheet Texture2D The spritesheet texture to draw (e.g. Game1.objectSpriteSheet for a vanilla object).
UniqueKey string A globally unique string key for the item, like radish_salad (vanilla item) or Pathoschild.ExampleMod_watermelon (mod item). This is assumed to only contain characters [a-zA-Z_.], so it can be used in fields delimited with spaces/slashes/commas, filenames, etc.

The ParentSheetIndex field is unchanged, except that it targets ParentSheet instead of a global texture (which would be the same for vanilla items).

Creating items

Creating an item would be the same as before, except that it'd take the key instead of the spritesheet index. For example:

new Object("634", 1); // 634 = unique key for apricot (see changes to data assets below)
new Object("Pathoschild.ExampleMod_watermelon", 1);

new Furniture("groovy_chair", Vector2.Zero);

The game would ideally provide a method to get any item by its key too (which would enable things like sending non-object items through the mail):

Item item = Game1.getItemByKey("groovy_chair");

Item references

Most item references would use the key instead. For example:

old code new code
item.ParentSheetIndex == 848 item.UniqueKey == "848"
IsNormalObjectAtParentSheetIndex(item, 74) item.UniqueKey == "74"
!item.bigCraftable && item.ParentSheetIndex == this.wantedIndex item.UniqueKey == this.wantedKey
item is Boots && item.ParentSheetIndex == 505 item.UniqueKey == "rubber_boots"

Changes to data assets

Assets which define an item

This section applies to:

  • Data/BigCraftablesInformation
  • Data/Boots
  • Data/ClothingInformation
  • Data/Crops
  • Data/Fish
  • Data/FruitTrees
  • Data/Furniture
  • Data/Hats
  • Data/ObjectInformation
  • Data/weapons

These all have two new fields:

field description
ParentSheetIndex (optional for objects) The item's index in the spritesheet. (For Data/ObjectInformation only: defaults to the unique key if numeric, else 0.)
ParentSheet (optional) The item spritesheet's asset name under Maps. Defaults to the vanilla spritesheet for that item type.

Data/ObjectInformation is identical for vanilla items, while custom items can use the new fields:

"634": "Apricot/50/15/Basic -79/Apricot/A tender little fruit with a rock-hard pit.",
"Pathoschild.ExampleMod_watermelon": "Watermelon/300/10/Basic -79/Watermelon/Takes 28 days to grow. Plant in summer./3/Pathoschild.ExampleMod_objectSprites"

Unfortunately non-objects can't use the same trick, since their unique keys would overlap with object keys. These have a unique key based on the name instead. For example, in Data/Furniture:

"groovy_chair": "Groovy Chair/chair/-1/-1/4/750/82"

Assets which reference an item

These now reference the unique key instead of the parent sheet index. Since those are the same for objects, many assets are unchanged.

For example, here's from Data/NPCDispositions with one custom item:

Universal_Like: "-2 -7 -26 -75 -80 72 395 613 634 635 636 637 638 724 459 Pathoschild.ExampleMod_watermelon"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment