Skip to content

Commit 81aa6bc

Browse files
committed
fix: update preserve handling and introduce narrowed types, fixes #93
1 parent fa0da1b commit 81aa6bc

File tree

5 files changed

+80
-5
lines changed

5 files changed

+80
-5
lines changed

StardewValleyDecompiled

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 5225ef409e42a6159a82cf81200bf6eb315c9961

codegen/helpers.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@ export const transformJSONItems = <
130130
precision: "Precision" in obj ? obj.Precision : undefined,
131131
}));
132132

133+
export type PreserveLabel =
134+
| "Wine"
135+
| "Jelly"
136+
| "Pickles"
137+
| "Juice"
138+
| "Roe"
139+
| "Aged Roe"
140+
| "Honey"
141+
| "Bait"
142+
| "Dried"
143+
| "Smoked";
144+
133145
interface ArtisanConfig {
134146
filter: (obj: RegularObject) => boolean;
135147
suffix?: string;
@@ -177,7 +189,7 @@ export const createArtisanGoods = (
177189
.find((color) => color !== undefined)
178190
: undefined,
179191
unpreservedItemId: obj._key,
180-
preservedItemName: artisanProduct.name,
192+
preservedItemName: artisanProduct.name as PreserveLabel,
181193
}));
182194

183195
const textureFilter = ["TileSheets", "/", "\\"];

codegen/items.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import type { PreserveLabel } from "./helpers.js";
12
import type { TypeEnum } from "./save.js";
23

34
export interface ItemBase {
@@ -26,7 +27,7 @@ export interface RegularObject extends ItemBase {
2627
tags?: string[];
2728
color?: string;
2829
unpreservedItemId?: string;
29-
preservedItemName?: string;
30+
preservedItemName?: PreserveLabel;
3031
}
3132

3233
export interface BigCraftable extends ItemBase {

codegen/save.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1361,7 +1361,7 @@ export interface Item {
13611361
synchronized?: boolean;
13621362
specialChestType?: SpecialChestType;
13631363
globalInventoryId?: StringContainer;
1364-
preserve?: string;
1364+
preserve?: Preserve;
13651365
preservedParentSheetIndex?: number;
13661366
color?: Color;
13671367
colorSameIndexAsParentSheetIndex?: boolean;
@@ -1547,3 +1547,17 @@ export interface SpecialOrderReward {
15471547
grantedMails?: StringContainer;
15481548
host?: BoolContainer;
15491549
}
1550+
1551+
export enum Preserve {
1552+
Wine = "Wine",
1553+
Jelly = "Jelly",
1554+
Pickle = "Pickle",
1555+
Juice = "Juice",
1556+
Roe = "Roe",
1557+
AgedRoe = "AgedRoe",
1558+
Honey = "Honey",
1559+
Bait = "Bait",
1560+
DriedFruit = "DriedFruit",
1561+
DriedMushroom = "DriedMushroom",
1562+
SmokedFish = "SmokedFish",
1563+
}

src/lib/proxies/Item.svelte.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,64 @@ import {
1313
import type { ParentIndex } from "$lib/ItemParentIndex";
1414
import { Color } from "$lib/proxies/Color.svelte";
1515
import { Sprite } from "$lib/Sprite.svelte";
16+
import type { PreserveLabel } from "$types/helpers";
1617
import {
1718
FurnitureType,
1819
type ItemInformation,
1920
ObjectCategory,
2021
type ToolClass,
2122
} from "$types/items";
22-
import { ClothesType, type Item as ItemModel, TypeEnum } from "$types/save";
23+
import {
24+
ClothesType,
25+
type Item as ItemModel,
26+
Preserve,
27+
TypeEnum,
28+
} from "$types/save";
2329
import { type DataProxy, Raw } from ".";
2430

2531
const nil = { "@_xsi:nil": "true" };
2632

33+
/**
34+
* Stardew serializes `Object.preserve` as an enum name (see `Object.PreserveType`).
35+
* Our generated item metadata historically stored *display labels* like "Smoked" or
36+
* "Pickles", which don't round-trip back into valid save XML.
37+
*/
38+
function normalizePreserveType(
39+
label: PreserveLabel,
40+
outputItemId: string,
41+
): Preserve {
42+
// Common legacy-ish labels from our `generated/iteminfo.json`.
43+
// The game's enum values are:
44+
// Wine, Jelly, Pickle, Juice, Roe, AgedRoe, Honey, Bait, DriedFruit, DriedMushroom, SmokedFish
45+
switch (label) {
46+
case "Pickles":
47+
return Preserve.Pickle;
48+
case "Aged Roe":
49+
return Preserve.AgedRoe;
50+
case "Smoked":
51+
return Preserve.SmokedFish;
52+
case "Dried":
53+
// The game differentiates fruit vs mushroom in the enum.
54+
return outputItemId === "DriedMushrooms"
55+
? Preserve.DriedMushroom
56+
: Preserve.DriedFruit;
57+
case "Wine":
58+
return Preserve.Wine;
59+
case "Jelly":
60+
return Preserve.Jelly;
61+
case "Juice":
62+
return Preserve.Juice;
63+
case "Roe":
64+
return Preserve.Roe;
65+
case "Honey":
66+
return Preserve.Honey;
67+
case "Bait":
68+
return Preserve.Bait;
69+
default:
70+
throw new Error(`Unknown preserve type: ${label}`);
71+
}
72+
}
73+
2774
// Mapping of data types to item types
2875
const typeToItemTypeMap = new Map<ItemInformation["_type"], string>([
2976
["Object", "Object"],
@@ -488,7 +535,7 @@ export class Item implements DataProxy<ItemModel> {
488535
10,
489536
);
490537

491-
item.preserve = data.preservedItemName;
538+
item.preserve = normalizePreserveType(data.preservedItemName, data._key);
492539
}
493540

494541
// Handle colored items (e.g. Wines, Juices)

0 commit comments

Comments
 (0)