style: clean up code with prettier and eslint
This commit is contained in:
1 parent
60278b9e71
commit
fb8e77bb68
378 files changed
+22407
-20689
No files matched your search
@@ -1,165 +1,161 @@
|
||||
import { existsSync, promises as fs } from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { withAdmin } from '@/lib/api-handler'
|
||||
import { apiError, apiOk } from '@/lib/api-response'
|
||||
import { PERMS } from '@/lib/permissions'
|
||||
import { prisma } from '@/lib/prisma'
|
||||
import { logAudit } from '@/lib/services/audit'
|
||||
import { getFurniAssetDirs } from '@/lib/services/furni-asset-dirs'
|
||||
import { readFurniData, withFurniDataLock, writeFurniData } from '@/lib/services/furni-data'
|
||||
import { rcon } from '@/lib/services/rcon'
|
||||
import { existsSync, promises as fs } from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { withAdmin } from "@/lib/api-handler";
|
||||
import { apiError, apiOk } from "@/lib/api-response";
|
||||
import { PERMS } from "@/lib/permissions";
|
||||
import { prisma } from "@/lib/prisma";
|
||||
import { logAudit } from "@/lib/services/audit";
|
||||
import { getFurniAssetDirs } from "@/lib/services/furni-asset-dirs";
|
||||
import { readFurniData, withFurniDataLock, writeFurniData } from "@/lib/services/furni-data";
|
||||
import { rcon } from "@/lib/services/rcon";
|
||||
import {
|
||||
computeDefaultDir,
|
||||
createNitroBundle,
|
||||
extractPartColors,
|
||||
parseNitroBundle,
|
||||
} from '@/lib/services/swf-to-nitro'
|
||||
} from "@/lib/services/swf-to-nitro";
|
||||
|
||||
function baseClassname(classname: string): string {
|
||||
return classname.includes('*') ? classname.split('*')[0] : classname
|
||||
return classname.includes("*") ? classname.split("*")[0] : classname;
|
||||
}
|
||||
|
||||
// ── GET: Read .nitro metadata ──────────────────────────────────────
|
||||
|
||||
export const GET = withAdmin({ permission: PERMS.ASSETS_IMPORT }, async (request: NextRequest) => {
|
||||
const rawClassname = request.nextUrl.searchParams.get('classname')
|
||||
if (!rawClassname) return apiError('Missing classname', 400)
|
||||
const rawClassname = request.nextUrl.searchParams.get("classname");
|
||||
if (!rawClassname) return apiError("Missing classname", 400);
|
||||
|
||||
const base = baseClassname(rawClassname)
|
||||
const { nitroDir } = await getFurniAssetDirs()
|
||||
const nitroPath = path.join(/*turbopackIgnore: true*/ nitroDir, `${base}.nitro`)
|
||||
const base = baseClassname(rawClassname);
|
||||
const { nitroDir } = await getFurniAssetDirs();
|
||||
const nitroPath = path.join(/*turbopackIgnore: true*/ nitroDir, `${base}.nitro`);
|
||||
|
||||
if (!existsSync(/*turbopackIgnore: true*/ nitroPath)) return apiError('Nitro file not found', 404)
|
||||
if (!existsSync(/*turbopackIgnore: true*/ nitroPath)) return apiError("Nitro file not found", 404);
|
||||
|
||||
try {
|
||||
const buffer = await fs.readFile(/*turbopackIgnore: true*/ nitroPath)
|
||||
const { json } = parseNitroBundle(buffer)
|
||||
const buffer = await fs.readFile(/*turbopackIgnore: true*/ nitroPath);
|
||||
const { json } = parseNitroBundle(buffer);
|
||||
|
||||
// Fetch interaction flags from DB
|
||||
const items = await prisma.$queryRaw<
|
||||
Array<{
|
||||
allow_sit: string
|
||||
allow_lay: string
|
||||
allow_walk: string
|
||||
allow_sit: string;
|
||||
allow_lay: string;
|
||||
allow_walk: string;
|
||||
}>
|
||||
>`
|
||||
SELECT allow_sit, allow_lay, allow_walk
|
||||
FROM items_base WHERE item_name = ${rawClassname} LIMIT 1
|
||||
`
|
||||
`;
|
||||
|
||||
const dbRow = items[0]
|
||||
const dbRow = items[0];
|
||||
const flags = {
|
||||
canstandon: dbRow?.allow_walk === '1',
|
||||
cansiton: dbRow?.allow_sit === '1',
|
||||
canlayon: dbRow?.allow_lay === '1',
|
||||
}
|
||||
canstandon: dbRow?.allow_walk === "1",
|
||||
cansiton: dbRow?.allow_sit === "1",
|
||||
canlayon: dbRow?.allow_lay === "1",
|
||||
};
|
||||
|
||||
return apiOk({ metadata: json, flags })
|
||||
return apiOk({ metadata: json, flags });
|
||||
} catch (err) {
|
||||
console.error('[nitro-editor] Failed to parse .nitro:', (err as Error).message)
|
||||
return apiError('Failed to parse .nitro file', 500)
|
||||
console.error("[nitro-editor] Failed to parse .nitro:", (err as Error).message);
|
||||
return apiError("Failed to parse .nitro file", 500);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// ── PUT: Save .nitro metadata ──────────────────────────────────────
|
||||
|
||||
export const PUT = withAdmin(
|
||||
{ permission: PERMS.ASSETS_IMPORT },
|
||||
async (request: NextRequest, ctx) => {
|
||||
const body = await request.json()
|
||||
const { classname: rawClassname, metadata, canstandon, cansiton, canlayon } = body
|
||||
export const PUT = withAdmin({ permission: PERMS.ASSETS_IMPORT }, async (request: NextRequest, ctx) => {
|
||||
const body = await request.json();
|
||||
const { classname: rawClassname, metadata, canstandon, cansiton, canlayon } = body;
|
||||
|
||||
if (!rawClassname || !metadata) return apiError('Missing classname or metadata', 400)
|
||||
if (!rawClassname || !metadata) return apiError("Missing classname or metadata", 400);
|
||||
|
||||
const base = baseClassname(rawClassname)
|
||||
const { nitroDir } = await getFurniAssetDirs()
|
||||
const nitroPath = path.join(/*turbopackIgnore: true*/ nitroDir, `${base}.nitro`)
|
||||
const base = baseClassname(rawClassname);
|
||||
const { nitroDir } = await getFurniAssetDirs();
|
||||
const nitroPath = path.join(/*turbopackIgnore: true*/ nitroDir, `${base}.nitro`);
|
||||
|
||||
if (!existsSync(/*turbopackIgnore: true*/ nitroPath))
|
||||
return apiError('Nitro file not found', 404)
|
||||
if (!existsSync(/*turbopackIgnore: true*/ nitroPath)) return apiError("Nitro file not found", 404);
|
||||
|
||||
// 1. Read existing .nitro to extract PNG
|
||||
const existingBuffer = await fs.readFile(/*turbopackIgnore: true*/ nitroPath)
|
||||
const { png } = parseNitroBundle(existingBuffer)
|
||||
// 1. Read existing .nitro to extract PNG
|
||||
const existingBuffer = await fs.readFile(/*turbopackIgnore: true*/ nitroPath);
|
||||
const { png } = parseNitroBundle(existingBuffer);
|
||||
|
||||
// 2. Rebuild .nitro with updated JSON + same PNG
|
||||
const newBundle = createNitroBundle(metadata, png, base)
|
||||
await fs.writeFile(nitroPath, newBundle)
|
||||
// 2. Rebuild .nitro with updated JSON + same PNG
|
||||
const newBundle = createNitroBundle(metadata, png, base);
|
||||
await fs.writeFile(nitroPath, newBundle);
|
||||
|
||||
// 3. Extract dimensions from metadata
|
||||
const dims = metadata.logic?.model?.dimensions || { x: 1, y: 1, z: 0 }
|
||||
const directions: number[] = metadata.logic?.model?.directions || [0]
|
||||
const visualizations = metadata.visualizations || []
|
||||
// 3. Extract dimensions from metadata
|
||||
const dims = metadata.logic?.model?.dimensions || { x: 1, y: 1, z: 0 };
|
||||
const directions: number[] = metadata.logic?.model?.directions || [0];
|
||||
const visualizations = metadata.visualizations || [];
|
||||
|
||||
// 4. Update FurnitureData.json (best-effort)
|
||||
try {
|
||||
await withFurniDataLock(async () => {
|
||||
const furniData = (await readFurniData()) as Record<
|
||||
string,
|
||||
{ furnitype: Array<Record<string, unknown>> }
|
||||
>
|
||||
// 4. Update FurnitureData.json (best-effort)
|
||||
try {
|
||||
await withFurniDataLock(async () => {
|
||||
const furniData = (await readFurniData()) as Record<
|
||||
string,
|
||||
{ furnitype: Array<Record<string, unknown>> }
|
||||
>;
|
||||
|
||||
for (const section of ['roomitemtypes', 'wallitemtypes'] as const) {
|
||||
const types = furniData[section]?.furnitype
|
||||
if (!Array.isArray(types)) continue
|
||||
const idx = types.findIndex((e) => e.classname === rawClassname)
|
||||
if (idx !== -1) {
|
||||
types[idx].xdim = dims.x
|
||||
types[idx].ydim = dims.y
|
||||
types[idx].defaultdir = computeDefaultDir(directions)
|
||||
types[idx].partcolors = extractPartColors(visualizations)
|
||||
types[idx].canstandon = canstandon ?? false
|
||||
types[idx].cansiton = cansiton ?? false
|
||||
types[idx].canlayon = canlayon ?? false
|
||||
break
|
||||
}
|
||||
for (const section of ["roomitemtypes", "wallitemtypes"] as const) {
|
||||
const types = furniData[section]?.furnitype;
|
||||
if (!Array.isArray(types)) continue;
|
||||
const idx = types.findIndex((e) => e.classname === rawClassname);
|
||||
if (idx !== -1) {
|
||||
types[idx].xdim = dims.x;
|
||||
types[idx].ydim = dims.y;
|
||||
types[idx].defaultdir = computeDefaultDir(directions);
|
||||
types[idx].partcolors = extractPartColors(visualizations);
|
||||
types[idx].canstandon = canstandon ?? false;
|
||||
types[idx].cansiton = cansiton ?? false;
|
||||
types[idx].canlayon = canlayon ?? false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await writeFurniData(furniData as Record<string, unknown>)
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('[nitro-editor] FurnitureData.json update failed:', (err as Error).message)
|
||||
}
|
||||
await writeFurniData(furniData as Record<string, unknown>);
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn("[nitro-editor] FurnitureData.json update failed:", (err as Error).message);
|
||||
}
|
||||
|
||||
// 5. Update items_base (best-effort)
|
||||
try {
|
||||
await prisma.$executeRaw`
|
||||
// 5. Update items_base (best-effort)
|
||||
try {
|
||||
await prisma.$executeRaw`
|
||||
UPDATE items_base
|
||||
SET width = ${dims.x}, length = ${dims.y}, stack_height = ${dims.z},
|
||||
allow_sit = ${cansiton ? '1' : '0'},
|
||||
allow_lay = ${canlayon ? '1' : '0'},
|
||||
allow_walk = ${canstandon ? '1' : '0'}
|
||||
allow_sit = ${cansiton ? "1" : "0"},
|
||||
allow_lay = ${canlayon ? "1" : "0"},
|
||||
allow_walk = ${canstandon ? "1" : "0"}
|
||||
WHERE item_name = ${rawClassname}
|
||||
`
|
||||
} catch (err) {
|
||||
console.warn('[nitro-editor] items_base update failed:', (err as Error).message)
|
||||
}
|
||||
`;
|
||||
} catch (err) {
|
||||
console.warn("[nitro-editor] items_base update failed:", (err as Error).message);
|
||||
}
|
||||
|
||||
// 6. RCON refresh (best-effort)
|
||||
try {
|
||||
await rcon.updateItems()
|
||||
} catch (err) {
|
||||
console.warn('[nitro-editor] RCON updateItems failed:', (err as Error).message)
|
||||
}
|
||||
// 6. RCON refresh (best-effort)
|
||||
try {
|
||||
await rcon.updateItems();
|
||||
} catch (err) {
|
||||
console.warn("[nitro-editor] RCON updateItems failed:", (err as Error).message);
|
||||
}
|
||||
|
||||
// 7. Audit log
|
||||
try {
|
||||
const dbItem = await prisma.itemsBase.findFirst({
|
||||
where: { itemName: rawClassname },
|
||||
select: { id: true },
|
||||
})
|
||||
await logAudit({
|
||||
userId: ctx.session.user.id,
|
||||
action: 'furni_edit_nitro',
|
||||
target: 'ItemsBase',
|
||||
targetId: dbItem?.id ?? 0,
|
||||
after: { classname: rawClassname, dimensions: dims, canstandon, cansiton, canlayon },
|
||||
})
|
||||
} catch (err) {
|
||||
console.warn('[nitro-editor] Audit log failed:', (err as Error).message)
|
||||
}
|
||||
// 7. Audit log
|
||||
try {
|
||||
const dbItem = await prisma.itemsBase.findFirst({
|
||||
where: { itemName: rawClassname },
|
||||
select: { id: true },
|
||||
});
|
||||
await logAudit({
|
||||
userId: ctx.session.user.id,
|
||||
action: "furni_edit_nitro",
|
||||
target: "ItemsBase",
|
||||
targetId: dbItem?.id ?? 0,
|
||||
after: { classname: rawClassname, dimensions: dims, canstandon, cansiton, canlayon },
|
||||
});
|
||||
} catch (err) {
|
||||
console.warn("[nitro-editor] Audit log failed:", (err as Error).message);
|
||||
}
|
||||
|
||||
return apiOk({ dimensions: dims })
|
||||
},
|
||||
)
|
||||
return apiOk({ dimensions: dims });
|
||||
});
|
||||
Reference in new issue
Block a user