import test from "node:test"; import assert from "node:assert/strict"; import { composeWowAdtTerrainWeights, decodeWowAdtAlphaMap, wowAdtNormalizedUv } from "./wow-adt-terrain-material.mjs"; function layer(index, alphaMapEncoding, alphaMapDataOffset, alphaMapBytes, flags = 0x100) { return { index, usesAlphaMap: (flags & 0x100) !== 0, alphaMapCompressed: (flags & 0x200) !== 0, alphaMapAvailable: true, alphaMapEncoding, alphaMapDataOffset, alphaMapBytes, alphaOffset: alphaMapDataOffset, flags, }; } test("classic 4-bit maps expand and get deterministic edge repair", () => { const bytes = Buffer.alloc(2048, 0x21); const chunk = { indexX: 4, indexY: 7, flags: 0, layers: [] }; const decoded = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "packed-4", 0, 2048)); assert.equal(decoded[0], 17); assert.equal(decoded[1], 34); assert.equal(decoded[63], decoded[62]); assert.equal(decoded[63 * 64], decoded[62 * 64]); chunk.flags = 0x8000; const untouched = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "packed-4", 0, 2048)); assert.equal(untouched[63], 34); assert.equal(untouched[63 * 64], 17); }); test("classic 4-bit opacity layers become ordered residual weights", () => { const bytes = Buffer.alloc(4096, 0x88); const chunk = { indexX: 0, indexY: 0, flags: 0x8000, layers: [ { index: 0, usesAlphaMap: false }, layer(1, "packed-4", 0, 2048), layer(2, "packed-4", 2048, 2048), ], }; const weights = composeWowAdtTerrainWeights(bytes, chunk); assert.equal(weights.sourcePolicy, "classic-nibble-to-big-alpha"); assert.deepEqual(weights.channelLayerIndices, [1, 2]); assert.equal(weights.rgba[0], 63); // earlier overlay receives only remaining coverage assert.equal(weights.rgba[1], 136); // last layer remains topmost assert.equal(weights.rgba[2], 0); assert.equal(weights.rgba[3], 255); assert.equal(weights.maxWeightSum, 199); }); test("compressed 8-bit MCAL fills exactly one 64x64 map", () => { const packed = []; let remaining = 4096; while (remaining) { const count = Math.min(127, remaining); packed.push(0x80 | count, 37); remaining -= count; } const bytes = Buffer.from(packed); const chunk = { indexX: 1, indexY: 2, flags: 0x8000, layers: [] }; const decoded = decodeWowAdtAlphaMap(bytes, chunk, layer(1, "rle-8", 0, bytes.length, 0x300)); assert.equal(decoded.length, 4096); assert.equal(decoded[0], 37); assert.equal(decoded[4095], 37); assert.throws(() => decodeWowAdtAlphaMap(Buffer.from([0x81]), chunk, layer(1, "rle-8", 0, 1, 0x300)), /truncated MCAL fill/); }); test("normalized MCVT UVs follow source-positive local rows and stagger", () => { assert.deepEqual(wowAdtNormalizedUv(0, 0), [0, 0]); assert.deepEqual(wowAdtNormalizedUv(1, 0), [0.0625, 0.0625]); assert.deepEqual(wowAdtNormalizedUv(16, 8), [1, 1]); });