Backfill icons too in the Gamedata bundle sync
Extend the post-import backfill to also copy missing _icon.png files into /var/www/Gamedata/icons (in addition to nitros into bundled/furniture) so all imported furniture shows an icon in-game. Report copied nitros and icons separately in the API/SSE responses.
This commit is contained in:
1 parent
bcd24bfca4
commit
b4021f6b42
4 files changed
+99
-54
No files matched your search
@@ -347,53 +347,91 @@ export async function ensureFurniOwnership(): Promise<{ fixed: string[] }> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy every .nitro file that is missing from the emulator's Gamedata
|
||||
* bundle directory (/var/www/Gamedata/bundled/furniture) so all imported
|
||||
* furniture stays renderable in-game even when a mirror write was skipped.
|
||||
*/
|
||||
export async function syncNitrosToGamedataBundle(): Promise<{
|
||||
copied: string[];
|
||||
}> {
|
||||
if (process.platform === "win32") return { copied: [] };
|
||||
|
||||
const gamedataRoot = await getGamedataRoot();
|
||||
if (!gamedataRoot) return { copied: [] };
|
||||
|
||||
const targetDir = path.join(gamedataRoot, "bundled/furniture");
|
||||
const { nitroDir } = await getFurniAssetDirs();
|
||||
if (nitroDir === targetDir) return { copied: [] };
|
||||
if (!existsSync(nitroDir)) return { copied: [] };
|
||||
|
||||
/** Copy a single missing file from source dir into target dir; logs on failure. */
|
||||
async function copyIfMissing(
|
||||
sourceDir: string,
|
||||
targetDir: string,
|
||||
entry: string,
|
||||
copied: string[],
|
||||
): Promise<void> {
|
||||
const dest = path.join(targetDir, entry);
|
||||
if (existsSync(dest)) return;
|
||||
try {
|
||||
await fs.mkdir(targetDir, { recursive: true });
|
||||
} catch {
|
||||
return { copied: [] };
|
||||
}
|
||||
|
||||
const copied: string[] = [];
|
||||
try {
|
||||
const entries = await fs.readdir(nitroDir);
|
||||
for (const entry of entries) {
|
||||
if (!entry.endsWith(".nitro")) continue;
|
||||
const dest = path.join(targetDir, entry);
|
||||
if (existsSync(dest)) continue;
|
||||
try {
|
||||
await fs.copyFile(path.join(nitroDir, entry), dest);
|
||||
copied.push(entry);
|
||||
} catch (err) {
|
||||
logger.warn("[import-furni] nitro sync copy failed", {
|
||||
entry,
|
||||
error: (err as Error).message,
|
||||
});
|
||||
}
|
||||
}
|
||||
await fs.copyFile(path.join(sourceDir, entry), dest);
|
||||
copied.push(entry);
|
||||
} catch (err) {
|
||||
logger.warn("[import-furni] nitro sync scan failed", {
|
||||
logger.warn("[import-furni] gamedata bundle sync copy failed", {
|
||||
entry,
|
||||
error: (err as Error).message,
|
||||
});
|
||||
}
|
||||
return { copied };
|
||||
}
|
||||
|
||||
/** Scan a source dir and copy every file that is missing from the target dir. */
|
||||
async function syncDirMissingFiles(
|
||||
sourceDir: string,
|
||||
targetDir: string,
|
||||
predicate: (entry: string) => boolean,
|
||||
): Promise<string[]> {
|
||||
if (!existsSync(sourceDir)) return [];
|
||||
try {
|
||||
await fs.mkdir(targetDir, { recursive: true });
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
const copied: string[] = [];
|
||||
try {
|
||||
const entries = await fs.readdir(sourceDir);
|
||||
for (const entry of entries) {
|
||||
if (!predicate(entry)) continue;
|
||||
await copyIfMissing(sourceDir, targetDir, entry, copied);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.warn("[import-furni] gamedata bundle sync scan failed", {
|
||||
error: (err as Error).message,
|
||||
});
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Backfill any nitro and icon files missing from the emulator's Gamedata
|
||||
* bundle (/var/www/Gamedata/bundled/furniture and /var/www/Gamedata/icons)
|
||||
* so all imported furniture stays renderable in-game even when a mirror
|
||||
* write was skipped.
|
||||
*/
|
||||
export async function syncAssetsToGamedataBundle(): Promise<{
|
||||
copiedNitros: string[];
|
||||
copiedIcons: string[];
|
||||
}> {
|
||||
if (process.platform === "win32")
|
||||
return { copiedNitros: [], copiedIcons: [] };
|
||||
|
||||
const gamedataRoot = await getGamedataRoot();
|
||||
if (!gamedataRoot) return { copiedNitros: [], copiedIcons: [] };
|
||||
|
||||
const { nitroDir, iconDir } = await getFurniAssetDirs();
|
||||
|
||||
const copiedNitros: string[] = [];
|
||||
const copiedIcons: string[] = [];
|
||||
|
||||
const nitroTarget = path.join(gamedataRoot, "bundled/furniture");
|
||||
if (nitroDir !== nitroTarget) {
|
||||
const copied = await syncDirMissingFiles(nitroDir, nitroTarget, (entry) =>
|
||||
entry.endsWith(".nitro"),
|
||||
);
|
||||
copiedNitros.push(...copied);
|
||||
}
|
||||
|
||||
const iconTarget = path.join(gamedataRoot, "icons");
|
||||
if (iconDir !== iconTarget) {
|
||||
const copied = await syncDirMissingFiles(iconDir, iconTarget, (entry) =>
|
||||
entry.endsWith("_icon.png"),
|
||||
);
|
||||
copiedIcons.push(...copied);
|
||||
}
|
||||
|
||||
return { copiedNitros, copiedIcons };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in new issue
Block a user