import test from 'node:test'; import assert from 'node:assert/strict'; import {SectionVoxelMap} from '../section-voxel-map.js'; import {decodeSection,applySectionView,applySectionBatch} from '../section-stream.js'; import {samplePhysicsWorld} from '../player-physics.js'; const record=(section,id=1)=>({section,palette:[id],runs:[4096,0]}); const view=()=>({world:'world',revision:0,blocks:new SectionVoxelMap(),loadedSections:new Set(),viewGeneration:0}); const message=(generation=1)=>({world:'world',revision:0,generation,view_center:[0,0,0],view_min:[-48,-32,-48],view_max:[63,47,63],unload:[]}); test('compact sections decode known air and preserve negative coordinates without per-voxel keys',()=>{ const world=new SectionVoxelMap(),cells=decodeSection(record([-1,-4,1],3)).cells; world.setSection('-1,-4,1',cells);assert.equal(world.getAt(-1,-64,16),3);assert.equal(world.size,4096);assert.equal(world.byteLength,4); world.delete('-1,-64,16');assert.equal(world.size,4095);assert.equal(world.getAt(-1,-64,16),0); world.setSection('0,0,0',new Uint32Array(4096));assert.equal(world.hasSection('0,0,0'),true);assert.equal(world.size,4095); assert.deepEqual([...world.materialIds()],[3]);world.deleteSection('-1,-4,1');assert.equal(world.size,0);assert.equal(world.sectionCount,1); }); test('malformed compact sections are rejected before any valid section is applied',()=>{ const v=view();applySectionView(v,message()); const bad={...record([1,0,0]),runs:[4097,0]}; assert.equal(applySectionBatch(v,{...message(),sections:[record([0,0,0]),bad]}).status,'resync');assert.equal(v.blocks.size,0); for(const runs of [[4095,0],[4096,1],[0,0],[4096.1,0],[4096,-1]])assert.throws(()=>decodeSection({...record([0,0,0]),runs})); }); test('new views retain overlap and reject delayed batches from previous generations',()=>{ const v=view();applySectionView(v,message()); applySectionBatch(v,{...message(),sections:[record([-3,0,0]),record([0,0,0])]});const cells=[...v.blocks.sectionEntries()][1][1]; const moved={...message(2),view_center:[16,0,0],view_min:[-32,-32,-48],view_max:[79,47,63],unload:[[-3,0,0]]}; assert.deepEqual(applySectionView(v,moved).unload,[[-3,0,0]]);assert.equal(v.blocks.hasSection('-3,0,0'),false); assert.equal([...v.blocks.sectionEntries()][0][1],cells); assert.equal(applySectionBatch(v,{...message(),sections:[record([-3,0,0])]}).status,'ignored'); assert.equal(v.blocks.hasSection('-3,0,0'),false); }); test('collision sampling distinguishes missing terrain from a received air section',()=>{ const world=new SectionVoxelMap(),body={position:[8,3,8],velocity:[0,0,0],pose:'standing'},bounds={min:[0,0,0],max:[15,15,15]}; assert.equal(samplePhysicsWorld(body,world,new Map(),bounds),null); world.setSection('0,0,0',new Uint32Array(4096));assert.deepEqual(samplePhysicsWorld(body,world,new Map(),bounds),{blocks:[]}); }); test('uniform sections remain compact across worker copies and expand only when edited',()=>{ const world=new SectionVoxelMap(); world.setSection('0,0,0',new Uint32Array([7])); world.setSection('1,0,0',new Uint32Array([0])); assert.equal(world.byteLength,8);assert.equal(world.size,4096); const samples=[];world.forEachBlock((x,y,z,id)=>samples.push([x,y,z,id]),{min:[14,0,0],max:[17,0,0]}); assert.deepEqual(samples,[[14,0,0,7],[15,0,0,7]]); assert.equal([...world.keysInSection('1,0,0')].length,0); world.set('15,0,0',9);assert.equal(world.byteLength,16388); assert.equal(world.getAt(14,0,0),7);assert.equal(world.getAt(15,0,0),9); assert.deepEqual([...world.materialIds()],[7,9]); world.deleteSection('0,0,0');assert.equal(world.byteLength,4);assert.equal(world.size,0); world.clear();assert.equal(world.byteLength,0); }); test('full-height worlds allow flight above the ceiling but still require interior collision data',()=>{ const blocks=new SectionVoxelMap(),bounds={min:[-32,-64,-32],max:[47,319,47],fullHeight:true}; const body={position:[8,400,8],velocity:[0,0,0],pose:'standing'}; assert.deepEqual(samplePhysicsWorld(body,blocks,new Map(),bounds),{blocks:[]}); body.position[1]=310;assert.equal(samplePhysicsWorld(body,blocks,new Map(),bounds),null); blocks.setSection('0,19,0',new Uint32Array([0])); assert.deepEqual(samplePhysicsWorld(body,blocks,new Map(),bounds),{blocks:[]}); }); test('large uniform batches load compactly and reject oversized batches atomically',()=>{ const v=view(),m={...message(),view_min:[-48,-64,-48],view_max:[63,319,63],full_height:true}; applySectionView(v,m); const sections=Array.from({length:128},(_,i)=>record([i%7-3,Math.floor(i/7)-4,0],0)); assert.equal(applySectionBatch(v,{...m,sections}).status,'applied'); assert.equal(v.blocks.sectionCount,128);assert.equal(v.blocks.byteLength,512); const oversized=[...sections,record([0,0,1])]; assert.equal(applySectionBatch(v,{...m,sections:oversized}).status,'resync'); assert.equal(v.blocks.hasSection('0,0,1'),false); });