fix(catalog): check source assets and offer reachable import alternatives
This commit is contained in:
1 parent
8c1efae296
commit
159b1f7d1b
10 files changed
+646
-56
No files matched your search
@@ -619,45 +619,6 @@ export async function importSingleFurni(params: {
|
||||
const bestRevision = revision || officialHabbo?.revision || 0;
|
||||
const bestCategory = category || officialHabbo?.category || "unknown";
|
||||
|
||||
// ── Insert into DB with enriched data ──────────────────────────────
|
||||
onProgress?.("writing_db");
|
||||
try {
|
||||
if (preservingExisting) {
|
||||
warnings.push(
|
||||
`Existing furniture #${itemId}: SQL settings and catalog offers preserved`,
|
||||
);
|
||||
} else if (isUpdate) {
|
||||
// NOTE: live Arcturus `items_base` has no description/revision/rare columns —
|
||||
// those metadata fields are persisted in FurnitureData.json (see entry below),
|
||||
// not in the DB. Only refresh the columns this import manages.
|
||||
await db.execute(sql`
|
||||
UPDATE items_base SET sprite_id = ${spriteId}, public_name = ${bestName}, item_name = ${classname}, type = ${itemType}
|
||||
WHERE id = ${spriteId}
|
||||
`);
|
||||
} else {
|
||||
itemId = await reserveFurnitureId(
|
||||
originalId,
|
||||
classname,
|
||||
async (allocatedId) => {
|
||||
await db.execute(
|
||||
sql`INSERT INTO items_base (id, sprite_id, public_name, item_name, type) VALUES (${allocatedId}, ${allocatedId}, ${bestName}, ${classname}, ${itemType})`,
|
||||
);
|
||||
},
|
||||
);
|
||||
spriteId = itemId;
|
||||
if (spriteId !== originalId)
|
||||
warnings.push(
|
||||
`Source ID ${originalId} is occupied; imported with local ID ${spriteId}`,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
ok: false,
|
||||
warnings,
|
||||
error: `DB ${isUpdate ? "update" : "insert"} failed: ${(err as Error).message}`,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Derive file-safe names ────────────────────────────────────────
|
||||
const rev = bestRevision;
|
||||
const assetTargets = await getFurniAssetWriteTargets();
|
||||
@@ -828,7 +789,7 @@ export async function importSingleFurni(params: {
|
||||
.catch(() => null);
|
||||
const nitroValid = nitroStat && nitroStat.size >= 128;
|
||||
|
||||
if (!nitroValid && !conversionResult) {
|
||||
if (!nitroValid) {
|
||||
if (nitroStat) {
|
||||
warnings.push(
|
||||
`Nitro file too small/corrupt (${nitroStat.size} bytes) — removing`,
|
||||
@@ -839,24 +800,56 @@ export async function importSingleFurni(params: {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (!isUpdate)
|
||||
await db.execute(
|
||||
sql`DELETE FROM items_base WHERE id = ${itemId} AND item_name = ${classname}`,
|
||||
);
|
||||
} catch {
|
||||
/* best effort cleanup */
|
||||
}
|
||||
|
||||
return {
|
||||
ok: false,
|
||||
warnings,
|
||||
error: `${isUpdate ? "No .nitro file could be created; existing furniture was preserved" : "Import rolled back: no .nitro file could be created"} (${classname}, revision ${rev}). ${warnings
|
||||
error: `${isUpdate ? "No .nitro file could be created; existing furniture was preserved" : "Import not started: no .nitro file could be created"} (${classname}, revision ${rev}). ${warnings
|
||||
.filter((warning) => /conversion|download|SWF/.test(warning))
|
||||
.slice(-3)
|
||||
.join(". ")}`,
|
||||
};
|
||||
}
|
||||
|
||||
// ── Insert into DB with enriched data ──────────────────────────────
|
||||
onProgress?.("writing_db");
|
||||
try {
|
||||
if (preservingExisting) {
|
||||
warnings.push(
|
||||
`Existing furniture #${itemId}: SQL settings and catalog offers preserved`,
|
||||
);
|
||||
} else if (isUpdate) {
|
||||
// NOTE: live Arcturus `items_base` has no description/revision/rare columns —
|
||||
// those metadata fields are persisted in FurnitureData.json (see entry below),
|
||||
// not in the DB. Only refresh the columns this import manages.
|
||||
await db.execute(sql`
|
||||
UPDATE items_base SET sprite_id = ${spriteId}, public_name = ${bestName}, item_name = ${classname}, type = ${itemType}
|
||||
WHERE id = ${spriteId}
|
||||
`);
|
||||
} else {
|
||||
itemId = await reserveFurnitureId(
|
||||
originalId,
|
||||
classname,
|
||||
async (allocatedId) => {
|
||||
await db.execute(
|
||||
sql`INSERT INTO items_base (id, sprite_id, public_name, item_name, type) VALUES (${allocatedId}, ${allocatedId}, ${bestName}, ${classname}, ${itemType})`,
|
||||
);
|
||||
},
|
||||
);
|
||||
spriteId = itemId;
|
||||
if (spriteId !== originalId)
|
||||
warnings.push(
|
||||
`Source ID ${originalId} is occupied; imported with local ID ${spriteId}`,
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
return {
|
||||
ok: false,
|
||||
warnings,
|
||||
error: `DB ${isUpdate ? "update" : "insert"} failed: ${(err as Error).message}`,
|
||||
};
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
mirrorFileToDirs(swfPath, `${safeSwfName}.swf`, mirrorSwfDirs, warnings),
|
||||
mirrorFileToDirs(
|
||||
|
||||
Reference in new issue
Block a user