Files
shacraft-core/client/edit-mesh-controller.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

44 lines
2.2 KiB
JavaScript

/** Small independent edit jobs cannot queue behind whole-view lighting. */
export class EditMeshController {
constructor({capture,onError=()=>{},workerFactory}={}) {
this.capture=capture;this.onError=onError;this.epoch=0;this.job=0;
this.pending=new Map();this.tickets=new Map();this.ready=new Map();this.busy=null;
try {
this.worker=workerFactory ? workerFactory() : new Worker(new URL('./edit-mesh-worker.js',import.meta.url),{type:'module'});
this.worker.onmessage=({data})=>this.receive(data);
this.worker.onerror=event=>{event.preventDefault();this.fail(event.message);};
} catch(error) {this.fail(error.message);}
}
fail(error) {this.error=error;this.dispose();this.onError(error);}
request(ids) {
if(this.error||this.disposed)return;
for(const id of ids) {
const job=++this.job;
this.pending.set(id,job);this.tickets.set(id,job);this.ready.delete(id);
}
}
cancel(id) {this.pending.delete(id);this.tickets.delete(id);this.ready.delete(id);}
reset() {this.epoch++;this.pending.clear();this.tickets.clear();this.ready.clear();this.busy=null;}
isCurrent(result) {return result.epoch===this.epoch&&this.tickets.get(result.id)===result.editJob;}
pump() {
if(this.error||this.disposed||this.busy||this.ready.size>=2||!this.pending.size)return;
const [id,editJob]=this.pending.entries().next().value;
this.pending.delete(id);
try {
const start=performance.now(),packet={...this.capture(id),epoch:this.epoch,editJob};
const transfers=packet.sections.map(s=>s.cells.buffer);
if(packet.light)transfers.push(packet.light.data.buffer,packet.light.blockLevels.buffer,packet.light.skyLevels.buffer);
this.busy={id,editJob,epoch:this.epoch};this.worker.postMessage(packet,transfers);
this.prepareMilliseconds=performance.now()-start;
} catch(error) {this.fail(error.message);}
}
receive(result) {
if(this.disposed||result.epoch!==this.epoch||result.editJob!==this.busy?.editJob)return;
this.busy=null;
if(!this.isCurrent(result))return;
if(result.error){this.fail(result.error);return;}
this.meshMilliseconds=result.milliseconds;this.ready.set(result.id,result);
}
dispose() {this.disposed=true;this.reset();this.worker?.terminate();}
}