73 lines
3.1 KiB
JavaScript
73 lines
3.1 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
import { decodeWotlkM2Effects, parseDbc, parseRunewakerImageRecords } from "./generate-manifest.mjs";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
function tinyDbc() {
|
|
const strings = Buffer.from("\0hello\0", "utf8");
|
|
const buffer = Buffer.alloc(20 + 8 + strings.length);
|
|
buffer.write("WDBC", 0, "ascii");
|
|
buffer.writeUInt32LE(1, 4);
|
|
buffer.writeUInt32LE(2, 8);
|
|
buffer.writeUInt32LE(8, 12);
|
|
buffer.writeUInt32LE(strings.length, 16);
|
|
buffer.writeUInt32LE(42, 20);
|
|
buffer.writeUInt32LE(1, 24);
|
|
strings.copy(buffer, 28);
|
|
return buffer;
|
|
}
|
|
|
|
test("parses numeric and string DBC fields", () => {
|
|
const table = parseDbc(tinyDbc(), "fixture");
|
|
assert.equal(table.row(0).uint(0), 42);
|
|
assert.equal(table.row(0).string(1), "hello");
|
|
});
|
|
|
|
test("classifies paths from fixed RuneWaker ImageObject records", () => {
|
|
const buffer = Buffer.alloc(140 + 3712);
|
|
buffer.writeInt32LE(1, 132);
|
|
buffer.writeInt32LE(573727, 140);
|
|
Buffer.from("model\\fx\\skill\\fire\\act_fireball01_f_i.ros\0", "ascii").copy(buffer, 140 + 300);
|
|
const records = parseRunewakerImageRecords(buffer, [573727]);
|
|
assert.deepEqual(records.get(573727), ["model/fx/skill/fire/act_fireball01_f_i.ros"]);
|
|
});
|
|
|
|
test("decodes supported WotLK M2 particle and ribbon records", () => {
|
|
const particleOffset = 304;
|
|
const buffer = Buffer.alloc(particleOffset + 476);
|
|
buffer.write("MD20", 0, "ascii");
|
|
buffer.writeUInt32LE(1, 296);
|
|
buffer.writeUInt32LE(particleOffset, 300);
|
|
buffer.writeUInt32LE(17, particleOffset);
|
|
buffer.writeUInt16LE(4, particleOffset + 20);
|
|
buffer.writeUInt16LE(9, particleOffset + 22);
|
|
buffer.writeUInt8(2, particleOffset + 40);
|
|
buffer.writeUInt8(1, particleOffset + 41);
|
|
buffer.writeUInt16LE(4, particleOffset + 48);
|
|
buffer.writeUInt16LE(8, particleOffset + 50);
|
|
buffer.writeUInt16LE(1, particleOffset + 56);
|
|
buffer.writeUInt32LE(3, particleOffset + 56 + 12);
|
|
const decoded = decodeWotlkM2Effects(buffer, "fixture");
|
|
assert.equal(decoded.particles[0].id, 17);
|
|
assert.equal(decoded.particles[0].textureIndex, 9);
|
|
assert.equal(decoded.particles[0].blendMode, 2);
|
|
assert.equal(decoded.particles[0].textureColumns, 8);
|
|
assert.equal(decoded.particles[0].tracks.emissionSpeed.interpolation, 1);
|
|
assert.equal(decoded.particles[0].tracks.emissionSpeed.keyCount, 3);
|
|
});
|
|
|
|
test("generated coverage packages every referenced source sound", () => {
|
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
const manifest = JSON.parse(fs.readFileSync(path.join(root, "public", "assets", "game", "combat-effects", "manifest.json"), "utf8"));
|
|
assert.equal(manifest.coverage.requested, manifest.coverage.authentic + manifest.coverage.fallback);
|
|
assert.deepEqual(manifest.coverage.audio.missing, []);
|
|
const sounds = manifest.entries.flatMap((entry) => entry.sounds ?? []);
|
|
assert.ok(sounds.length > 0);
|
|
for (const sound of sounds) {
|
|
assert.ok(sound.url?.startsWith("/assets/game/combat-effects/audio/"));
|
|
assert.ok(fs.existsSync(path.join(root, "public", sound.url)));
|
|
}
|
|
});
|