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
|
- PORT=3002
|
||||||
|
|
||||||
byparr:
|
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
|
# `latest` is een drijvende tag. Zonder pull_policy haalt compose de
|
||||||
# bestaande image nooit opnieuw op en blijft byparr hangen op de eerste
|
# bestaande image nooit opnieuw op en blijft byparr hangen op de eerste
|
||||||
# versie die ooit werd binnengehaald.
|
# versie die ooit werd binnengehaald.
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
withFurniDataLock,
|
withFurniDataLock,
|
||||||
writeFurniData,
|
writeFurniData,
|
||||||
} from "@/lib/services/furni-data";
|
} from "@/lib/services/furni-data";
|
||||||
|
import { autoDetectInteraction, nitroAnimationStatesCount } from "@/lib/furni/auto-interaction";
|
||||||
import { rcon } from "@/lib/services/rcon";
|
import { rcon } from "@/lib/services/rcon";
|
||||||
import {
|
import {
|
||||||
computeDefaultDir,
|
computeDefaultDir,
|
||||||
@@ -164,9 +165,27 @@ export const PUT = withAdmin(
|
|||||||
|
|
||||||
// 5. Update items_base (best-effort)
|
// 5. Update items_base (best-effort)
|
||||||
try {
|
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`
|
await db.execute(sql`
|
||||||
UPDATE items_base
|
UPDATE items_base
|
||||||
SET width = ${dims.x}, length = ${dims.y}, stack_height = ${dims.z},
|
SET width = ${dims.x}, length = ${dims.y}, stack_height = ${dims.z},
|
||||||
|
interaction_modes_count = ${interactionModesCount},
|
||||||
allow_sit = ${cansiton ? "1" : "0"},
|
allow_sit = ${cansiton ? "1" : "0"},
|
||||||
allow_lay = ${canlayon ? "1" : "0"},
|
allow_lay = ${canlayon ? "1" : "0"},
|
||||||
allow_walk = ${canstandon ? "1" : "0"}
|
allow_walk = ${canstandon ? "1" : "0"}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
export interface FurnitureInspection {
|
export interface FurnitureInspection {
|
||||||
classname: string;
|
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<{
|
catalog: Array<{
|
||||||
id: number;
|
id: number;
|
||||||
pageId: number;
|
pageId: number;
|
||||||
@@ -13,6 +13,10 @@ export interface FurnitureInspection {
|
|||||||
description: string;
|
description: string;
|
||||||
revision: number;
|
revision: number;
|
||||||
type: string;
|
type: string;
|
||||||
|
width?: number;
|
||||||
|
length?: number;
|
||||||
|
stackHeight?: number;
|
||||||
|
interactionModesCount?: number;
|
||||||
}>;
|
}>;
|
||||||
furnidataReadable: boolean;
|
furnidataReadable: boolean;
|
||||||
nitro: { exists: boolean | null; bytes: number };
|
nitro: { exists: boolean | null; bytes: number };
|
||||||
@@ -32,11 +36,20 @@ export function validateClassnames(value: unknown): string[] | null {
|
|||||||
return [...new Set(value)];
|
return [...new Set(value)];
|
||||||
}
|
}
|
||||||
export function compareFurniture(
|
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,
|
local: FurnitureInspection,
|
||||||
) {
|
) {
|
||||||
const fd = local.furnidata[0],
|
const fd = local.furnidata[0];
|
||||||
sql = local.sql[0];
|
const sql = local.sql[0];
|
||||||
const values = [
|
const values = [
|
||||||
["Name", sql?.name ?? fd?.name, source.name],
|
["Name", sql?.name ?? fd?.name, source.name],
|
||||||
["Description", fd?.description, source.description],
|
["Description", fd?.description, source.description],
|
||||||
@@ -46,16 +59,23 @@ export function compareFurniture(
|
|||||||
sql ? (sql.type === "i" ? "wallitem" : "flooritem") : fd?.type,
|
sql ? (sql.type === "i" ? "wallitem" : "flooritem") : fd?.type,
|
||||||
source.type,
|
source.type,
|
||||||
],
|
],
|
||||||
] as const;
|
["Width", sql?.width ?? fd?.width, source.width],
|
||||||
const fields = values.map(([label, before, after]) => ({
|
["Length", sql?.length ?? fd?.length, source.length],
|
||||||
label,
|
["Height", sql?.stackHeight ?? fd?.stackHeight, source.height],
|
||||||
before,
|
["Interaction Modes Count", sql?.interactionModesCount ?? fd?.interactionModesCount, source.interactionModesCount],
|
||||||
after,
|
];
|
||||||
changed:
|
const fields = values.map((item) => {
|
||||||
before !== undefined &&
|
const [label, before, after] = item;
|
||||||
after !== undefined &&
|
return {
|
||||||
String(before) !== String(after),
|
label,
|
||||||
}));
|
before,
|
||||||
|
after,
|
||||||
|
changed:
|
||||||
|
before !== undefined &&
|
||||||
|
after !== undefined &&
|
||||||
|
String(before) !== String(after),
|
||||||
|
};
|
||||||
|
});
|
||||||
const state = hasFurnitureConflict(local)
|
const state = hasFurnitureConflict(local)
|
||||||
? "conflict"
|
? "conflict"
|
||||||
: !local.furnidataReadable
|
: !local.furnidataReadable
|
||||||
@@ -65,7 +85,7 @@ export function compareFurniture(
|
|||||||
: fields.some((f) => f.changed)
|
: fields.some((f) => f.changed)
|
||||||
? "changed"
|
? "changed"
|
||||||
: "present";
|
: "present";
|
||||||
return { state, fields } as const;
|
return { state, fields };
|
||||||
}
|
}
|
||||||
export function furnitureHealth(local: FurnitureInspection) {
|
export function furnitureHealth(local: FurnitureInspection) {
|
||||||
const missing: string[] = [];
|
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 ────────────────────────────
|
// ── Build enriched FurnitureData entry ────────────────────────────
|
||||||
const dims =
|
const dims =
|
||||||
conversionResult?.dimensions ||
|
conversionResult?.dimensions ||
|
||||||
@@ -1144,6 +1089,65 @@ export async function importSingleFurni(params: {
|
|||||||
});
|
});
|
||||||
const interactionModesCount = autoInteraction.interactionModesCount;
|
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
|
// When the .nitro logicType produced no specific handler, fall back to the
|
||||||
// auto-detected type (classname mechanic + keyword + real flags) exactly
|
// auto-detected type (classname mechanic + keyword + real flags) exactly
|
||||||
// like the post-import verification sweep, so newly imported items carry the
|
// like the post-import verification sweep, so newly imported items carry the
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ export async function inspectFurniture(
|
|||||||
const rows = await queryRows<
|
const rows = await queryRows<
|
||||||
FurnitureInspection["sql"][number] & { classname: string }
|
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<
|
const offers = await queryRows<
|
||||||
FurnitureInspection["catalog"][number] & { classname: string }
|
FurnitureInspection["catalog"][number] & { classname: string }
|
||||||
@@ -89,6 +89,10 @@ export async function inspectFurniture(
|
|||||||
description: String(entry.description ?? ""),
|
description: String(entry.description ?? ""),
|
||||||
revision: Number(entry.revision ?? 0),
|
revision: Number(entry.revision ?? 0),
|
||||||
type,
|
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);
|
entries.set(key, values);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user