diff --git a/src/lib/services/catalog-audit.ts b/src/lib/services/catalog-audit.ts index 843e353c..a62e060e 100644 --- a/src/lib/services/catalog-audit.ts +++ b/src/lib/services/catalog-audit.ts @@ -154,16 +154,18 @@ export async function runCatalogAudit( item_name: string; public_name: string; type: string; + interaction_type: string; }>; try { const [rows] = (await db.execute(sql` - SELECT id, item_name, public_name, type FROM items_base ORDER BY id + SELECT id, item_name, public_name, type, interaction_type FROM items_base ORDER BY id `)) as unknown as [ Array<{ id: number; item_name: string; public_name: string; type: string; + interaction_type: string; }>, unknown, ]; @@ -242,7 +244,11 @@ export async function runCatalogAudit( }); // Only include items that actually have a .nitro asset — a catalog // entry for a furni without a bundle would be un-placeable in-game. - if (nitroSet.has(`${item.item_name}.nitro`)) { + // Badge items use .gif files, not .nitro bundles. + if ( + item.interaction_type !== "badge" && + nitroSet.has(`${item.item_name}.nitro`) + ) { missingCatalogEntries.push({ classname: item.item_name, itemId: item.id, @@ -311,6 +317,8 @@ export async function runCatalogAudit( const missingNitroClassnames: string[] = []; for (let i = 0; i < items.length; i++) { const item = items[i]; + // Badge items use .gif files, not .nitro bundles. + if (item.interaction_type === "badge") continue; if (!nitroSet.has(`${item.item_name}.nitro`)) { missingNitroClassnames.push(item.item_name); issues.push({ diff --git a/src/lib/services/furni-import.ts b/src/lib/services/furni-import.ts index 66dc0d04..ab3f626d 100644 --- a/src/lib/services/furni-import.ts +++ b/src/lib/services/furni-import.ts @@ -620,6 +620,7 @@ export async function importSingleFurni(params: { else if (logicType.includes("exchange")) interactionType = "exchange"; else if (logicType.includes("habbowheel")) interactionType = "habbowheel"; else if (logicType.includes("soundmachine")) interactionType = "jukebox"; + else if (logicType.includes("badge")) interactionType = "badge"; if (interactionType === "default" && /^wf_/.test(classname)) { interactionType = classname; diff --git a/src/lib/services/repair-icons.ts b/src/lib/services/repair-icons.ts index fa81ad13..1651b0cc 100644 --- a/src/lib/services/repair-icons.ts +++ b/src/lib/services/repair-icons.ts @@ -140,11 +140,14 @@ export async function repairMissingIcons( ...targets.mirrorDirs.map((d) => d.nitroDir), ]); - let items: Array<{ id: number; item_name: string }>; + let items: Array<{ id: number; item_name: string; interaction_type: string }>; try { const [rows] = (await db.execute(sql` - SELECT id, item_name FROM items_base ORDER BY id - `)) as unknown as [Array<{ id: number; item_name: string }>, unknown]; + SELECT id, item_name, interaction_type FROM items_base ORDER BY id + `)) as unknown as [ + Array<{ id: number; item_name: string; interaction_type: string }>, + unknown, + ]; items = rows; } catch (err) { onEvent?.({ @@ -157,7 +160,11 @@ export async function repairMissingIcons( const total = items.length; onEvent?.({ type: "started", total }); - const processItem = async (classname: string) => { + const processItem = async (classname: string, interactionType: string) => { + // Badge items use .gif icons, not .png icons. + if (interactionType === "badge") { + return { status: "skipped" } as const; + } const fileName = `${classname}_icon.png`; // A dir may already have the icon (e.g. the full gamedata) while the @@ -326,7 +333,7 @@ export async function repairMissingIcons( await runPool(items, REPAIR_CONCURRENCY, async (item, i) => { const classname = item.item_name; - const result = await processItem(classname); + const result = await processItem(classname, item.interaction_type); if (result.status === "skipped") { skipped++; onEvent?.({ diff --git a/src/lib/services/repair-nitros.ts b/src/lib/services/repair-nitros.ts index 8717402d..235f74a3 100644 --- a/src/lib/services/repair-nitros.ts +++ b/src/lib/services/repair-nitros.ts @@ -136,11 +136,14 @@ export async function repairMissingNitros( ...targets.mirrorDirs.map((d) => d.nitroDir), ]); - let items: Array<{ id: number; item_name: string }>; + let items: Array<{ id: number; item_name: string; interaction_type: string }>; try { const [rows] = (await db.execute(sql` - SELECT id, item_name FROM items_base ORDER BY id - `)) as unknown as [Array<{ id: number; item_name: string }>, unknown]; + SELECT id, item_name, interaction_type FROM items_base ORDER BY id + `)) as unknown as [ + Array<{ id: number; item_name: string; interaction_type: string }>, + unknown, + ]; items = rows; } catch (err) { onEvent?.({ @@ -153,7 +156,11 @@ export async function repairMissingNitros( const total = items.length; onEvent?.({ type: "started", total }); - const processItem = async (classname: string) => { + const processItem = async (classname: string, interactionType: string) => { + // Badge items use .gif files, not .nitro bundles. + if (interactionType === "badge") { + return { status: "skipped" } as const; + } const fileName = `${classname}.nitro`; const presentDirs = nitroDirs.filter((dir) => @@ -259,7 +266,7 @@ export async function repairMissingNitros( await runPool(items, REPAIR_CONCURRENCY, async (item, i) => { const classname = item.item_name; - const result = await processItem(classname); + const result = await processItem(classname, item.interaction_type); if (result.status === "skipped") { skipped++; onEvent?.({