Files
shacraft-core/client/tests/texture-pack.test.js
Emil c7e86663d8
MVP checks / mvp (push) Waiting to run
Expand voxel gameplay, lighting, full-height streaming and world imports
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.
2026-09-17 02:10:53 +03:00

71 lines
4.0 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import {prepareTexturePack, textureSubset, BLOCK_FACES} from '../texture-pack.js';
import {getBlockFaceTextures, getFaceUV} from '../block-textures.js';
import {buildSectionMesh} from '../mesh-geometry.js';
const limits = {layers:256, size:2048};
const files = new Map([['atlas.png', {}]]);
const descriptor = () => ({pixel_size:32, atlas:{path:'atlas.png', columns:40, rows:32},
textures:Array.from({length:1269}, (_,i)=>({name:`tile_${i}`}))});
test('atlas supports the full catalog on a GPU with only 256 array layers', () => {
const result = prepareTexturePack(descriptor(), files, limits);
assert.deepEqual([result.width,result.height,result.layers.size],[1280,1024,1269]);
assert.equal(result.layers.get('tile_1268'),1268);
const regular = {...descriptor(),atlas:undefined};
assert.throws(()=>prepareTexturePack(regular,files,limits),/размер/);
});
test('atlas bounds, verified resources, and names are validated before allocating GPU memory', () => {
assert.throws(()=>prepareTexturePack(descriptor(),new Map(),limits),/атлас/);
assert.throws(()=>prepareTexturePack(descriptor(),files,{...limits,size:1024}),/видеокарты/);
for(const atlas of [{path:'atlas.png',columns:1,rows:1},{path:'atlas.png',columns:40.5,rows:32}])
assert.throws(()=>prepareTexturePack({...descriptor(),atlas},files,limits),/атлас/);
for(const textures of [[{name:'same'},{name:'same'}],[{}],[{name:'../escape'}]])
assert.throws(()=>prepareTexturePack({...descriptor(),textures},files,limits),/ресурс/);
});
test('state faces and UV transforms survive worker transfer and reach section geometry', () => {
const d=descriptor();
const face={texture:'tile_1268',tint:[.4,.7,.3],cutout:true,uv:[0,0,1,0,0,-1,0,1]};
d.block_faces={sets:[Array(6).fill(face),Array(6).fill(null)],
states:{'minecraft:test[facing=east,half=top]':0},defaults:{'minecraft:test':1}};
const {layers}=prepareTexturePack(d,files,limits);
const cloned=new Map(structuredClone([...layers]));
const state='minecraft:test[half=top,facing=east]';
const faces=getBlockFaceTextures(state,cloned);
assert.equal(faces[0].layer,1268);
assert.deepEqual(getFaceUV(0,[.25,.5,.75],state,faces[0]),[.75,.5]);
assert.deepEqual(getBlockFaceTextures('minecraft:test',cloned),Array(6).fill(null));
const mesh=buildSectionMesh({id:'0,0,0',blocks:new Map([['0,0,0',1]]),
materials:new Map([[1,{state,color:[255,255,255],render:[{min:[0,0,0],max:[1,1,1]}]}]]),textureLayers:cloned});
for(let i=0;i<mesh.vertices.length;i+=20){
assert.equal(mesh.vertices[i+13],1268);
assert.equal(mesh.vertices[i+11],mesh.vertices[i+2]);
assert.equal(mesh.vertices[i+12],1-mesh.vertices[i+1]);
}
});
test('bad state references and non-finite face data cannot enter mesh workers', () => {
for(const face of [{texture:'missing'},{texture:'tile_0',tint:[NaN,1,1]},
{texture:'tile_0',uv:Array(8).fill(Infinity)}]){
const d=descriptor();d.block_faces={sets:[Array(6).fill(face)],states:{},defaults:{}};
assert.throws(()=>prepareTexturePack(d,files,limits),/гран/);
}
const d=descriptor();d.block_faces={sets:[Array(6).fill(null)],states:{'minecraft:stone':9},defaults:{}};
assert.throws(()=>prepareTexturePack(d,files,limits),/состояние/);
});
test('edit snapshots send only nearby state mappings from a large texture catalog',()=>{
const d=descriptor();
d.block_faces={sets:[Array(6).fill({texture:'tile_0'}),Array(6).fill({texture:'tile_1'})],
states:{'minecraft:stone':0,'minecraft:dirt':1},defaults:{'minecraft:stone':0,'minecraft:dirt':1}};
const {layers}=prepareTexturePack(d,files,limits);
const subset=textureSubset(layers,new Map([[1,{state:'minecraft:dirt'}]]));
assert.equal(subset.get(BLOCK_FACES).sets.length,1);
assert.deepEqual(Object.keys(subset.get(BLOCK_FACES).states),['minecraft:dirt']);
assert.equal(getBlockFaceTextures('minecraft:dirt',subset)[0].layer,1);
assert.equal(layers.get(BLOCK_FACES).sets.length,2);
});