murow 0.0.73 → 0.1.3
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/clock/clock.js +1 -0
- package/dist/cjs/core/clock/index.js +1 -0
- 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/hitbox/hitbox-library.js +1 -0
- package/dist/cjs/core/hitbox/hitbox.js +1 -0
- package/dist/cjs/core/hitbox/index.js +1 -0
- package/dist/cjs/core/hitbox/test.js +1 -0
- package/dist/cjs/core/index.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/prediction/prediction.js +1 -1
- package/dist/cjs/core/ray/ray-3d.js +1 -1
- package/dist/cjs/core/raycast/hit-buffer.js +1 -0
- package/dist/cjs/core/raycast/index.js +1 -0
- package/dist/cjs/core/raycast/raycaster.js +1 -0
- package/dist/cjs/core/slot-map/index.js +1 -0
- package/dist/cjs/core/slot-map/slot-map.js +1 -0
- package/dist/cjs/core/state-machine/index.js +1 -0
- package/dist/cjs/core/state-machine/state-machine.js +1 -0
- package/dist/cjs/core/timeline/index.js +1 -0
- package/dist/cjs/core/timeline/timeline.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/game/loop/ticker-schedule.js +1 -0
- package/dist/cjs/net/adapters/bun-websocket.js +1 -1
- package/dist/cjs/renderer/index.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/cjs/renderer/raycast/index.js +1 -0
- package/dist/cjs/renderer/raycast/raycast.js +1 -0
- package/dist/esm/core/binary-codec/binary-codec.js +1 -1
- package/dist/esm/core/clock/clock.js +1 -0
- package/dist/esm/core/clock/index.js +1 -0
- 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/hitbox/hitbox-library.js +1 -0
- package/dist/esm/core/hitbox/hitbox.js +1 -0
- package/dist/esm/core/hitbox/index.js +1 -0
- package/dist/esm/core/hitbox/test.js +1 -0
- package/dist/esm/core/index.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/prediction/prediction.js +1 -1
- package/dist/esm/core/ray/ray-3d.js +1 -1
- package/dist/esm/core/raycast/hit-buffer.js +1 -0
- package/dist/esm/core/raycast/index.js +1 -0
- package/dist/esm/core/raycast/raycaster.js +1 -0
- package/dist/esm/core/slot-map/index.js +1 -0
- package/dist/esm/core/slot-map/slot-map.js +1 -0
- package/dist/esm/core/state-machine/index.js +1 -0
- package/dist/esm/core/state-machine/state-machine.js +1 -0
- package/dist/esm/core/timeline/index.js +1 -0
- package/dist/esm/core/timeline/timeline.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/game/loop/ticker-schedule.js +1 -0
- package/dist/esm/net/adapters/bun-websocket.js +1 -1
- package/dist/esm/renderer/index.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/esm/renderer/raycast/index.js +1 -0
- package/dist/esm/renderer/raycast/raycast.js +1 -0
- package/dist/netcode/cjs/index.js +1556 -0
- package/dist/netcode/esm/index.js +1534 -0
- package/dist/netcode/types/client/game-client.d.ts +139 -0
- package/dist/netcode/types/client/index.d.ts +1 -0
- package/dist/netcode/types/client/strategies/snapshot-interpolation.d.ts +33 -0
- package/dist/netcode/types/client/strategies/snapshot-interpolation.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 +49 -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/clock/clock.d.ts +37 -0
- package/dist/types/core/clock/index.d.ts +1 -0
- 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/hitbox/hitbox-library.d.ts +29 -0
- package/dist/types/core/hitbox/hitbox.d.ts +50 -0
- package/dist/types/core/hitbox/index.d.ts +3 -0
- package/dist/types/core/hitbox/test.d.ts +44 -0
- package/dist/types/core/index.d.ts +6 -0
- 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/core/prediction/prediction.d.ts +35 -58
- package/dist/types/core/ray/ray-3d.d.ts +21 -1
- package/dist/types/core/raycast/hit-buffer.d.ts +43 -0
- package/dist/types/core/raycast/index.d.ts +2 -0
- package/dist/types/core/raycast/raycaster.d.ts +54 -0
- package/dist/types/core/slot-map/index.d.ts +1 -0
- package/dist/types/core/slot-map/slot-map.d.ts +109 -0
- package/dist/types/core/state-machine/index.d.ts +1 -0
- package/dist/types/core/state-machine/state-machine.d.ts +114 -0
- package/dist/types/core/timeline/index.d.ts +1 -0
- package/dist/types/core/timeline/timeline.d.ts +34 -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 +51 -2
- package/dist/types/game/loop/ticker-schedule.d.ts +52 -0
- package/dist/types/net/adapters/bun-websocket.d.ts +19 -3
- package/dist/types/renderer/index.d.ts +1 -0
- package/dist/types/renderer/prefab-bucket/concrete.d.ts +16 -6
- package/dist/types/renderer/prefab-bucket/index.d.ts +11 -7
- package/dist/types/renderer/prefab-bucket/specs.d.ts +10 -0
- package/dist/types/renderer/raycast/index.d.ts +1 -0
- package/dist/types/renderer/raycast/raycast.d.ts +24 -0
- package/dist/types/renderer/types.d.ts +1 -0
- package/dist/webgpu/cjs/index.js +1897 -592
- package/dist/webgpu/esm/index.js +1889 -578
- package/dist/webgpu/types/2d/raycast.d.ts +45 -0
- package/dist/webgpu/types/2d/renderer.d.ts +11 -0
- package/dist/webgpu/types/2d/sprite-accessor.d.ts +3 -1
- package/dist/webgpu/types/3d/hitbox.d.ts +32 -0
- package/dist/webgpu/types/3d/lights.d.ts +113 -0
- package/dist/webgpu/types/3d/lights.test.d.ts +1 -0
- package/dist/webgpu/types/3d/raycast.d.ts +44 -0
- package/dist/webgpu/types/3d/renderer.d.ts +88 -1
- package/dist/webgpu/types/3d/shader.d.ts +88 -5
- package/dist/webgpu/types/core/types.d.ts +55 -0
- package/dist/webgpu/types/geometry/geometry-builder.d.ts +1 -4
- package/dist/webgpu/types/index.d.ts +1 -0
- package/dist/webgpu/types/shaders/utils.d.ts +24 -0
- package/package.json +6 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface TimelineEntry<S> {
|
|
2
|
+
tick: number;
|
|
3
|
+
receivedAt: number;
|
|
4
|
+
sample: S;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* A bounded, tick-ordered ring of timestamped samples. Inserts in tick order
|
|
8
|
+
* (dedup by tick), prunes to capacity, and drops history when a wall-clock gap
|
|
9
|
+
* exceeds the stale window. Knows nothing about what a sample contains.
|
|
10
|
+
*/
|
|
11
|
+
export declare class Timeline<S> {
|
|
12
|
+
private entries;
|
|
13
|
+
private _latestReceivedAt;
|
|
14
|
+
capacity: number;
|
|
15
|
+
staleWindow: number;
|
|
16
|
+
constructor(capacity: number, staleWindowMs: number);
|
|
17
|
+
get length(): number;
|
|
18
|
+
get latestReceivedAt(): number;
|
|
19
|
+
at(index: number): TimelineEntry<S>;
|
|
20
|
+
newest(): TimelineEntry<S> | undefined;
|
|
21
|
+
oldest(): TimelineEntry<S> | undefined;
|
|
22
|
+
setStaleWindow(staleWindowMs: number): void;
|
|
23
|
+
clear(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Insert a sample in tick order. Returns true if a wall-clock gap beyond
|
|
26
|
+
* the stale window dropped the existing history first.
|
|
27
|
+
*/
|
|
28
|
+
record(tick: number, receivedAt: number, sample: S): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Indices `[a, b]` of the consecutive entries straddling `tick`
|
|
31
|
+
* (`entries[a].tick <= tick <= entries[b].tick`), or null if none.
|
|
32
|
+
*/
|
|
33
|
+
straddle(tick: number): [number, number] | null;
|
|
34
|
+
}
|
|
@@ -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 {};
|
|
@@ -96,7 +96,7 @@ export declare class EntityHandle {
|
|
|
96
96
|
* const velocityVx = entity.field(Velocity, 'vx');
|
|
97
97
|
*
|
|
98
98
|
* // Direct array access - same as RAW API!
|
|
99
|
-
* transformX[entity.id] += velocityVx[entity.id] *
|
|
99
|
+
* transformX[entity.id] += velocityVx[entity.id] * deltaTime;
|
|
100
100
|
* ```
|
|
101
101
|
*/
|
|
102
102
|
field<T extends object, K extends keyof T>(component: Component<T>, field: K): Float32Array | Int32Array | Uint32Array | Uint16Array | Uint8Array;
|
|
@@ -149,8 +149,8 @@ export declare class EntityHandle {
|
|
|
149
149
|
* const velocity = entity.get(Velocity); // Uses cached data
|
|
150
150
|
*
|
|
151
151
|
* entity
|
|
152
|
-
* .setField(Transform, 'x', transform.x + velocity.vx *
|
|
153
|
-
* .setField(Transform, 'y', transform.y + velocity.vy *
|
|
152
|
+
* .setField(Transform, 'x', transform.x + velocity.vx * deltaTime)
|
|
153
|
+
* .setField(Transform, 'y', transform.y + velocity.vy * deltaTime)
|
|
154
154
|
* .flush();
|
|
155
155
|
* ```
|
|
156
156
|
*/
|
|
@@ -189,8 +189,8 @@ export declare class EntityHandle {
|
|
|
189
189
|
* ```typescript
|
|
190
190
|
* // Mutate fields directly
|
|
191
191
|
* entity.setFields(Transform, function (t) {
|
|
192
|
-
* t.x += velocity.vx *
|
|
193
|
-
* t.y += velocity.vy *
|
|
192
|
+
* t.x += velocity.vx * deltaTime;
|
|
193
|
+
* t.y += velocity.vy * deltaTime;
|
|
194
194
|
* });
|
|
195
195
|
*
|
|
196
196
|
* // Conditional mutation
|
|
@@ -120,10 +120,23 @@ export declare class ExecutableSystem {
|
|
|
120
120
|
private queryMask;
|
|
121
121
|
private conditionPredicate?;
|
|
122
122
|
private proxyEntity;
|
|
123
|
+
/**
|
|
124
|
+
* Indices of queried components that have `__sync` metadata. Cached at
|
|
125
|
+
* construction so `execute()` can flip dirty bits without re-checking
|
|
126
|
+
* each tick. Empty for systems whose query touches no synced components,
|
|
127
|
+
* which keeps the hot path zero-overhead.
|
|
128
|
+
*/
|
|
129
|
+
private syncedComponentIndices;
|
|
123
130
|
constructor(world: World, components: Component<any>[], userCallback: (entity: any, deltaTime: number, world: World) => void, fieldDescs: FieldDesc[], queryMaskKey: string, queryMask: number[], conditionPredicate?: (entity: any) => boolean);
|
|
124
131
|
/**
|
|
125
132
|
* Execute the system for all matching entities.
|
|
126
133
|
*
|
|
134
|
+
* If the system's query includes any synced components, every entity
|
|
135
|
+
* touched by the system is marked dirty for those components after the
|
|
136
|
+
* callback runs (coarse strategy. the network layer assumes any
|
|
137
|
+
* entity that flowed through a system whose query included its synced
|
|
138
|
+
* component may have changed).
|
|
139
|
+
*
|
|
127
140
|
* @param deltaTime - Time delta to pass to system callback
|
|
128
141
|
*/
|
|
129
142
|
execute(deltaTime: number): void;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ArrayFromField, Schema } from "../core/binary-codec";
|
|
1
2
|
import { Component } from "./component";
|
|
2
3
|
import { ComponentStore } from "./component-store";
|
|
3
4
|
import { EntityHandle } from "./entity-handle";
|
|
@@ -70,6 +71,21 @@ export declare class World extends WorldSystems {
|
|
|
70
71
|
private queryMaskCache;
|
|
71
72
|
private despawnedBuffer;
|
|
72
73
|
private despawnedCount;
|
|
74
|
+
/**
|
|
75
|
+
* Per-component dirty bitmask, indexed by [componentIndex][entity>>>5].
|
|
76
|
+
* `null` for components without `__sync` metadata: no overhead when
|
|
77
|
+
* networking isn't in play. Higher-level packages might read these
|
|
78
|
+
* to build per-peer snapshot deltas.
|
|
79
|
+
*/
|
|
80
|
+
private dirtyBitsByComponent;
|
|
81
|
+
/**
|
|
82
|
+
* Per-component field bundle: a frozen object whose keys are the
|
|
83
|
+
* component's field names and whose values are the same typed-array
|
|
84
|
+
* references returned by `getFieldArray`. Built once at registration,
|
|
85
|
+
* shared forever — `world.fields(C)` returns the same object on every
|
|
86
|
+
* call (zero garbage). Indexed by `component.__worldIndex`.
|
|
87
|
+
*/
|
|
88
|
+
private fieldsByComponent;
|
|
73
89
|
private worldId;
|
|
74
90
|
constructor(config: WorldConfig);
|
|
75
91
|
/**
|
|
@@ -150,6 +166,34 @@ export declare class World extends WorldSystems {
|
|
|
150
166
|
* Invalidate all query caches (called on archetype changes).
|
|
151
167
|
*/
|
|
152
168
|
private invalidateQueryCache;
|
|
169
|
+
/**
|
|
170
|
+
* Mark an entity dirty for a given component index. No-op for
|
|
171
|
+
* components without `__sync` metadata. Called internally by every
|
|
172
|
+
* write path (`add`, `set`, `update`, `system-builder` field setters).
|
|
173
|
+
*/
|
|
174
|
+
markDirty(entity: Entity, componentIndex: number): void;
|
|
175
|
+
/**
|
|
176
|
+
* Test whether an entity is currently marked dirty for a component.
|
|
177
|
+
* Used by snapshot builders.
|
|
178
|
+
*/
|
|
179
|
+
isDirty(entity: Entity, component: Component<any>): boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Clear the dirty bit for an entity/component pair. Called by the
|
|
182
|
+
* snapshot builder after a delta for the entity has been acknowledged
|
|
183
|
+
* by all peers.
|
|
184
|
+
*/
|
|
185
|
+
clearDirty(entity: Entity, component: Component<any>): void;
|
|
186
|
+
/**
|
|
187
|
+
* Iterate dirty entities for a synced component. Calls `cb` for each
|
|
188
|
+
* entity whose dirty bit is set. Returns immediately for unsynced
|
|
189
|
+
* components.
|
|
190
|
+
*/
|
|
191
|
+
forEachDirty(component: Component<any>, cb: (entity: Entity) => void): void;
|
|
192
|
+
/**
|
|
193
|
+
* Clear all dirty bits across all components. Usually the snapshot
|
|
194
|
+
* pipeline clears bits per-entity as it processes them.
|
|
195
|
+
*/
|
|
196
|
+
clearAllDirty(): void;
|
|
153
197
|
/**
|
|
154
198
|
* Add a component to an entity with initial data.
|
|
155
199
|
*/
|
|
@@ -223,8 +267,8 @@ export declare class World extends WorldSystems {
|
|
|
223
267
|
* const t = world.get(entity, Transform);
|
|
224
268
|
* const v = world.get(entity, Velocity);
|
|
225
269
|
* world.update(entity, Transform, {
|
|
226
|
-
* x: t.x + v.vx *
|
|
227
|
-
* y: t.y + v.vy *
|
|
270
|
+
* x: t.x + v.vx * deltaTime,
|
|
271
|
+
* y: t.y + v.vy * deltaTime
|
|
228
272
|
* });
|
|
229
273
|
* }
|
|
230
274
|
* ```
|
|
@@ -289,12 +333,36 @@ export declare class World extends WorldSystems {
|
|
|
289
333
|
* const velocityVy = world.getFieldArray(Velocity, 'vy');
|
|
290
334
|
*
|
|
291
335
|
* for (const entity of world.query(Transform, Velocity)) {
|
|
292
|
-
* transformX[entity] += velocityVx[entity] *
|
|
293
|
-
* transformY[entity] += velocityVy[entity] *
|
|
336
|
+
* transformX[entity] += velocityVx[entity] * deltaTime;
|
|
337
|
+
* transformY[entity] += velocityVy[entity] * deltaTime;
|
|
294
338
|
* }
|
|
295
339
|
* ```
|
|
296
340
|
*/
|
|
297
341
|
getFieldArray<T extends object>(component: Component<T>, fieldName: keyof T): Float32Array | Int32Array | Uint32Array | Uint16Array | Uint8Array;
|
|
342
|
+
/**
|
|
343
|
+
* Get a typed-array bundle for every field of a component.
|
|
344
|
+
*
|
|
345
|
+
* Returns the same frozen object on every call - built once at component
|
|
346
|
+
* registration and shared forever. Each field name maps to its underlying
|
|
347
|
+
* typed array, with the EXACT element type inferred from the schema:
|
|
348
|
+
* `f32 -> Float32Array`, `u8 -> Uint8Array`, `u16 -> Uint16Array`, etc.
|
|
349
|
+
* No casts needed in caller code.
|
|
350
|
+
*
|
|
351
|
+
* Use this when you want RAW-speed per-entity reads/writes without the
|
|
352
|
+
* `world.update({...})` allocation + `for...in` overhead. Bypasses dirty
|
|
353
|
+
* tracking: for networked components, see `ctx.fields()` in `murow/netcode`
|
|
354
|
+
* which auto-marks dirty, or call `world.markDirty(entity, index)` yourself.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* const pos = world.fields(Position); // pos.x, pos.z typed as Float32Array
|
|
359
|
+
* pos.x[entity] += velocity.x * dt;
|
|
360
|
+
* pos.z[entity] += velocity.z * dt;
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
fields<T extends object, S extends Schema<T>>(component: Component<T, S>): Readonly<{
|
|
364
|
+
[K in keyof S]: ArrayFromField<S[K]>;
|
|
365
|
+
}>;
|
|
298
366
|
/**
|
|
299
367
|
* Create an EntityHandle wrapper for fluent API usage.
|
|
300
368
|
*
|
|
@@ -29,6 +29,7 @@ export declare class GameLoop<T extends GameLoopType = DriverType> {
|
|
|
29
29
|
private _tickData;
|
|
30
30
|
private _skipData;
|
|
31
31
|
private _renderData;
|
|
32
|
+
private _scheduler;
|
|
32
33
|
constructor(options: GameLoopOptions<T>);
|
|
33
34
|
step(deltaTime: number): void;
|
|
34
35
|
/**
|
|
@@ -47,12 +48,41 @@ export declare class GameLoop<T extends GameLoopType = DriverType> {
|
|
|
47
48
|
* Stops the game ticker and emits a 'stop' event.
|
|
48
49
|
*/
|
|
49
50
|
stop(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Registers a callback to run on a fixed tick interval.
|
|
53
|
+
*
|
|
54
|
+
* The unit methods resolve to a tick count from the loop's `tickRate`, so
|
|
55
|
+
* every schedule fires in lockstep with the simulation regardless of unit.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* const id = loop.every(2).seconds(spawnWave);
|
|
59
|
+
* loop.clearSchedule(id);
|
|
60
|
+
*/
|
|
61
|
+
every(count: number): ScheduleBuilder;
|
|
62
|
+
/**
|
|
63
|
+
* Cancels a single schedule by the id returned from `every`.
|
|
64
|
+
*/
|
|
65
|
+
clearSchedule(id: number): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Cancels every registered schedule.
|
|
68
|
+
*/
|
|
69
|
+
clearSchedules(): void;
|
|
70
|
+
}
|
|
71
|
+
interface ScheduleBuilder {
|
|
72
|
+
ticks(cb: () => void): number;
|
|
73
|
+
seconds(cb: () => void): number;
|
|
74
|
+
milliseconds(cb: () => void): number;
|
|
50
75
|
}
|
|
51
76
|
interface GameLoopOptions<T extends GameLoopType> {
|
|
52
77
|
tickRate: number;
|
|
53
78
|
type: T;
|
|
54
|
-
|
|
55
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Maximum number of simultaneously live schedules registered via `every`.
|
|
81
|
+
* Defaults to 32.
|
|
82
|
+
*/
|
|
83
|
+
maxSchedules?: number;
|
|
84
|
+
onTick?: (deltaTime: number, tick: number, input: ReturnType<InputManager["snapshot"]>) => void;
|
|
85
|
+
onRender?: (deltaTime: number, alpha: number, input: ReturnType<InputManager["peek"]>) => void;
|
|
56
86
|
}
|
|
57
87
|
type BaseEvents = [
|
|
58
88
|
[
|
|
@@ -64,6 +94,25 @@ type BaseEvents = [
|
|
|
64
94
|
startedAt: number;
|
|
65
95
|
}
|
|
66
96
|
],
|
|
97
|
+
[
|
|
98
|
+
"sync",
|
|
99
|
+
{
|
|
100
|
+
/**
|
|
101
|
+
* Current tick number.
|
|
102
|
+
*/
|
|
103
|
+
tick: number;
|
|
104
|
+
/**
|
|
105
|
+
* Delta time since the last tick.
|
|
106
|
+
*/
|
|
107
|
+
deltaTime: number;
|
|
108
|
+
/**
|
|
109
|
+
* Input snapshot at the start of the tick.
|
|
110
|
+
*
|
|
111
|
+
* **Only available in client loops.**
|
|
112
|
+
*/
|
|
113
|
+
input: ReturnType<InputManager["snapshot"]>;
|
|
114
|
+
}
|
|
115
|
+
],
|
|
67
116
|
[
|
|
68
117
|
"pre-tick",
|
|
69
118
|
{
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixed-capacity, zero-GC scheduler of tick-interval callbacks for the game loop.
|
|
3
|
+
*
|
|
4
|
+
* Schedules are stored in a pre-allocated object pool indexed by a {@link SlotMap}
|
|
5
|
+
* slot, so registering and cancelling reuse objects instead of producing garbage.
|
|
6
|
+
* Ids returned by {@link every} pack the slot with a generation counter, so an id
|
|
7
|
+
* left over from a cancelled schedule can never cancel the schedule that later
|
|
8
|
+
* reuses its slot.
|
|
9
|
+
*/
|
|
10
|
+
export declare class TickerSchedule {
|
|
11
|
+
private readonly _capacity;
|
|
12
|
+
private readonly _slots;
|
|
13
|
+
private readonly _generations;
|
|
14
|
+
private readonly _pool;
|
|
15
|
+
private _dirty;
|
|
16
|
+
private _running;
|
|
17
|
+
constructor(capacity: number);
|
|
18
|
+
/**
|
|
19
|
+
* Number of live schedules.
|
|
20
|
+
*/
|
|
21
|
+
get size(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Maximum number of simultaneously live schedules.
|
|
24
|
+
*/
|
|
25
|
+
get capacity(): number;
|
|
26
|
+
/**
|
|
27
|
+
* Registers a callback to fire every `intervalTicks`, starting `intervalTicks`
|
|
28
|
+
* after `currentTick`. Returns a stable id for {@link clear}, or `-1` if the
|
|
29
|
+
* scheduler is at capacity.
|
|
30
|
+
*/
|
|
31
|
+
every(intervalTicks: number, cb: () => void, currentTick: number): number;
|
|
32
|
+
/**
|
|
33
|
+
* Cancels the schedule for `id`. No-op (returns `false`) if the id is stale,
|
|
34
|
+
* unknown, or already cancelled.
|
|
35
|
+
*/
|
|
36
|
+
clear(id: number): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Cancels every live schedule.
|
|
39
|
+
*/
|
|
40
|
+
clearAll(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Fires every schedule whose interval has elapsed at `currentTick`, then
|
|
43
|
+
* realigns it relative to `currentTick` (a long frame fires once, not a burst).
|
|
44
|
+
*/
|
|
45
|
+
run(currentTick: number): void;
|
|
46
|
+
/**
|
|
47
|
+
* Re-anchors every live schedule's next fire relative to `baseTick`. Called
|
|
48
|
+
* when the loop restarts and the tick count resets.
|
|
49
|
+
*/
|
|
50
|
+
rebase(baseTick: number): void;
|
|
51
|
+
private _compact;
|
|
52
|
+
}
|
|
@@ -63,7 +63,10 @@ export declare class BunWebSocketServerTransport implements ServerTransportAdapt
|
|
|
63
63
|
getPeerIds(): string[];
|
|
64
64
|
close(): void;
|
|
65
65
|
/**
|
|
66
|
-
* Internal: Register a new peer
|
|
66
|
+
* Internal: Register a new peer. Records the peer in the internal map
|
|
67
|
+
* but does NOT fire connection handlers: that's `_handlePeerConnection`'s
|
|
68
|
+
* job, called separately by the `open` callback. Splitting registration
|
|
69
|
+
* from notification keeps the handler count to exactly one per connect.
|
|
67
70
|
*/
|
|
68
71
|
_registerPeer(socket: ServerWebSocket<unknown>): string;
|
|
69
72
|
/**
|
|
@@ -76,7 +79,20 @@ export declare class BunWebSocketServerTransport implements ServerTransportAdapt
|
|
|
76
79
|
_handlePeerDisconnection(peerId: string): void;
|
|
77
80
|
_handlePeerConnection(peerId: string): void;
|
|
78
81
|
/**
|
|
79
|
-
* Static factory method to create a Bun WebSocket server
|
|
82
|
+
* Static factory method to create a Bun WebSocket server.
|
|
83
|
+
*
|
|
84
|
+
* @param port - Port to listen on.
|
|
85
|
+
* @param opts - Optional configuration:
|
|
86
|
+
* - `path`: If set, only requests to this URL pathname are upgraded
|
|
87
|
+
* (e.g., `/ws`). Other paths fall through to `fetch`. Defaults to
|
|
88
|
+
* accepting any path.
|
|
89
|
+
* - `fetch`: Handler for non-upgrade HTTP requests on the same port.
|
|
90
|
+
* Useful for serving a static bundle alongside the WS endpoint so
|
|
91
|
+
* the whole app runs on one port. If omitted, non-upgrade requests
|
|
92
|
+
* get a 400 response (matches the previous WS-only behavior).
|
|
80
93
|
*/
|
|
81
|
-
static create(port: number
|
|
94
|
+
static create(port: number, opts?: {
|
|
95
|
+
path?: string;
|
|
96
|
+
fetch?: (req: Request, server: Server<unknown>) => Response | Promise<Response>;
|
|
97
|
+
}): BunWebSocketServerTransport;
|
|
82
98
|
}
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
* bucket.get('typo'); // ❌ TS error: '"typo"' not in '"minion" | "floor"'
|
|
17
17
|
* ```
|
|
18
18
|
*/
|
|
19
|
-
import { BasePrefabBucket, type StringOr } from './index';
|
|
19
|
+
import { BasePrefabBucket, type SpecWithHitbox, type StringOr } from './index';
|
|
20
|
+
import type { HitboxLibrary } from '../../core/hitbox/hitbox-library';
|
|
20
21
|
import type { CompositePrefab, PartOffset, Prefab2D, Prefab2DSpec, Prefab3D, Prefab3DSpec, PrefabFor } from './specs';
|
|
21
22
|
type SpecForMode<M> = M extends '3d' ? Prefab3DSpec : Prefab2DSpec;
|
|
22
23
|
type PrefabUnionForMode<M> = M extends '3d' ? Prefab3D : Prefab2D;
|
|
@@ -27,20 +28,29 @@ type PrefabUnionForMode<M> = M extends '3d' ? Prefab3D : Prefab2D;
|
|
|
27
28
|
* to register new specs and their prefab types. Call `load` to parse all registered
|
|
28
29
|
* specs and populate the bucket's internal prefab registry.
|
|
29
30
|
*/
|
|
30
|
-
export declare class PrefabBucket<M extends '2d' | '3d' = '3d', Specs extends Record<string, SpecForMode<M>> = {}> extends BasePrefabBucket<M, SpecForMode<M>, PrefabUnionForMode<M>, Specs> {
|
|
31
|
+
export declare class PrefabBucket<M extends '2d' | '3d' = '3d', Specs extends Record<string, SpecForMode<M>> = {}, HB extends string = never> extends BasePrefabBucket<M, SpecForMode<M>, PrefabUnionForMode<M>, Specs, HB> {
|
|
32
|
+
private _hitboxLibrary;
|
|
31
33
|
constructor(mode: M);
|
|
34
|
+
/**
|
|
35
|
+
* Register the hitbox library backing this bucket. Specs may then set
|
|
36
|
+
* `hitbox` to any of the library's names, autocompleted and type-checked.
|
|
37
|
+
*/
|
|
38
|
+
hitboxes<N extends string>(library: HitboxLibrary<M, N>): PrefabBucket<M, Specs, N>;
|
|
39
|
+
/** The registered hitbox library, or `null` if none was set. */
|
|
40
|
+
get hitboxLibrary(): HitboxLibrary<M> | null;
|
|
32
41
|
/**
|
|
33
42
|
* Add a spec. Chains return the subclass type so the bucket variable's
|
|
34
43
|
* static type accumulates id→spec mappings, enabling `get` to narrow.
|
|
44
|
+
* When a hitbox library is registered, `hitbox` must be one of its names.
|
|
35
45
|
*/
|
|
36
|
-
add<const S extends SpecForMode<M>>(spec: S): PrefabBucket<M, Specs & {
|
|
46
|
+
add<const S extends SpecWithHitbox<SpecForMode<M>, HB>>(spec: S): PrefabBucket<M, Specs & {
|
|
37
47
|
[K in S['id']]: S;
|
|
38
|
-
}>;
|
|
39
|
-
addAll<const Ss extends readonly SpecForMode<M>[]>(specs: Ss): PrefabBucket<M, Specs & {
|
|
48
|
+
}, HB>;
|
|
49
|
+
addAll<const Ss extends readonly SpecWithHitbox<SpecForMode<M>, HB>[]>(specs: Ss): PrefabBucket<M, Specs & {
|
|
40
50
|
[K in Ss[number]['id']]: Extract<Ss[number], {
|
|
41
51
|
id: K;
|
|
42
52
|
}>;
|
|
43
|
-
}>;
|
|
53
|
+
}, HB>;
|
|
44
54
|
/**
|
|
45
55
|
* Return the parsed prefab variant for this id. Narrow type — `get('minion')`
|
|
46
56
|
* returns `GltfPrefab` (with `.animations`, `.jointCount`), not the union.
|
|
@@ -22,6 +22,10 @@ export type PrefabMode = '2d' | '3d';
|
|
|
22
22
|
* suggestions for the known set.
|
|
23
23
|
*/
|
|
24
24
|
export type StringOr<T extends string> = T | (string & {});
|
|
25
|
+
/** A spec union with its `hitbox` field constrained to the hitbox names `HB`. */
|
|
26
|
+
export type SpecWithHitbox<S, HB extends string> = S extends unknown ? Omit<S, 'hitbox'> & {
|
|
27
|
+
readonly hitbox?: StringOr<HB>;
|
|
28
|
+
} : never;
|
|
25
29
|
export interface PrefabSpecBase {
|
|
26
30
|
readonly type: string;
|
|
27
31
|
readonly id: string;
|
|
@@ -56,7 +60,7 @@ export interface PrefabParserContext {
|
|
|
56
60
|
*/
|
|
57
61
|
export type PrefabParser<Spec extends PrefabSpecBase = PrefabSpecBase, Prefab extends PrefabBase = PrefabBase> = (spec: Spec, ctx: PrefabParserContext) => Promise<Prefab> | Prefab;
|
|
58
62
|
export type PrefabParserMap<Spec extends PrefabSpecBase, Prefab extends PrefabBase> = Record<string, PrefabParser<Spec, Prefab>>;
|
|
59
|
-
export declare class BasePrefabBucket<M extends PrefabMode = PrefabMode, Spec extends PrefabSpecBase = PrefabSpecBase, Prefab extends PrefabBase = PrefabBase, Specs extends Record<string, Spec> = {}> {
|
|
63
|
+
export declare class BasePrefabBucket<M extends PrefabMode = PrefabMode, Spec extends PrefabSpecBase = PrefabSpecBase, Prefab extends PrefabBase = PrefabBase, Specs extends Record<string, Spec> = {}, HB extends string = string> {
|
|
60
64
|
readonly mode: M;
|
|
61
65
|
/** Shared notification channel - see `PrefabBucketEvents`. */
|
|
62
66
|
readonly events: EventSystem<PrefabBucketEvents>;
|
|
@@ -68,26 +72,26 @@ export declare class BasePrefabBucket<M extends PrefabMode = PrefabMode, Spec ex
|
|
|
68
72
|
protected groups: Map<string, string[]>;
|
|
69
73
|
constructor(mode: M, parsers?: PrefabParserMap<Spec, Prefab>);
|
|
70
74
|
/** Add a single spec. Throws if id is a duplicate, contains '.', or if the bucket is already loaded. */
|
|
71
|
-
add<const S extends Spec
|
|
75
|
+
add<const S extends SpecWithHitbox<Spec, HB>>(spec: S): BasePrefabBucket<M, Spec, Prefab, Specs & {
|
|
72
76
|
[K in S['id']]: S;
|
|
73
|
-
}>;
|
|
77
|
+
}, HB>;
|
|
74
78
|
/**
|
|
75
79
|
* Internal add that skips the '.' validation. Used by `addGroup` on
|
|
76
80
|
* subclasses to register parts under group-path ids (e.g. `'campfire.logs'`)
|
|
77
81
|
* after the group itself has validated user input.
|
|
78
82
|
*/
|
|
79
|
-
protected addUnchecked<const S extends Spec
|
|
83
|
+
protected addUnchecked<const S extends SpecWithHitbox<Spec, HB>>(spec: S): BasePrefabBucket<M, Spec, Prefab, Specs & {
|
|
80
84
|
[K in S['id']]: S;
|
|
81
|
-
}>;
|
|
85
|
+
}, HB>;
|
|
82
86
|
/**
|
|
83
87
|
* Add multiple specs. Validates the whole batch (ids unique, not loaded) before
|
|
84
88
|
* committing, so the bucket never lands in a half-applied state.
|
|
85
89
|
*/
|
|
86
|
-
addAll<const Ss extends readonly Spec[]>(specs: Ss): BasePrefabBucket<M, Spec, Prefab, Specs & {
|
|
90
|
+
addAll<const Ss extends readonly SpecWithHitbox<Spec, HB>[]>(specs: Ss): BasePrefabBucket<M, Spec, Prefab, Specs & {
|
|
87
91
|
[K in Ss[number]['id']]: Extract<Ss[number], {
|
|
88
92
|
id: K;
|
|
89
93
|
}>;
|
|
90
|
-
}>;
|
|
94
|
+
}, HB>;
|
|
91
95
|
/** Load all pending specs in parallel. Idempotent if already loaded. */
|
|
92
96
|
load(): Promise<void>;
|
|
93
97
|
/**
|
|
@@ -42,6 +42,7 @@ export interface GltfSpec {
|
|
|
42
42
|
readonly freezeAnimations?: boolean;
|
|
43
43
|
/** Optional user-defined sidecar data (scale, speed, gameplay hints, etc). */
|
|
44
44
|
readonly metadata?: Record<string, unknown>;
|
|
45
|
+
readonly hitbox?: string;
|
|
45
46
|
}
|
|
46
47
|
export interface GridSpec {
|
|
47
48
|
readonly type: 'grid';
|
|
@@ -52,6 +53,7 @@ export interface GridSpec {
|
|
|
52
53
|
readonly lineWidth: number;
|
|
53
54
|
/** Optional user-defined sidecar data (scale, speed, gameplay hints, etc). */
|
|
54
55
|
readonly metadata?: Record<string, unknown>;
|
|
56
|
+
readonly hitbox?: string;
|
|
55
57
|
}
|
|
56
58
|
/** Unit cube prefab centered at origin. Use the instance's `scale` to size it. */
|
|
57
59
|
export interface CubeSpec {
|
|
@@ -60,6 +62,7 @@ export interface CubeSpec {
|
|
|
60
62
|
/** Edge length. Defaults to 1. */
|
|
61
63
|
readonly size?: number;
|
|
62
64
|
readonly metadata?: Record<string, unknown>;
|
|
65
|
+
readonly hitbox?: string;
|
|
63
66
|
}
|
|
64
67
|
/** Local transform offset applied to a part inside a composite/group at spawn time. */
|
|
65
68
|
export interface PartOffset {
|
|
@@ -80,6 +83,7 @@ export interface CompositeSpec {
|
|
|
80
83
|
readonly offset?: PartOffset;
|
|
81
84
|
}[];
|
|
82
85
|
readonly metadata?: Record<string, unknown>;
|
|
86
|
+
readonly hitbox?: string;
|
|
83
87
|
}
|
|
84
88
|
export type Prefab3DSpec = GltfSpec | GridSpec | CubeSpec | CompositeSpec;
|
|
85
89
|
/**
|
|
@@ -126,6 +130,7 @@ type GltfPrefabBase<S extends GltfSpec> = {
|
|
|
126
130
|
readonly totalVertexCount: number;
|
|
127
131
|
/** Passed through from the spec. */
|
|
128
132
|
readonly metadata: MetadataOf<S>;
|
|
133
|
+
readonly hitbox?: string;
|
|
129
134
|
};
|
|
130
135
|
/**
|
|
131
136
|
* Animation record/list fields, narrowed by what the spec declared:
|
|
@@ -161,12 +166,14 @@ export interface GridPrefab<S extends GridSpec = GridSpec> {
|
|
|
161
166
|
readonly step: number;
|
|
162
167
|
readonly lineWidth: number;
|
|
163
168
|
readonly metadata: MetadataOf<S>;
|
|
169
|
+
readonly hitbox?: string;
|
|
164
170
|
}
|
|
165
171
|
export interface CubePrefab<S extends CubeSpec = CubeSpec> {
|
|
166
172
|
readonly type: 'cube';
|
|
167
173
|
readonly id: S['id'];
|
|
168
174
|
readonly size: number;
|
|
169
175
|
readonly metadata: MetadataOf<S>;
|
|
176
|
+
readonly hitbox?: string;
|
|
170
177
|
}
|
|
171
178
|
export interface CompositePrefab<S extends CompositeSpec = CompositeSpec> {
|
|
172
179
|
readonly type: 'composite';
|
|
@@ -176,6 +183,7 @@ export interface CompositePrefab<S extends CompositeSpec = CompositeSpec> {
|
|
|
176
183
|
readonly offset?: PartOffset;
|
|
177
184
|
}[];
|
|
178
185
|
readonly metadata: MetadataOf<S>;
|
|
186
|
+
readonly hitbox?: string;
|
|
179
187
|
}
|
|
180
188
|
export type Prefab3D = GltfPrefab | GridPrefab | CubePrefab | CompositePrefab;
|
|
181
189
|
export interface SpritesheetSpec {
|
|
@@ -188,6 +196,7 @@ export interface SpritesheetSpec {
|
|
|
188
196
|
/** URL to a texture-packer JSON file. Mutually exclusive with frameWidth/frameHeight. */
|
|
189
197
|
readonly data?: string;
|
|
190
198
|
readonly metadata?: Record<string, unknown>;
|
|
199
|
+
readonly hitbox?: string;
|
|
191
200
|
}
|
|
192
201
|
export type Prefab2DSpec = SpritesheetSpec;
|
|
193
202
|
export interface SpritesheetPrefab<S extends SpritesheetSpec = SpritesheetSpec> {
|
|
@@ -198,6 +207,7 @@ export interface SpritesheetPrefab<S extends SpritesheetSpec = SpritesheetSpec>
|
|
|
198
207
|
readonly width: number;
|
|
199
208
|
readonly height: number;
|
|
200
209
|
readonly metadata: MetadataOf<S>;
|
|
210
|
+
readonly hitbox?: string;
|
|
201
211
|
}
|
|
202
212
|
export type Prefab2D = SpritesheetPrefab;
|
|
203
213
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './raycast';
|