Fix CI/CD: Disable memory caps for Act Runner
CI / check (push) Failing after 33s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / tests-imaging-browsers (push) Skipped
CI / tests-quality (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
CI / check (push) Failing after 33s
CI / tests-unit (push) Skipped
CI / tests-integration (push) Skipped
CI / tests-ui (push) Skipped
CI / tests-imaging-browsers (push) Skipped
CI / tests-quality (push) Skipped
CI / preflight (push) Skipped
CI / deploy (push) Skipped
This commit is contained in:
+1
-1
@@ -82,7 +82,7 @@ services:
|
||||
- PORT=3002
|
||||
|
||||
byparr:
|
||||
image: ghcr.io/thephaseless/byparr:v3.0.4
|
||||
image: ghcr.io/thephaseless/byparr:main
|
||||
# `latest` is een drijvende tag. Zonder pull_policy haalt compose de
|
||||
# bestaande image nooit opnieuw op en blijft byparr hangen op de eerste
|
||||
# versie die ooit werd binnengehaald.
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
withFurniDataLock,
|
||||
writeFurniData,
|
||||
} from "@/lib/services/furni-data";
|
||||
import { autoDetectInteraction, nitroAnimationStatesCount } from "@/lib/furni/auto-interaction";
|
||||
import { rcon } from "@/lib/services/rcon";
|
||||
import {
|
||||
computeDefaultDir,
|
||||
@@ -164,9 +165,27 @@ export const PUT = withAdmin(
|
||||
|
||||
// 5. Update items_base (best-effort)
|
||||
try {
|
||||
const autoInteraction = autoDetectInteraction(
|
||||
rawClassname,
|
||||
typeof metadata?.name === "string" ? metadata.name : rawClassname,
|
||||
{
|
||||
cansiton,
|
||||
canlayon,
|
||||
canstandon,
|
||||
logicType:
|
||||
typeof metadata?.logic?.logicType === "string"
|
||||
? metadata.logic.logicType
|
||||
: undefined,
|
||||
animationStates: nitroAnimationStatesCount(metadata),
|
||||
hasActionData: true,
|
||||
},
|
||||
);
|
||||
const interactionModesCount = autoInteraction.interactionModesCount;
|
||||
|
||||
await db.execute(sql`
|
||||
UPDATE items_base
|
||||
SET width = ${dims.x}, length = ${dims.y}, stack_height = ${dims.z},
|
||||
interaction_modes_count = ${interactionModesCount},
|
||||
allow_sit = ${cansiton ? "1" : "0"},
|
||||
allow_lay = ${canlayon ? "1" : "0"},
|
||||
allow_walk = ${canstandon ? "1" : "0"}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface FurnitureInspection {
|
||||
classname: string;
|
||||
sql: Array<{ id: number; spriteId: number; name: string; type: string }>;
|
||||
sql: Array<{ id: number; spriteId: number; name: string; type: string; width?: number; length?: number; stackHeight?: number; interactionModesCount?: number }>;
|
||||
catalog: Array<{
|
||||
id: number;
|
||||
pageId: number;
|
||||
@@ -13,6 +13,10 @@ export interface FurnitureInspection {
|
||||
description: string;
|
||||
revision: number;
|
||||
type: string;
|
||||
width?: number;
|
||||
length?: number;
|
||||
stackHeight?: number;
|
||||
interactionModesCount?: number;
|
||||
}>;
|
||||
furnidataReadable: boolean;
|
||||
nitro: { exists: boolean | null; bytes: number };
|
||||
@@ -32,11 +36,20 @@ export function validateClassnames(value: unknown): string[] | null {
|
||||
return [...new Set(value)];
|
||||
}
|
||||
export function compareFurniture(
|
||||
source: { name: string; description: string; revision: number; type: string },
|
||||
source: {
|
||||
name: string;
|
||||
description: string;
|
||||
revision: number;
|
||||
type: string;
|
||||
width?: number;
|
||||
length?: number;
|
||||
height?: number;
|
||||
interactionModesCount?: number;
|
||||
},
|
||||
local: FurnitureInspection,
|
||||
) {
|
||||
const fd = local.furnidata[0],
|
||||
sql = local.sql[0];
|
||||
const fd = local.furnidata[0];
|
||||
const sql = local.sql[0];
|
||||
const values = [
|
||||
["Name", sql?.name ?? fd?.name, source.name],
|
||||
["Description", fd?.description, source.description],
|
||||
@@ -46,16 +59,23 @@ export function compareFurniture(
|
||||
sql ? (sql.type === "i" ? "wallitem" : "flooritem") : fd?.type,
|
||||
source.type,
|
||||
],
|
||||
] as const;
|
||||
const fields = values.map(([label, before, after]) => ({
|
||||
label,
|
||||
before,
|
||||
after,
|
||||
changed:
|
||||
before !== undefined &&
|
||||
after !== undefined &&
|
||||
String(before) !== String(after),
|
||||
}));
|
||||
["Width", sql?.width ?? fd?.width, source.width],
|
||||
["Length", sql?.length ?? fd?.length, source.length],
|
||||
["Height", sql?.stackHeight ?? fd?.stackHeight, source.height],
|
||||
["Interaction Modes Count", sql?.interactionModesCount ?? fd?.interactionModesCount, source.interactionModesCount],
|
||||
];
|
||||
const fields = values.map((item) => {
|
||||
const [label, before, after] = item;
|
||||
return {
|
||||
label,
|
||||
before,
|
||||
after,
|
||||
changed:
|
||||
before !== undefined &&
|
||||
after !== undefined &&
|
||||
String(before) !== String(after),
|
||||
};
|
||||
});
|
||||
const state = hasFurnitureConflict(local)
|
||||
? "conflict"
|
||||
: !local.furnidataReadable
|
||||
@@ -65,7 +85,7 @@ export function compareFurniture(
|
||||
: fields.some((f) => f.changed)
|
||||
? "changed"
|
||||
: "present";
|
||||
return { state, fields } as const;
|
||||
return { state, fields };
|
||||
}
|
||||
export function furnitureHealth(local: FurnitureInspection) {
|
||||
const missing: string[] = [];
|
||||
|
||||
@@ -1009,61 +1009,6 @@ export async function importSingleFurni(params: {
|
||||
};
|
||||
}
|
||||
|
||||
// ── Insert into DB with enriched data ──────────────────────────────
|
||||
await 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(
|
||||
iconPath,
|
||||
`${iconFileName}_icon.png`,
|
||||
mirrorIconDirs,
|
||||
warnings,
|
||||
),
|
||||
mirrorFileToDirs(
|
||||
resolveNitro() ?? nitroPath,
|
||||
`${safeNitroName}${LOCAL_BUNDLE_EXT}`,
|
||||
mirrorNitroDirs,
|
||||
warnings,
|
||||
),
|
||||
]);
|
||||
|
||||
// ── Build enriched FurnitureData entry ────────────────────────────
|
||||
const dims =
|
||||
conversionResult?.dimensions ||
|
||||
@@ -1144,6 +1089,65 @@ export async function importSingleFurni(params: {
|
||||
});
|
||||
const interactionModesCount = autoInteraction.interactionModesCount;
|
||||
|
||||
// ── Insert into DB with enriched data ──────────────────────────────
|
||||
await 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},
|
||||
width = ${dims.x}, length = ${dims.y}, stack_height = ${dims.z},
|
||||
interaction_modes_count = ${interactionModesCount}, interaction_type = ${interactionType}
|
||||
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(
|
||||
iconPath,
|
||||
`${iconFileName}_icon.png`,
|
||||
mirrorIconDirs,
|
||||
warnings,
|
||||
),
|
||||
mirrorFileToDirs(
|
||||
resolveNitro() ?? nitroPath,
|
||||
`${safeNitroName}${LOCAL_BUNDLE_EXT}`,
|
||||
mirrorNitroDirs,
|
||||
warnings,
|
||||
),
|
||||
]);
|
||||
|
||||
|
||||
// When the .nitro logicType produced no specific handler, fall back to the
|
||||
// auto-detected type (classname mechanic + keyword + real flags) exactly
|
||||
// like the post-import verification sweep, so newly imported items carry the
|
||||
|
||||
@@ -46,7 +46,7 @@ export async function inspectFurniture(
|
||||
const rows = await queryRows<
|
||||
FurnitureInspection["sql"][number] & { classname: string }
|
||||
>(
|
||||
sql`SELECT id, sprite_id AS spriteId, item_name AS classname, public_name AS name, type FROM items_base WHERE LOWER(TRIM(item_name)) IN (${namesSql})`,
|
||||
sql`SELECT id, sprite_id AS spriteId, item_name AS classname, public_name AS name, type, width, length, stack_height AS stackHeight, interaction_modes_count AS interactionModesCount FROM items_base WHERE LOWER(TRIM(item_name)) IN (${namesSql})`,
|
||||
);
|
||||
const offers = await queryRows<
|
||||
FurnitureInspection["catalog"][number] & { classname: string }
|
||||
@@ -89,6 +89,10 @@ export async function inspectFurniture(
|
||||
description: String(entry.description ?? ""),
|
||||
revision: Number(entry.revision ?? 0),
|
||||
type,
|
||||
width: Number(entry.xdim ?? 0),
|
||||
length: Number(entry.ydim ?? 0),
|
||||
stackHeight: Number(entry.zdim ?? entry.defaultdir ?? 0),
|
||||
interactionModesCount: Number(entry.interaction_modes_count ?? 0),
|
||||
});
|
||||
entries.set(key, values);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user