MVP checks / mvp (push) Waiting to run
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.
44 lines
2.2 KiB
JavaScript
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();}
|
|
}
|