murow 0.0.72 → 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/core/sparse-batcher/sparse-batcher.js +1 -1
- 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/cjs/renderer/base/renderer-3d.js +1 -1
- package/dist/cjs/renderer/prefab-bucket/concrete.js +1 -1
- package/dist/cjs/renderer/prefab-bucket/index.js +1 -1
- package/dist/cjs/renderer/prefab-bucket/parsers.js +1 -1
- package/dist/cjs/renderer/prefab-bucket/specs.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/core/sparse-batcher/sparse-batcher.js +1 -1
- 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/esm/renderer/base/renderer-3d.js +1 -1
- package/dist/esm/renderer/prefab-bucket/concrete.js +1 -1
- package/dist/esm/renderer/prefab-bucket/index.js +1 -1
- package/dist/esm/renderer/prefab-bucket/parsers.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 +17 -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/types/renderer/base/renderer-3d.d.ts +1 -1
- package/dist/types/renderer/prefab-bucket/concrete.d.ts +42 -2
- package/dist/types/renderer/prefab-bucket/index.d.ts +12 -2
- package/dist/types/renderer/prefab-bucket/specs.d.ts +46 -3
- package/dist/types/renderer/types.d.ts +5 -3
- package/dist/webgpu/cjs/index.js +591 -40
- package/dist/webgpu/esm/index.js +591 -40
- package/dist/webgpu/types/3d/renderer.d.ts +111 -5
- package/package.json +6 -1
|
@@ -2,8 +2,19 @@
|
|
|
2
2
|
* A binary field descriptor.
|
|
3
3
|
* Defines how a single value is serialized/deserialized
|
|
4
4
|
* at a fixed byte size.
|
|
5
|
+
*
|
|
6
|
+
* The second type parameter `A` is a compile-time-only marker for the
|
|
7
|
+
* typed array kind used when this field is stored in an ECS World's
|
|
8
|
+
* Structure-of-Arrays column. Tagging `f32 → Float32Array`, `u8 →
|
|
9
|
+
* Uint8Array`, etc. lets `world.fields(Component)` return precisely
|
|
10
|
+
* typed Float32Array / Int32Array / ... per field without casts. The
|
|
11
|
+
* parameter is purely structural — it never appears at runtime.
|
|
12
|
+
*
|
|
13
|
+
* Defaults to `unknown` so existing call sites continue to compile.
|
|
14
|
+
* Composite fields (vec2/vec3/color/string) leave `A` defaulted; only
|
|
15
|
+
* the scalar primitives narrow it.
|
|
5
16
|
*/
|
|
6
|
-
export type Field<T> = {
|
|
17
|
+
export type Field<T, A = unknown> = {
|
|
7
18
|
/** Size of the field in bytes */
|
|
8
19
|
size: number;
|
|
9
20
|
/**
|
|
@@ -23,6 +34,13 @@ export type Field<T> = {
|
|
|
23
34
|
* Returns the nil value
|
|
24
35
|
*/
|
|
25
36
|
toNil(): T;
|
|
37
|
+
/**
|
|
38
|
+
* Compile-time-only phantom marker for the SoA typed array kind. Never
|
|
39
|
+
* read at runtime; never written by any of the primitives. Exists so
|
|
40
|
+
* `Field<number, Float32Array>` and `Field<number, Uint8Array>` are
|
|
41
|
+
* structurally distinguishable to TypeScript.
|
|
42
|
+
*/
|
|
43
|
+
readonly __array?: A;
|
|
26
44
|
};
|
|
27
45
|
/**
|
|
28
46
|
* A schema mapping object keys to binary fields.
|
|
@@ -33,8 +51,19 @@ export type Field<T> = {
|
|
|
33
51
|
* Do not rely on computed or dynamic keys.
|
|
34
52
|
*/
|
|
35
53
|
export type Schema<T> = {
|
|
36
|
-
[K in keyof T]: Field<T[K]>;
|
|
54
|
+
[K in keyof T]: Field<T[K], any>;
|
|
37
55
|
};
|
|
56
|
+
/**
|
|
57
|
+
* Helper for extracting the per-field typed-array kind from a schema.
|
|
58
|
+
*
|
|
59
|
+
* Given a precise schema literal like `{ x: BinaryCodec.f32, y: BinaryCodec.u8 }`
|
|
60
|
+
* (inferred narrowly, not widened to `Schema<T>`), this maps each field to
|
|
61
|
+
* its tagged array kind: `{ x: Float32Array, y: Uint8Array }`.
|
|
62
|
+
*
|
|
63
|
+
* Fields whose `A` is `unknown` (composites: vec/color/string) fall back
|
|
64
|
+
* to the broad TypedArray union.
|
|
65
|
+
*/
|
|
66
|
+
export type ArrayFromField<F> = F extends Field<any, infer A> ? unknown extends A ? Float32Array | Int32Array | Uint32Array | Uint16Array | Uint8Array | Int8Array | Int16Array | Float64Array : A : never;
|
|
38
67
|
/**
|
|
39
68
|
* Base codec implementation.
|
|
40
69
|
* Handles schema-driven encoding/decoding.
|
|
@@ -69,25 +98,25 @@ export declare class BaseBinaryCodec {
|
|
|
69
98
|
*/
|
|
70
99
|
export declare class BinaryPrimitives {
|
|
71
100
|
/** Unsigned 8-bit integer */
|
|
72
|
-
static readonly u8: Field<number>;
|
|
101
|
+
static readonly u8: Field<number, Uint8Array>;
|
|
73
102
|
/** Unsigned 16-bit integer (big-endian) */
|
|
74
|
-
static readonly u16: Field<number>;
|
|
103
|
+
static readonly u16: Field<number, Uint16Array>;
|
|
75
104
|
/** Unsigned 32-bit integer (big-endian) */
|
|
76
|
-
static readonly u32: Field<number>;
|
|
105
|
+
static readonly u32: Field<number, Uint32Array>;
|
|
77
106
|
/** Signed 8-bit integer */
|
|
78
|
-
static readonly i8: Field<number>;
|
|
107
|
+
static readonly i8: Field<number, Int8Array>;
|
|
79
108
|
/** Signed 16-bit integer (big-endian) */
|
|
80
|
-
static readonly i16: Field<number>;
|
|
109
|
+
static readonly i16: Field<number, Int16Array>;
|
|
81
110
|
/** Signed 32-bit integer (big-endian) */
|
|
82
|
-
static readonly i32: Field<number>;
|
|
83
|
-
/** 16-bit floating point number (IEEE 754, big-endian) */
|
|
84
|
-
static readonly f16: Field<number>;
|
|
111
|
+
static readonly i32: Field<number, Int32Array>;
|
|
112
|
+
/** 16-bit floating point number (IEEE 754, big-endian) — stored as raw u16 bits */
|
|
113
|
+
static readonly f16: Field<number, Uint16Array>;
|
|
85
114
|
/** 32-bit floating point number (IEEE 754, big-endian) */
|
|
86
|
-
static readonly f32: Field<number>;
|
|
115
|
+
static readonly f32: Field<number, Float32Array>;
|
|
87
116
|
/** 64-bit floating point number (double, big-endian) */
|
|
88
|
-
static readonly f64: Field<number>;
|
|
117
|
+
static readonly f64: Field<number, Float64Array>;
|
|
89
118
|
/** Boolean stored as 1 byte (0 = false, 1 = true) */
|
|
90
|
-
static readonly bool: Field<boolean>;
|
|
119
|
+
static readonly bool: Field<boolean, Uint8Array>;
|
|
91
120
|
/**
|
|
92
121
|
* String field with UTF-8 encoding and 2-byte length prefix.
|
|
93
122
|
* @param maxLength Maximum number of bytes allowed
|
|
@@ -112,17 +141,17 @@ export declare class BinaryPrimitives {
|
|
|
112
141
|
a: number;
|
|
113
142
|
}>;
|
|
114
143
|
/** 32-bit floating point number (IEEE 754, little-endian) */
|
|
115
|
-
static readonly f32_le: Field<number>;
|
|
144
|
+
static readonly f32_le: Field<number, Float32Array>;
|
|
116
145
|
/** 64-bit floating point number (double, little-endian) */
|
|
117
|
-
static readonly f64_le: Field<number>;
|
|
146
|
+
static readonly f64_le: Field<number, Float64Array>;
|
|
118
147
|
/** Unsigned 16-bit integer (little-endian) */
|
|
119
|
-
static readonly u16_le: Field<number>;
|
|
148
|
+
static readonly u16_le: Field<number, Uint16Array>;
|
|
120
149
|
/** Unsigned 32-bit integer (little-endian) */
|
|
121
|
-
static readonly u32_le: Field<number>;
|
|
150
|
+
static readonly u32_le: Field<number, Uint32Array>;
|
|
122
151
|
/** Signed 16-bit integer (little-endian) */
|
|
123
|
-
static readonly i16_le: Field<number>;
|
|
152
|
+
static readonly i16_le: Field<number, Int16Array>;
|
|
124
153
|
/** Signed 32-bit integer (little-endian) */
|
|
125
|
-
static readonly i32_le: Field<number>;
|
|
154
|
+
static readonly i32_le: Field<number, Int32Array>;
|
|
126
155
|
/**
|
|
127
156
|
* 2D vector of f32 stored as a tuple [x, y] (little-endian).
|
|
128
157
|
* Useful for compact math data or shader-friendly layouts.
|
|
@@ -145,43 +174,43 @@ export declare class BinaryPrimitives {
|
|
|
145
174
|
*/
|
|
146
175
|
export declare class BinaryCodec extends BaseBinaryCodec {
|
|
147
176
|
/** Unsigned 8-bit integer field */
|
|
148
|
-
static readonly u8: Field<number
|
|
177
|
+
static readonly u8: Field<number, Uint8Array<ArrayBufferLike>>;
|
|
149
178
|
/** Unsigned 16-bit integer field */
|
|
150
|
-
static readonly u16: Field<number
|
|
179
|
+
static readonly u16: Field<number, Uint16Array<ArrayBufferLike>>;
|
|
151
180
|
/** Unsigned 32-bit integer field */
|
|
152
|
-
static readonly u32: Field<number
|
|
181
|
+
static readonly u32: Field<number, Uint32Array<ArrayBufferLike>>;
|
|
153
182
|
/** Signed 8-bit integer field */
|
|
154
|
-
static readonly i8: Field<number
|
|
183
|
+
static readonly i8: Field<number, Int8Array<ArrayBufferLike>>;
|
|
155
184
|
/** Signed 16-bit integer field */
|
|
156
|
-
static readonly i16: Field<number
|
|
185
|
+
static readonly i16: Field<number, Int16Array<ArrayBufferLike>>;
|
|
157
186
|
/** Signed 32-bit integer field */
|
|
158
|
-
static readonly i32: Field<number
|
|
187
|
+
static readonly i32: Field<number, Int32Array<ArrayBufferLike>>;
|
|
159
188
|
/** 16-bit floating point field */
|
|
160
|
-
static readonly f16: Field<number
|
|
189
|
+
static readonly f16: Field<number, Uint16Array<ArrayBufferLike>>;
|
|
161
190
|
/** 32-bit floating point field */
|
|
162
|
-
static readonly f32: Field<number
|
|
191
|
+
static readonly f32: Field<number, Float32Array<ArrayBufferLike>>;
|
|
163
192
|
/** Boolean field */
|
|
164
|
-
static readonly bool: Field<boolean
|
|
193
|
+
static readonly bool: Field<boolean, Uint8Array<ArrayBufferLike>>;
|
|
165
194
|
/** String field with length prefix */
|
|
166
195
|
static string: typeof BinaryPrimitives.string;
|
|
167
196
|
/** 2D vector field */
|
|
168
197
|
static readonly vec2: Field<{
|
|
169
198
|
x: number;
|
|
170
199
|
y: number;
|
|
171
|
-
}>;
|
|
200
|
+
}, unknown>;
|
|
172
201
|
/** 3D vector field */
|
|
173
202
|
static readonly vec3: Field<{
|
|
174
203
|
x: number;
|
|
175
204
|
y: number;
|
|
176
205
|
z: number;
|
|
177
|
-
}>;
|
|
206
|
+
}, unknown>;
|
|
178
207
|
/** RGBA color field */
|
|
179
208
|
static readonly color: Field<{
|
|
180
209
|
r: number;
|
|
181
210
|
g: number;
|
|
182
211
|
b: number;
|
|
183
212
|
a: number;
|
|
184
|
-
}>;
|
|
213
|
+
}, unknown>;
|
|
185
214
|
/**
|
|
186
215
|
* Encodes an object into a binary buffer.
|
|
187
216
|
*/
|
|
@@ -191,3 +220,32 @@ export declare class BinaryCodec extends BaseBinaryCodec {
|
|
|
191
220
|
*/
|
|
192
221
|
static decode<T extends object>(schema: Schema<T>, buf: Uint8Array, target: T): T;
|
|
193
222
|
}
|
|
223
|
+
export declare const u8: Field<number, Uint8Array<ArrayBufferLike>>;
|
|
224
|
+
export declare const u16: Field<number, Uint16Array<ArrayBufferLike>>;
|
|
225
|
+
export declare const u32: Field<number, Uint32Array<ArrayBufferLike>>;
|
|
226
|
+
export declare const i8: Field<number, Int8Array<ArrayBufferLike>>;
|
|
227
|
+
export declare const i16: Field<number, Int16Array<ArrayBufferLike>>;
|
|
228
|
+
export declare const i32: Field<number, Int32Array<ArrayBufferLike>>;
|
|
229
|
+
export declare const f16: Field<number, Uint16Array<ArrayBufferLike>>;
|
|
230
|
+
export declare const f32: Field<number, Float32Array<ArrayBufferLike>>;
|
|
231
|
+
export declare const f64: Field<number, Float64Array<ArrayBufferLike>>;
|
|
232
|
+
export declare const bool: Field<boolean, Uint8Array<ArrayBufferLike>>;
|
|
233
|
+
export declare const string: typeof BinaryPrimitives.string;
|
|
234
|
+
export declare const vec2: Field<{
|
|
235
|
+
x: number;
|
|
236
|
+
y: number;
|
|
237
|
+
}, unknown>;
|
|
238
|
+
export declare const vec3: Field<{
|
|
239
|
+
x: number;
|
|
240
|
+
y: number;
|
|
241
|
+
z: number;
|
|
242
|
+
}, unknown>;
|
|
243
|
+
export declare const vec2_le: Field<[number, number], unknown>;
|
|
244
|
+
export declare const vec3_le: Field<[number, number, number], unknown>;
|
|
245
|
+
export declare const vec4_le: Field<[number, number, number, number], unknown>;
|
|
246
|
+
export declare const color: Field<{
|
|
247
|
+
r: number;
|
|
248
|
+
g: number;
|
|
249
|
+
b: number;
|
|
250
|
+
a: number;
|
|
251
|
+
}, unknown>;
|
|
@@ -13,7 +13,7 @@ export interface LoopDriver {
|
|
|
13
13
|
/** Internal loop iteration method */
|
|
14
14
|
loop(): void;
|
|
15
15
|
/** Update callback invoked each frame with delta time in seconds */
|
|
16
|
-
update(
|
|
16
|
+
update(deltaTime: number): void;
|
|
17
17
|
}
|
|
18
18
|
/**
|
|
19
19
|
* Type of driver to use for the game loop.
|
|
@@ -35,24 +35,24 @@ export type DriverType = 'server-immediate' | 'client' | 'server-timeout';
|
|
|
35
35
|
* @example
|
|
36
36
|
* ```typescript
|
|
37
37
|
* // Client
|
|
38
|
-
* const clientDriver = createDriver('client', (
|
|
39
|
-
* game.update(
|
|
38
|
+
* const clientDriver = createDriver('client', (deltaTime) => {
|
|
39
|
+
* game.update(deltaTime);
|
|
40
40
|
* renderer.render();
|
|
41
41
|
* });
|
|
42
42
|
* clientDriver.start();
|
|
43
43
|
*
|
|
44
44
|
* // Server (maximum performance)
|
|
45
|
-
* const serverDriver = createDriver('server', (
|
|
46
|
-
* simulation.tick(
|
|
45
|
+
* const serverDriver = createDriver('server', (deltaTime) => {
|
|
46
|
+
* simulation.tick(deltaTime);
|
|
47
47
|
* });
|
|
48
48
|
* serverDriver.start();
|
|
49
49
|
*
|
|
50
50
|
* // Server (balanced with I/O)
|
|
51
|
-
* const balancedDriver = createDriver('server-timeout', (
|
|
52
|
-
* simulation.tick(
|
|
51
|
+
* const balancedDriver = createDriver('server-timeout', (deltaTime) => {
|
|
52
|
+
* simulation.tick(deltaTime);
|
|
53
53
|
* handleNetworkIO();
|
|
54
54
|
* });
|
|
55
55
|
* balancedDriver.start();
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
58
|
-
export declare function createDriver(type: DriverType, update: (
|
|
58
|
+
export declare function createDriver(type: DriverType, update: (deltaTime: number) => void): ImmediateDriver | RafDriver | TimeoutDriver;
|
|
@@ -11,19 +11,19 @@ import { LoopDriver } from "../driver";
|
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
|
-
* const driver = new ImmediateDriver((
|
|
15
|
-
* world.tick(
|
|
14
|
+
* const driver = new ImmediateDriver((deltaTime) => {
|
|
15
|
+
* world.tick(deltaTime);
|
|
16
16
|
* broadcastState();
|
|
17
17
|
* });
|
|
18
18
|
* driver.start();
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
export declare class ImmediateDriver implements LoopDriver {
|
|
22
|
-
update: (
|
|
22
|
+
update: (deltaTime: number) => void;
|
|
23
23
|
/**
|
|
24
24
|
* @param update - Callback invoked each tick with delta time in seconds
|
|
25
25
|
*/
|
|
26
|
-
constructor(update: (
|
|
26
|
+
constructor(update: (deltaTime: number) => void);
|
|
27
27
|
private last;
|
|
28
28
|
private running;
|
|
29
29
|
/**
|
|
@@ -9,26 +9,36 @@ import { LoopDriver } from "../driver";
|
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```typescript
|
|
12
|
-
* const driver = new RafDriver((
|
|
13
|
-
* player.update(
|
|
12
|
+
* const driver = new RafDriver((deltaTime) => {
|
|
13
|
+
* player.update(deltaTime);
|
|
14
14
|
* renderer.render();
|
|
15
15
|
* });
|
|
16
16
|
* driver.start();
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
19
|
export declare class RafDriver implements LoopDriver {
|
|
20
|
-
update: (
|
|
20
|
+
update: (deltaTime: number) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Hard upper bound on a single frame's delta, in ms. Long pauses (tab
|
|
23
|
+
* backgrounded, breakpoint hit, browser throttling) deliver one huge
|
|
24
|
+
* frame on resume. Clamping keeps the engine from trying to "catch up"
|
|
25
|
+
* by replaying that lost time at high speed.
|
|
26
|
+
*/
|
|
27
|
+
private static readonly MAX_DELTA_MS;
|
|
21
28
|
/**
|
|
22
29
|
* @param update - Callback invoked each frame with delta time in seconds
|
|
23
30
|
*/
|
|
24
|
-
constructor(update: (
|
|
31
|
+
constructor(update: (deltaTime: number) => void);
|
|
25
32
|
private last;
|
|
26
33
|
private running;
|
|
27
34
|
private rafId;
|
|
35
|
+
private visibilityHandler;
|
|
28
36
|
/**
|
|
29
37
|
* Starts the game loop using requestAnimationFrame.
|
|
30
38
|
*
|
|
31
|
-
* Resets timing to prevent large initial delta
|
|
39
|
+
* Resets timing to prevent large initial delta and installs a
|
|
40
|
+
* visibilitychange handler so the first frame after a hidden tab
|
|
41
|
+
* doesn't deliver a multi-second delta.
|
|
32
42
|
*/
|
|
33
43
|
start(): void;
|
|
34
44
|
/**
|
|
@@ -38,7 +48,8 @@ export declare class RafDriver implements LoopDriver {
|
|
|
38
48
|
/**
|
|
39
49
|
* Internal loop method that calculates delta time and schedules the next frame.
|
|
40
50
|
*
|
|
41
|
-
* Delta time is provided in seconds
|
|
51
|
+
* Delta time is provided in seconds, clamped to `MAX_DELTA_MS` so a paused
|
|
52
|
+
* tab doesn't deliver a multi-second frame.
|
|
42
53
|
*/
|
|
43
54
|
loop: () => void;
|
|
44
55
|
}
|
|
@@ -16,19 +16,19 @@ import { LoopDriver } from "../driver";
|
|
|
16
16
|
*
|
|
17
17
|
* @example
|
|
18
18
|
* ```typescript
|
|
19
|
-
* const driver = new TimeoutDriver((
|
|
20
|
-
* world.tick(
|
|
19
|
+
* const driver = new TimeoutDriver((deltaTime) => {
|
|
20
|
+
* world.tick(deltaTime);
|
|
21
21
|
* broadcastState();
|
|
22
22
|
* });
|
|
23
23
|
* driver.start();
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
26
|
export declare class TimeoutDriver implements LoopDriver {
|
|
27
|
-
update: (
|
|
27
|
+
update: (deltaTime: number) => void;
|
|
28
28
|
/**
|
|
29
29
|
* @param update - Callback invoked each tick with delta time in seconds
|
|
30
30
|
*/
|
|
31
|
-
constructor(update: (
|
|
31
|
+
constructor(update: (deltaTime: number) => void);
|
|
32
32
|
private last;
|
|
33
33
|
private running;
|
|
34
34
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./mouse-look";
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { InputSnapshot } from "../types";
|
|
2
|
+
export interface AxisOptions {
|
|
3
|
+
/** Initial value, radians. Default 0. */
|
|
4
|
+
initial?: number;
|
|
5
|
+
/** Lower clamp, radians. Default -Infinity (unbounded). */
|
|
6
|
+
min?: number;
|
|
7
|
+
/** Upper clamp, radians. Default +Infinity (unbounded). */
|
|
8
|
+
max?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface MouseLookOptions {
|
|
11
|
+
/** Radians per pixel of mouse motion. Default 0.002. */
|
|
12
|
+
sensitivity?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Yaw axis config. Default: unbounded (yaw wraps freely around the
|
|
15
|
+
* vertical axis). Clamp it for cameras that don't rotate fully.
|
|
16
|
+
*/
|
|
17
|
+
yaw?: AxisOptions;
|
|
18
|
+
/**
|
|
19
|
+
* Pitch axis config. Default min/max: ±PI/2 - 0.01 (just shy of
|
|
20
|
+
* straight up/down so the basis vectors stay well-defined).
|
|
21
|
+
*/
|
|
22
|
+
pitch?: AxisOptions;
|
|
23
|
+
/**
|
|
24
|
+
* Flip horizontal look direction. With the default (false), moving
|
|
25
|
+
* the mouse right rotates the view right; set true to invert.
|
|
26
|
+
*/
|
|
27
|
+
invertX?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Flip vertical look direction. With the default (false), moving the
|
|
30
|
+
* mouse up tilts the view up; set true for flight-sim style.
|
|
31
|
+
*/
|
|
32
|
+
invertY?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Accept drag-to-look as a fallback for platforms without Pointer Lock
|
|
35
|
+
* (iOS Safari). When true, `update(input)` accumulates while
|
|
36
|
+
* `dragButton` is held even without an active lock. Default true.
|
|
37
|
+
*/
|
|
38
|
+
drag?: boolean;
|
|
39
|
+
/** Mouse button that drives drag-to-look. Default 'left'. */
|
|
40
|
+
dragButton?: "left" | "middle" | "right";
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Yaw/pitch state driven by mouse motion, with optional pointer lock and
|
|
44
|
+
* drag-to-look fallback.
|
|
45
|
+
*
|
|
46
|
+
* The class owns the input handling. Output helpers (`forward`, `right`,
|
|
47
|
+
* `up`, `orbit`) are read-only views computed from yaw/pitch each call.
|
|
48
|
+
*
|
|
49
|
+
* Zero-alloc: each output has its own backing `Float32Array(3)` reused
|
|
50
|
+
* across calls. Don't hold a reference past the next call to the same
|
|
51
|
+
* accessor; the values will overwrite. Copy if you need to persist.
|
|
52
|
+
*
|
|
53
|
+
* Usage:
|
|
54
|
+
* ```ts
|
|
55
|
+
* const look = new MouseLook({ sensitivity: 0.002 });
|
|
56
|
+
*
|
|
57
|
+
* canvas.addEventListener('click', () => {
|
|
58
|
+
* look.lock(canvas).catch(() => {}); // iOS: drag-to-look takes over
|
|
59
|
+
* });
|
|
60
|
+
*
|
|
61
|
+
* loop.events.on('tick', ({ input }) => {
|
|
62
|
+
* look.update(input);
|
|
63
|
+
*
|
|
64
|
+
* // FPS:
|
|
65
|
+
* const pos = renderer.camera.position;
|
|
66
|
+
* const f = look.forward;
|
|
67
|
+
* renderer.camera.setTarget(pos[0] + f[0], pos[1] + f[1], pos[2] + f[2]);
|
|
68
|
+
*
|
|
69
|
+
* // Or TPS / orbit:
|
|
70
|
+
* const c = look.orbit(playerPos, 8);
|
|
71
|
+
* renderer.camera.setPosition(c[0], c[1], c[2]);
|
|
72
|
+
* renderer.camera.setTarget(playerPos[0], playerPos[1], playerPos[2]);
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare class MouseLook {
|
|
77
|
+
yaw: number;
|
|
78
|
+
pitch: number;
|
|
79
|
+
sensitivity: number;
|
|
80
|
+
yawMin: number;
|
|
81
|
+
yawMax: number;
|
|
82
|
+
pitchMin: number;
|
|
83
|
+
pitchMax: number;
|
|
84
|
+
invertX: boolean;
|
|
85
|
+
invertY: boolean;
|
|
86
|
+
drag: boolean;
|
|
87
|
+
dragButton: "left" | "middle" | "right";
|
|
88
|
+
private lockedElement;
|
|
89
|
+
/** Active `pointerlockchange`/`error` listeners from an in-flight `lock()`. */
|
|
90
|
+
private pendingLockCleanup;
|
|
91
|
+
private _forward;
|
|
92
|
+
private _right;
|
|
93
|
+
private _up;
|
|
94
|
+
private _orbit;
|
|
95
|
+
constructor(opts?: MouseLookOptions);
|
|
96
|
+
/**
|
|
97
|
+
* Apply input deltas. Gated internally: writes happen when pointer
|
|
98
|
+
* lock is active, or (if `drag` is true) while `dragButton` is held.
|
|
99
|
+
*/
|
|
100
|
+
update(input: InputSnapshot): void;
|
|
101
|
+
/**
|
|
102
|
+
* Request pointer lock on `element`. Resolves once locked. Rejects if
|
|
103
|
+
* Pointer Lock API is unavailable (iOS Safari) or the browser denies
|
|
104
|
+
* the request, in which case drag-to-look takes over (if enabled).
|
|
105
|
+
*/
|
|
106
|
+
lock(element: HTMLElement): Promise<void>;
|
|
107
|
+
/** Release pointer lock if currently held. */
|
|
108
|
+
unlock(): void;
|
|
109
|
+
/** True while pointer lock is active on the element we locked to. */
|
|
110
|
+
get locked(): boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Unit vector pointing the way the camera is facing. Shared buffer:
|
|
113
|
+
* don't hold the returned reference past the next `forward` read.
|
|
114
|
+
*/
|
|
115
|
+
get forward(): Float32Array;
|
|
116
|
+
/**
|
|
117
|
+
* Right direction. Lies in the XZ plane, independent of pitch.
|
|
118
|
+
* Shared buffer: don't hold the returned reference past the next
|
|
119
|
+
* `right` read.
|
|
120
|
+
*/
|
|
121
|
+
get right(): Float32Array;
|
|
122
|
+
/**
|
|
123
|
+
* Camera-local up. Tilts with pitch. Shared buffer: don't hold the
|
|
124
|
+
* returned reference past the next `up` read.
|
|
125
|
+
*/
|
|
126
|
+
get up(): Float32Array;
|
|
127
|
+
/**
|
|
128
|
+
* Camera position in orbit around `target` at `distance`, given the
|
|
129
|
+
* current yaw/pitch. Pairs naturally with `setTarget(target)` to
|
|
130
|
+
* point the camera back at the orbited object. Shared buffer: don't
|
|
131
|
+
* hold the returned reference past the next `orbit` call.
|
|
132
|
+
*/
|
|
133
|
+
orbit(target: ArrayLike<number>, distance: number): Float32Array;
|
|
134
|
+
/**
|
|
135
|
+
* Release pointer lock, drop the locked element, and detach any
|
|
136
|
+
* in-flight `lock()` listeners. Safe to call multiple times.
|
|
137
|
+
*/
|
|
138
|
+
destroy(): void;
|
|
139
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./scroll-zoom";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { InputSnapshot } from "../types";
|
|
2
|
+
export interface ScrollZoomOptions {
|
|
3
|
+
/** Starting value. */
|
|
4
|
+
initial: number;
|
|
5
|
+
/** Lower clamp. */
|
|
6
|
+
min: number;
|
|
7
|
+
/** Upper clamp. */
|
|
8
|
+
max: number;
|
|
9
|
+
/**
|
|
10
|
+
* Multiplied with the per-tick scroll delta. Positive scroll (wheel
|
|
11
|
+
* forward / two-finger up) increases `value` by `sensitivity *
|
|
12
|
+
* deltaScrollY`. Use a negative sensitivity to invert. Default 0.01.
|
|
13
|
+
*/
|
|
14
|
+
sensitivity?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Scroll-wheel driven scalar with clamps. Use for orbit distance, FOV,
|
|
18
|
+
* RTS camera height, anything that's "scroll to change a number."
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```ts
|
|
22
|
+
* const zoom = new ScrollZoom({ initial: 8, min: 3, max: 20 });
|
|
23
|
+
*
|
|
24
|
+
* loop.events.on('tick', ({ input }) => {
|
|
25
|
+
* zoom.update(input);
|
|
26
|
+
* const [cx, cy, cz] = mouseLook.orbit(playerPos, zoom.value);
|
|
27
|
+
* // ...
|
|
28
|
+
* });
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class ScrollZoom {
|
|
32
|
+
value: number;
|
|
33
|
+
min: number;
|
|
34
|
+
max: number;
|
|
35
|
+
sensitivity: number;
|
|
36
|
+
constructor(opts: ScrollZoomOptions);
|
|
37
|
+
update(input: InputSnapshot): void;
|
|
38
|
+
}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { Schema } from "../core/binary-codec";
|
|
2
2
|
import { ArrayField } from "../core/pooled-codec";
|
|
3
3
|
/**
|
|
4
|
-
* Metadata for a component definition
|
|
4
|
+
* Metadata for a component definition.
|
|
5
|
+
*
|
|
6
|
+
* The second type parameter `S` carries the precise schema literal type
|
|
7
|
+
* (e.g. `{ x: Field<number, Float32Array>, y: Field<number, Uint8Array> }`)
|
|
8
|
+
* so that `world.fields(component)` can return a per-field typed-array
|
|
9
|
+
* map without casts. Defaults to the loose `Schema<T>` for compatibility
|
|
10
|
+
* with callers that don't preserve the narrow schema.
|
|
5
11
|
*/
|
|
6
|
-
export interface ComponentMeta<T extends object> {
|
|
12
|
+
export interface ComponentMeta<T extends object, S extends Schema<T> = Schema<T>> {
|
|
7
13
|
/** Schema defining the component's binary layout */
|
|
8
|
-
schema:
|
|
14
|
+
schema: S;
|
|
9
15
|
/** Unique name for this component type */
|
|
10
16
|
name: string;
|
|
11
17
|
/** Size of the component in bytes */
|
|
@@ -18,33 +24,83 @@ export interface ComponentMeta<T extends object> {
|
|
|
18
24
|
arrayCodec: ArrayField<T>;
|
|
19
25
|
}
|
|
20
26
|
/**
|
|
21
|
-
* Component type returned by defineComponent
|
|
27
|
+
* Component type returned by defineComponent.
|
|
28
|
+
*
|
|
29
|
+
* `T` is the value-shape inferred from the schema. `S` is the precise
|
|
30
|
+
* schema literal type, used by `world.fields()` to return per-field
|
|
31
|
+
* typed-array maps with exact element types (Float32Array vs Uint8Array
|
|
32
|
+
* vs ...). When omitted, `S` defaults to the loose `Schema<T>` and
|
|
33
|
+
* `world.fields()` falls back to a broad TypedArray union per field.
|
|
22
34
|
*/
|
|
23
|
-
export type Component<T extends object = any> = ComponentMeta<T> & {
|
|
35
|
+
export type Component<T extends object = any, S extends Schema<T> = Schema<T>> = ComponentMeta<T, S> & {
|
|
24
36
|
/** Type marker for TypeScript inference */
|
|
25
37
|
__type?: T;
|
|
26
38
|
/** Internal: Index assigned by World when registered */
|
|
27
39
|
__worldIndex?: number;
|
|
40
|
+
/**
|
|
41
|
+
* Opaque metadata attached by higher-level packages (e.g. `murow/netcode`
|
|
42
|
+
* stores `SyncSpec` here to mark a component as networked). Core never
|
|
43
|
+
* interprets this; readers narrow it to the shape they own.
|
|
44
|
+
*/
|
|
45
|
+
__sync?: unknown;
|
|
28
46
|
};
|
|
29
47
|
/**
|
|
30
48
|
* Infer the data type from a Component
|
|
31
49
|
*/
|
|
32
|
-
export type InferComponentType<C> = C extends Component<infer T> ? T : never;
|
|
50
|
+
export type InferComponentType<C> = C extends Component<infer T, any> ? T : never;
|
|
51
|
+
/**
|
|
52
|
+
* Descriptor form of `defineComponent`. Pass `{ schema, sync }` to attach
|
|
53
|
+
* opaque sync metadata (consumed by `murow/netcode` to mark the component
|
|
54
|
+
* as networked).
|
|
55
|
+
*/
|
|
56
|
+
export interface ComponentDescriptor<T extends object, S extends Schema<T> = Schema<T>> {
|
|
57
|
+
schema: S;
|
|
58
|
+
sync: unknown;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Helper: derive the value-shape `T` from a narrowly-typed schema literal.
|
|
62
|
+
* Each entry must be a `Field<T[K], any>`, and we extract the `T[K]` per key.
|
|
63
|
+
*/
|
|
64
|
+
type InferSchemaShape<S> = {
|
|
65
|
+
[K in keyof S]: S[K] extends import("../core/binary-codec").Field<infer V, any> ? V : never;
|
|
66
|
+
};
|
|
33
67
|
/**
|
|
34
68
|
* Define a component type with its binary schema.
|
|
35
69
|
*
|
|
36
|
-
*
|
|
70
|
+
* Two call shapes are supported:
|
|
71
|
+
* - Bare schema (the common case): `defineComponent(name, schema)`
|
|
72
|
+
* - Descriptor with sync metadata: `defineComponent(name, { schema, sync })`
|
|
73
|
+
*
|
|
74
|
+
* The descriptor form attaches `__sync` to the returned component. Core
|
|
75
|
+
* doesn't interpret `__sync`; it's read by higher-level packages such as
|
|
76
|
+
* `murow/netcode`. The check for descriptor form is `'schema' in arg &&
|
|
77
|
+
* 'sync' in arg`, which is unambiguous because real component field names
|
|
78
|
+
* never collide with both keys at once.
|
|
79
|
+
*
|
|
80
|
+
* The schema literal type is preserved through inference so that
|
|
81
|
+
* `world.fields(component)` returns precisely-typed typed arrays per
|
|
82
|
+
* field (Float32Array vs Uint8Array vs Uint16Array etc.) without casts.
|
|
83
|
+
*
|
|
84
|
+
* @example Bare schema
|
|
37
85
|
* ```typescript
|
|
38
86
|
* const Transform = defineComponent('Transform', {
|
|
39
87
|
* x: BinaryCodec.f32,
|
|
40
88
|
* y: BinaryCodec.f32,
|
|
41
89
|
* rotation: BinaryCodec.f32,
|
|
42
90
|
* });
|
|
91
|
+
* ```
|
|
43
92
|
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
93
|
+
* @example Descriptor with sync
|
|
94
|
+
* ```typescript
|
|
95
|
+
* const Position = defineComponent('Position', {
|
|
96
|
+
* schema: { x: f32, y: f32 },
|
|
97
|
+
* sync: { rate: 'every-tick', interest: 'aoi' },
|
|
47
98
|
* });
|
|
48
99
|
* ```
|
|
49
100
|
*/
|
|
50
|
-
export declare function defineComponent<
|
|
101
|
+
export declare function defineComponent<S extends Record<string, import("../core/binary-codec").Field<any, any>>>(name: string, schema: S): Component<InferSchemaShape<S> & object, S extends Schema<InferSchemaShape<S> & object> ? S : never>;
|
|
102
|
+
export declare function defineComponent<S extends Record<string, import("../core/binary-codec").Field<any, any>>>(name: string, def: {
|
|
103
|
+
schema: S;
|
|
104
|
+
sync: unknown;
|
|
105
|
+
}): Component<InferSchemaShape<S> & object, S extends Schema<InferSchemaShape<S> & object> ? S : never>;
|
|
106
|
+
export {};
|