62 lines
2.9 KiB
JavaScript
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);
|
|
});
|