forked from phenom/healer-man
Update Healer Man server
This commit is contained in:
1 parent
6114a2295f
commit
69809f7228
593 files changed
+903643
-40774
No files matched your search
@@ -0,0 +1,69 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { createHash } from "node:crypto";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import { NodeIO } from "@gltf-transform/core";
|
||||
import { ALL_EXTENSIONS } from "@gltf-transform/extensions";
|
||||
|
||||
const option = name => process.argv.find(value => value.startsWith(`--${name}=`))?.slice(name.length + 3);
|
||||
const stage = option("stage-root") ?? "artifacts/playtest/rom-room-coverage/native-alpha-stage";
|
||||
const slugs = (option("slugs") ?? "cave-water-dragon,kulech-bones-nest,mystic-altar,raksha-temple,sardo-castle,tomb-seven-heroes").split(",");
|
||||
const reportName = option("report-name") ?? "native-waterfall-alpha-stage-report.json";
|
||||
const sha = bytes => createHash("sha256").update(bytes).digest("hex");
|
||||
const io = new NodeIO().registerExtensions(ALL_EXTENSIONS);
|
||||
function accessor(value) {
|
||||
if (!value) return null;
|
||||
const array = value.getArray();
|
||||
assert.ok(array);
|
||||
return { type: value.getType(), componentType: value.getComponentType(), normalized: value.getNormalized(),
|
||||
count: value.getCount(), sha256: sha(new Uint8Array(array.buffer, array.byteOffset, array.byteLength)) };
|
||||
}
|
||||
function layout(document) {
|
||||
const root = document.getRoot();
|
||||
const meshes = root.listMeshes();
|
||||
const nodes = root.listNodes();
|
||||
return {
|
||||
meshes: meshes.map(mesh => ({ name: mesh.getName(), primitives: mesh.listPrimitives().map(primitive => ({
|
||||
mode: primitive.getMode(), indices: accessor(primitive.getIndices()),
|
||||
attributes: Object.fromEntries(primitive.listSemantics().sort().map(name => [name, accessor(primitive.getAttribute(name))])),
|
||||
targets: primitive.listTargets().map(target => Object.fromEntries(target.listSemantics().sort().map(name => [name, accessor(target.getAttribute(name))]))),
|
||||
})) })),
|
||||
nodes: nodes.map(node => ({ name: node.getName(), translation: node.getTranslation(), rotation: node.getRotation(),
|
||||
scale: node.getScale(), weights: node.getWeights(), mesh: meshes.indexOf(node.getMesh()),
|
||||
children: node.listChildren().map(child => nodes.indexOf(child)) })),
|
||||
scenes: root.listScenes().map(scene => ({ name: scene.getName(), children: scene.listChildren().map(node => nodes.indexOf(node)) })),
|
||||
};
|
||||
}
|
||||
function images(document) {
|
||||
return document.getRoot().listTextures().map(texture => ({ name: texture.getName(), mimeType: texture.getMimeType(),
|
||||
sha256: sha(texture.getImage()) })).sort((a, b) => JSON.stringify(a).localeCompare(JSON.stringify(b)));
|
||||
}
|
||||
function binHash(bytes) {
|
||||
for (let offset = 12; offset < bytes.length;) {
|
||||
const length = bytes.readUInt32LE(offset);
|
||||
if (bytes.readUInt32LE(offset + 4) === 0x004e4942) return sha(bytes.subarray(offset + 8, offset + 8 + length));
|
||||
offset += length + 8;
|
||||
}
|
||||
throw new Error("Missing BIN chunk");
|
||||
}
|
||||
for (const slug of slugs) {
|
||||
const directory = process.argv.includes("--flat") ? stage : `${stage}/${slug}`;
|
||||
const report = JSON.parse(await readFile(`${directory}/${reportName}`, "utf8"));
|
||||
const sourceBytes = await readFile(report.sourceVisual.file);
|
||||
const stagedBytes = await readFile(report.stagedSource.file);
|
||||
assert.equal(sha(sourceBytes), report.sourceVisual.sha256);
|
||||
assert.equal(sha(stagedBytes), report.stagedSource.sha256);
|
||||
const source = await io.readBinary(sourceBytes);
|
||||
const staged = await io.readBinary(stagedBytes);
|
||||
const sourceLayout = layout(source), stagedLayout = layout(staged);
|
||||
const sourceImages = images(source), stagedImages = images(staged);
|
||||
assert.deepEqual(stagedLayout, sourceLayout, `${slug}: final staged geometry/transforms changed`);
|
||||
assert.deepEqual(stagedImages, sourceImages, `${slug}: final staged image bytes changed`);
|
||||
const proof = { schemaVersion: 1, dungeonId: slug, sourceSha256: sha(sourceBytes), stagedSha256: sha(stagedBytes),
|
||||
geometryAndHierarchyUnchanged: true, sourceImageBytesUnchanged: true,
|
||||
geometryLayoutSha256: sha(JSON.stringify(sourceLayout)), imageInventorySha256: sha(JSON.stringify(sourceImages)),
|
||||
meshCount: sourceLayout.meshes.length, nodeCount: sourceLayout.nodes.length, textureCount: sourceImages.length,
|
||||
sourceBinSha256: binHash(sourceBytes), stagedBinSha256: binHash(stagedBytes),
|
||||
note: "The JSON-only alpha patch retains BIN bytes. Subsequent native unlit semantics use NodeIO and may repack BIN layout; final decoded streams, hierarchy/TRS and image bytes are verified separately here." };
|
||||
await writeFile(`${directory}/final-source-layout-proof.json`, `${JSON.stringify(proof, null, 2)}\n`);
|
||||
console.log(`${slug}: final geometry, UVs, hierarchy and ${sourceImages.length} exact source images preserved`);
|
||||
}
|
||||
Reference in new issue
Block a user