diff --git a/src/common/rpg/components/equipment.ts b/src/common/rpg/components/equipment.ts index 1532d3b..13764a7 100644 --- a/src/common/rpg/components/equipment.ts +++ b/src/common/rpg/components/equipment.ts @@ -34,7 +34,7 @@ interface SlotRecord { } interface EquipmentState { - slots: SlotRecord[]; + slots: Record; } export type SlotInput = @@ -46,17 +46,17 @@ export class Equipment extends Component { #cachedVars: RPGVariables | null = null; constructor(slots: SlotInput[]) { - super({ - slots: slots.map(s => { - const slotName = typeof s === 'string' ? s : s.slotName; - const type = typeof s === 'object' && s.type ? s.type : null; - return { slotName, type, itemId: null, appliedEffectKeys: [] }; - }), - }); + const record: Record = {}; + for (const s of slots) { + const slotName = typeof s === 'string' ? s : s.slotName; + const type = typeof s === 'object' && s.type ? s.type : null; + record[slotName] = { slotName, type, itemId: null, appliedEffectKeys: [] }; + } + super({ slots: record }); } #slot(slotName: string): SlotRecord | undefined { - return this.state.slots.find(s => s.slotName === slotName); + return this.state.slots[slotName]; } /** ItemId in the named slot, or null if empty. */ @@ -71,7 +71,7 @@ export class Equipment extends Component { */ findCompatibleSlot(slotType: string): string | null { let genericFallback: string | null = null; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.itemId !== null) continue; if (slot.type === null) { genericFallback ??= slot.slotName; continue; } if (slot.type === slotType) return slot.slotName; @@ -81,7 +81,7 @@ export class Equipment extends Component { /** All currently equipped `{ slotName, itemId }` pairs. */ getEquipped(): { slotName: string; itemId: string }[] { - return this.state.slots + return Object.values(this.state.slots) .filter((s): s is SlotRecord & { itemId: string } => s.itemId !== null) .map(({ slotName, itemId }) => ({ slotName, itemId })); } @@ -154,7 +154,7 @@ export class Equipment extends Component { if (this.#cachedVars) return this.#cachedVars; const result: RPGVariables = {}; - for (const { slotName, itemId } of this.state.slots) { + for (const { slotName, itemId } of Object.values(this.state.slots)) { result[slotName] = itemId ?? ''; } this.#cachedVars = result; diff --git a/src/common/rpg/components/inventory.ts b/src/common/rpg/components/inventory.ts index eea3216..ee33b78 100644 --- a/src/common/rpg/components/inventory.ts +++ b/src/common/rpg/components/inventory.ts @@ -15,29 +15,25 @@ interface SlotRecord { interface InventoryState { infinite: boolean; nextSlotId: number; // auto-increment counter for infinite mode - slots: SlotRecord[]; + slots: Record; } function buildInventoryState(input?: number | InventorySlotInput[]): InventoryState { if (input === undefined) { - return { infinite: true, nextSlotId: 0, slots: [] }; + return { infinite: true, nextSlotId: 0, slots: {} as Record }; } if (typeof input === 'number') { - return { - infinite: false, - nextSlotId: 0, - slots: Array.from({ length: input }, (_, i) => ({ slotId: i, limit: undefined, contents: null })), - }; + const slots = {} as Record; + for (let i = 0; i < input; i++) slots[i] = { slotId: i, limit: undefined, contents: null }; + return { infinite: false, nextSlotId: 0, slots }; } - return { - infinite: false, - nextSlotId: 0, - slots: input.map(def => ({ - slotId: typeof def === 'object' ? def.slotId : def, - limit: typeof def === 'object' ? def.limit : undefined, - contents: null, - })), - }; + const slots = {} as Record; + for (const def of input) { + const slotId = typeof def === 'object' ? def.slotId : def; + const limit = typeof def === 'object' ? def.limit : undefined; + slots[slotId] = { slotId, limit, contents: null }; + } + return { infinite: false, nextSlotId: 0, slots }; } @component @@ -55,7 +51,7 @@ export class Inventory extends Component { } #slot(slotId: SlotId): SlotRecord | undefined { - return this.state.slots.find(s => s.slotId === slotId); + return this.state.slots[slotId]; } #capFor(slot: SlotRecord, itemId: string): number { @@ -94,7 +90,7 @@ export class Inventory extends Component { // ── Finite inventory: two-phase (check → apply) ─────────────────────── if (!this.state.infinite) { let canFit = 0; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents === null || slot.contents.itemId === itemId) canFit += this.#roomFor(slot, itemId); } @@ -102,7 +98,7 @@ export class Inventory extends Component { let remaining = amount; const slotIds: SlotId[] = []; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents?.itemId === itemId && remaining > 0) { const take = Math.min(this.#roomFor(slot, itemId), remaining); slot.contents!.amount += take; @@ -110,7 +106,7 @@ export class Inventory extends Component { slotIds.push(slot.slotId); } } - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents === null && remaining > 0) { const take = Math.min(this.#capFor(slot, itemId), remaining); slot.contents = { itemId, amount: take }; @@ -126,7 +122,7 @@ export class Inventory extends Component { let remaining = amount; const slotIds: SlotId[] = []; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents?.itemId === itemId && remaining > 0) { const take = Math.min(this.#roomFor(slot, itemId), remaining); if (take > 0) { @@ -136,7 +132,7 @@ export class Inventory extends Component { } } } - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents === null && remaining > 0) { const take = Math.min(this.#capFor(slot, itemId), remaining); slot.contents = { itemId, amount: take }; @@ -146,7 +142,7 @@ export class Inventory extends Component { } while (remaining > 0) { const newSlot: SlotRecord = { slotId: this.state.nextSlotId++, limit: undefined, contents: null }; - this.state.slots.push(newSlot); + this.state.slots[newSlot.slotId] = newSlot; const take = Math.min(this.#capFor(newSlot, itemId), remaining); newSlot.contents = { itemId, amount: take }; remaining -= take; @@ -177,7 +173,7 @@ export class Inventory extends Component { let remaining = amount; const slotIds: SlotId[] = []; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents?.itemId === itemId && remaining > 0) { const take = Math.min(slot.contents.amount, remaining); slot.contents.amount -= take; @@ -290,7 +286,7 @@ export class Inventory extends Component { return slot?.contents?.itemId === itemId ? slot.contents.amount : 0; } let total = 0; - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents?.itemId === itemId) total += slot.contents.amount; } return total; @@ -298,7 +294,7 @@ export class Inventory extends Component { getItems(): Map { const result = new Map(); - for (const slot of this.state.slots) { + for (const slot of Object.values(this.state.slots)) { if (slot.contents) { const { itemId, amount } = slot.contents; result.set(itemId, (result.get(itemId) ?? 0) + amount);