Exclude badge items from catalog audit and repair checks
CI / check (push) Successful in 24s
CI / release (push) Skipped
CI / deploy (push) Successful in 1m5s

Badge items use .gif files, not .nitro bundles, so they should not
be flagged as missing .nitro or missing catalog entries. Also add
badge logicType handling in furni-import.ts so badges get the correct
interaction_type when imported.
This commit is contained in:
openhands committed 2026-08-03 21:23:13 +02:00
1 parent 1cbb33a4e2
commit 86d59195ec
4 files changed
+35 -12

No files matched your search

+10 -2
View File
@@ -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({
+1
View File
@@ -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;
+12 -5
View File
@@ -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?.({
+12 -5
View File
@@ -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?.({