fix(import): make effects and figure/clothing import work on deployment
- resolveGamedataFile: detect Windows drive/UNC paths explicitly instead of path.win32.isAbsolute (which is true for any /-prefixed path on Linux), so /nitro-assets URLs are no longer returned verbatim; add deployment gamedata root fallback (/var/www/Gamedata/config) and keep public/Gamedata/config. - effect/figure import dirs now resolve via site settings then the gamedata root bundled dir, instead of hardcoded public paths. - effect list falls back to the local EffectMap when the official habbo.com endpoint is unreachable, keeping the admin import page usable. - update staff smoke contract for db:migrate and instant=false (Cache Components migration).
This commit is contained in:
1 parent
694a24c791
commit
dd708a64fb
10 files changed
+172
-56
No files matched your search
@@ -9,7 +9,9 @@ import {
|
||||
mergeEffect,
|
||||
removeEffect,
|
||||
} from "@/lib/services/effectmap";
|
||||
import { getGamedataRoot } from "@/lib/services/furni-asset-dirs";
|
||||
import { downloadFile } from "@/lib/services/import/core/download";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
import { convertSwfToNitro } from "@/lib/services/swf-to-nitro";
|
||||
import type {
|
||||
EffectListItem,
|
||||
@@ -17,18 +19,40 @@ import type {
|
||||
ImportEffectResult,
|
||||
} from "@/types/effects";
|
||||
|
||||
export const EFFECT_NITRO_DIR = path.join(
|
||||
const EFFECT_NITRO_DIR_FALLBACK = path.join(
|
||||
/*turbopackIgnore: true*/ process.cwd(),
|
||||
"public/nitro-assets/bundled/effect",
|
||||
);
|
||||
export const EFFECT_SWF_DIR = path.join(
|
||||
const EFFECT_SWF_DIR_FALLBACK = path.join(
|
||||
/*turbopackIgnore: true*/ process.cwd(),
|
||||
"public/swf/gordon",
|
||||
);
|
||||
|
||||
async function getEffectNitroDir(): Promise<string> {
|
||||
const configured = (
|
||||
(await siteSettings.get("effect_nitro_dir", "")) ?? ""
|
||||
).trim();
|
||||
if (configured) return configured;
|
||||
const gamedataRoot = await getGamedataRoot();
|
||||
if (gamedataRoot)
|
||||
return path.join(/*turbopackIgnore: true*/ gamedataRoot, "bundled/effect");
|
||||
return EFFECT_NITRO_DIR_FALLBACK;
|
||||
}
|
||||
|
||||
async function getEffectSwfDir(): Promise<string> {
|
||||
const configured = (
|
||||
(await siteSettings.get("effect_swf_dir", "")) ?? ""
|
||||
).trim();
|
||||
return configured || EFFECT_SWF_DIR_FALLBACK;
|
||||
}
|
||||
|
||||
export async function ensureEffectDirs(): Promise<void> {
|
||||
const [nitroDir, swfDir] = await Promise.all([
|
||||
getEffectNitroDir(),
|
||||
getEffectSwfDir(),
|
||||
]);
|
||||
await Promise.all(
|
||||
[EFFECT_NITRO_DIR, EFFECT_SWF_DIR]
|
||||
[nitroDir, swfDir]
|
||||
.filter((dir) => !existsSync(/*turbopackIgnore: true*/ dir))
|
||||
.map((dir) =>
|
||||
fs.mkdir(/*turbopackIgnore: true*/ dir, { recursive: true }),
|
||||
@@ -36,8 +60,11 @@ export async function ensureEffectDirs(): Promise<void> {
|
||||
);
|
||||
}
|
||||
|
||||
function nitroPathFor(lib: string): string {
|
||||
return path.join(/*turbopackIgnore: true*/ EFFECT_NITRO_DIR, `${lib}.nitro`);
|
||||
async function nitroPathFor(lib: string): Promise<string> {
|
||||
return path.join(
|
||||
/*turbopackIgnore: true*/ await getEffectNitroDir(),
|
||||
`${lib}.nitro`,
|
||||
);
|
||||
}
|
||||
|
||||
export async function importSingleEffect(params: {
|
||||
@@ -51,12 +78,12 @@ export async function importSingleEffect(params: {
|
||||
const warnings: string[] = [];
|
||||
await ensureEffectDirs();
|
||||
|
||||
const nitroPath = nitroPathFor(lib);
|
||||
const nitroPath = await nitroPathFor(lib);
|
||||
|
||||
// Download SWF
|
||||
onProgress?.("downloading");
|
||||
const swfPath = path.join(
|
||||
/*turbopackIgnore: true*/ EFFECT_SWF_DIR,
|
||||
/*turbopackIgnore: true*/ await getEffectSwfDir(),
|
||||
`${lib}.swf`,
|
||||
);
|
||||
let swfUrl: string;
|
||||
@@ -116,7 +143,7 @@ export async function deleteImportedEffect(
|
||||
const removed = await removeEffect(idOrLib);
|
||||
let deletedFile = false;
|
||||
if (entry) {
|
||||
const p = nitroPathFor(entry.lib);
|
||||
const p = await nitroPathFor(entry.lib);
|
||||
if (existsSync(/*turbopackIgnore: true*/ p)) {
|
||||
await fs.unlink(/*turbopackIgnore: true*/ p).catch(() => {});
|
||||
deletedFile = true;
|
||||
@@ -126,20 +153,23 @@ export async function deleteImportedEffect(
|
||||
}
|
||||
|
||||
export async function getEffectList(search: string): Promise<EffectListItem[]> {
|
||||
const [official, local] = await Promise.all([
|
||||
const [official, local, nitroDir] = await Promise.all([
|
||||
listOfficialEffects(),
|
||||
listLocalEffects(),
|
||||
getEffectNitroDir(),
|
||||
]);
|
||||
// The official Habbo effectmap endpoint is frequently unreachable/dead.
|
||||
// Fall back to the locally cached map so the list stays usable.
|
||||
const base = official.length > 0 ? official : local;
|
||||
const localByLib = new Map(local.map((e) => [e.lib, e]));
|
||||
const term = search.trim().toLowerCase();
|
||||
const merged = official.map((e) => {
|
||||
const present = localByLib.has(e.lib);
|
||||
return {
|
||||
...e,
|
||||
present,
|
||||
nitroExists: existsSync(/*turbopackIgnore: true*/ nitroPathFor(e.lib)),
|
||||
};
|
||||
});
|
||||
const merged = base.map((e) => ({
|
||||
...e,
|
||||
present: localByLib.has(e.lib),
|
||||
nitroExists: existsSync(
|
||||
/*turbopackIgnore: true*/ path.join(nitroDir, `${e.lib}.nitro`),
|
||||
),
|
||||
}));
|
||||
return term
|
||||
? merged.filter(
|
||||
(e) =>
|
||||
@@ -160,10 +190,16 @@ export async function getEffectStats(): Promise<{
|
||||
listLocalEffects(),
|
||||
]);
|
||||
const localLibs = new Set(local.map((e) => e.lib));
|
||||
const imported = official.filter((e) => localLibs.has(e.lib)).length;
|
||||
const imported =
|
||||
official.length > 0
|
||||
? official.filter((e) => localLibs.has(e.lib)).length
|
||||
: localLibs.size;
|
||||
return {
|
||||
official: official.length,
|
||||
official: official.length > 0 ? official.length : local.length,
|
||||
imported,
|
||||
missing: official.length - imported,
|
||||
missing:
|
||||
official.length > 0
|
||||
? official.length - imported
|
||||
: local.length - imported,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user