This commit is contained in:
2026-11-05 09:57:11 -05:00
parent d34388bf2c
commit 89e392cc2e
81 changed files with 12410 additions and 1135 deletions
+13 -5
View File
@@ -9,6 +9,7 @@ import path from 'node:path';
import { inflateSync } from 'node:zlib';
import { generateAssets } from '../scripts/assets.mjs';
import { CHARACTER_ART_MANIFEST, CHARACTER_OPTIONS, characterLayer, characterMesh, compositeCharacter } from '../scripts/character-art.mjs';
import { FAUNA_ART_MANIFEST } from '../scripts/fauna-art.mjs';
import { ANIMATIONS, ATLAS, PLAYER_HEIGHT, playerB3D, SAMPLE_RATE, SOUND_HASHES, SOUND_PROFILES, soundWAV, soundOGG, loadVorbisCodec, TOOL_NAMES, toolOBJ } from '../scripts/media.mjs';
import { inventory } from '../scripts/files.mjs';
import { packageGame, SOURCE, verifyPackage } from '../scripts/package.mjs';
@@ -142,7 +143,7 @@ for (const profile of CHARACTER_OPTIONS.bodies) test(`B3D ${profile} has bounded
const model = parseB3D(playerB3D(profile));
assert.deepEqual(model.animation,[0,100,24]);
assert.equal(model.chunks.filter(c => c==='MESH').length,1);
assert.equal(model.vertices.length,240); assert.equal(model.triangles.length,120);
assert.equal(model.vertices.length,384); assert.equal(model.triangles.length,192);
assert.equal(Math.max(...model.vertices.map(v => v[1])),PLAYER_HEIGHT);
assert.equal(Math.min(...model.vertices.map(v => v[1])),0);
assert.equal(PLAYER_HEIGHT/10,1.75);
@@ -195,8 +196,10 @@ test('all body profiles share exact rig, rigid assignments, UVs and 100 keys; on
widths.push(Math.max(...torso.map(v=>v[0])));
assert.ok(Math.max(...torso.filter(v=>v[1]===8).map(v=>v[0]))<widths.at(-1),'waist taper');
}
assert.ok(widths[0]<widths[1] && widths[1]<widths[2]);
assert.ok(Math.abs(Math.max(...balanced.bones.get('Head').weights.map(([id])=>balanced.vertices[id][0]))-1.6)<1e-6);
assert.ok(widths.length===CHARACTER_OPTIONS.bodies.length && widths.every((value,i)=>i===0||widths[i-1]<value));
assert.ok(Math.max(...balanced.bones.get('Head').weights.map(([id])=>balanced.vertices[id][0]))<=1.6);
assert.ok(Math.max(...balanced.bones.get('Head').weights.map(([id])=>balanced.vertices[id][2]))>1.5,
'added nose and ears stay within the existing broad head collision envelope');
for (const bad of ['toString','../broad','BALANCED',null,{},0]) assert.throws(()=>playerB3D(bad));
});
@@ -396,7 +399,7 @@ test('all mod Lua colors are scanned recursively; scripts and non-Lua are not in
assert.deepEqual(manifest.images,CHARACTER_ART_MANIFEST);
assert.deepEqual(manifest.options,CHARACTER_OPTIONS);
assert.deepEqual(manifest.meshes,CHARACTER_OPTIONS.bodies.map(body=>({body,filename:characterMesh(body)})));
assert.equal(names.filter(n=>n.startsWith('hearth_char_')).length,170);
assert.equal(names.filter(n=>n.startsWith('hearth_char_')).length,CHARACTER_ART_MANIFEST.length);
for (const {filename} of CHARACTER_ART_MANIFEST) {
const decoded=parsePNG(await fs.readFile(path.join(textures,filename))), layer=characterLayer(filename);
assert.equal(decoded.width,64); assert.equal(decoded.height,64);
@@ -428,7 +431,7 @@ test('original Ogg media is part of the verified package manifest without a runt
await fs.copyFile(path.join(SOURCE,name),path.join(source,name));
for (const name of ['init','model','runtime','content','encounters']) await fs.writeFile(path.join(source,'mods/hearth',name+'.lua'),'-- fixture\n');
const destination = path.join(root,'package'); await packageGame(destination,{source});
const {entries} = await verifyPackage(destination);
const {entries} = await verifyPackage(destination,{requireBundled:false});
for (const name of Object.keys(SOUND_PROFILES)) {
const entry = entries.find(e=>e.path===`mods/hearth/sounds/${name}.ogg`);
assert.ok(entry,name); assert.equal(entry.sha256,SOUND_HASHES[name]);
@@ -440,6 +443,11 @@ test('original Ogg media is part of the verified package manifest without a runt
assert.ok(entries.some(e=>e.path==='character-art.json'));
for (const {filename} of CHARACTER_ART_MANIFEST)
assert.ok(entries.some(e=>e.path===`mods/hearth/textures/${filename}`),filename);
for (const {id,mesh,texture} of FAUNA_ART_MANIFEST) {
assert.ok(entries.some(e=>e.path===`mods/hearth/models/${mesh}`),`${id} model`);
assert.ok(entries.some(e=>e.path===`mods/hearth/textures/${texture}`),`${id} texture`);
}
assert.ok(entries.some(e=>e.path==='fauna-art.json'));
for (const body of CHARACTER_OPTIONS.bodies)
assert.ok(entries.some(e=>e.path===`mods/hearth/models/${characterMesh(body)}`));
});