Files
healer-man/scripts/combat-effects/package-rom-particles.test.mjs
T
2026-09-24 16:42:43 -04:00

62 lines
2.9 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
import test from "node:test";
import { verifiedRuneWakerParticleModels } from "./rom-particle-readiness.mjs";
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const publicRoot = path.join(root, "public");
const index = JSON.parse(fs.readFileSync(path.join(publicRoot,
"assets/game/combat-effects/original/runewaker/manifest.json"), "utf8"));
function assetFile(url) {
assert.match(url, /^\/assets\/game\/combat-effects\/original\/runewaker\/[\w/.-]+\.(?:json|png|hlsl)$/);
const file = path.resolve(publicRoot, url.slice(1));
assert.ok(file.startsWith(`${publicRoot}${path.sep}`));
return file;
}
test("primary-five RuneWaker particle archive resolves its decoded graphs and textures", () => {
assert.equal(index.requestedModels, 123);
assert.equal(index.processedModels, index.requestedModels);
assert.equal(index.failedModels, 0);
assert.equal(index.results.length, index.requestedModels);
let spriteControllers = 0;
let textureReferences = 0;
for (const result of index.results) {
assert.ok(result.graphUrl, result.model);
const graph = JSON.parse(fs.readFileSync(assetFile(result.graphUrl), "utf8"));
assert.equal(graph.kind, "runewaker-ros-particle-archive");
assert.equal(graph.sourceModel, result.model);
assert.equal(graph.rendererReady, result.rendererReady);
assert.equal(result.rendererReady, verifiedRuneWakerParticleModels.has(result.model)
&& result.errors.length === 0
&& result.unsupported.every((type) => type === "CRuController_EventTrigger"));
assert.equal(graph.shader.name, "ruSHADER_PARTICLE_SPRITEEX");
for (const [stage, signature] of [["vertex", "VS_OUTPUT main"], ["pixel", "PS_OUTPUT main"]]) {
const shader = fs.readFileSync(assetFile(graph.shader[`${stage}SourceUrl`]), "utf8");
assert.ok(shader.includes(signature));
assert.ok(shader.endsWith("\n"));
assert.ok(!shader.trimEnd().endsWith("\\n\\"));
}
assert.equal(graph.textures.length, result.textures);
spriteControllers += result.spriteControllers;
for (const texture of graph.textures) {
const png = fs.readFileSync(assetFile(texture.url));
assert.equal(png.subarray(0, 8).toString("hex"), "89504e470d0a1a0a");
textureReferences++;
}
for (const motion of graph.motions) for (const controller of motion.controllers) {
if (controller.type === "sprite" && controller.textureAssetUrl) {
assert.ok(graph.textures.some((texture) => texture.url === controller.textureAssetUrl));
assert.equal(controller.shader, "ruSHADER_PARTICLE_SPRITEEX");
assert.ok(Array.isArray(controller.tileSizePixels));
}
if (controller.type === "emitter") assert.equal(controller.tracks.length, 27);
}
}
assert.equal(spriteControllers, 510);
assert.ok(textureReferences >= 103);
});