MVP checks / mvp (push) Canceled after 0s
Add shared Rust/WASM physics, worker meshing and diagnostics, 64-chunk full-height streaming, atlas texture support, and baseline world import. Document the current implementation and include the supplied in-game lobby screenshot.
87 lines
5.7 KiB
JavaScript
87 lines
5.7 KiB
JavaScript
import test from "node:test";
|
|
import assert from "node:assert/strict";
|
|
import { normalizeViewDistance, viewDistanceProfile, MAX_VIEW_CELLS, MAX_LIGHT_CELLS } from "../view-distance.js";
|
|
import { applySectionView, applySectionBatch } from "../section-stream.js";
|
|
import { SectionVoxelMap } from "../section-voxel-map.js";
|
|
import { buildBlockLight } from "../block-light.js";
|
|
import {actorLightBounds} from '../terrain-state.js';
|
|
|
|
const message = (radius, generation, center = [0, 64, 0]) => ({
|
|
world: "test", revision: 7, generation, view_distance: radius,
|
|
view_center: center, view_min: center.map((v,i) => v - (i===1?2:radius)*16),
|
|
view_max: center.map((v,i) => v + (i===1?3:radius+1)*16-1),
|
|
unload: [], total_sections: (radius*2+1)**2*5,
|
|
});
|
|
test("distance settings are bounded and projection, fog and memory scale together", () => {
|
|
for (const value of [null, undefined, "bad", 1, 65, 3.5, Infinity]) assert.equal(normalizeViewDistance(value), 3);
|
|
assert.equal(normalizeViewDistance("8"), 8);
|
|
const initial=viewDistanceProfile(3), maximum=viewDistanceProfile(64);
|
|
assert.equal(initial.sections, 1176); assert.equal(maximum.sections, 399384);
|
|
assert.equal(maximum.width, 2064); assert.equal(maximum.streamVoxelBytes, MAX_VIEW_CELLS*4);
|
|
assert.ok(maximum.drawRadius>initial.drawRadius);
|
|
assert.ok(maximum.farClip>maximum.drawRadius);
|
|
assert.ok(maximum.fogDistance>initial.fogDistance);
|
|
});
|
|
test("resizing retains overlapping arrays, accepts the far ring and ignores obsolete batches", () => {
|
|
const view={world:"test",revision:7,viewGeneration:0,blocks:new SectionVoxelMap(),loadedSections:new Set()};
|
|
applySectionView(view,message(3,1));
|
|
const cells=new Uint32Array(4096).fill(1);view.blocks.setSection("0,4,0",cells);view.loadedSections.add("0,4,0");
|
|
assert.deepEqual(applySectionView(view,message(8,2)),{unload:[]});
|
|
assert.equal(view.totalSections,1445);assert.equal([...view.blocks.sectionEntries()][0][1],cells);
|
|
const batch={world:"test",revision:7,generation:2,sections:[{section:[8,4,8],palette:[0],runs:[4096,0]}]};
|
|
assert.equal(applySectionBatch(view,batch).status,"applied");
|
|
const shrunk=applySectionView(view,message(2,3));
|
|
assert.deepEqual(shrunk.unload,[[8,4,8]]);assert.equal(view.totalSections,125);
|
|
assert.equal(view.blocks.sectionCount,1);assert.equal([...view.blocks.sectionEntries()][0][1],cells);
|
|
assert.equal(applySectionBatch(view,batch).status,"ignored");
|
|
assert.equal(applySectionView(view,message(66,4)),"resync");
|
|
});
|
|
test("the maximum view permits the small air margin beyond the playable border", () => {
|
|
const view={world:"test",revision:7,viewGeneration:0,blocks:new SectionVoxelMap(),loadedSections:new Set()};
|
|
assert.notEqual(applySectionView(view,message(8,1,[29_999_872,64,-29_999_872])),"resync");
|
|
assert.equal(applySectionBatch(view,{world:"test",revision:7,generation:1,sections:[{section:[1_875_000,4,-1_874_992],palette:[0],runs:[4096,0]}]}).status,"applied");
|
|
});
|
|
test("lighting accepts the largest negotiated volume and still rejects larger allocations", () => {
|
|
const bounds={min:[0,0,0],max:[303,79,303]};
|
|
const columns=new Map();
|
|
for(let x=0;x<19;x++)for(let z=0;z<19;z++)columns.set(`${x},${z}`,new Int16Array(256).fill(100));
|
|
const field=buildBlockLight(new SectionVoxelMap(),new Map(),bounds,columns);
|
|
assert.equal(field.data.length,MAX_LIGHT_CELLS*4);assert.equal(field.sample([130,50,130]).skyLevel,0);
|
|
assert.throws(()=>buildBlockLight(new Map(),new Map(),{min:[0,0,0],max:[304,80,304]}),RangeError);
|
|
});
|
|
|
|
test('buffered views fit the allocation bound while preserving the requested render distance',()=>{
|
|
const view={world:'test',revision:7,viewGeneration:0,blocks:new SectionVoxelMap(),loadedSections:new Set()};
|
|
const expanded={...message(9,1),view_distance:8,stream_radius:9};
|
|
assert.deepEqual(applySectionView(view,expanded),{unload:[]});
|
|
assert.equal(view.totalSections,1805);assert.equal(viewDistanceProfile(8).streamSections,8664);
|
|
assert.equal(applySectionView(view,message(66,2)),'resync');
|
|
});
|
|
|
|
test('64 chunk radius accepts the outer buffer without allocating a giant light volume',()=>{
|
|
const view={world:'test',revision:7,viewGeneration:0,blocks:new SectionVoxelMap(),loadedSections:new Set()};
|
|
assert.deepEqual(applySectionView(view,{...message(65,1),view_distance:64,stream_radius:65}),{unload:[]});
|
|
assert.equal(view.totalSections,85805);
|
|
assert.equal(applySectionBatch(view,{world:'test',revision:7,generation:1,sections:[
|
|
{section:[64,4,-64],palette:[5],runs:[4096,0]},
|
|
{section:[65,4,65],palette:[0],runs:[4096,0]},
|
|
]}).status,'applied');
|
|
assert.equal(view.blocks.getAt(1024,64,-1024),5);
|
|
assert.equal(view.blocks.byteLength,8);
|
|
const bounds=actorLightBounds(view.viewBounds);
|
|
assert.equal((bounds.max[0]-bounds.min[0]+1)*(bounds.max[2]-bounds.min[2]+1),112**2);
|
|
assert.ok(112**2*80<MAX_LIGHT_CELLS);
|
|
});
|
|
|
|
test('full-height views keep ground and ceiling across vertical flight, including above the world',()=>{
|
|
const view={world:'test',revision:7,viewGeneration:0,blocks:new SectionVoxelMap(),loadedSections:new Set()};
|
|
const full={...message(65,1),full_height:true,view_min:[-1040,-64,-1040],view_max:[1055,319,1055],total_sections:411864};
|
|
assert.deepEqual(applySectionView(view,full),{unload:[]});
|
|
const sections=[{section:[0,-4,0],palette:[1],runs:[4096,0]}, {section:[0,19,0],palette:[2],runs:[4096,0]}];
|
|
assert.equal(applySectionBatch(view,{world:'test',revision:7,generation:1,sections}).status,'applied');
|
|
assert.deepEqual(applySectionView(view,{...full,generation:2,view_center:[0,512,0]}),{unload:[]});
|
|
assert.equal(view.blocks.getAt(0,-64,0),1);assert.equal(view.blocks.getAt(0,319,0),2);
|
|
assert.equal(view.totalSections,411864);assert.equal(view.viewBounds.fullHeight,true);
|
|
assert.equal(applySectionView(view,{...full,generation:3,view_min:[-1040,-48,-1040]}),'resync');
|
|
});
|