murow 0.0.73 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -1
- package/dist/cjs/core/binary-codec/binary-codec.js +1 -1
- package/dist/cjs/core/driver/driver.js +1 -1
- package/dist/cjs/core/driver/drivers/immediate.js +1 -1
- package/dist/cjs/core/driver/drivers/raf.js +1 -1
- package/dist/cjs/core/driver/drivers/timeout.js +1 -1
- package/dist/cjs/core/input/index.js +1 -1
- package/dist/cjs/core/input/mouse-look/index.js +1 -0
- package/dist/cjs/core/input/mouse-look/mouse-look.js +1 -0
- package/dist/cjs/core/input/scroll-zoom/index.js +1 -0
- package/dist/cjs/core/input/scroll-zoom/scroll-zoom.js +1 -0
- package/dist/cjs/ecs/component.js +1 -1
- package/dist/cjs/ecs/system-builder.js +1 -1
- package/dist/cjs/ecs/world.js +1 -1
- package/dist/cjs/game/loop/loop.js +1 -1
- package/dist/cjs/net/adapters/bun-websocket.js +1 -1
- package/dist/esm/core/binary-codec/binary-codec.js +1 -1
- package/dist/esm/core/driver/drivers/immediate.js +1 -1
- package/dist/esm/core/driver/drivers/raf.js +1 -1
- package/dist/esm/core/driver/drivers/timeout.js +1 -1
- package/dist/esm/core/input/index.js +1 -1
- package/dist/esm/core/input/mouse-look/index.js +1 -0
- package/dist/esm/core/input/mouse-look/mouse-look.js +1 -0
- package/dist/esm/core/input/scroll-zoom/index.js +1 -0
- package/dist/esm/core/input/scroll-zoom/scroll-zoom.js +1 -0
- package/dist/esm/ecs/component.js +1 -1
- package/dist/esm/ecs/system-builder.js +1 -1
- package/dist/esm/ecs/world.js +1 -1
- package/dist/esm/game/loop/loop.js +1 -1
- package/dist/esm/net/adapters/bun-websocket.js +1 -1
- package/dist/netcode/cjs/index.js +1552 -0
- package/dist/netcode/esm/index.js +1530 -0
- package/dist/netcode/types/client/game-client.d.ts +125 -0
- package/dist/netcode/types/client/index.d.ts +1 -0
- package/dist/netcode/types/client/interpolation-buffer.d.ts +37 -0
- package/dist/netcode/types/client/interpolation-buffer.test.d.ts +1 -0
- package/dist/netcode/types/codec/delta-codec.d.ts +17 -0
- package/dist/netcode/types/codec/delta-codec.test.d.ts +1 -0
- package/dist/netcode/types/codec/index.d.ts +1 -0
- package/dist/netcode/types/components/index.d.ts +1 -0
- package/dist/netcode/types/components/sync-spec.d.ts +43 -0
- package/dist/netcode/types/components/sync-spec.test.d.ts +1 -0
- package/dist/netcode/types/ctx.d.ts +105 -0
- package/dist/netcode/types/ctx.test.d.ts +1 -0
- package/dist/netcode/types/handlers/define-handlers.d.ts +47 -0
- package/dist/netcode/types/handlers/index.d.ts +1 -0
- package/dist/netcode/types/index.d.ts +11 -0
- package/dist/netcode/types/integration.test.d.ts +1 -0
- package/dist/netcode/types/intents/define-intents.d.ts +53 -0
- package/dist/netcode/types/intents/define-intents.test.d.ts +1 -0
- package/dist/netcode/types/intents/index.d.ts +1 -0
- package/dist/netcode/types/network/base.d.ts +120 -0
- package/dist/netcode/types/network/index.d.ts +2 -0
- package/dist/netcode/types/network/transport.d.ts +1 -0
- package/dist/netcode/types/packets/convergence.test.d.ts +1 -0
- package/dist/netcode/types/packets/harness.d.ts +103 -0
- package/dist/netcode/types/packets/index.d.ts +2 -0
- package/dist/netcode/types/packets/intermittent-intents.test.d.ts +1 -0
- package/dist/netcode/types/packets/pathological.test.d.ts +1 -0
- package/dist/netcode/types/packets/peer-interpolation.test.d.ts +1 -0
- package/dist/netcode/types/packets/reordering.test.d.ts +1 -0
- package/dist/netcode/types/packets/virtual-network.d.ts +65 -0
- package/dist/netcode/types/predictions/define-predictions.d.ts +45 -0
- package/dist/netcode/types/predictions/define-predictions.test.d.ts +1 -0
- package/dist/netcode/types/predictions/index.d.ts +1 -0
- package/dist/netcode/types/reconciliation.test.d.ts +1 -0
- package/dist/netcode/types/rpcs/define-rpcs.d.ts +44 -0
- package/dist/netcode/types/rpcs/define-rpcs.test.d.ts +1 -0
- package/dist/netcode/types/rpcs/index.d.ts +1 -0
- package/dist/netcode/types/server/game-server.d.ts +77 -0
- package/dist/netcode/types/server/index.d.ts +2 -0
- package/dist/netcode/types/server/plugins/aoi-grid.d.ts +34 -0
- package/dist/netcode/types/server/plugins/index.d.ts +3 -0
- package/dist/netcode/types/server/plugins/lag-compensation.d.ts +34 -0
- package/dist/netcode/types/server/plugins/plugin.d.ts +24 -0
- package/dist/netcode/types/tick-rate.test.d.ts +1 -0
- package/dist/netcode/types/transports/index.d.ts +1 -0
- package/dist/netcode/types/transports/memory-transport.d.ts +51 -0
- package/dist/netcode/types/types.test.d.ts +1 -0
- package/dist/types/core/binary-codec/binary-codec.d.ts +89 -31
- package/dist/types/core/driver/driver.d.ts +8 -8
- package/dist/types/core/driver/drivers/immediate.d.ts +4 -4
- package/dist/types/core/driver/drivers/raf.d.ts +6 -6
- package/dist/types/core/driver/drivers/timeout.d.ts +4 -4
- package/dist/types/core/input/index.d.ts +2 -0
- package/dist/types/core/input/mouse-look/index.d.ts +1 -0
- package/dist/types/core/input/mouse-look/mouse-look.d.ts +139 -0
- package/dist/types/core/input/scroll-zoom/index.d.ts +1 -0
- package/dist/types/core/input/scroll-zoom/scroll-zoom.d.ts +38 -0
- package/dist/types/ecs/component.d.ts +67 -11
- package/dist/types/ecs/entity-handle.d.ts +5 -5
- package/dist/types/ecs/system-builder.d.ts +13 -0
- package/dist/types/ecs/world.d.ts +72 -4
- package/dist/types/game/loop/loop.d.ts +21 -2
- package/dist/types/net/adapters/bun-websocket.d.ts +19 -3
- package/dist/webgpu/cjs/index.js +120 -5
- package/dist/webgpu/esm/index.js +120 -5
- package/dist/webgpu/types/3d/renderer.d.ts +38 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ High-performance ECS with **SoA (Structure of Arrays)** storage, bitmask queries
|
|
|
42
42
|
- `EntityHandle` — Fluent chainable entity API
|
|
43
43
|
|
|
44
44
|
### [Game](./src/game) — Game loop abstractions
|
|
45
|
-
- [`GameLoop`](./src/game/loop) — Client/server tick loop with
|
|
45
|
+
- [`GameLoop`](./src/game/loop) — Client/server tick loop with `sync` / `pre-tick` / `tick` / `post-tick` / `render` phases, plus input tracking and frame interpolation
|
|
46
46
|
|
|
47
47
|
### [Protocol](./src/protocol) — Networking primitives
|
|
48
48
|
Minimalist networking primitives:
|
|
@@ -80,6 +80,20 @@ import { WebGPU2DRenderer, WebGPU3DRenderer } from 'murow/webgpu';
|
|
|
80
80
|
|
|
81
81
|
See [WebGPU README](../webgpu/README.md) for full documentation.
|
|
82
82
|
|
|
83
|
+
### [Netcode](./src/../netcode) — Multiplayer layer
|
|
84
|
+
Opinionated multiplayer layer built on the `Protocol` and `Network`
|
|
85
|
+
primitives above. Adds snapshot-based state sync, client-side prediction
|
|
86
|
+
with rollback, jitter interpolation, server-pushed entity assignment,
|
|
87
|
+
and spatial-interest plugins.
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { GameServer, GameClient, defineIntents, definePredictions } from 'murow/netcode';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
See [Netcode README](../netcode/README.md) for full documentation. If
|
|
94
|
+
its opinions don't fit, drop down to the `Protocol` and `Network`
|
|
95
|
+
primitives directly.
|
|
96
|
+
|
|
83
97
|
## Building
|
|
84
98
|
|
|
85
99
|
```bash
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var F=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var U=Object.getOwnPropertyNames;var m=Object.prototype.hasOwnProperty;var A=(s,e)=>{for(var t in e)F(s,t,{get:e[t],enumerable:!0})},z=(s,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of U(e))!m.call(s,o)&&o!==t&&F(s,o,{get:()=>e[o],enumerable:!(r=w(e,o))||r.enumerable});return s};var p=s=>z(F({},"__esModule",{value:!0}),s);var M={};A(M,{BaseBinaryCodec:()=>g,BinaryCodec:()=>T,BinaryPrimitives:()=>n,bool:()=>B,color:()=>H,f16:()=>V,f32:()=>j,f64:()=>E,i16:()=>k,i32:()=>h,i8:()=>S,string:()=>D,u16:()=>I,u32:()=>_,u8:()=>N,vec2:()=>O,vec2_le:()=>$,vec3:()=>C,vec3_le:()=>K,vec4_le:()=>R});module.exports=p(M);const f=Symbol("schemaSize");function b(s){const e=s[f];if(e!==void 0)return e;let t=0;for(const r of Object.keys(s))t+=s[r].size;return s[f]=t,t}class g{static encodeInto(e,t){const r=b(e),o=new ArrayBuffer(r),l=new DataView(o);let a=0;for(const i of Object.keys(e)){const c=e[i];c.write(l,a,t[i]),a+=c.size}return new Uint8Array(o)}static decodeInto(e,t,r){const o=b(e);if(t.byteLength<o)throw new RangeError(`Buffer too small: expected ${o} bytes, got ${t.byteLength}`);const l=new DataView(t.buffer,t.byteOffset,t.byteLength);let a=0;for(const i of Object.keys(e)){const c=e[i];r[i]=c.read(l,a),a+=c.size}return r}}class n{static{this.u8={size:1,write:(e,t,r)=>e.setUint8(t,r),read:(e,t)=>e.getUint8(t),toNil:()=>0}}static{this.u16={size:2,write:(e,t,r)=>e.setUint16(t,r,!1),read:(e,t)=>e.getUint16(t,!1),toNil:()=>0}}static{this.u32={size:4,write:(e,t,r)=>e.setUint32(t,r,!1),read:(e,t)=>e.getUint32(t,!1),toNil:()=>0}}static{this.i8={size:1,write:(e,t,r)=>e.setInt8(t,r),read:(e,t)=>e.getInt8(t),toNil:()=>0}}static{this.i16={size:2,write:(e,t,r)=>e.setInt16(t,r,!1),read:(e,t)=>e.getInt16(t,!1),toNil:()=>0}}static{this.i32={size:4,write:(e,t,r)=>e.setInt32(t,r,!1),read:(e,t)=>e.getInt32(t,!1),toNil:()=>0}}static{this.f16={size:2,write:(e,t,r)=>{const o=new Float32Array(1),l=new Uint32Array(o.buffer);o[0]=r;const a=l[0],i=a>>>31&1;let c=a>>>23&255,u=a&8388607,y;if(c===255)y=i<<15|31744|(u?512:0);else if(c===0)y=i<<15;else{const d=c-127+15;if(d>=31)y=i<<15|31744;else if(d<=0)y=i<<15;else{const x=u>>>13;y=i<<15|d<<10|x}}e.setUint16(t,y,!1)},read:(e,t)=>{const r=e.getUint16(t,!1),o=r>>>15&1,l=r>>>10&31,a=r&1023;let i;if(l===0)i=o<<31;else if(l===31)i=o<<31|255<<23|(a?a<<13:0);else{const y=l-15+127;i=o<<31|y<<23|a<<13}const c=new Uint32Array([i]);return new Float32Array(c.buffer)[0]},toNil:()=>0}}static{this.f32={size:4,write:(e,t,r)=>e.setFloat32(t,r,!1),read:(e,t)=>e.getFloat32(t,!1),toNil:()=>0}}static{this.f64={size:8,write:(e,t,r)=>e.setFloat64(t,r,!1),read:(e,t)=>e.getFloat64(t,!1),toNil:()=>0}}static{this.bool={size:1,write:(e,t,r)=>e.setUint8(t,r?1:0),read:(e,t)=>e.getUint8(t)!==0,toNil:()=>!1}}static string(e){return{size:e+2,write(t,r,o){const a=new TextEncoder().encode(o);if(a.length>e)throw new RangeError(`String too long, max ${e} bytes`);t.setUint16(r,a.length,!1);for(let i=0;i<a.length;i++)t.setUint8(r+2+i,a[i]);for(let i=a.length;i<e;i++)t.setUint8(r+2+i,0)},read(t,r){const o=t.getUint16(r,!1),l=new Uint8Array(o);for(let a=0;a<o;a++)l[a]=t.getUint8(r+2+a);return new TextDecoder().decode(l)},toNil:()=>""}}static{this.vec2={size:8,write(e,t,r){e.setFloat32(t,r.x,!1),e.setFloat32(t+4,r.y,!1)},read(e,t){return{x:e.getFloat32(t,!1),y:e.getFloat32(t+4,!1)}},toNil:()=>({x:0,y:0})}}static{this.vec3={size:12,write(e,t,r){e.setFloat32(t,r.x,!1),e.setFloat32(t+4,r.y,!1),e.setFloat32(t+8,r.z,!1)},read(e,t){return{x:e.getFloat32(t,!1),y:e.getFloat32(t+4,!1),z:e.getFloat32(t+8,!1)}},toNil:()=>({x:0,y:0,z:0})}}static{this.color={size:4,write(e,t,r){e.setUint8(t,r.r),e.setUint8(t+1,r.g),e.setUint8(t+2,r.b),e.setUint8(t+3,r.a)},read(e,t){return{r:e.getUint8(t),g:e.getUint8(t+1),b:e.getUint8(t+2),a:e.getUint8(t+3)}},toNil:()=>({r:0,g:0,b:0,a:0})}}static{this.f32_le={size:4,write:(e,t,r)=>e.setFloat32(t,r,!0),read:(e,t)=>e.getFloat32(t,!0),toNil:()=>0}}static{this.f64_le={size:8,write:(e,t,r)=>e.setFloat64(t,r,!0),read:(e,t)=>e.getFloat64(t,!0),toNil:()=>0}}static{this.u16_le={size:2,write:(e,t,r)=>e.setUint16(t,r,!0),read:(e,t)=>e.getUint16(t,!0),toNil:()=>0}}static{this.u32_le={size:4,write:(e,t,r)=>e.setUint32(t,r,!0),read:(e,t)=>e.getUint32(t,!0),toNil:()=>0}}static{this.i16_le={size:2,write:(e,t,r)=>e.setInt16(t,r,!0),read:(e,t)=>e.getInt16(t,!0),toNil:()=>0}}static{this.i32_le={size:4,write:(e,t,r)=>e.setInt32(t,r,!0),read:(e,t)=>e.getInt32(t,!0),toNil:()=>0}}static{this.vec2_le={size:8,write:(e,t,r)=>{e.setFloat32(t,r[0],!0),e.setFloat32(t+4,r[1],!0)},read:(e,t)=>[e.getFloat32(t,!0),e.getFloat32(t+4,!0)],toNil:()=>[0,0]}}static{this.vec3_le={size:12,write:(e,t,r)=>{e.setFloat32(t,r[0],!0),e.setFloat32(t+4,r[1],!0),e.setFloat32(t+8,r[2],!0)},read:(e,t)=>[e.getFloat32(t,!0),e.getFloat32(t+4,!0),e.getFloat32(t+8,!0)],toNil:()=>[0,0,0]}}static{this.vec4_le={size:16,write:(e,t,r)=>{e.setFloat32(t,r[0],!0),e.setFloat32(t+4,r[1],!0),e.setFloat32(t+8,r[2],!0),e.setFloat32(t+12,r[3],!0)},read:(e,t)=>[e.getFloat32(t,!0),e.getFloat32(t+4,!0),e.getFloat32(t+8,!0),e.getFloat32(t+12,!0)],toNil:()=>[0,0,0,0]}}}class T extends g{static{this.u8=n.u8}static{this.u16=n.u16}static{this.u32=n.u32}static{this.i8=n.i8}static{this.i16=n.i16}static{this.i32=n.i32}static{this.f16=n.f16}static{this.f32=n.f32}static{this.bool=n.bool}static{this.string=n.string}static{this.vec2=n.vec2}static{this.vec3=n.vec3}static{this.color=n.color}static encode(e,t){return this.encodeInto(e,t)}static decode(e,t,r){return this.decodeInto(e,t,r)}}const N=n.u8,I=n.u16,_=n.u32,S=n.i8,k=n.i16,h=n.i32,V=n.f16,j=n.f32,E=n.f64,B=n.bool,D=n.string,O=n.vec2,C=n.vec3,$=n.vec2_le,K=n.vec3_le,R=n.vec4_le,H=n.color;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var v=Object.defineProperty;var n=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var
|
|
1
|
+
var v=Object.defineProperty;var n=Object.getOwnPropertyDescriptor;var d=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var a=(i,e)=>{for(var o in e)v(i,o,{get:e[o],enumerable:!0})},s=(i,e,o,m)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of d(e))!p.call(i,t)&&t!==o&&v(i,t,{get:()=>e[t],enumerable:!(m=n(e,t))||m.enumerable});return i};var u=i=>s(v({},"__esModule",{value:!0}),i);var f={};a(f,{ImmediateDriver:()=>r.ImmediateDriver,RafDriver:()=>r.RafDriver,TimeoutDriver:()=>r.TimeoutDriver,createDriver:()=>D});module.exports=u(f);var r=require("./drivers");function D(i,e){return i==="server-immediate"?new r.ImmediateDriver(e):i==="server-timeout"?new r.TimeoutDriver(e):new r.RafDriver(e)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var o=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(e,t)=>{for(var r in t)o(e,r,{get:t[r],enumerable:!0})},m=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of a(t))!p.call(e,i)&&i!==r&&o(e,i,{get:()=>t[i],enumerable:!(n=s(t,i))||n.enumerable});return e};var u=e=>m(o({},"__esModule",{value:!0}),e);var h={};l(h,{ImmediateDriver:()=>c});module.exports=u(h);class c{constructor(t){this.update=t;this.last=performance.now();this.running=!1;this.loop=()=>{if(!this.running)return;const t=performance.now(),r=(t-this.last)/1e3;this.last=t,this.update(r),setImmediate(this.loop)}}start(){this.running=!0,this.last=performance.now(),this.loop()}stop(){this.running=!1}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var u=(t,i)=>{for(var
|
|
1
|
+
var s=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var o=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var u=(t,i)=>{for(var e in i)s(t,e,{get:i[e],enumerable:!0})},m=(t,i,e,r)=>{if(i&&typeof i=="object"||typeof i=="function")for(let n of o(i))!d.call(t,n)&&n!==e&&s(t,n,{get:()=>i[n],enumerable:!(r=l(i,n))||r.enumerable});return t};var h=t=>m(s({},"__esModule",{value:!0}),t);var p={};u(p,{RafDriver:()=>a});module.exports=h(p);class a{constructor(i){this.update=i;this.last=performance.now();this.running=!1;this.rafId=null;this.visibilityHandler=null;this.loop=()=>{if(!this.running)return;const i=performance.now(),e=i-this.last;this.last=i;const r=Math.min(e,a.MAX_DELTA_MS)/1e3;this.update(r),requestAnimationFrame(this.loop)}}static{this.MAX_DELTA_MS=250}start(){this.running=!0,this.last=performance.now(),typeof document<"u"&&!this.visibilityHandler&&(this.visibilityHandler=()=>{document.visibilityState==="visible"&&(this.last=performance.now())},document.addEventListener("visibilitychange",this.visibilityHandler)),this.rafId=requestAnimationFrame(this.loop)}stop(){this.running=!1,this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.visibilityHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var i=Object.defineProperty;var
|
|
1
|
+
var i=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var a=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var l=(o,t)=>{for(var e in t)i(o,e,{get:t[e],enumerable:!0})},u=(o,t,e,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of a(t))!p.call(o,r)&&r!==e&&i(o,r,{get:()=>t[r],enumerable:!(n=s(t,r))||n.enumerable});return o};var m=o=>u(i({},"__esModule",{value:!0}),o);var f={};l(f,{TimeoutDriver:()=>h});module.exports=m(f);const c=1;class h{constructor(t){this.update=t;this.last=performance.now();this.running=!1;this.loop=()=>{if(!this.running)return;const t=performance.now(),e=(t-this.last)/1e3;this.last=t,this.update(e),setTimeout(this.loop,c)}}start(){this.running=!0,this.last=performance.now(),this.loop()}stop(){this.running=!1}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var m=(p,
|
|
1
|
+
var n=Object.defineProperty;var s=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var a=Object.prototype.hasOwnProperty;var m=(t,p,f,x)=>{if(p&&typeof p=="object"||typeof p=="function")for(let e of y(p))!a.call(t,e)&&e!==f&&n(t,e,{get:()=>p[e],enumerable:!(x=s(p,e))||x.enumerable});return t},r=(t,p,f)=>(m(t,p,"default"),f&&m(f,p,"default"));var h=t=>m(n({},"__esModule",{value:!0}),t);var o={};module.exports=h(o);r(o,require("./manager"),module.exports);r(o,require("./sources"),module.exports);r(o,require("./mouse-look"),module.exports);r(o,require("./scroll-zoom"),module.exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var p=(r,o,f,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of c(o))!d.call(r,e)&&e!==f&&a(r,e,{get:()=>o[e],enumerable:!(x=b(o,e))||x.enumerable});return r},t=(r,o,f)=>(p(r,o,"default"),f&&p(f,o,"default"));var g=r=>p(a({},"__esModule",{value:!0}),r);var m={};module.exports=g(m);t(m,require("./mouse-look"),module.exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var a=Object.defineProperty;var l=Object.getOwnPropertyDescriptor;var u=Object.getOwnPropertyNames;var p=Object.prototype.hasOwnProperty;var d=(o,t)=>{for(var i in t)a(o,i,{get:t[i],enumerable:!0})},y=(o,t,i,e)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of u(t))!p.call(o,n)&&n!==i&&a(o,n,{get:()=>t[n],enumerable:!(e=l(t,n))||e.enumerable});return o};var m=o=>y(a({},"__esModule",{value:!0}),o);var w={};d(w,{MouseLook:()=>v});module.exports=m(w);class v{constructor(t={}){this.lockedElement=null;this.pendingLockCleanup=null;this._forward=new Float32Array(3);this._right=new Float32Array(3);this._up=new Float32Array(3);this._orbit=new Float32Array(3);this.sensitivity=t.sensitivity??.002;const i=t.yaw??{};this.yaw=i.initial??0,this.yawMin=i.min??-1/0,this.yawMax=i.max??1/0;const e=t.pitch??{};this.pitch=e.initial??0,this.pitchMin=e.min??-Math.PI/2+.01,this.pitchMax=e.max??Math.PI/2-.01,this.invertX=t.invertX??!1,this.invertY=t.invertY??!1,this.drag=t.drag??!0,this.dragButton=t.dragButton??"left"}update(t){const i=t.mouse[this.dragButton];if(!(this.locked||this.drag&&i.down))return;const n=t.mouse.delta.position.x,r=t.mouse.delta.position.y;n===0&&r===0||(this.yaw-=n*this.sensitivity*(this.invertX?-1:1),this.yaw<this.yawMin?this.yaw=this.yawMin:this.yaw>this.yawMax&&(this.yaw=this.yawMax),this.pitch-=r*this.sensitivity*(this.invertY?-1:1),this.pitch<this.pitchMin?this.pitch=this.pitchMin:this.pitch>this.pitchMax&&(this.pitch=this.pitchMax))}lock(t){const i=t.requestPointerLock;if(typeof i!="function")return Promise.reject(new Error("Pointer Lock unsupported"));this.lockedElement=t;const e=i.call(t);return e&&typeof e.then=="function"?e:new Promise((n,r)=>{const s=()=>{document.removeEventListener("pointerlockchange",h),document.removeEventListener("pointerlockerror",c),this.pendingLockCleanup===s&&(this.pendingLockCleanup=null)},h=()=>{s(),document.pointerLockElement===t?n():r(new Error("Pointer Lock denied"))},c=()=>{s(),r(new Error("Pointer Lock denied"))};document.addEventListener("pointerlockchange",h),document.addEventListener("pointerlockerror",c),this.pendingLockCleanup=s})}unlock(){typeof document<"u"&&document.exitPointerLock&&document.exitPointerLock()}get locked(){return typeof document>"u"||this.lockedElement===null?!1:document.pointerLockElement===this.lockedElement}get forward(){const t=Math.cos(this.pitch),i=this._forward;return i[0]=Math.sin(this.yaw)*t,i[1]=Math.sin(this.pitch),i[2]=Math.cos(this.yaw)*t,i}get right(){const t=this._right;return t[0]=Math.cos(this.yaw),t[1]=0,t[2]=-Math.sin(this.yaw),t}get up(){const t=Math.sin(this.pitch),i=this._up;return i[0]=-Math.sin(this.yaw)*t,i[1]=Math.cos(this.pitch),i[2]=-Math.cos(this.yaw)*t,i}orbit(t,i){const e=Math.cos(this.pitch),n=this._orbit;return n[0]=t[0]+i*e*Math.sin(this.yaw),n[1]=t[1]+i*Math.sin(this.pitch),n[2]=t[2]+i*e*Math.cos(this.yaw),n}destroy(){this.pendingLockCleanup?.(),this.pendingLockCleanup=null,this.unlock(),this.lockedElement=null}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var a=Object.defineProperty;var b=Object.getOwnPropertyDescriptor;var c=Object.getOwnPropertyNames;var d=Object.prototype.hasOwnProperty;var p=(r,o,f,x)=>{if(o&&typeof o=="object"||typeof o=="function")for(let e of c(o))!d.call(r,e)&&e!==f&&a(r,e,{get:()=>o[e],enumerable:!(x=b(o,e))||x.enumerable});return r},t=(r,o,f)=>(p(r,o,"default"),f&&p(f,o,"default"));var g=r=>p(a({},"__esModule",{value:!0}),r);var m={};module.exports=g(m);t(m,require("./scroll-zoom"),module.exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var n=Object.defineProperty;var a=Object.getOwnPropertyDescriptor;var r=Object.getOwnPropertyNames;var u=Object.prototype.hasOwnProperty;var l=(t,i)=>{for(var s in i)n(t,s,{get:i[s],enumerable:!0})},o=(t,i,s,m)=>{if(i&&typeof i=="object"||typeof i=="function")for(let e of r(i))!u.call(t,e)&&e!==s&&n(t,e,{get:()=>i[e],enumerable:!(m=a(i,e))||m.enumerable});return t};var h=t=>o(n({},"__esModule",{value:!0}),t);var c={};l(c,{ScrollZoom:()=>v});module.exports=h(c);class v{constructor(i){this.value=i.initial,this.min=i.min,this.max=i.max,this.sensitivity=i.sensitivity??.01}update(i){const s=i.mouse.delta.scroll.y;s!==0&&(this.value+=s*this.sensitivity,this.value<this.min?this.value=this.min:this.value>this.max&&(this.value=this.max))}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var r=Object.defineProperty;var d=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var f=Object.prototype.hasOwnProperty;var h=(n,e)=>{for(var o in e)r(n,o,{get:e[o],enumerable:!0})},T=(n,e,o,c)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of y(e))!f.call(n,t)&&t!==o&&r(n,t,{get:()=>e[t],enumerable:!(c=d(e,t))||c.enumerable});return n};var C=n=>T(r({},"__esModule",{value:!0}),n);var u={};h(u,{defineComponent:()=>b});module.exports=C(u);var m=require("../core/pooled-codec");function x(n){let e=0;for(const o of Object.keys(n))e+=n[o].size;return e}function b(n,e){const o=typeof e=="object"&&e!==null&&"schema"in e&&"sync"in e,c=o?e.schema:e,t=o?e.sync:void 0,i=x(c),s=Object.keys(c),S=s.length,p=m.PooledCodec.array(c),a={name:n,schema:c,size:i,fieldCount:S,fieldNames:s,arrayCodec:p};return t!==void 0&&(a.__sync=t),a}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var g=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var
|
|
1
|
+
var g=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var w=Object.getOwnPropertyNames;var I=Object.prototype.hasOwnProperty;var k=(c,e)=>{for(var n in e)g(c,n,{get:e[n],enumerable:!0})},v=(c,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of w(e))!I.call(c,i)&&i!==n&&g(c,i,{get:()=>e[i],enumerable:!(o=F(e,i))||o.enumerable});return c};var E=c=>v(g({},"__esModule",{value:!0}),c);var P={};k(P,{ExecutableSystem:()=>h,SystemBuilder:()=>m});module.exports=E(P);class m{constructor(e,n,o,i,t){this.world=e;this.components=n;this.fieldMappings=o;this.userCallback=i;this.conditionPredicate=t}query(...e){return new m(this.world,e,this.fieldMappings,this.userCallback,this.conditionPredicate)}fields(e){return new m(this.world,this.components,e,this.userCallback,this.conditionPredicate)}when(e){if(!this.fieldMappings)throw new Error("Must call .fields() before .when()");const n={};for(let t=0;t<this.components.length;t++){const a=this.components[t],l=this.fieldMappings[t];if(!l)continue;const d=Object.keys(l)[0],y=l[d];for(const s of y){const p=`${d}_${s}`,r=this.world.getFieldArray(a,s);n[p]=r}}const o={eid:0};for(const t in n){const a=n[t];Object.defineProperty(o,t,{get(){return a[this.eid]},set(l){a[this.eid]=l},enumerable:!0,configurable:!1}),o[`${t}_array`]=a}Object.seal(o);const i=e;return new m(this.world,this.components,this.fieldMappings,this.userCallback,i)}run(e){return new m(this.world,this.components,this.fieldMappings,e,this.conditionPredicate).buildAndRegister()}buildAndRegister(){if(!this.userCallback)throw new Error("System callback must be set");if(!this.fieldMappings)throw new Error("Field mappings must be set");const e=this.world,n=this.components,o=this.fieldMappings,i=this.userCallback,t={},a={},l=[];for(let r=0;r<n.length;r++){const u=n[r],f=o[r];if(!f)continue;const x=Object.keys(f)[0],M=f[x];l.push(x),a[x]=u,t[x]={};for(const C of M){const b=e.getFieldArray(u,C);t[x][C]=b}}const d=[];for(const r of l){const u=t[r];for(const f in u)d.push({prop:`${r}_${f}`,array:u[f]})}e.query(...n);const y=e._getQueryMaskKey(n),s=e.getQueryMask(n),p=new h(e,n,i,d,y,s,this.conditionPredicate);return e._registerSystem(p),p}}class h{constructor(e,n,o,i,t,a,l){this.world=e;this.components=n;this.userCallback=o;this.fieldDescs=i;this.queryMaskKey=t;this.queryMask=a;this.conditionPredicate=l;this.syncedComponentIndices=[];this.proxyEntity=this.createProxyEntity();for(const d of n)d.__sync!==void 0&&d.__worldIndex!==void 0&&this.syncedComponentIndices.push(d.__worldIndex)}execute(e){const n=this.world._queryByMaskKey(this.queryMaskKey,this.queryMask),o=this.userCallback,i=this.world,t=this.proxyEntity,a=n.length,l=this.syncedComponentIndices,d=l.length;if(!this.conditionPredicate&&d===0){for(let s=0;s<a;s++)t.eid=n[s],o(t,e,i);return}if(!this.conditionPredicate){for(let s=0;s<a;s++){const p=n[s];t.eid=p,o(t,e,i);for(let r=0;r<d;r++)i.markDirty(p,l[r])}return}const y=this.conditionPredicate;if(d===0){for(let s=0;s<a;s++)t.eid=n[s],y(t)&&o(t,e,i);return}for(let s=0;s<a;s++){const p=n[s];if(t.eid=p,y(t)){o(t,e,i);for(let r=0;r<d;r++)i.markDirty(p,l[r])}}}createProxyEntity(){const e=this.world,n={eid:0,despawn(){e.despawn(this.eid)}};for(let o=0;o<this.fieldDescs.length;o++){const{prop:i,array:t}=this.fieldDescs[o];n[`${i}_array`]=t,Object.defineProperty(n,i,{get(){return t[this.eid]},set(a){t[this.eid]=a},enumerable:!0,configurable:!1})}return Object.seal(n),Object.preventExtensions(n),n}getComponents(){return this.components}}
|
package/dist/cjs/ecs/world.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var C=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var k=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var I=(d,l)=>{for(var t in l)C(d,t,{get:l[t],enumerable:!0})},T=(d,l,t,e)=>{if(l&&typeof l=="object"||typeof l=="function")for(let n of k(l))!b.call(d,n)&&n!==t&&C(d,n,{get:()=>l[n],enumerable:!(e=A(l,n))||e.enumerable});return d};var B=d=>T(C({},"__esModule",{value:!0}),d);var U={};I(U,{World:()=>$});module.exports=B(U);var g=require("../core/generate-id"),x=require("./component-store"),M=require("./entity-handle"),w=require("./world-systems");class $ extends w.WorldSystems{constructor(t){super();this.nextEntityId=0;this.freeEntityHead=0;this.freeEntityTail=0;this.freeEntityCount=0;this.freeEntityMask=0;this.aliveEntitiesArray=[];this.numMaskWords=0;this.components=[];this.queryResultBuffers={};this.archetypeVersion=0;this.queryCacheVersions={};this.queryMaskCache={};this.despawnedCount=0;this.worldId=(0,g.generateId)({prefix:"world_"});this.maxEntities=t.maxEntities??1e4,this.numMaskWords=Math.ceil(t.components.length/32),this.componentMasks=[];for(let n=0;n<this.numMaskWords;n++)this.componentMasks.push(new Uint32Array(this.maxEntities));this.numMaskWords>0&&(this.componentMasks0=this.componentMasks[0]);const e=Math.pow(2,Math.ceil(Math.log2(this.maxEntities)));this.freeEntityIds=new Uint32Array(e),this.freeEntityMask=e-1,this.aliveEntitiesIndices=new Uint32Array(this.maxEntities),this.aliveEntityFlags=new Uint8Array(this.maxEntities),this.despawnedBuffer=new Uint32Array(this.maxEntities),this.componentStoresArray=new Array(t.components.length),t.components.forEach((n,s)=>{this.components.push(n),n.__worldIndex=s;const c=new x.ComponentStore(n,this.maxEntities);this.componentStoresArray[s]=c})}getComponentIndex(t){const e=t.__worldIndex;if(e===void 0){const n=this.components.map(s=>s.name).join(", ");throw new Error(`Component ${t.name} not registered in World[${this.worldId}]. Registered components: [${n}]. Did you forget to include it in the WorldConfig?`)}return e}setComponentBit(t,e){const n=e>>>5,s=e&31;this.componentMasks[n][t]|=1<<s}clearComponentBit(t,e){const n=e>>>5,s=e&31;this.componentMasks[n][t]&=~(1<<s)}hasComponentBit(t,e){const n=e>>>5,s=e&31;return(this.componentMasks[n][t]&1<<s)!==0}clearAllComponentBits(t){if(this.numMaskWords===1)this.componentMasks0[t]=0;else if(this.numMaskWords===2)this.componentMasks0[t]=0,this.componentMasks[1][t]=0;else if(this.numMaskWords===3)this.componentMasks0[t]=0,this.componentMasks[1][t]=0,this.componentMasks[2][t]=0;else for(let e=0;e<this.numMaskWords;e++)this.componentMasks[e][t]=0}matchesComponentMask(t,e){const n=e.length;if(n===1)return(this.componentMasks0[t]&e[0])===e[0];if(n===2)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1];if(n===3)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2];if(n===4)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2]&&(this.componentMasks[3][t]&e[3])===e[3];for(let s=0;s<n;s++)if((this.componentMasks[s][t]&e[s])!==e[s])return!1;return!0}getQueryMask(t){const e=t.map(i=>i.name).sort().join(","),n=this.queryMaskCache[e];if(n)return n;let s=-1;const c=[];for(const i of t){const o=i.__worldIndex;if(o===void 0)return null;c.push(o),o>s&&(s=o)}const h=Math.floor(s/32)+1,p=new Array(h).fill(0);for(const i of c){const o=i>>>5,r=i&31;p[o]|=1<<r}return this.queryMaskCache[e]=p,p}maskToKey(t){let e="";for(let n=0;n<t.length;n++)t[n]!==0&&(e+=`${n}:${t[n].toString(36)},`);return e}_getQueryMaskKey(t){const e=this.getQueryMask(t);return e?this.maskToKey(e):""}_queryByMaskKey(t,e){let n=this.queryResultBuffers[t];if(n||(n=[],this.queryResultBuffers[t]=n),this.queryCacheVersions[t]===this.archetypeVersion)return n;const s=this.aliveEntitiesArray,c=s.length,h=e.length;let p=0;if(h===1){const i=e[0],o=this.componentMasks0;for(let r=0;r<c;r++){const a=s[r];(o[a]&i)===i&&(n[p++]=a)}}else if(h===2){const i=e[0],o=e[1],r=this.componentMasks0,a=this.componentMasks[1];for(let m=0;m<c;m++){const y=s[m];(r[y]&i)===i&&(a[y]&o)===o&&(n[p++]=y)}}else if(h===3){const i=e[0],o=e[1],r=e[2],a=this.componentMasks0,m=this.componentMasks[1],y=this.componentMasks[2];for(let f=0;f<c;f++){const u=s[f];(a[u]&i)===i&&(m[u]&o)===o&&(y[u]&r)===r&&(n[p++]=u)}}else if(h===4){const i=e[0],o=e[1],r=e[2],a=e[3],m=this.componentMasks0,y=this.componentMasks[1],f=this.componentMasks[2],u=this.componentMasks[3];for(let v=0;v<c;v++){const E=s[v];(m[E]&i)===i&&(y[E]&o)===o&&(f[E]&r)===r&&(u[E]&a)===a&&(n[p++]=E)}}else{const i=this.componentMasks;t:for(let o=0;o<c;o++){const r=s[o];for(let a=0;a<h;a++)if((i[a][r]&e[a])!==e[a])continue t;n[p++]=r}}return n.length=p,this.queryCacheVersions[t]=this.archetypeVersion,n}spawn(){let t=this.nextEntityId;if(this.freeEntityCount>0?(t=this.freeEntityIds[this.freeEntityTail],this.freeEntityTail=this.freeEntityTail+1&this.freeEntityMask,this.freeEntityCount--):this.nextEntityId++,t>=this.maxEntities)throw new Error(`Maximum entities (${this.maxEntities}) reached. Current alive: ${this.aliveEntitiesArray.length}, Free list: ${this.freeEntityCount}`);return this.aliveEntityFlags[t]=1,this.aliveEntitiesIndices[t]=this.aliveEntitiesArray.length,this.aliveEntitiesArray.push(t),this.clearAllComponentBits(t),this.invalidateQueryCache(),t}despawn(t){if(this.aliveEntityFlags[t]===0)return;this.despawnedBuffer[this.despawnedCount++]=t,this.aliveEntityFlags[t]=0;const e=this.aliveEntitiesIndices[t],n=this.aliveEntitiesArray.length-1;if(e!==n){const h=this.aliveEntitiesArray[n];this.aliveEntitiesArray[e]=h,this.aliveEntitiesIndices[h]=e}this.aliveEntitiesArray.pop();const s=this.componentStoresArray,c=this.components.length;for(let h=0;h<c;h++)this.hasComponentBit(t,h)&&s[h].clear(t);this.clearAllComponentBits(t),this.freeEntityIds[this.freeEntityHead]=t,this.freeEntityHead=this.freeEntityHead+1&this.freeEntityMask,this.freeEntityCount++,this.invalidateQueryCache()}isAlive(t){return this.aliveEntityFlags[t]===1}getDespawned(){return this.despawnedBuffer.subarray(0,this.despawnedCount)}flushDespawned(){this.despawnedCount=0}invalidateQueryCache(){this.archetypeVersion++}add(t,e,n){if(this.aliveEntityFlags[t]===0)throw new Error(`Cannot add component ${e.name} to entity ${t}: entity is not alive (was it despawned?). Current alive entities: ${this.aliveEntitiesArray.length}`);const s=this.getComponentIndex(e),c=this.componentStoresArray[s];this.setComponentBit(t,s),c.set(t,n),this.invalidateQueryCache()}remove(t,e){const n=e.__worldIndex;if(n===void 0)return;this.clearComponentBit(t,n);const s=this.componentStoresArray[n];s&&s.clear(t),this.invalidateQueryCache()}has(t,e){const n=e.__worldIndex;return n===void 0?!1:this.hasComponentBit(t,n)}get(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n)){const s=this.getEntityComponentNames(t);throw new Error(`Cannot get component ${e.name} from entity ${t}: entity does not have this component. Entity has: [${s.join(", ")}]. Did you forget to call world.add()?`)}return this.componentStoresArray[n].get(t)}getMutable(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n))throw new Error(`Entity ${t} does not have component ${e.name}`);return this.componentStoresArray[n].getMutable(t)}set(t,e,n){const s=this.getComponentIndex(e);if(!this.hasComponentBit(t,s))throw new Error(`Cannot set component ${e.name} on entity ${t}: entity does not have this component. Use add() first.`);this.componentStoresArray[s].set(t,n)}update(t,e,n){const s=this.getComponentIndex(e);if(!this.hasComponentBit(t,s))throw new Error(`Entity ${t} does not have component ${e.name}`);this.componentStoresArray[s].update(t,n)}query(...t){const e=this.getQueryMask(t);if(e===null)return[];const n=this.maskToKey(e);let s=this.queryResultBuffers[n];if(s||(s=[],this.queryResultBuffers[n]=s),this.queryCacheVersions[n]===this.archetypeVersion)return s;const c=this.aliveEntitiesArray,h=c.length,p=e.length;let i=0;if(p===1){const o=e[0],r=this.componentMasks0;for(let a=0;a<h;a++){const m=c[a];(r[m]&o)===o&&(s[i++]=m)}}else for(let o=0;o<h;o++){const r=c[o];this.matchesComponentMask(r,e)&&(s[i++]=r)}return s.length=i,this.queryCacheVersions[n]=this.archetypeVersion,s}getEntities(){return this.aliveEntitiesArray}getEntityCount(){return this.aliveEntitiesArray.length}getMaxEntities(){return this.maxEntities}getComponents(){return this.components}getEntityComponentNames(t){const e=[];for(let n=0;n<this.components.length;n++)this.hasComponentBit(t,n)&&e.push(this.components[n].name);return e}serialize(t,e){const n=e??Array.from(this.aliveEntitiesArray),s=[];for(const i of t){const o=i.__worldIndex;if(o===void 0)continue;const r=this.componentStoresArray[o];if(!r)continue;const a=[];for(const m of n)this.has(m,i)&&a.push({entity:m,...r.getMutable(m)});if(a.length>0){const m=i.arrayCodec.encode(a);s.push(m)}}const c=s.reduce((i,o)=>i+o.length,0),h=new Uint8Array(c);let p=0;for(const i of s)h.set(i,p),p+=i.length;return h}deserialize(t,e){throw new Error("Deserialization not yet implemented")}getFieldArray(t,e){const n=this.getComponentIndex(t);return this.componentStoresArray[n].getFieldArray(e)}entity(t){return new M.EntityHandle(this,t)}}
|
|
1
|
+
var v=Object.defineProperty;var M=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var B=(p,m)=>{for(var t in m)v(p,t,{get:m[t],enumerable:!0})},I=(p,m,t,e)=>{if(m&&typeof m=="object"||typeof m=="function")for(let n of b(m))!k.call(p,n)&&n!==t&&v(p,n,{get:()=>m[n],enumerable:!(e=M(m,n))||e.enumerable});return p};var T=p=>I(v({},"__esModule",{value:!0}),p);var S={};B(S,{World:()=>U});module.exports=T(S);var g=require("../core/generate-id"),x=require("./component-store"),A=require("./entity-handle"),w=require("./world-systems");class U extends w.WorldSystems{constructor(t){super();this.nextEntityId=0;this.freeEntityHead=0;this.freeEntityTail=0;this.freeEntityCount=0;this.freeEntityMask=0;this.aliveEntitiesArray=[];this.numMaskWords=0;this.components=[];this.queryResultBuffers={};this.archetypeVersion=0;this.queryCacheVersions={};this.queryMaskCache={};this.despawnedCount=0;this.dirtyBitsByComponent=[];this.fieldsByComponent=[];this.worldId=(0,g.generateId)({prefix:"world_"});this.maxEntities=t.maxEntities??1e4,this.numMaskWords=Math.ceil(t.components.length/32),this.componentMasks=[];for(let i=0;i<this.numMaskWords;i++)this.componentMasks.push(new Uint32Array(this.maxEntities));this.numMaskWords>0&&(this.componentMasks0=this.componentMasks[0]);const e=Math.pow(2,Math.ceil(Math.log2(this.maxEntities)));this.freeEntityIds=new Uint32Array(e),this.freeEntityMask=e-1,this.aliveEntitiesIndices=new Uint32Array(this.maxEntities),this.aliveEntityFlags=new Uint8Array(this.maxEntities),this.despawnedBuffer=new Uint32Array(this.maxEntities),this.componentStoresArray=new Array(t.components.length);const n=Math.ceil(this.maxEntities/32);this.fieldsByComponent=new Array(t.components.length),t.components.forEach((i,a)=>{this.components.push(i),i.__worldIndex=a;const r=new x.ComponentStore(i,this.maxEntities);this.componentStoresArray[a]=r,this.dirtyBitsByComponent[a]=i.__sync!==void 0?new Uint32Array(n):null;const l={};for(let s=0;s<i.fieldNames.length;s++){const o=i.fieldNames[s];l[o]=r.getFieldArray(o)}Object.freeze(l),this.fieldsByComponent[a]=l})}getComponentIndex(t){const e=t.__worldIndex;if(e===void 0){const n=this.components.map(i=>i.name).join(", ");throw new Error(`Component ${t.name} not registered in World[${this.worldId}]. Registered components: [${n}]. Did you forget to include it in the WorldConfig?`)}return e}setComponentBit(t,e){const n=e>>>5,i=e&31;this.componentMasks[n][t]|=1<<i}clearComponentBit(t,e){const n=e>>>5,i=e&31;this.componentMasks[n][t]&=~(1<<i)}hasComponentBit(t,e){const n=e>>>5,i=e&31;return(this.componentMasks[n][t]&1<<i)!==0}clearAllComponentBits(t){if(this.numMaskWords===1)this.componentMasks0[t]=0;else if(this.numMaskWords===2)this.componentMasks0[t]=0,this.componentMasks[1][t]=0;else if(this.numMaskWords===3)this.componentMasks0[t]=0,this.componentMasks[1][t]=0,this.componentMasks[2][t]=0;else for(let e=0;e<this.numMaskWords;e++)this.componentMasks[e][t]=0}matchesComponentMask(t,e){const n=e.length;if(n===1)return(this.componentMasks0[t]&e[0])===e[0];if(n===2)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1];if(n===3)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2];if(n===4)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2]&&(this.componentMasks[3][t]&e[3])===e[3];for(let i=0;i<n;i++)if((this.componentMasks[i][t]&e[i])!==e[i])return!1;return!0}getQueryMask(t){const e=t.map(s=>s.name).sort().join(","),n=this.queryMaskCache[e];if(n)return n;let i=-1;const a=[];for(const s of t){const o=s.__worldIndex;if(o===void 0)return null;a.push(o),o>i&&(i=o)}const r=Math.floor(i/32)+1,l=new Array(r).fill(0);for(const s of a){const o=s>>>5,h=s&31;l[o]|=1<<h}return this.queryMaskCache[e]=l,l}maskToKey(t){let e="";for(let n=0;n<t.length;n++)t[n]!==0&&(e+=`${n}:${t[n].toString(36)},`);return e}_getQueryMaskKey(t){const e=this.getQueryMask(t);return e?this.maskToKey(e):""}_queryByMaskKey(t,e){let n=this.queryResultBuffers[t];if(n||(n=[],this.queryResultBuffers[t]=n),this.queryCacheVersions[t]===this.archetypeVersion)return n;const i=this.aliveEntitiesArray,a=i.length,r=e.length;let l=0;if(r===1){const s=e[0],o=this.componentMasks0;for(let h=0;h<a;h++){const c=i[h];(o[c]&s)===s&&(n[l++]=c)}}else if(r===2){const s=e[0],o=e[1],h=this.componentMasks0,c=this.componentMasks[1];for(let d=0;d<a;d++){const y=i[d];(h[y]&s)===s&&(c[y]&o)===o&&(n[l++]=y)}}else if(r===3){const s=e[0],o=e[1],h=e[2],c=this.componentMasks0,d=this.componentMasks[1],y=this.componentMasks[2];for(let u=0;u<a;u++){const f=i[u];(c[f]&s)===s&&(d[f]&o)===o&&(y[f]&h)===h&&(n[l++]=f)}}else if(r===4){const s=e[0],o=e[1],h=e[2],c=e[3],d=this.componentMasks0,y=this.componentMasks[1],u=this.componentMasks[2],f=this.componentMasks[3];for(let C=0;C<a;C++){const E=i[C];(d[E]&s)===s&&(y[E]&o)===o&&(u[E]&h)===h&&(f[E]&c)===c&&(n[l++]=E)}}else{const s=this.componentMasks;t:for(let o=0;o<a;o++){const h=i[o];for(let c=0;c<r;c++)if((s[c][h]&e[c])!==e[c])continue t;n[l++]=h}}return n.length=l,this.queryCacheVersions[t]=this.archetypeVersion,n}spawn(){let t=this.nextEntityId;if(this.freeEntityCount>0?(t=this.freeEntityIds[this.freeEntityTail],this.freeEntityTail=this.freeEntityTail+1&this.freeEntityMask,this.freeEntityCount--):this.nextEntityId++,t>=this.maxEntities)throw new Error(`Maximum entities (${this.maxEntities}) reached. Current alive: ${this.aliveEntitiesArray.length}, Free list: ${this.freeEntityCount}`);return this.aliveEntityFlags[t]=1,this.aliveEntitiesIndices[t]=this.aliveEntitiesArray.length,this.aliveEntitiesArray.push(t),this.clearAllComponentBits(t),this.invalidateQueryCache(),t}despawn(t){if(this.aliveEntityFlags[t]===0)return;this.despawnedBuffer[this.despawnedCount++]=t,this.aliveEntityFlags[t]=0;const e=this.aliveEntitiesIndices[t],n=this.aliveEntitiesArray.length-1;if(e!==n){const r=this.aliveEntitiesArray[n];this.aliveEntitiesArray[e]=r,this.aliveEntitiesIndices[r]=e}this.aliveEntitiesArray.pop();const i=this.componentStoresArray,a=this.components.length;for(let r=0;r<a;r++)this.hasComponentBit(t,r)&&i[r].clear(t);this.clearAllComponentBits(t),this.freeEntityIds[this.freeEntityHead]=t,this.freeEntityHead=this.freeEntityHead+1&this.freeEntityMask,this.freeEntityCount++,this.invalidateQueryCache()}isAlive(t){return this.aliveEntityFlags[t]===1}getDespawned(){return this.despawnedBuffer.subarray(0,this.despawnedCount)}flushDespawned(){this.despawnedCount=0}invalidateQueryCache(){this.archetypeVersion++}markDirty(t,e){const n=this.dirtyBitsByComponent[e];n!=null&&(n[t>>>5]|=1<<(t&31))}isDirty(t,e){const n=e.__worldIndex;if(n===void 0)return!1;const i=this.dirtyBitsByComponent[n];return i==null?!1:(i[t>>>5]&1<<(t&31))!==0}clearDirty(t,e){const n=e.__worldIndex;if(n===void 0)return;const i=this.dirtyBitsByComponent[n];i!=null&&(i[t>>>5]&=~(1<<(t&31)))}forEachDirty(t,e){const n=t.__worldIndex;if(n===void 0)return;const i=this.dirtyBitsByComponent[n];if(i!=null)for(let a=0;a<i.length;a++){let r=i[a];if(r===0)continue;const l=a<<5;for(;r!==0;){const s=r&-r,o=31-Math.clz32(s);e(l+o),r^=s}}}clearAllDirty(){for(let t=0;t<this.dirtyBitsByComponent.length;t++){const e=this.dirtyBitsByComponent[t];e?.fill(0)}}add(t,e,n){if(this.aliveEntityFlags[t]===0)throw new Error(`Cannot add component ${e.name} to entity ${t}: entity is not alive (was it despawned?). Current alive entities: ${this.aliveEntitiesArray.length}`);const i=this.getComponentIndex(e),a=this.componentStoresArray[i];this.setComponentBit(t,i),a.set(t,n),this.markDirty(t,i),this.invalidateQueryCache()}remove(t,e){const n=e.__worldIndex;if(n===void 0)return;this.clearComponentBit(t,n);const i=this.componentStoresArray[n];i&&i.clear(t),this.invalidateQueryCache()}has(t,e){const n=e.__worldIndex;return n===void 0?!1:this.hasComponentBit(t,n)}get(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n)){const i=this.getEntityComponentNames(t);throw new Error(`Cannot get component ${e.name} from entity ${t}: entity does not have this component. Entity has: [${i.join(", ")}]. Did you forget to call world.add()?`)}return this.componentStoresArray[n].get(t)}getMutable(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n))throw new Error(`Entity ${t} does not have component ${e.name}`);return this.componentStoresArray[n].getMutable(t)}set(t,e,n){const i=this.getComponentIndex(e);if(!this.hasComponentBit(t,i))throw new Error(`Cannot set component ${e.name} on entity ${t}: entity does not have this component. Use add() first.`);this.componentStoresArray[i].set(t,n),this.markDirty(t,i)}update(t,e,n){const i=this.getComponentIndex(e);if(!this.hasComponentBit(t,i))throw new Error(`Entity ${t} does not have component ${e.name}`);this.componentStoresArray[i].update(t,n),this.markDirty(t,i)}query(...t){const e=this.getQueryMask(t);if(e===null)return[];const n=this.maskToKey(e);let i=this.queryResultBuffers[n];if(i||(i=[],this.queryResultBuffers[n]=i),this.queryCacheVersions[n]===this.archetypeVersion)return i;const a=this.aliveEntitiesArray,r=a.length,l=e.length;let s=0;if(l===1){const o=e[0],h=this.componentMasks0;for(let c=0;c<r;c++){const d=a[c];(h[d]&o)===o&&(i[s++]=d)}}else for(let o=0;o<r;o++){const h=a[o];this.matchesComponentMask(h,e)&&(i[s++]=h)}return i.length=s,this.queryCacheVersions[n]=this.archetypeVersion,i}getEntities(){return this.aliveEntitiesArray}getEntityCount(){return this.aliveEntitiesArray.length}getMaxEntities(){return this.maxEntities}getComponents(){return this.components}getEntityComponentNames(t){const e=[];for(let n=0;n<this.components.length;n++)this.hasComponentBit(t,n)&&e.push(this.components[n].name);return e}serialize(t,e){const n=e??Array.from(this.aliveEntitiesArray),i=[];for(const s of t){const o=s.__worldIndex;if(o===void 0)continue;const h=this.componentStoresArray[o];if(!h)continue;const c=[];for(const d of n)this.has(d,s)&&c.push({entity:d,...h.getMutable(d)});if(c.length>0){const d=s.arrayCodec.encode(c);i.push(d)}}const a=i.reduce((s,o)=>s+o.length,0),r=new Uint8Array(a);let l=0;for(const s of i)r.set(s,l),l+=s.length;return r}deserialize(t,e){throw new Error("Deserialization not yet implemented")}getFieldArray(t,e){const n=this.getComponentIndex(t);return this.componentStoresArray[n].getFieldArray(e)}fields(t){const e=this.getComponentIndex(t);return this.fieldsByComponent[e]}entity(t){return new A.EntityHandle(this,t)}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var k=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var D=(i,t)=>{for(var e in t)k(i,e,{get:t[e],enumerable:!0})},f=(i,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of g(t))!b.call(i,n)&&n!==e&&k(i,n,{get:()=>t[n],enumerable:!(a=E(t,n))||a.enumerable});return i};var S=i=>f(k({},"__esModule",{value:!0}),i);var
|
|
1
|
+
var k=Object.defineProperty;var E=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var D=(i,t)=>{for(var e in t)k(i,e,{get:t[e],enumerable:!0})},f=(i,t,e,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of g(t))!b.call(i,n)&&n!==e&&k(i,n,{get:()=>t[n],enumerable:!(a=E(t,n))||a.enumerable});return i};var S=i=>f(k({},"__esModule",{value:!0}),i);var M={};D(M,{GameLoop:()=>C});module.exports=S(M);var p=require("../../core"),h=require("../../core/input");class C{constructor(t){this.options=t;this.fps=0;this.status="stopped";this._tickData={deltaTime:0,tick:0,input:null};this._skipData={ticks:0};this._renderData={deltaTime:0,alpha:0,input:null};const e=new Set(["client","manual-client"]),a=new Set(["manual-client","manual-server"]);this._isClient=e.has(this.options.type),this._isManual=a.has(this.options.type);const n=["sync","pre-tick","tick","post-tick","skip","start","stop","toggle-pause"];this._isClient&&n.push("render"),this.events=new p.EventSystem({events:n}),this._input=new h.InputManager;const o=this.events;if(this.ticker=new p.FixedTicker({rate:this.options.tickRate,onTick:(s,r=0)=>{const u=this._input.snapshot();this._tickData.deltaTime=s,this._tickData.tick=r,this._tickData.input=u,o.emit("sync",this._tickData),o.emit("pre-tick",this._tickData),this.options.onTick?.(s,r,u),o.emit("tick",this._tickData),o.emit("post-tick",this._tickData)},onTickSkipped:s=>{this._skipData.ticks=s,o.emit("skip",this._skipData)}}),this._isManual||(this._driver=(0,p.createDriver)(this.options.type,s=>{this.step(s)})),this._isClient){const s=this.events,r=Math.round(this.options.tickRate/2),u=new Array(r).fill(0);let m=0,d=performance.now(),v=0,l=0;s.on("tick",()=>{v=(v+1)%r;const T=performance.now(),y=T-d;if(y>0){const c=m*1e3/y;u[v]=c,l<r&&l++}m=0,d=T;let _=0;for(let c=0;c<l;c++)_+=u[c];this.fps=Math.round(_/l)}),s.on("render",()=>{m++})}}step(t){if(this.ticker.tick(t),this._isClient){const e=this._input.peek(),a=this.ticker.alpha;this.options.onRender?.(t,a,e),this._renderData.deltaTime=t,this._renderData.alpha=a,this._renderData.input=e,this.events.emit("render",this._renderData)}}pause(){this._driver&&this._driver.stop(),this.status="paused",this.events.emit("toggle-pause",{paused:!0,lastToggledAt:Date.now(),lastToggleTick:this.ticker.tickCount})}resume(){this._driver&&this._driver.start(),this.status="running",this.events.emit("toggle-pause",{paused:!1,lastToggledAt:Date.now(),lastToggleTick:this.ticker.tickCount})}start(){if(this._driver&&this._driver.start(),this.status="running",this.events.emit("start",{startedAt:Date.now()}),this._isClient){const t=new h.BrowserInputSource(document,document.body);this._input.listen(t)}}stop(){this._driver&&this._driver.stop(),this.ticker.resetTickCount(),this.status="stopped",this.events.emit("stop",{stoppedAt:Date.now()}),this._isClient&&this._input.unlisten()}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var p=Object.defineProperty;var k=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var S=Object.prototype.hasOwnProperty;var y=(a,e)=>{for(var r in e)p(a,r,{get:e[r],enumerable:!0})},A=(a,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of g(e))!S.call(a,s)&&s!==r&&p(a,s,{get:()=>e[s],enumerable:!(t=k(e,s))||t.enumerable});return a};var H=a=>A(p({},"__esModule",{value:!0}),a);var b={};y(b,{BunWebSocketClientTransport:()=>l,BunWebSocketPeerTransport:()=>f,BunWebSocketServerTransport:()=>h});module.exports=H(b);var v=require("../../core/generate-id/generate-id");class l{constructor(e){this.messageHandlers=[];this.closeHandlers=[];this.errorHandlers=[];this.socket=e,this.setupHandlers()}send(e){this.socket.readyState===WebSocket.OPEN&&this.socket.send(e)}onMessage(e){this.messageHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}onError(e){this.errorHandlers.push(e)}close(){this.socket.close()}setupHandlers(){this.socket.binaryType="arraybuffer",this.socket.addEventListener("message",e=>{if(e.data instanceof ArrayBuffer){const r=new Uint8Array(e.data);for(const t of this.messageHandlers)t(r)}else{const r=new Error(`Unexpected message type: ${typeof e.data}`);for(const t of this.errorHandlers)t(r)}}),this.socket.addEventListener("close",()=>{for(const e of this.closeHandlers)e()}),this.socket.addEventListener("error",()=>{const e=new Error("WebSocket error");for(const r of this.errorHandlers)r(e)})}static connect(e){return new Promise((r,t)=>{const s=new WebSocket(e),d=new l(s);s.addEventListener("open",()=>{r(d)}),s.addEventListener("error",i=>{t(i)})})}}class f{constructor(e){this.messageHandlers=[];this.closeHandlers=[];this.errorHandlers=[];this.socket=e}send(e){this.socket.send(e)}onMessage(e){this.messageHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}onError(e){this.errorHandlers.push(e)}close(){this.socket.close()}_handleOpen(){}_handleMessage(e){for(const r of this.messageHandlers)r(e)}_handleClose(){for(const e of this.closeHandlers)e()}_handleError(e){for(const r of this.errorHandlers)r(e)}}class h{constructor(e){this.peers=new Map;this.connectionHandlers=[];this.disconnectionHandlers=[];this.server=e}onConnection(e){this.connectionHandlers.push(e)}onDisconnection(e){this.disconnectionHandlers.push(e)}getPeer(e){return this.peers.get(e)}getPeerIds(){return Array.from(this.peers.keys())}close(){this.server.stop(),this.peers.clear()}_registerPeer(e){const r=(0,v.generateId)({prefix:"peer_"}),t=new f(e);return this.peers.set(r,t),r}_handlePeerMessage(e,r){const t=this.peers.get(e);t&&t._handleMessage(r)}_handlePeerDisconnection(e){const r=this.peers.get(e);if(r){r._handleClose(),this.peers.delete(e);for(const t of this.disconnectionHandlers)t(e)}}_handlePeerConnection(e){const r=this.peers.get(e);if(r)for(const t of this.connectionHandlers)t(r,e)}static create(e,r){const t=new WeakMap,s=r?.path,d=r?.fetch;let i;const u=Bun.serve({port:e,fetch(o,n){if(!((s===void 0||new URL(o.url).pathname===s)&&n.upgrade(o)))return d!==void 0?d(o,n):new Response("Expected WebSocket connection",{status:400})},websocket:{open(o){const n=i._registerPeer(o);t.set(o,n),i._handlePeerConnection(n)},message(o,n){const c=t.get(o);c&&n instanceof Uint8Array?i._handlePeerMessage(c,n):c&&n instanceof ArrayBuffer&&i._handlePeerMessage(c,new Uint8Array(n))},close(o){const n=t.get(o);n&&(i._handlePeerDisconnection(n),t.delete(o))}}});return i=new h(u),i}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const F=Symbol("schemaSize");function f(y){const t=y[F];if(t!==void 0)return t;let e=0;for(const r of Object.keys(y))e+=y[r].size;return y[F]=e,e}class g{static encodeInto(t,e){const r=f(t),o=new ArrayBuffer(r),s=new DataView(o);let a=0;for(const i of Object.keys(t)){const l=t[i];l.write(s,a,e[i]),a+=l.size}return new Uint8Array(o)}static decodeInto(t,e,r){const o=f(t);if(e.byteLength<o)throw new RangeError(`Buffer too small: expected ${o} bytes, got ${e.byteLength}`);const s=new DataView(e.buffer,e.byteOffset,e.byteLength);let a=0;for(const i of Object.keys(t)){const l=t[i];r[i]=l.read(s,a),a+=l.size}return r}}class n{static{this.u8={size:1,write:(t,e,r)=>t.setUint8(e,r),read:(t,e)=>t.getUint8(e),toNil:()=>0}}static{this.u16={size:2,write:(t,e,r)=>t.setUint16(e,r,!1),read:(t,e)=>t.getUint16(e,!1),toNil:()=>0}}static{this.u32={size:4,write:(t,e,r)=>t.setUint32(e,r,!1),read:(t,e)=>t.getUint32(e,!1),toNil:()=>0}}static{this.i8={size:1,write:(t,e,r)=>t.setInt8(e,r),read:(t,e)=>t.getInt8(e),toNil:()=>0}}static{this.i16={size:2,write:(t,e,r)=>t.setInt16(e,r,!1),read:(t,e)=>t.getInt16(e,!1),toNil:()=>0}}static{this.i32={size:4,write:(t,e,r)=>t.setInt32(e,r,!1),read:(t,e)=>t.getInt32(e,!1),toNil:()=>0}}static{this.f16={size:2,write:(t,e,r)=>{const o=new Float32Array(1),s=new Uint32Array(o.buffer);o[0]=r;const a=s[0],i=a>>>31&1;let l=a>>>23&255,u=a&8388607,c;if(l===255)c=i<<15|31744|(u?512:0);else if(l===0)c=i<<15;else{const d=l-127+15;if(d>=31)c=i<<15|31744;else if(d<=0)c=i<<15;else{const b=u>>>13;c=i<<15|d<<10|b}}t.setUint16(e,c,!1)},read:(t,e)=>{const r=t.getUint16(e,!1),o=r>>>15&1,s=r>>>10&31,a=r&1023;let i;if(s===0)i=o<<31;else if(s===31)i=o<<31|255<<23|(a?a<<13:0);else{const c=s-15+127;i=o<<31|c<<23|a<<13}const l=new Uint32Array([i]);return new Float32Array(l.buffer)[0]},toNil:()=>0}}static{this.f32={size:4,write:(t,e,r)=>t.setFloat32(e,r,!1),read:(t,e)=>t.getFloat32(e,!1),toNil:()=>0}}static{this.f64={size:8,write:(t,e,r)=>t.setFloat64(e,r,!1),read:(t,e)=>t.getFloat64(e,!1),toNil:()=>0}}static{this.bool={size:1,write:(t,e,r)=>t.setUint8(e,r?1:0),read:(t,e)=>t.getUint8(e)!==0,toNil:()=>!1}}static string(t){return{size:t+2,write(e,r,o){const a=new TextEncoder().encode(o);if(a.length>t)throw new RangeError(`String too long, max ${t} bytes`);e.setUint16(r,a.length,!1);for(let i=0;i<a.length;i++)e.setUint8(r+2+i,a[i]);for(let i=a.length;i<t;i++)e.setUint8(r+2+i,0)},read(e,r){const o=e.getUint16(r,!1),s=new Uint8Array(o);for(let a=0;a<o;a++)s[a]=e.getUint8(r+2+a);return new TextDecoder().decode(s)},toNil:()=>""}}static{this.vec2={size:8,write(t,e,r){t.setFloat32(e,r.x,!1),t.setFloat32(e+4,r.y,!1)},read(t,e){return{x:t.getFloat32(e,!1),y:t.getFloat32(e+4,!1)}},toNil:()=>({x:0,y:0})}}static{this.vec3={size:12,write(t,e,r){t.setFloat32(e,r.x,!1),t.setFloat32(e+4,r.y,!1),t.setFloat32(e+8,r.z,!1)},read(t,e){return{x:t.getFloat32(e,!1),y:t.getFloat32(e+4,!1),z:t.getFloat32(e+8,!1)}},toNil:()=>({x:0,y:0,z:0})}}static{this.color={size:4,write(t,e,r){t.setUint8(e,r.r),t.setUint8(e+1,r.g),t.setUint8(e+2,r.b),t.setUint8(e+3,r.a)},read(t,e){return{r:t.getUint8(e),g:t.getUint8(e+1),b:t.getUint8(e+2),a:t.getUint8(e+3)}},toNil:()=>({r:0,g:0,b:0,a:0})}}static{this.f32_le={size:4,write:(t,e,r)=>t.setFloat32(e,r,!0),read:(t,e)=>t.getFloat32(e,!0),toNil:()=>0}}static{this.f64_le={size:8,write:(t,e,r)=>t.setFloat64(e,r,!0),read:(t,e)=>t.getFloat64(e,!0),toNil:()=>0}}static{this.u16_le={size:2,write:(t,e,r)=>t.setUint16(e,r,!0),read:(t,e)=>t.getUint16(e,!0),toNil:()=>0}}static{this.u32_le={size:4,write:(t,e,r)=>t.setUint32(e,r,!0),read:(t,e)=>t.getUint32(e,!0),toNil:()=>0}}static{this.i16_le={size:2,write:(t,e,r)=>t.setInt16(e,r,!0),read:(t,e)=>t.getInt16(e,!0),toNil:()=>0}}static{this.i32_le={size:4,write:(t,e,r)=>t.setInt32(e,r,!0),read:(t,e)=>t.getInt32(e,!0),toNil:()=>0}}static{this.vec2_le={size:8,write:(t,e,r)=>{t.setFloat32(e,r[0],!0),t.setFloat32(e+4,r[1],!0)},read:(t,e)=>[t.getFloat32(e,!0),t.getFloat32(e+4,!0)],toNil:()=>[0,0]}}static{this.vec3_le={size:12,write:(t,e,r)=>{t.setFloat32(e,r[0],!0),t.setFloat32(e+4,r[1],!0),t.setFloat32(e+8,r[2],!0)},read:(t,e)=>[t.getFloat32(e,!0),t.getFloat32(e+4,!0),t.getFloat32(e+8,!0)],toNil:()=>[0,0,0]}}static{this.vec4_le={size:16,write:(t,e,r)=>{t.setFloat32(e,r[0],!0),t.setFloat32(e+4,r[1],!0),t.setFloat32(e+8,r[2],!0),t.setFloat32(e+12,r[3],!0)},read:(t,e)=>[t.getFloat32(e,!0),t.getFloat32(e+4,!0),t.getFloat32(e+8,!0),t.getFloat32(e+12,!0)],toNil:()=>[0,0,0,0]}}}class x extends g{static{this.u8=n.u8}static{this.u16=n.u16}static{this.u32=n.u32}static{this.i8=n.i8}static{this.i16=n.i16}static{this.i32=n.i32}static{this.f16=n.f16}static{this.f32=n.f32}static{this.bool=n.bool}static{this.string=n.string}static{this.vec2=n.vec2}static{this.vec3=n.vec3}static{this.color=n.color}static encode(t,e){return this.encodeInto(t,e)}static decode(t,e,r){return this.decodeInto(t,e,r)}}const w=n.u8,U=n.u16,m=n.u32,A=n.i8,z=n.i16,p=n.i32,T=n.f16,N=n.f32,I=n.f64,_=n.bool,S=n.string,k=n.vec2,h=n.vec3,V=n.vec2_le,j=n.vec3_le,E=n.vec4_le,B=n.color;export{g as BaseBinaryCodec,x as BinaryCodec,n as BinaryPrimitives,_ as bool,B as color,T as f16,N as f32,I as f64,z as i16,p as i32,A as i8,S as string,U as u16,m as u32,w as u8,k as vec2,V as vec2_le,h as vec3,j as vec3_le,E as vec4_le};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class n{constructor(t){this.update=t;this.last=performance.now();this.running=!1;this.loop=()=>{if(!this.running)return;const t=performance.now(),
|
|
1
|
+
class n{constructor(t){this.update=t;this.last=performance.now();this.running=!1;this.loop=()=>{if(!this.running)return;const t=performance.now(),e=(t-this.last)/1e3;this.last=t,this.update(e),setImmediate(this.loop)}}start(){this.running=!0,this.last=performance.now(),this.loop()}stop(){this.running=!1}}export{n as ImmediateDriver};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class t{constructor(i){this.update=i;this.last=performance.now();this.running=!1;this.rafId=null;this.visibilityHandler=null;this.loop=()=>{if(!this.running)return;const i=performance.now(),
|
|
1
|
+
class t{constructor(i){this.update=i;this.last=performance.now();this.running=!1;this.rafId=null;this.visibilityHandler=null;this.loop=()=>{if(!this.running)return;const i=performance.now(),e=i-this.last;this.last=i;const n=Math.min(e,t.MAX_DELTA_MS)/1e3;this.update(n),requestAnimationFrame(this.loop)}}static{this.MAX_DELTA_MS=250}start(){this.running=!0,this.last=performance.now(),typeof document<"u"&&!this.visibilityHandler&&(this.visibilityHandler=()=>{document.visibilityState==="visible"&&(this.last=performance.now())},document.addEventListener("visibilitychange",this.visibilityHandler)),this.rafId=requestAnimationFrame(this.loop)}stop(){this.running=!1,this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.visibilityHandler&&typeof document<"u"&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null)}}export{t as RafDriver};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const e=1;class s{constructor(t){this.update=t;this.last=performance.now();this.running=!1;this.loop=()=>{if(!this.running)return;const t=performance.now(),o=(t-this.last)/1e3;this.last=t,this.update(o),setTimeout(this.loop,e)}}start(){this.running=!0,this.last=performance.now(),this.loop()}stop(){this.running=!1}}export{s as TimeoutDriver};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./manager";export*from"./sources";
|
|
1
|
+
export*from"./manager";export*from"./sources";export*from"./mouse-look";export*from"./scroll-zoom";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./mouse-look";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class c{constructor(t={}){this.lockedElement=null;this.pendingLockCleanup=null;this._forward=new Float32Array(3);this._right=new Float32Array(3);this._up=new Float32Array(3);this._orbit=new Float32Array(3);this.sensitivity=t.sensitivity??.002;const i=t.yaw??{};this.yaw=i.initial??0,this.yawMin=i.min??-1/0,this.yawMax=i.max??1/0;const n=t.pitch??{};this.pitch=n.initial??0,this.pitchMin=n.min??-Math.PI/2+.01,this.pitchMax=n.max??Math.PI/2-.01,this.invertX=t.invertX??!1,this.invertY=t.invertY??!1,this.drag=t.drag??!0,this.dragButton=t.dragButton??"left"}update(t){const i=t.mouse[this.dragButton];if(!(this.locked||this.drag&&i.down))return;const e=t.mouse.delta.position.x,o=t.mouse.delta.position.y;e===0&&o===0||(this.yaw-=e*this.sensitivity*(this.invertX?-1:1),this.yaw<this.yawMin?this.yaw=this.yawMin:this.yaw>this.yawMax&&(this.yaw=this.yawMax),this.pitch-=o*this.sensitivity*(this.invertY?-1:1),this.pitch<this.pitchMin?this.pitch=this.pitchMin:this.pitch>this.pitchMax&&(this.pitch=this.pitchMax))}lock(t){const i=t.requestPointerLock;if(typeof i!="function")return Promise.reject(new Error("Pointer Lock unsupported"));this.lockedElement=t;const n=i.call(t);return n&&typeof n.then=="function"?n:new Promise((e,o)=>{const r=()=>{document.removeEventListener("pointerlockchange",s),document.removeEventListener("pointerlockerror",a),this.pendingLockCleanup===r&&(this.pendingLockCleanup=null)},s=()=>{r(),document.pointerLockElement===t?e():o(new Error("Pointer Lock denied"))},a=()=>{r(),o(new Error("Pointer Lock denied"))};document.addEventListener("pointerlockchange",s),document.addEventListener("pointerlockerror",a),this.pendingLockCleanup=r})}unlock(){typeof document<"u"&&document.exitPointerLock&&document.exitPointerLock()}get locked(){return typeof document>"u"||this.lockedElement===null?!1:document.pointerLockElement===this.lockedElement}get forward(){const t=Math.cos(this.pitch),i=this._forward;return i[0]=Math.sin(this.yaw)*t,i[1]=Math.sin(this.pitch),i[2]=Math.cos(this.yaw)*t,i}get right(){const t=this._right;return t[0]=Math.cos(this.yaw),t[1]=0,t[2]=-Math.sin(this.yaw),t}get up(){const t=Math.sin(this.pitch),i=this._up;return i[0]=-Math.sin(this.yaw)*t,i[1]=Math.cos(this.pitch),i[2]=-Math.cos(this.yaw)*t,i}orbit(t,i){const n=Math.cos(this.pitch),e=this._orbit;return e[0]=t[0]+i*n*Math.sin(this.yaw),e[1]=t[1]+i*Math.sin(this.pitch),e[2]=t[2]+i*n*Math.cos(this.yaw),e}destroy(){this.pendingLockCleanup?.(),this.pendingLockCleanup=null,this.unlock(),this.lockedElement=null}}export{c as MouseLook};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./scroll-zoom";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
class e{constructor(i){this.value=i.initial,this.min=i.min,this.max=i.max,this.sensitivity=i.sensitivity??.01}update(i){const t=i.mouse.delta.scroll.y;t!==0&&(this.value+=t*this.sensitivity,this.value<this.min?this.value=this.min:this.value>this.max&&(this.value=this.max))}}export{e as ScrollZoom};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{PooledCodec as
|
|
1
|
+
import{PooledCodec as S}from"../core/pooled-codec";function p(n){let e=0;for(const o of Object.keys(n))e+=n[o].size;return e}function T(n,e){const o=typeof e=="object"&&e!==null&&"schema"in e&&"sync"in e,t=o?e.schema:e,c=o?e.sync:void 0,a=p(t),r=Object.keys(t),m=r.length,i=S.array(t),s={name:n,schema:t,size:a,fieldCount:m,fieldNames:r,arrayCodec:i};return c!==void 0&&(s.__sync=c),s}export{T as defineComponent};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
class
|
|
1
|
+
class u{constructor(t,n,o,r,e){this.world=t;this.components=n;this.fieldMappings=o;this.userCallback=r;this.conditionPredicate=e}query(...t){return new u(this.world,t,this.fieldMappings,this.userCallback,this.conditionPredicate)}fields(t){return new u(this.world,this.components,t,this.userCallback,this.conditionPredicate)}when(t){if(!this.fieldMappings)throw new Error("Must call .fields() before .when()");const n={};for(let e=0;e<this.components.length;e++){const a=this.components[e],l=this.fieldMappings[e];if(!l)continue;const d=Object.keys(l)[0],c=l[d];for(const i of c){const p=`${d}_${i}`,s=this.world.getFieldArray(a,i);n[p]=s}}const o={eid:0};for(const e in n){const a=n[e];Object.defineProperty(o,e,{get(){return a[this.eid]},set(l){a[this.eid]=l},enumerable:!0,configurable:!1}),o[`${e}_array`]=a}Object.seal(o);const r=t;return new u(this.world,this.components,this.fieldMappings,this.userCallback,r)}run(t){return new u(this.world,this.components,this.fieldMappings,t,this.conditionPredicate).buildAndRegister()}buildAndRegister(){if(!this.userCallback)throw new Error("System callback must be set");if(!this.fieldMappings)throw new Error("Field mappings must be set");const t=this.world,n=this.components,o=this.fieldMappings,r=this.userCallback,e={},a={},l=[];for(let s=0;s<n.length;s++){const f=n[s],y=o[s];if(!y)continue;const m=Object.keys(y)[0],g=y[m];l.push(m),a[m]=f,e[m]={};for(const x of g){const C=t.getFieldArray(f,x);e[m][x]=C}}const d=[];for(const s of l){const f=e[s];for(const y in f)d.push({prop:`${s}_${y}`,array:f[y]})}t.query(...n);const c=t._getQueryMaskKey(n),i=t.getQueryMask(n),p=new h(t,n,r,d,c,i,this.conditionPredicate);return t._registerSystem(p),p}}class h{constructor(t,n,o,r,e,a,l){this.world=t;this.components=n;this.userCallback=o;this.fieldDescs=r;this.queryMaskKey=e;this.queryMask=a;this.conditionPredicate=l;this.syncedComponentIndices=[];this.proxyEntity=this.createProxyEntity();for(const d of n)d.__sync!==void 0&&d.__worldIndex!==void 0&&this.syncedComponentIndices.push(d.__worldIndex)}execute(t){const n=this.world._queryByMaskKey(this.queryMaskKey,this.queryMask),o=this.userCallback,r=this.world,e=this.proxyEntity,a=n.length,l=this.syncedComponentIndices,d=l.length;if(!this.conditionPredicate&&d===0){for(let i=0;i<a;i++)e.eid=n[i],o(e,t,r);return}if(!this.conditionPredicate){for(let i=0;i<a;i++){const p=n[i];e.eid=p,o(e,t,r);for(let s=0;s<d;s++)r.markDirty(p,l[s])}return}const c=this.conditionPredicate;if(d===0){for(let i=0;i<a;i++)e.eid=n[i],c(e)&&o(e,t,r);return}for(let i=0;i<a;i++){const p=n[i];if(e.eid=p,c(e)){o(e,t,r);for(let s=0;s<d;s++)r.markDirty(p,l[s])}}}createProxyEntity(){const t=this.world,n={eid:0,despawn(){t.despawn(this.eid)}};for(let o=0;o<this.fieldDescs.length;o++){const{prop:r,array:e}=this.fieldDescs[o];n[`${r}_array`]=e,Object.defineProperty(n,r,{get(){return e[this.eid]},set(a){e[this.eid]=a},enumerable:!0,configurable:!1})}return Object.seal(n),Object.preventExtensions(n),n}getComponents(){return this.components}}export{h as ExecutableSystem,u as SystemBuilder};
|
package/dist/esm/ecs/world.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{generateId as E}from"../core/generate-id";import{ComponentStore as v}from"./component-store";import{EntityHandle as C}from"./entity-handle";import{WorldSystems as g}from"./world-systems";class B extends g{constructor(t){super();this.nextEntityId=0;this.freeEntityHead=0;this.freeEntityTail=0;this.freeEntityCount=0;this.freeEntityMask=0;this.aliveEntitiesArray=[];this.numMaskWords=0;this.components=[];this.queryResultBuffers={};this.archetypeVersion=0;this.queryCacheVersions={};this.queryMaskCache={};this.despawnedCount=0;this.worldId=E({prefix:"world_"});this.maxEntities=t.maxEntities??1e4,this.numMaskWords=Math.ceil(t.components.length/32),this.componentMasks=[];for(let n=0;n<this.numMaskWords;n++)this.componentMasks.push(new Uint32Array(this.maxEntities));this.numMaskWords>0&&(this.componentMasks0=this.componentMasks[0]);const e=Math.pow(2,Math.ceil(Math.log2(this.maxEntities)));this.freeEntityIds=new Uint32Array(e),this.freeEntityMask=e-1,this.aliveEntitiesIndices=new Uint32Array(this.maxEntities),this.aliveEntityFlags=new Uint8Array(this.maxEntities),this.despawnedBuffer=new Uint32Array(this.maxEntities),this.componentStoresArray=new Array(t.components.length),t.components.forEach((n,s)=>{this.components.push(n),n.__worldIndex=s;const c=new v(n,this.maxEntities);this.componentStoresArray[s]=c})}getComponentIndex(t){const e=t.__worldIndex;if(e===void 0){const n=this.components.map(s=>s.name).join(", ");throw new Error(`Component ${t.name} not registered in World[${this.worldId}]. Registered components: [${n}]. Did you forget to include it in the WorldConfig?`)}return e}setComponentBit(t,e){const n=e>>>5,s=e&31;this.componentMasks[n][t]|=1<<s}clearComponentBit(t,e){const n=e>>>5,s=e&31;this.componentMasks[n][t]&=~(1<<s)}hasComponentBit(t,e){const n=e>>>5,s=e&31;return(this.componentMasks[n][t]&1<<s)!==0}clearAllComponentBits(t){if(this.numMaskWords===1)this.componentMasks0[t]=0;else if(this.numMaskWords===2)this.componentMasks0[t]=0,this.componentMasks[1][t]=0;else if(this.numMaskWords===3)this.componentMasks0[t]=0,this.componentMasks[1][t]=0,this.componentMasks[2][t]=0;else for(let e=0;e<this.numMaskWords;e++)this.componentMasks[e][t]=0}matchesComponentMask(t,e){const n=e.length;if(n===1)return(this.componentMasks0[t]&e[0])===e[0];if(n===2)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1];if(n===3)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2];if(n===4)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2]&&(this.componentMasks[3][t]&e[3])===e[3];for(let s=0;s<n;s++)if((this.componentMasks[s][t]&e[s])!==e[s])return!1;return!0}getQueryMask(t){const e=t.map(i=>i.name).sort().join(","),n=this.queryMaskCache[e];if(n)return n;let s=-1;const c=[];for(const i of t){const o=i.__worldIndex;if(o===void 0)return null;c.push(o),o>s&&(s=o)}const h=Math.floor(s/32)+1,p=new Array(h).fill(0);for(const i of c){const o=i>>>5,r=i&31;p[o]|=1<<r}return this.queryMaskCache[e]=p,p}maskToKey(t){let e="";for(let n=0;n<t.length;n++)t[n]!==0&&(e+=`${n}:${t[n].toString(36)},`);return e}_getQueryMaskKey(t){const e=this.getQueryMask(t);return e?this.maskToKey(e):""}_queryByMaskKey(t,e){let n=this.queryResultBuffers[t];if(n||(n=[],this.queryResultBuffers[t]=n),this.queryCacheVersions[t]===this.archetypeVersion)return n;const s=this.aliveEntitiesArray,c=s.length,h=e.length;let p=0;if(h===1){const i=e[0],o=this.componentMasks0;for(let r=0;r<c;r++){const a=s[r];(o[a]&i)===i&&(n[p++]=a)}}else if(h===2){const i=e[0],o=e[1],r=this.componentMasks0,a=this.componentMasks[1];for(let m=0;m<c;m++){const l=s[m];(r[l]&i)===i&&(a[l]&o)===o&&(n[p++]=l)}}else if(h===3){const i=e[0],o=e[1],r=e[2],a=this.componentMasks0,m=this.componentMasks[1],l=this.componentMasks[2];for(let y=0;y<c;y++){const d=s[y];(a[d]&i)===i&&(m[d]&o)===o&&(l[d]&r)===r&&(n[p++]=d)}}else if(h===4){const i=e[0],o=e[1],r=e[2],a=e[3],m=this.componentMasks0,l=this.componentMasks[1],y=this.componentMasks[2],d=this.componentMasks[3];for(let f=0;f<c;f++){const u=s[f];(m[u]&i)===i&&(l[u]&o)===o&&(y[u]&r)===r&&(d[u]&a)===a&&(n[p++]=u)}}else{const i=this.componentMasks;t:for(let o=0;o<c;o++){const r=s[o];for(let a=0;a<h;a++)if((i[a][r]&e[a])!==e[a])continue t;n[p++]=r}}return n.length=p,this.queryCacheVersions[t]=this.archetypeVersion,n}spawn(){let t=this.nextEntityId;if(this.freeEntityCount>0?(t=this.freeEntityIds[this.freeEntityTail],this.freeEntityTail=this.freeEntityTail+1&this.freeEntityMask,this.freeEntityCount--):this.nextEntityId++,t>=this.maxEntities)throw new Error(`Maximum entities (${this.maxEntities}) reached. Current alive: ${this.aliveEntitiesArray.length}, Free list: ${this.freeEntityCount}`);return this.aliveEntityFlags[t]=1,this.aliveEntitiesIndices[t]=this.aliveEntitiesArray.length,this.aliveEntitiesArray.push(t),this.clearAllComponentBits(t),this.invalidateQueryCache(),t}despawn(t){if(this.aliveEntityFlags[t]===0)return;this.despawnedBuffer[this.despawnedCount++]=t,this.aliveEntityFlags[t]=0;const e=this.aliveEntitiesIndices[t],n=this.aliveEntitiesArray.length-1;if(e!==n){const h=this.aliveEntitiesArray[n];this.aliveEntitiesArray[e]=h,this.aliveEntitiesIndices[h]=e}this.aliveEntitiesArray.pop();const s=this.componentStoresArray,c=this.components.length;for(let h=0;h<c;h++)this.hasComponentBit(t,h)&&s[h].clear(t);this.clearAllComponentBits(t),this.freeEntityIds[this.freeEntityHead]=t,this.freeEntityHead=this.freeEntityHead+1&this.freeEntityMask,this.freeEntityCount++,this.invalidateQueryCache()}isAlive(t){return this.aliveEntityFlags[t]===1}getDespawned(){return this.despawnedBuffer.subarray(0,this.despawnedCount)}flushDespawned(){this.despawnedCount=0}invalidateQueryCache(){this.archetypeVersion++}add(t,e,n){if(this.aliveEntityFlags[t]===0)throw new Error(`Cannot add component ${e.name} to entity ${t}: entity is not alive (was it despawned?). Current alive entities: ${this.aliveEntitiesArray.length}`);const s=this.getComponentIndex(e),c=this.componentStoresArray[s];this.setComponentBit(t,s),c.set(t,n),this.invalidateQueryCache()}remove(t,e){const n=e.__worldIndex;if(n===void 0)return;this.clearComponentBit(t,n);const s=this.componentStoresArray[n];s&&s.clear(t),this.invalidateQueryCache()}has(t,e){const n=e.__worldIndex;return n===void 0?!1:this.hasComponentBit(t,n)}get(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n)){const s=this.getEntityComponentNames(t);throw new Error(`Cannot get component ${e.name} from entity ${t}: entity does not have this component. Entity has: [${s.join(", ")}]. Did you forget to call world.add()?`)}return this.componentStoresArray[n].get(t)}getMutable(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n))throw new Error(`Entity ${t} does not have component ${e.name}`);return this.componentStoresArray[n].getMutable(t)}set(t,e,n){const s=this.getComponentIndex(e);if(!this.hasComponentBit(t,s))throw new Error(`Cannot set component ${e.name} on entity ${t}: entity does not have this component. Use add() first.`);this.componentStoresArray[s].set(t,n)}update(t,e,n){const s=this.getComponentIndex(e);if(!this.hasComponentBit(t,s))throw new Error(`Entity ${t} does not have component ${e.name}`);this.componentStoresArray[s].update(t,n)}query(...t){const e=this.getQueryMask(t);if(e===null)return[];const n=this.maskToKey(e);let s=this.queryResultBuffers[n];if(s||(s=[],this.queryResultBuffers[n]=s),this.queryCacheVersions[n]===this.archetypeVersion)return s;const c=this.aliveEntitiesArray,h=c.length,p=e.length;let i=0;if(p===1){const o=e[0],r=this.componentMasks0;for(let a=0;a<h;a++){const m=c[a];(r[m]&o)===o&&(s[i++]=m)}}else for(let o=0;o<h;o++){const r=c[o];this.matchesComponentMask(r,e)&&(s[i++]=r)}return s.length=i,this.queryCacheVersions[n]=this.archetypeVersion,s}getEntities(){return this.aliveEntitiesArray}getEntityCount(){return this.aliveEntitiesArray.length}getMaxEntities(){return this.maxEntities}getComponents(){return this.components}getEntityComponentNames(t){const e=[];for(let n=0;n<this.components.length;n++)this.hasComponentBit(t,n)&&e.push(this.components[n].name);return e}serialize(t,e){const n=e??Array.from(this.aliveEntitiesArray),s=[];for(const i of t){const o=i.__worldIndex;if(o===void 0)continue;const r=this.componentStoresArray[o];if(!r)continue;const a=[];for(const m of n)this.has(m,i)&&a.push({entity:m,...r.getMutable(m)});if(a.length>0){const m=i.arrayCodec.encode(a);s.push(m)}}const c=s.reduce((i,o)=>i+o.length,0),h=new Uint8Array(c);let p=0;for(const i of s)h.set(i,p),p+=i.length;return h}deserialize(t,e){throw new Error("Deserialization not yet implemented")}getFieldArray(t,e){const n=this.getComponentIndex(t);return this.componentStoresArray[n].getFieldArray(e)}entity(t){return new C(this,t)}}export{B as World};
|
|
1
|
+
import{generateId as E}from"../core/generate-id";import{ComponentStore as C}from"./component-store";import{EntityHandle as v}from"./entity-handle";import{WorldSystems as g}from"./world-systems";class T extends g{constructor(t){super();this.nextEntityId=0;this.freeEntityHead=0;this.freeEntityTail=0;this.freeEntityCount=0;this.freeEntityMask=0;this.aliveEntitiesArray=[];this.numMaskWords=0;this.components=[];this.queryResultBuffers={};this.archetypeVersion=0;this.queryCacheVersions={};this.queryMaskCache={};this.despawnedCount=0;this.dirtyBitsByComponent=[];this.fieldsByComponent=[];this.worldId=E({prefix:"world_"});this.maxEntities=t.maxEntities??1e4,this.numMaskWords=Math.ceil(t.components.length/32),this.componentMasks=[];for(let i=0;i<this.numMaskWords;i++)this.componentMasks.push(new Uint32Array(this.maxEntities));this.numMaskWords>0&&(this.componentMasks0=this.componentMasks[0]);const e=Math.pow(2,Math.ceil(Math.log2(this.maxEntities)));this.freeEntityIds=new Uint32Array(e),this.freeEntityMask=e-1,this.aliveEntitiesIndices=new Uint32Array(this.maxEntities),this.aliveEntityFlags=new Uint8Array(this.maxEntities),this.despawnedBuffer=new Uint32Array(this.maxEntities),this.componentStoresArray=new Array(t.components.length);const n=Math.ceil(this.maxEntities/32);this.fieldsByComponent=new Array(t.components.length),t.components.forEach((i,a)=>{this.components.push(i),i.__worldIndex=a;const r=new C(i,this.maxEntities);this.componentStoresArray[a]=r,this.dirtyBitsByComponent[a]=i.__sync!==void 0?new Uint32Array(n):null;const l={};for(let s=0;s<i.fieldNames.length;s++){const o=i.fieldNames[s];l[o]=r.getFieldArray(o)}Object.freeze(l),this.fieldsByComponent[a]=l})}getComponentIndex(t){const e=t.__worldIndex;if(e===void 0){const n=this.components.map(i=>i.name).join(", ");throw new Error(`Component ${t.name} not registered in World[${this.worldId}]. Registered components: [${n}]. Did you forget to include it in the WorldConfig?`)}return e}setComponentBit(t,e){const n=e>>>5,i=e&31;this.componentMasks[n][t]|=1<<i}clearComponentBit(t,e){const n=e>>>5,i=e&31;this.componentMasks[n][t]&=~(1<<i)}hasComponentBit(t,e){const n=e>>>5,i=e&31;return(this.componentMasks[n][t]&1<<i)!==0}clearAllComponentBits(t){if(this.numMaskWords===1)this.componentMasks0[t]=0;else if(this.numMaskWords===2)this.componentMasks0[t]=0,this.componentMasks[1][t]=0;else if(this.numMaskWords===3)this.componentMasks0[t]=0,this.componentMasks[1][t]=0,this.componentMasks[2][t]=0;else for(let e=0;e<this.numMaskWords;e++)this.componentMasks[e][t]=0}matchesComponentMask(t,e){const n=e.length;if(n===1)return(this.componentMasks0[t]&e[0])===e[0];if(n===2)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1];if(n===3)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2];if(n===4)return(this.componentMasks0[t]&e[0])===e[0]&&(this.componentMasks[1][t]&e[1])===e[1]&&(this.componentMasks[2][t]&e[2])===e[2]&&(this.componentMasks[3][t]&e[3])===e[3];for(let i=0;i<n;i++)if((this.componentMasks[i][t]&e[i])!==e[i])return!1;return!0}getQueryMask(t){const e=t.map(s=>s.name).sort().join(","),n=this.queryMaskCache[e];if(n)return n;let i=-1;const a=[];for(const s of t){const o=s.__worldIndex;if(o===void 0)return null;a.push(o),o>i&&(i=o)}const r=Math.floor(i/32)+1,l=new Array(r).fill(0);for(const s of a){const o=s>>>5,h=s&31;l[o]|=1<<h}return this.queryMaskCache[e]=l,l}maskToKey(t){let e="";for(let n=0;n<t.length;n++)t[n]!==0&&(e+=`${n}:${t[n].toString(36)},`);return e}_getQueryMaskKey(t){const e=this.getQueryMask(t);return e?this.maskToKey(e):""}_queryByMaskKey(t,e){let n=this.queryResultBuffers[t];if(n||(n=[],this.queryResultBuffers[t]=n),this.queryCacheVersions[t]===this.archetypeVersion)return n;const i=this.aliveEntitiesArray,a=i.length,r=e.length;let l=0;if(r===1){const s=e[0],o=this.componentMasks0;for(let h=0;h<a;h++){const c=i[h];(o[c]&s)===s&&(n[l++]=c)}}else if(r===2){const s=e[0],o=e[1],h=this.componentMasks0,c=this.componentMasks[1];for(let d=0;d<a;d++){const m=i[d];(h[m]&s)===s&&(c[m]&o)===o&&(n[l++]=m)}}else if(r===3){const s=e[0],o=e[1],h=e[2],c=this.componentMasks0,d=this.componentMasks[1],m=this.componentMasks[2];for(let y=0;y<a;y++){const p=i[y];(c[p]&s)===s&&(d[p]&o)===o&&(m[p]&h)===h&&(n[l++]=p)}}else if(r===4){const s=e[0],o=e[1],h=e[2],c=e[3],d=this.componentMasks0,m=this.componentMasks[1],y=this.componentMasks[2],p=this.componentMasks[3];for(let u=0;u<a;u++){const f=i[u];(d[f]&s)===s&&(m[f]&o)===o&&(y[f]&h)===h&&(p[f]&c)===c&&(n[l++]=f)}}else{const s=this.componentMasks;t:for(let o=0;o<a;o++){const h=i[o];for(let c=0;c<r;c++)if((s[c][h]&e[c])!==e[c])continue t;n[l++]=h}}return n.length=l,this.queryCacheVersions[t]=this.archetypeVersion,n}spawn(){let t=this.nextEntityId;if(this.freeEntityCount>0?(t=this.freeEntityIds[this.freeEntityTail],this.freeEntityTail=this.freeEntityTail+1&this.freeEntityMask,this.freeEntityCount--):this.nextEntityId++,t>=this.maxEntities)throw new Error(`Maximum entities (${this.maxEntities}) reached. Current alive: ${this.aliveEntitiesArray.length}, Free list: ${this.freeEntityCount}`);return this.aliveEntityFlags[t]=1,this.aliveEntitiesIndices[t]=this.aliveEntitiesArray.length,this.aliveEntitiesArray.push(t),this.clearAllComponentBits(t),this.invalidateQueryCache(),t}despawn(t){if(this.aliveEntityFlags[t]===0)return;this.despawnedBuffer[this.despawnedCount++]=t,this.aliveEntityFlags[t]=0;const e=this.aliveEntitiesIndices[t],n=this.aliveEntitiesArray.length-1;if(e!==n){const r=this.aliveEntitiesArray[n];this.aliveEntitiesArray[e]=r,this.aliveEntitiesIndices[r]=e}this.aliveEntitiesArray.pop();const i=this.componentStoresArray,a=this.components.length;for(let r=0;r<a;r++)this.hasComponentBit(t,r)&&i[r].clear(t);this.clearAllComponentBits(t),this.freeEntityIds[this.freeEntityHead]=t,this.freeEntityHead=this.freeEntityHead+1&this.freeEntityMask,this.freeEntityCount++,this.invalidateQueryCache()}isAlive(t){return this.aliveEntityFlags[t]===1}getDespawned(){return this.despawnedBuffer.subarray(0,this.despawnedCount)}flushDespawned(){this.despawnedCount=0}invalidateQueryCache(){this.archetypeVersion++}markDirty(t,e){const n=this.dirtyBitsByComponent[e];n!=null&&(n[t>>>5]|=1<<(t&31))}isDirty(t,e){const n=e.__worldIndex;if(n===void 0)return!1;const i=this.dirtyBitsByComponent[n];return i==null?!1:(i[t>>>5]&1<<(t&31))!==0}clearDirty(t,e){const n=e.__worldIndex;if(n===void 0)return;const i=this.dirtyBitsByComponent[n];i!=null&&(i[t>>>5]&=~(1<<(t&31)))}forEachDirty(t,e){const n=t.__worldIndex;if(n===void 0)return;const i=this.dirtyBitsByComponent[n];if(i!=null)for(let a=0;a<i.length;a++){let r=i[a];if(r===0)continue;const l=a<<5;for(;r!==0;){const s=r&-r,o=31-Math.clz32(s);e(l+o),r^=s}}}clearAllDirty(){for(let t=0;t<this.dirtyBitsByComponent.length;t++){const e=this.dirtyBitsByComponent[t];e?.fill(0)}}add(t,e,n){if(this.aliveEntityFlags[t]===0)throw new Error(`Cannot add component ${e.name} to entity ${t}: entity is not alive (was it despawned?). Current alive entities: ${this.aliveEntitiesArray.length}`);const i=this.getComponentIndex(e),a=this.componentStoresArray[i];this.setComponentBit(t,i),a.set(t,n),this.markDirty(t,i),this.invalidateQueryCache()}remove(t,e){const n=e.__worldIndex;if(n===void 0)return;this.clearComponentBit(t,n);const i=this.componentStoresArray[n];i&&i.clear(t),this.invalidateQueryCache()}has(t,e){const n=e.__worldIndex;return n===void 0?!1:this.hasComponentBit(t,n)}get(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n)){const i=this.getEntityComponentNames(t);throw new Error(`Cannot get component ${e.name} from entity ${t}: entity does not have this component. Entity has: [${i.join(", ")}]. Did you forget to call world.add()?`)}return this.componentStoresArray[n].get(t)}getMutable(t,e){const n=this.getComponentIndex(e);if(!this.hasComponentBit(t,n))throw new Error(`Entity ${t} does not have component ${e.name}`);return this.componentStoresArray[n].getMutable(t)}set(t,e,n){const i=this.getComponentIndex(e);if(!this.hasComponentBit(t,i))throw new Error(`Cannot set component ${e.name} on entity ${t}: entity does not have this component. Use add() first.`);this.componentStoresArray[i].set(t,n),this.markDirty(t,i)}update(t,e,n){const i=this.getComponentIndex(e);if(!this.hasComponentBit(t,i))throw new Error(`Entity ${t} does not have component ${e.name}`);this.componentStoresArray[i].update(t,n),this.markDirty(t,i)}query(...t){const e=this.getQueryMask(t);if(e===null)return[];const n=this.maskToKey(e);let i=this.queryResultBuffers[n];if(i||(i=[],this.queryResultBuffers[n]=i),this.queryCacheVersions[n]===this.archetypeVersion)return i;const a=this.aliveEntitiesArray,r=a.length,l=e.length;let s=0;if(l===1){const o=e[0],h=this.componentMasks0;for(let c=0;c<r;c++){const d=a[c];(h[d]&o)===o&&(i[s++]=d)}}else for(let o=0;o<r;o++){const h=a[o];this.matchesComponentMask(h,e)&&(i[s++]=h)}return i.length=s,this.queryCacheVersions[n]=this.archetypeVersion,i}getEntities(){return this.aliveEntitiesArray}getEntityCount(){return this.aliveEntitiesArray.length}getMaxEntities(){return this.maxEntities}getComponents(){return this.components}getEntityComponentNames(t){const e=[];for(let n=0;n<this.components.length;n++)this.hasComponentBit(t,n)&&e.push(this.components[n].name);return e}serialize(t,e){const n=e??Array.from(this.aliveEntitiesArray),i=[];for(const s of t){const o=s.__worldIndex;if(o===void 0)continue;const h=this.componentStoresArray[o];if(!h)continue;const c=[];for(const d of n)this.has(d,s)&&c.push({entity:d,...h.getMutable(d)});if(c.length>0){const d=s.arrayCodec.encode(c);i.push(d)}}const a=i.reduce((s,o)=>s+o.length,0),r=new Uint8Array(a);let l=0;for(const s of i)r.set(s,l),l+=s.length;return r}deserialize(t,e){throw new Error("Deserialization not yet implemented")}getFieldArray(t,e){const n=this.getComponentIndex(t);return this.componentStoresArray[n].getFieldArray(e)}fields(t){const e=this.getComponentIndex(t);return this.fieldsByComponent[e]}entity(t){return new v(this,t)}}export{T as World};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{createDriver as d,EventSystem as T,FixedTicker as
|
|
1
|
+
import{createDriver as d,EventSystem as T,FixedTicker as y}from"../../core";import{InputManager as _,BrowserInputSource as E}from"../../core/input";class C{constructor(e){this.options=e;this.fps=0;this.status="stopped";this._tickData={deltaTime:0,tick:0,input:null};this._skipData={ticks:0};this._renderData={deltaTime:0,alpha:0,input:null};const r=new Set(["client","manual-client"]),p=new Set(["manual-client","manual-server"]);this._isClient=r.has(this.options.type),this._isManual=p.has(this.options.type);const l=["sync","pre-tick","tick","post-tick","skip","start","stop","toggle-pause"];this._isClient&&l.push("render"),this.events=new T({events:l}),this._input=new _;const i=this.events;if(this.ticker=new y({rate:this.options.tickRate,onTick:(t,s=0)=>{const n=this._input.snapshot();this._tickData.deltaTime=t,this._tickData.tick=s,this._tickData.input=n,i.emit("sync",this._tickData),i.emit("pre-tick",this._tickData),this.options.onTick?.(t,s,n),i.emit("tick",this._tickData),i.emit("post-tick",this._tickData)},onTickSkipped:t=>{this._skipData.ticks=t,i.emit("skip",this._skipData)}}),this._isManual||(this._driver=d(this.options.type,t=>{this.step(t)})),this._isClient){const t=this.events,s=Math.round(this.options.tickRate/2),n=new Array(s).fill(0);let u=0,h=performance.now(),c=0,o=0;t.on("tick",()=>{c=(c+1)%s;const m=performance.now(),v=m-h;if(v>0){const a=u*1e3/v;n[c]=a,o<s&&o++}u=0,h=m;let k=0;for(let a=0;a<o;a++)k+=n[a];this.fps=Math.round(k/o)}),t.on("render",()=>{u++})}}step(e){if(this.ticker.tick(e),this._isClient){const r=this._input.peek(),p=this.ticker.alpha;this.options.onRender?.(e,p,r),this._renderData.deltaTime=e,this._renderData.alpha=p,this._renderData.input=r,this.events.emit("render",this._renderData)}}pause(){this._driver&&this._driver.stop(),this.status="paused",this.events.emit("toggle-pause",{paused:!0,lastToggledAt:Date.now(),lastToggleTick:this.ticker.tickCount})}resume(){this._driver&&this._driver.start(),this.status="running",this.events.emit("toggle-pause",{paused:!1,lastToggledAt:Date.now(),lastToggleTick:this.ticker.tickCount})}start(){if(this._driver&&this._driver.start(),this.status="running",this.events.emit("start",{startedAt:Date.now()}),this._isClient){const e=new E(document,document.body);this._input.listen(e)}}stop(){this._driver&&this._driver.stop(),this.ticker.resetTickCount(),this.status="stopped",this.events.emit("stop",{stoppedAt:Date.now()}),this._isClient&&this._input.unlisten()}}export{C as GameLoop};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{generateId as
|
|
1
|
+
import{generateId as h}from"../../core/generate-id/generate-id";class c{constructor(e){this.messageHandlers=[];this.closeHandlers=[];this.errorHandlers=[];this.socket=e,this.setupHandlers()}send(e){this.socket.readyState===WebSocket.OPEN&&this.socket.send(e)}onMessage(e){this.messageHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}onError(e){this.errorHandlers.push(e)}close(){this.socket.close()}setupHandlers(){this.socket.binaryType="arraybuffer",this.socket.addEventListener("message",e=>{if(e.data instanceof ArrayBuffer){const r=new Uint8Array(e.data);for(const t of this.messageHandlers)t(r)}else{const r=new Error(`Unexpected message type: ${typeof e.data}`);for(const t of this.errorHandlers)t(r)}}),this.socket.addEventListener("close",()=>{for(const e of this.closeHandlers)e()}),this.socket.addEventListener("error",()=>{const e=new Error("WebSocket error");for(const r of this.errorHandlers)r(e)})}static connect(e){return new Promise((r,t)=>{const i=new WebSocket(e),a=new c(i);i.addEventListener("open",()=>{r(a)}),i.addEventListener("error",o=>{t(o)})})}}class v{constructor(e){this.messageHandlers=[];this.closeHandlers=[];this.errorHandlers=[];this.socket=e}send(e){this.socket.send(e)}onMessage(e){this.messageHandlers.push(e)}onClose(e){this.closeHandlers.push(e)}onError(e){this.errorHandlers.push(e)}close(){this.socket.close()}_handleOpen(){}_handleMessage(e){for(const r of this.messageHandlers)r(e)}_handleClose(){for(const e of this.closeHandlers)e()}_handleError(e){for(const r of this.errorHandlers)r(e)}}class p{constructor(e){this.peers=new Map;this.connectionHandlers=[];this.disconnectionHandlers=[];this.server=e}onConnection(e){this.connectionHandlers.push(e)}onDisconnection(e){this.disconnectionHandlers.push(e)}getPeer(e){return this.peers.get(e)}getPeerIds(){return Array.from(this.peers.keys())}close(){this.server.stop(),this.peers.clear()}_registerPeer(e){const r=h({prefix:"peer_"}),t=new v(e);return this.peers.set(r,t),r}_handlePeerMessage(e,r){const t=this.peers.get(e);t&&t._handleMessage(r)}_handlePeerDisconnection(e){const r=this.peers.get(e);if(r){r._handleClose(),this.peers.delete(e);for(const t of this.disconnectionHandlers)t(e)}}_handlePeerConnection(e){const r=this.peers.get(e);if(r)for(const t of this.connectionHandlers)t(r,e)}static create(e,r){const t=new WeakMap,i=r?.path,a=r?.fetch;let o;const l=Bun.serve({port:e,fetch(s,n){if(!((i===void 0||new URL(s.url).pathname===i)&&n.upgrade(s)))return a!==void 0?a(s,n):new Response("Expected WebSocket connection",{status:400})},websocket:{open(s){const n=o._registerPeer(s);t.set(s,n),o._handlePeerConnection(n)},message(s,n){const d=t.get(s);d&&n instanceof Uint8Array?o._handlePeerMessage(d,n):d&&n instanceof ArrayBuffer&&o._handlePeerMessage(d,new Uint8Array(n))},close(s){const n=t.get(s);n&&(o._handlePeerDisconnection(n),t.delete(s))}}});return o=new p(l),o}}export{c as BunWebSocketClientTransport,v as BunWebSocketPeerTransport,p as BunWebSocketServerTransport};
|