code wiki / _hdl_build / nx_wasm_mineworld_html.nx
nx_wasm_mineworld_html.nx source
↩ module page · 28 lines · 5151 B
1// nx_wasm_mineworld_html.nx -- SOVEREIGN packager for MineWorld (the INFINITE procgen voxel world). Emits a
2// self-contained playable .html whose JS is LOGIC-FREE (operator law): NO Math.*, NO physics, NO camera code --
3// the wasm core owns the whole sim (start/tick/render_cam/dig/put with integer trig). The page only captures
4// raw input (key bitmask, pointer-lock mouse deltas), calls tick+render_cam per rAF, and blits the framebuffer.
5// usage: nx_wasm_mineworld_html <in.wasm> <out.html>. license_tier: ORIGINAL
6import "nx_syscalls.nx"
7import "nx_base64.nx"
8
9func hw(fd: i64, s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } sys_write(fd, s, n); return 0 }
10
11func main(argc: i64, argv: *i64) -> i64 {
12 if argc < 3 { hw(2, "usage: nx_wasm_mineworld_html <in.wasm> <out.html>\n" as *u8); return 2 }
13 let wlen_p: *i64 = sys_mmap(8) as *i64
14 let wbytes: *u8 = sys_read_file(argv[1] as *u8, wlen_p)
15 if (wbytes as i64) == 0 { hw(2, "read wasm failed\n" as *u8); return 3 }
16 let wlen: i64 = wlen_p[0]
17 let b64: *u8 = sys_mmap(wlen * 2 + 64) as *u8
18 let b64len: i64 = b64_encode(wbytes, wlen, b64)
19 let fd: i64 = sys_openat_wr(argv[2] as *u8, 0x1a4)
20 if fd < 0 { hw(2, "open html failed\n" as *u8); return 4 }
21 hw(fd, "<!doctype html><html><head><meta charset='utf-8'><title>Nishi MineWorld -- infinite sovereign voxel world</title><style>html,body{background:#000;margin:0;height:100%;overflow:hidden;font-family:sans-serif;color:#cdd}#wrap{display:flex;align-items:center;justify-content:center;height:100vh;width:100vw}canvas{image-rendering:pixelated;width:100vw;height:100vh;object-fit:contain;background:#9ec3e6;cursor:pointer}#hud{position:fixed;top:10px;left:0;right:0;text-align:center;font-size:13px;color:#aef;text-shadow:0 1px 2px #000;pointer-events:none}</style></head><body><div id='wrap'><canvas id='c'></canvas></div><div id='hud'>click to play · WASD walk · mouse look · L-dig R-place · Space jump · F fly · G FULLSCREEN · I/O flip look axes — INFINITE procgen world, the ENTIRE game runs in sovereign wasm: no engine, no DirectX, zero JS game logic</div><script>\n" as *u8)
22 hw(fd, "const B='" as *u8)
23 sys_write(fd, b64, b64len)
24 hw(fd, "';\nconst hud=document.getElementById('hud');function diag(m){hud.textContent=m;}window.onerror=(m,s,l)=>{diag('JS ERROR: '+m+' @line '+l);};\nconst bytes=Uint8Array.from(atob(B),c=>c.charCodeAt(0));\nWebAssembly.instantiate(bytes).then(r=>{const ex=r.instance.exports;const W=Number(ex.ww()),H=Number(ex.hh()),off=Number(ex.fb_off());const cv=document.getElementById('c');cv.width=W;cv.height=H;const ctx=cv.getContext('2d');const img=ctx.createImageData(W,H);const mem=new Uint8Array(ex.memory.buffer);ex.start();let modn=0;if(location.hash.indexOf('#mod=')===0){for(const rec of location.hash.slice(5).split(';')){const p=rec.split(',');if(p.length===4){const pk=v=>((v>>16)&255)|(((v>>8)&255)<<8)|((v&255)<<16);const h1=parseInt(p[1],16),h2=parseInt(p[2],16);if(!isNaN(h1)&&!isNaN(h2)&&Number(ex.pack_block(BigInt(p[0]|0),BigInt(pk(h1)),BigInt(pk(h2)),BigInt(p[3]|0)))===0)modn++;}}}let keys=0,adx=0,ady=0,frames=0;const t0=performance.now();const KM={KeyW:1,KeyS:2,KeyA:4,KeyD:8,Space:16,ShiftLeft:32,ShiftRight:32,KeyF:64,KeyI:128,KeyO:256};addEventListener('keydown',e=>{keys|=(KM[e.code]||0);if(e.code=='Space')e.preventDefault();if(e.code=='KeyG'){if(document.fullscreenElement)document.exitFullscreen();else document.documentElement.requestFullscreen();}});addEventListener('keyup',e=>{keys&=~(KM[e.code]||0);});addEventListener('mousemove',e=>{if(document.pointerLockElement===cv){adx+=e.movementX;ady+=e.movementY;}});cv.addEventListener('mousedown',e=>{if(document.pointerLockElement!==cv){cv.requestPointerLock();return;}e.preventDefault();if(e.button===0)ex.dig();else if(e.button===2)ex.put();});cv.addEventListener('contextmenu',e=>e.preventDefault());function inv(){const s=Number(ex.invert_state());return 'invert Y:'+((s>=10)?'on':'off')+' X:'+((s%10)?'on':'off');}function frame(){try{ex.tick(BigInt(keys),BigInt(adx),BigInt(ady));adx=0;ady=0;ex.render_cam();for(let i=0;i<W*H;i++){const b=off+i*8;img.data[i*4]=mem[b];img.data[i*4+1]=mem[b+1];img.data[i*4+2]=mem[b+2];img.data[i*4+3]=255;}ctx.putImageData(img,0,0);ctx.fillStyle='rgba(255,255,255,0.8)';ctx.fillRect((W>>1)-1,(H>>1)-5,2,11);ctx.fillRect((W>>1)-5,(H>>1)-1,11,2);frames++;if(frames===1){const ns=Number(ex.drawn_px());diag('BUILD R10-VISUAL ok'+(modn?' MOD:'+modn+' block(s) loaded from URL':'')+', frame1 terrain-px='+ns+(ns<6000?' MOSTLY SKY - REPORT THIS':' - WASD, mouse, L-dig R-place, Space jump, F fly, I/O flip axes; #mod=id,top,side,style re-skins'));}if(frames%240===0){diag('R10-VISUAL '+Math.round(frames*1000/(performance.now()-t0))+' fps - '+inv()+' (I/O to flip) - WASD, L-dig R-place, Space jump, F fly');}}catch(e){diag('GAME ERROR: '+e);return;}requestAnimationFrame(frame);}frame();}).catch(e=>{diag('WASM LOAD ERROR: '+e);});\n</script></body></html>\n" as *u8)
25 sys_close(fd)
26 hw(1, "nx_wasm_mineworld_html: wrote html (logic-free JS)\n" as *u8)
27 return 0
28}