@genex-ai/multiplayer 0.17.6 → 0.17.9
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/PROTOCOL.md +102 -31
- package/README.md +35 -14
- package/WORLD-GLTF.md +109 -0
- package/WORLD-SCENE.md +135 -0
- package/dist/authority/fast-udp.d.ts +4 -2
- package/dist/authority/fast-udp.js +8 -46
- package/dist/authority/fast-webtransport.d.ts +26 -4
- package/dist/authority/fast-webtransport.js +12 -115
- package/dist/authority/index.d.ts +379 -41
- package/dist/authority/index.js +247 -47
- package/dist/authority/module.d.ts +2 -1
- package/dist/authority/module.js +1 -1
- package/dist/bridge-authority.d.ts +3 -2
- package/dist/bridge-authority.global.js +10 -9
- package/dist/bridge-authority.js +11 -6
- package/dist/bridge.global.js +5 -5
- package/dist/bridge.js +3 -3
- package/dist/chunk-2NGXXQDS.js +1916 -0
- package/dist/{chunk-7QVOIHJF.js → chunk-DJ2XYETS.js} +2 -2
- package/dist/{chunk-Y6XHXDIK.js → chunk-MQYARUGU.js} +864 -539
- package/dist/{chunk-K3SF5VDS.js → chunk-OD6NRSX2.js} +3 -1
- package/dist/{chunk-UX3F6YTV.js → chunk-TEHGMFAG.js} +1 -1
- package/dist/chunk-TSYEWPVO.js +44 -0
- package/dist/chunk-TVTVIMIH.js +675 -0
- package/dist/{chunk-ZSWF4VCN.js → chunk-WEMRRIHH.js} +80 -2
- package/dist/chunk-YWQ3ALYY.js +69 -0
- package/dist/{chunk-5JGRFT2N.js → chunk-ZDGSUR6E.js} +879 -1898
- package/dist/{fast-client-CZ41v-oB.d.ts → fast-client--A88q0kk.d.ts} +85 -4
- package/dist/index.js +3 -3
- package/dist/level-build-CbRqrYJq.d.ts +140 -0
- package/dist/{module-DqtFb5wA.d.ts → module-CSpXrzFc.d.ts} +151 -400
- package/dist/{physics-predict-49udN3a1.d.ts → physics-predict-C7ZB1gDG.d.ts} +18 -3
- package/dist/protocol.d.ts +90 -2
- package/dist/protocol.js +17 -1
- package/dist/shot-world-D22tqOUT.d.ts +485 -0
- package/dist/world-fit/index.d.ts +549 -0
- package/dist/world-fit/index.js +4763 -0
- package/dist/world-fit/three.d.ts +77 -0
- package/dist/world-fit/three.js +140 -0
- package/package.json +15 -3
|
@@ -0,0 +1,485 @@
|
|
|
1
|
+
/** Preset names. Append-only: a name, once published, keeps its step function forever. */
|
|
2
|
+
declare const Preset: {
|
|
3
|
+
/** Planar movement on x/y with an aim angle: the server-authority spike's arena. */
|
|
4
|
+
readonly TOPDOWN: "topdown";
|
|
5
|
+
/** Source-engine character movement through a static box-and-ramp world, z up (§17.7). */
|
|
6
|
+
readonly FIRSTPERSON: "firstperson";
|
|
7
|
+
/** An arcade car (Rocket League's ground and air handling, kept level) through the same world (§17.7). */
|
|
8
|
+
readonly VEHICLE: "vehicle";
|
|
9
|
+
};
|
|
10
|
+
type PresetName = (typeof Preset)[keyof typeof Preset];
|
|
11
|
+
/** The longest step a preset simulates; a longer dt (a stalled tab, a hostile value) is cut to it. */
|
|
12
|
+
declare const PRESET_MAX_DT_S = 0.25;
|
|
13
|
+
/** `topdown` parameters. */
|
|
14
|
+
interface TopdownParams {
|
|
15
|
+
/** Movement speed, world units per second. */
|
|
16
|
+
speed: number;
|
|
17
|
+
/** Half the arena's side: x and y stay within [-arena, arena]. */
|
|
18
|
+
arena: number;
|
|
19
|
+
}
|
|
20
|
+
declare const TOPDOWN_DEFAULTS: Readonly<TopdownParams>;
|
|
21
|
+
/** One parameter's accepted range: a finite number in [min, max], above 0 when `positive`, and an
|
|
22
|
+
* integer when `integer` (absent = any number). */
|
|
23
|
+
interface PresetParamRange {
|
|
24
|
+
min: number;
|
|
25
|
+
max: number;
|
|
26
|
+
positive: boolean;
|
|
27
|
+
integer?: true;
|
|
28
|
+
}
|
|
29
|
+
/** The fields a `topdown` step reads and writes. */
|
|
30
|
+
interface TopdownBody {
|
|
31
|
+
x: number;
|
|
32
|
+
y: number;
|
|
33
|
+
/** Aim, radians. */
|
|
34
|
+
yaw: number;
|
|
35
|
+
}
|
|
36
|
+
/** The input fields a `topdown` step reads. */
|
|
37
|
+
interface TopdownInput {
|
|
38
|
+
moveX?: unknown;
|
|
39
|
+
moveY?: unknown;
|
|
40
|
+
yaw?: unknown;
|
|
41
|
+
}
|
|
42
|
+
/** Whether `name` is a known preset. */
|
|
43
|
+
declare function isPresetName(name: unknown): name is PresetName;
|
|
44
|
+
/** Whether `params` is acceptable for preset `name`: absent, or an object whose every key is one of
|
|
45
|
+
* the preset's parameters with a finite number in its range. */
|
|
46
|
+
declare function presetParamsValid(name: PresetName, params: unknown): boolean;
|
|
47
|
+
/** Preset `name`'s parameters from a module's `preset.params`: its defaults for anything unset or
|
|
48
|
+
* invalid, key by key in the order of its range table. */
|
|
49
|
+
declare function resolvePresetParams(name: PresetName, params: unknown): Record<string, number>;
|
|
50
|
+
/** `topdown` parameters from a module's `preset.params`: defaults for anything unset or invalid. */
|
|
51
|
+
declare function resolveTopdownParams(params: unknown): TopdownParams;
|
|
52
|
+
/**
|
|
53
|
+
* One fixed `topdown` step. Pure: returns the next body.
|
|
54
|
+
* - moveX, moveY: non-finite → 0, clamped to [-1, 1], float32; a vector longer than 1 is scaled to 1;
|
|
55
|
+
* - dt: non-finite or ≤ 0 → 0, capped at {@link PRESET_MAX_DT_S};
|
|
56
|
+
* - x' = fround(clamp(x + moveX * scale * speed * dt, -arena, arena)), y' likewise;
|
|
57
|
+
* - yaw' = the input yaw wrapped to [-π, π) as float32, or the previous yaw when it is not usable.
|
|
58
|
+
*/
|
|
59
|
+
declare function stepTopdown(body: TopdownBody, input: TopdownInput, dt: number, params: TopdownParams): TopdownBody;
|
|
60
|
+
/** `firstperson` parameters (§17.7's table, in its order). Each is used as float32. */
|
|
61
|
+
interface FirstpersonParams {
|
|
62
|
+
/** Run speed, units/s, before the body's `cap`. */
|
|
63
|
+
maxSpeed: number;
|
|
64
|
+
/** Speed multiplier while walk is held. */
|
|
65
|
+
walkSpeed: number;
|
|
66
|
+
/** Speed multiplier while ducking (wins over walk). */
|
|
67
|
+
crouchSpeed: number;
|
|
68
|
+
accelerate: number;
|
|
69
|
+
airAccelerate: number;
|
|
70
|
+
/** Air wish speed is clamped to this before the projection (what makes air-strafing work). */
|
|
71
|
+
airMaxWishSpeed: number;
|
|
72
|
+
friction: number;
|
|
73
|
+
/** Below this speed friction acts as if at this speed. */
|
|
74
|
+
stopSpeed: number;
|
|
75
|
+
/** Units/s² along −z. */
|
|
76
|
+
gravity: number;
|
|
77
|
+
/** The `vz` a jump sets. */
|
|
78
|
+
jumpImpulse: number;
|
|
79
|
+
/** Each velocity axis is clamped to ±this. */
|
|
80
|
+
maxVelocity: number;
|
|
81
|
+
/** Half the side of the hull's square footprint. */
|
|
82
|
+
radius: number;
|
|
83
|
+
standHeight: number;
|
|
84
|
+
crouchHeight: number;
|
|
85
|
+
/** Seconds to duck fully, and to stand back up. */
|
|
86
|
+
duckTime: number;
|
|
87
|
+
/** 1: a duck can deepen in the air, lifting the feet (a crouch-jump). 0: only on the ground. */
|
|
88
|
+
airDuck: number;
|
|
89
|
+
/** Highest ledge walked up without a jump. */
|
|
90
|
+
stepHeight: number;
|
|
91
|
+
/** Least z of a ramp top's unit normal that can be stood on. */
|
|
92
|
+
standable: number;
|
|
93
|
+
/** How far below the feet ground is found. */
|
|
94
|
+
groundTrace: number;
|
|
95
|
+
/** How far above the feet ground is found (a hull sunk that far is lifted out). */
|
|
96
|
+
groundSnap: number;
|
|
97
|
+
/** Clearance kept from a surface (Source's DIST_EPSILON). */
|
|
98
|
+
skin: number;
|
|
99
|
+
/** Largest |pitch|, radians. */
|
|
100
|
+
pitchLimit: number;
|
|
101
|
+
/** Button masks: any shared bit counts as held; 0 disables. */
|
|
102
|
+
jumpBit: number;
|
|
103
|
+
duckBit: number;
|
|
104
|
+
walkBit: number;
|
|
105
|
+
/** Sub-steps per step, an integer in [1, 8]. */
|
|
106
|
+
substeps: number;
|
|
107
|
+
/** 1: a jump works at `cap` 0. 0: a press at `cap` 0 is no jump (a freeze time). */
|
|
108
|
+
capZeroJump: number;
|
|
109
|
+
/** Button mask of a run the room owns: while not 0 and not held, speed is `jogSpeed`. 0: every move runs. */
|
|
110
|
+
runBit: number;
|
|
111
|
+
/** Speed multiplier without `runBit` (duck and walk win). */
|
|
112
|
+
jogSpeed: number;
|
|
113
|
+
/** The collision world's hash ({@link firstpersonWorld}), written by the sandbox. */
|
|
114
|
+
world: number;
|
|
115
|
+
}
|
|
116
|
+
/** 32-bit FNV-1a of the empty world: two zero counts (§17.7). */
|
|
117
|
+
declare const EMPTY_WORLD_HASH = 2615243109;
|
|
118
|
+
declare const FIRSTPERSON_DEFAULTS: Readonly<FirstpersonParams>;
|
|
119
|
+
/** `firstperson` parameters from a module's `preset.params`: defaults for anything unset or invalid. */
|
|
120
|
+
declare function resolveFirstpersonParams(params: unknown): FirstpersonParams;
|
|
121
|
+
/** `mstate` bits a `firstperson` step keeps. */
|
|
122
|
+
declare const MoveState: {
|
|
123
|
+
readonly ON_GROUND: 1;
|
|
124
|
+
readonly DUCKING: 2;
|
|
125
|
+
readonly JUMP_HELD: 4;
|
|
126
|
+
};
|
|
127
|
+
/** The fields a `firstperson` step reads (`cap` too, which it never writes). */
|
|
128
|
+
interface FirstpersonBody {
|
|
129
|
+
x: number;
|
|
130
|
+
y: number;
|
|
131
|
+
z: number;
|
|
132
|
+
vx: number;
|
|
133
|
+
vy: number;
|
|
134
|
+
vz: number;
|
|
135
|
+
/** Aim, radians: stored only. */
|
|
136
|
+
yaw: number;
|
|
137
|
+
pitch: number;
|
|
138
|
+
/** 0 standing, 1 fully ducked. */
|
|
139
|
+
duck: number;
|
|
140
|
+
/** {@link MoveState} bits. */
|
|
141
|
+
mstate: number;
|
|
142
|
+
/** Speed multiplier the module writes (a weapon's or a wound's), [0, 4]. */
|
|
143
|
+
cap?: number;
|
|
144
|
+
}
|
|
145
|
+
/** What a `firstperson` step writes: every body field but `cap`. */
|
|
146
|
+
type FirstpersonStep = Omit<FirstpersonBody, 'cap'>;
|
|
147
|
+
/** The input fields a `firstperson` step reads. `moveX`/`moveY` are WORLD axes. */
|
|
148
|
+
interface FirstpersonInput {
|
|
149
|
+
moveX?: unknown;
|
|
150
|
+
moveY?: unknown;
|
|
151
|
+
yaw?: unknown;
|
|
152
|
+
pitch?: unknown;
|
|
153
|
+
buttons?: unknown;
|
|
154
|
+
}
|
|
155
|
+
/** A box: `[minX, minY, minZ, maxX, maxY, maxZ]`. */
|
|
156
|
+
type WorldBox = readonly [number, number, number, number, number, number];
|
|
157
|
+
/** A ramp: a box whose top rises along x (`axis` 0) or y (`axis` 1), from `lo` at that axis's min
|
|
158
|
+
* end to `hi` at its max end: `[minX, minY, minZ, maxX, maxY, maxZ, axis, lo, hi]`. */
|
|
159
|
+
type WorldRamp = readonly [number, number, number, number, number, number, number, number, number];
|
|
160
|
+
/** A world as a module and a game give it (§17.7): boxes, then ramps. */
|
|
161
|
+
interface FirstpersonWorldSpec {
|
|
162
|
+
boxes?: readonly (readonly number[])[];
|
|
163
|
+
ramps?: readonly (readonly number[])[];
|
|
164
|
+
}
|
|
165
|
+
/** A validated world ({@link firstpersonWorld}): frozen, every value a float32 (−0 read as 0). */
|
|
166
|
+
interface FirstpersonWorld {
|
|
167
|
+
readonly boxes: readonly WorldBox[];
|
|
168
|
+
readonly ramps: readonly WorldRamp[];
|
|
169
|
+
/** 32-bit FNV-1a over its counts and values (§17.7): what `params.world` must equal. */
|
|
170
|
+
readonly hash: number;
|
|
171
|
+
/** Whether the step visits only the solids a bounding-volume tree over their boxes says could
|
|
172
|
+
* matter (the results are bit-identical to visiting every one; only the cost changes). */
|
|
173
|
+
readonly broadphase: boolean;
|
|
174
|
+
}
|
|
175
|
+
declare const WorldLimits: {
|
|
176
|
+
readonly MAX_BOXES: 32768;
|
|
177
|
+
readonly MAX_RAMPS: 4096;
|
|
178
|
+
/** Every world value's magnitude. */
|
|
179
|
+
readonly MAX_ABS: 1000000000;
|
|
180
|
+
};
|
|
181
|
+
/** Why a world was refused: the path of the first bad value. */
|
|
182
|
+
declare class WorldError extends RangeError {
|
|
183
|
+
readonly path: string;
|
|
184
|
+
constructor(path: string, message: string);
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Validates a collision world (§17.7) and returns it frozen, with its hash. Refused (a
|
|
188
|
+
* {@link WorldError}) unless it has at most 32768 boxes and 4096 ramps, each exactly six (box) or
|
|
189
|
+
* nine (ramp) numbers, every one a float32 of magnitude at most 1e9, min < max on every axis, and
|
|
190
|
+
* each ramp `axis` 0 or 1 with `minZ ≤ lo`, `minZ ≤ hi` and `maxZ = max(lo, hi)`. `undefined` is
|
|
191
|
+
* the empty world; a missing `boxes` or `ramps` is none, and other keys are ignored. `broadphase`
|
|
192
|
+
* (default true) builds the bounding-volume tree the step filters with; it never changes a result. A
|
|
193
|
+
* world this function returned is returned as is.
|
|
194
|
+
*/
|
|
195
|
+
declare function firstpersonWorld(raw: unknown, options?: {
|
|
196
|
+
broadphase?: boolean;
|
|
197
|
+
caps?: {
|
|
198
|
+
readonly MAX_BOXES: number;
|
|
199
|
+
readonly MAX_RAMPS: number;
|
|
200
|
+
};
|
|
201
|
+
}): FirstpersonWorld;
|
|
202
|
+
/** The empty world: no solids (a body in it falls until z reaches −1e9). */
|
|
203
|
+
declare const EMPTY_WORLD: FirstpersonWorld;
|
|
204
|
+
/** A solid posed for one tick beside the static world (a lift at its pose, a head slab): an
|
|
205
|
+
* axis-aligned box `[min, max]`; a box of half extents `half` about centre `c` turned about z by the
|
|
206
|
+
* angle whose sine and cosine are given (`obox`); or an upright disc of `radius` about `c`, `half` its
|
|
207
|
+
* half height. Visited after the static solids, in order, never by the broad phase's tree. */
|
|
208
|
+
type PosedSolid = {
|
|
209
|
+
readonly kind: 'box';
|
|
210
|
+
readonly min: readonly [number, number, number];
|
|
211
|
+
readonly max: readonly [number, number, number];
|
|
212
|
+
} | {
|
|
213
|
+
readonly kind: 'obox';
|
|
214
|
+
readonly c: readonly [number, number, number];
|
|
215
|
+
readonly half: readonly [number, number, number];
|
|
216
|
+
readonly sin: number;
|
|
217
|
+
readonly cos: number;
|
|
218
|
+
} | {
|
|
219
|
+
readonly kind: 'disc';
|
|
220
|
+
readonly c: readonly [number, number, number];
|
|
221
|
+
readonly radius: number;
|
|
222
|
+
readonly half: number;
|
|
223
|
+
};
|
|
224
|
+
/** Posed solids a tick may hold at most (32 lifts and a head slab for each of 64 seats). */
|
|
225
|
+
declare const POSED_MAX = 96;
|
|
226
|
+
/** The step's view of a tick's posed solids ({@link posedWorld}): one flat table per field. `min*`
|
|
227
|
+
* and `max*` are each solid's bounds on x, y and z (an obox's or a disc's box around it). */
|
|
228
|
+
interface PosedWorld {
|
|
229
|
+
readonly count: number;
|
|
230
|
+
readonly kind: Uint8Array;
|
|
231
|
+
readonly minX: Float64Array;
|
|
232
|
+
readonly minY: Float64Array;
|
|
233
|
+
readonly minZ: Float64Array;
|
|
234
|
+
readonly maxX: Float64Array;
|
|
235
|
+
readonly maxY: Float64Array;
|
|
236
|
+
readonly maxZ: Float64Array;
|
|
237
|
+
readonly cx: Float64Array;
|
|
238
|
+
readonly cy: Float64Array;
|
|
239
|
+
readonly hx: Float64Array;
|
|
240
|
+
readonly hy: Float64Array;
|
|
241
|
+
readonly sin: Float64Array;
|
|
242
|
+
readonly cos: Float64Array;
|
|
243
|
+
readonly radius: Float64Array;
|
|
244
|
+
}
|
|
245
|
+
/** A tick's posed solids compiled for the step, in the order given. */
|
|
246
|
+
declare function posedWorld(solids: readonly PosedSolid[]): PosedWorld;
|
|
247
|
+
/** No posed solids. */
|
|
248
|
+
declare const NO_POSED: PosedWorld;
|
|
249
|
+
/** What a tree key multiplies its Morton code by (see {@link leafOrder}): 23 index bits above the 30-bit
|
|
250
|
+
* code fill a float64's exact integers, far past any world's solids. A world that fitted the old 13 bits
|
|
251
|
+
* keeps its tree: the order is the code's, ties by index, at any width. */
|
|
252
|
+
declare const TREE_KEY_RADIX: number;
|
|
253
|
+
/** The order a broadphase's tree keeps `solids` in, leaves first (each solid a box, or a ramp whose first
|
|
254
|
+
* six values are its box): what every port's tree is held to, at any size (firstperson-large.json). */
|
|
255
|
+
declare function worldTreeOrder(solids: readonly (readonly number[])[]): Int32Array;
|
|
256
|
+
/** What a step does through its world, counted (see {@link withWorldCostMeter}). */
|
|
257
|
+
interface WorldCostMeter {
|
|
258
|
+
/** Tree entries a query walked. */
|
|
259
|
+
nodes: number;
|
|
260
|
+
/** Exact tests of a solid: a query's candidates, each of which its helper tests, and each solid
|
|
261
|
+
* `covered` looked at. */
|
|
262
|
+
tests: number;
|
|
263
|
+
/** A sweep's slab or wedge tests of its candidates. */
|
|
264
|
+
sweeps: number;
|
|
265
|
+
/** Of those, the wedges: seven planes and a slope against a slab's six, about three times the time. */
|
|
266
|
+
wedges: number;
|
|
267
|
+
}
|
|
268
|
+
/** Runs `run` with every step's world work counted into `meter`. Steps run one at a time, and a step's
|
|
269
|
+
* results do not depend on the meter. */
|
|
270
|
+
declare function withWorldCostMeter<T>(meter: WorldCostMeter, run: () => T): T;
|
|
271
|
+
/** A seat's body as the lift slots read it. */
|
|
272
|
+
interface HullBody {
|
|
273
|
+
readonly x: number;
|
|
274
|
+
readonly y: number;
|
|
275
|
+
readonly z: number;
|
|
276
|
+
readonly vz?: number;
|
|
277
|
+
readonly duck?: number;
|
|
278
|
+
}
|
|
279
|
+
/** What the lift slots ask of a preset's hull, against the world and a tick's posed solids. */
|
|
280
|
+
interface HullOps {
|
|
281
|
+
/** The posed solid (its index) the hull stands on: the highest standable top under it in
|
|
282
|
+
* [z − groundTrace, z + groundSnap] (`checkGround`'s test) when that top is a posed solid's (the
|
|
283
|
+
* first such in order), else −1; −1 too while rising (`vz > 0.1 · unit`). */
|
|
284
|
+
support(body: HullBody, solids: readonly PosedSolid[]): number;
|
|
285
|
+
/** Whether the hull is more than skin inside posed solid `k` (§17.7 *Starting inside*'s `inside`). */
|
|
286
|
+
inside(body: HullBody, solids: readonly PosedSolid[], k: number): boolean;
|
|
287
|
+
/** §17.7 *Starting inside* as `slideMove` applies it, with no move: up to four times, out through the
|
|
288
|
+
* face a zero-length sweep reports, by its depth then skin. `inside`: still inside some solid. */
|
|
289
|
+
pushOut(body: HullBody, solids: readonly PosedSolid[]): {
|
|
290
|
+
x: number;
|
|
291
|
+
y: number;
|
|
292
|
+
z: number;
|
|
293
|
+
inside: boolean;
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
/** The preset's hull among `world` and a tick's posed solids. */
|
|
297
|
+
declare function hullOps(preset: 'firstperson' | 'vehicle', params: Readonly<Record<string, number>>, world?: FirstpersonWorld): HullOps;
|
|
298
|
+
/**
|
|
299
|
+
* One fixed `firstperson` step (§17.7) through `world` (default: the empty world). Pure: returns the
|
|
300
|
+
* next `x y z vx vy vz yaw pitch duck mstate`; the body's `cap` is read, never written. `world` must
|
|
301
|
+
* be the world whose hash is `params.world` for the result to be the server's; the step itself does
|
|
302
|
+
* not compare them.
|
|
303
|
+
*/
|
|
304
|
+
declare function stepFirstperson(body: Partial<FirstpersonBody>, input: FirstpersonInput, dt: number, params: FirstpersonParams, world?: FirstpersonWorld, posed?: PosedWorld): FirstpersonStep;
|
|
305
|
+
/** `vehicle` parameters (§17.7's table, in its order). Each is used as float32 but the masks,
|
|
306
|
+
* `substeps` and `world`. */
|
|
307
|
+
interface VehicleParams {
|
|
308
|
+
/** Top speed on the throttle, units/s, before the body's `cap`. */
|
|
309
|
+
maxSpeed: number;
|
|
310
|
+
/** Throttle acceleration, units/s². */
|
|
311
|
+
accel: number;
|
|
312
|
+
/** Deceleration while the throttle opposes the motion. */
|
|
313
|
+
brake: number;
|
|
314
|
+
/** Deceleration with no throttle, and down to the throttle's speed when above it without boost. */
|
|
315
|
+
coast: number;
|
|
316
|
+
/** Boost's acceleration along the heading, on top of the throttle's. */
|
|
317
|
+
boostAccel: number;
|
|
318
|
+
/** Top speed under boost, before `cap`. */
|
|
319
|
+
boostMaxSpeed: number;
|
|
320
|
+
/** Fuel burned per second of boost (a full tank is 1). */
|
|
321
|
+
boostBurn: number;
|
|
322
|
+
/** Deceleration of the sideways speed on the ground, units/s². */
|
|
323
|
+
grip: number;
|
|
324
|
+
/** The same, while drift is held. */
|
|
325
|
+
driftGrip: number;
|
|
326
|
+
/** Yaw rate at full steer on the ground, rad/s, at or above `turnSpeed`. */
|
|
327
|
+
turnRate: number;
|
|
328
|
+
/** The forward speed at which the full turn rate is reached. */
|
|
329
|
+
turnSpeed: number;
|
|
330
|
+
/** How fast the yaw rate follows the steering on the ground, rad/s². */
|
|
331
|
+
spinAccel: number;
|
|
332
|
+
/** Yaw rate at full steer in the air, rad/s. */
|
|
333
|
+
airTurnRate: number;
|
|
334
|
+
/** How fast the yaw rate follows the steering in the air, rad/s². */
|
|
335
|
+
airSpinAccel: number;
|
|
336
|
+
/** Units/s² along −z. */
|
|
337
|
+
gravity: number;
|
|
338
|
+
/** The `vz` a jump sets. */
|
|
339
|
+
jumpImpulse: number;
|
|
340
|
+
/** Each velocity axis is clamped to ±this. */
|
|
341
|
+
maxVelocity: number;
|
|
342
|
+
/** Half the side of the hull's square footprint. */
|
|
343
|
+
radius: number;
|
|
344
|
+
/** Hull height. */
|
|
345
|
+
height: number;
|
|
346
|
+
/** Highest ledge driven up without a jump, and the deepest drop a sub-step follows down. */
|
|
347
|
+
stepHeight: number;
|
|
348
|
+
/** Least z of a ramp top's unit normal that can be driven on. */
|
|
349
|
+
standable: number;
|
|
350
|
+
/** How far below the hull's base ground is found. */
|
|
351
|
+
groundTrace: number;
|
|
352
|
+
/** How far above the hull's base ground is found. */
|
|
353
|
+
groundSnap: number;
|
|
354
|
+
/** Clearance kept from a surface. */
|
|
355
|
+
skin: number;
|
|
356
|
+
/** Button masks: any shared bit counts as held; 0 disables. */
|
|
357
|
+
jumpBit: number;
|
|
358
|
+
boostBit: number;
|
|
359
|
+
driftBit: number;
|
|
360
|
+
/** Sub-steps per step, an integer in [1, 8]. */
|
|
361
|
+
substeps: number;
|
|
362
|
+
/** 1: a jump works at `cap` 0. 0: a press at `cap` 0 is no jump (a freeze time). */
|
|
363
|
+
capZeroJump: number;
|
|
364
|
+
/** The collision world's hash ({@link firstpersonWorld}), written by the sandbox. */
|
|
365
|
+
world: number;
|
|
366
|
+
}
|
|
367
|
+
declare const VEHICLE_DEFAULTS: Readonly<VehicleParams>;
|
|
368
|
+
/** `vehicle` parameters from a module's `preset.params`: defaults for anything unset or invalid. */
|
|
369
|
+
declare function resolveVehicleParams(params: unknown): VehicleParams;
|
|
370
|
+
/** The fields a `vehicle` step reads (`cap` too, which it never writes; it never touches `pitch`
|
|
371
|
+
* or `duck`). */
|
|
372
|
+
interface VehicleBody {
|
|
373
|
+
x: number;
|
|
374
|
+
y: number;
|
|
375
|
+
z: number;
|
|
376
|
+
vx: number;
|
|
377
|
+
vy: number;
|
|
378
|
+
vz: number;
|
|
379
|
+
/** Heading, radians, +yaw counterclockwise seen from above (z up): body state, not input. */
|
|
380
|
+
yaw: number;
|
|
381
|
+
/** Yaw rate, rad/s, positive toward +yaw, [−1000, 1000]. */
|
|
382
|
+
spin: number;
|
|
383
|
+
/** The boost tank, [0, 1]. The module writes it to refuel; the step only burns it. */
|
|
384
|
+
fuel: number;
|
|
385
|
+
/** {@link MoveState} bits: onGround and jumpHeld. */
|
|
386
|
+
mstate: number;
|
|
387
|
+
/** Multiplier of both top speeds the module writes, [0, 4]. */
|
|
388
|
+
cap?: number;
|
|
389
|
+
}
|
|
390
|
+
/** What a `vehicle` step writes: every body field but `cap`. */
|
|
391
|
+
type VehicleStep = Omit<VehicleBody, 'cap'>;
|
|
392
|
+
/** The input fields a `vehicle` step reads: `moveY` the throttle, `moveX` the steer (+1 turns
|
|
393
|
+
* right, toward −yaw), `buttons` jump, boost and drift. */
|
|
394
|
+
interface VehicleInput {
|
|
395
|
+
moveX?: unknown;
|
|
396
|
+
moveY?: unknown;
|
|
397
|
+
buttons?: unknown;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* One fixed `vehicle` step (§17.7) through `world` (default: the empty world). Pure: returns the
|
|
401
|
+
* next `x y z vx vy vz yaw spin fuel mstate`; the body's `cap` is read, never written, and `pitch`
|
|
402
|
+
* and `duck` are never touched. `world` must be the world whose hash is `params.world` for the
|
|
403
|
+
* result to be the server's; the step itself does not compare them.
|
|
404
|
+
*/
|
|
405
|
+
declare function stepVehicle(body: Partial<VehicleBody>, input: VehicleInput, dt: number, params: VehicleParams, world?: FirstpersonWorld, posed?: PosedWorld): VehicleStep;
|
|
406
|
+
/** A body field a preset step may read and write: the entity's float32 pose and velocity,
|
|
407
|
+
* firstperson's aim pitch, duck amount, movement bits and speed cap, and vehicle's yaw rate and
|
|
408
|
+
* boost fuel. */
|
|
409
|
+
type PresetField = 'x' | 'y' | 'z' | 'vx' | 'vy' | 'vz' | 'yaw' | 'pitch' | 'duck' | 'mstate' | 'cap' | 'spin' | 'fuel';
|
|
410
|
+
/** The body a preset step reads: any of the fields, a missing one read as the step says (0, or 1
|
|
411
|
+
* for `cap`). */
|
|
412
|
+
type PresetBody = Readonly<Partial<Record<PresetField, number>>>;
|
|
413
|
+
/** The input a preset step reads (sanitized by the step itself). */
|
|
414
|
+
type PresetInput = Readonly<Partial<Record<'moveX' | 'moveY' | 'moveZ' | 'yaw' | 'pitch' | 'buttons', unknown>>>;
|
|
415
|
+
/** One preset, type-erased: what a validator, a reconciler and a test server need to run it by
|
|
416
|
+
* name. `fields` are the body fields its step writes (and so the fields a client mirrors);
|
|
417
|
+
* `reads` the further fields it only reads (a client mirrors those too, so a replay sees the
|
|
418
|
+
* server's value); `world` whether it steps through a collision world. */
|
|
419
|
+
interface PresetDefinition {
|
|
420
|
+
readonly defaults: Readonly<Record<string, number>>;
|
|
421
|
+
readonly ranges: Readonly<Record<string, PresetParamRange>>;
|
|
422
|
+
readonly fields: readonly PresetField[];
|
|
423
|
+
readonly reads: readonly PresetField[];
|
|
424
|
+
readonly world: boolean;
|
|
425
|
+
step(body: PresetBody, input: PresetInput, dt: number, params: Readonly<Record<string, number>>, world?: FirstpersonWorld, posed?: PosedWorld): Record<string, number>;
|
|
426
|
+
}
|
|
427
|
+
/** Every preset by name. A new preset is one entry here (plus its §17.7 text and vectors). */
|
|
428
|
+
declare const PRESETS: {
|
|
429
|
+
readonly [N in PresetName]: PresetDefinition;
|
|
430
|
+
};
|
|
431
|
+
/** Preset `name`'s table entry; undefined for a name not in the table (never one reached through
|
|
432
|
+
* the prototype). */
|
|
433
|
+
declare function definitionOf(name: unknown): PresetDefinition | undefined;
|
|
434
|
+
/** One fixed step of preset `name` with already resolved `params` ({@link resolvePresetParams}),
|
|
435
|
+
* through `world` for a preset that has one (default: the empty world). Pure: returns the next
|
|
436
|
+
* values of the preset's `fields`. */
|
|
437
|
+
declare function stepPreset(name: PresetName, body: PresetBody, input: PresetInput, dt: number, params: Readonly<Record<string, number>>, world?: FirstpersonWorld, posed?: PosedWorld): Record<string, number>;
|
|
438
|
+
|
|
439
|
+
/** Which world a ray asks. */
|
|
440
|
+
declare const WorldKey: {
|
|
441
|
+
readonly Shot: "shot";
|
|
442
|
+
};
|
|
443
|
+
type WorldKey = (typeof WorldKey)[keyof typeof WorldKey];
|
|
444
|
+
/** What `ctx.world.claim` made of a claimed stop. */
|
|
445
|
+
declare const ClaimVerdict: {
|
|
446
|
+
/** Within the tolerance of the shot world's stop: the claim stands. */
|
|
447
|
+
readonly Accepted: "accepted";
|
|
448
|
+
/** Past the shot world's stop by more than the tolerance: the shot stops there. */
|
|
449
|
+
readonly Refused: "refused";
|
|
450
|
+
/** Short of the shot world's stop by more than the tolerance: raised to the tolerance. */
|
|
451
|
+
readonly Capped: "capped";
|
|
452
|
+
/** Past it, through one wall of no more than the weapon's `pierce`. */
|
|
453
|
+
readonly Pierced: "pierced";
|
|
454
|
+
/** The weapon's `rule` said. */
|
|
455
|
+
readonly Ruled: "ruled";
|
|
456
|
+
};
|
|
457
|
+
type ClaimVerdict = (typeof ClaimVerdict)[keyof typeof ClaimVerdict];
|
|
458
|
+
/** What a shot world may cost, as a count (tree entries walked and solids tested) on seeded rays. */
|
|
459
|
+
declare const ShotWorldCost: {
|
|
460
|
+
/** Eight shots a tick at this cost are one seat's share of a step (16,000 operations, world-cost's budget). */
|
|
461
|
+
readonly MAX_OPS_PER_RAY: 2000;
|
|
462
|
+
readonly RAYS: 128;
|
|
463
|
+
readonly SEED: 2027;
|
|
464
|
+
/** Solids a room may hold, its world and its shot world together: at the .46 KiB a solid a real room measured (module text included,
|
|
465
|
+
* yard 152 m, 14.9 MiB at 33,233), this leaves the module a tenth of the 25.6 MiB a room is ended at. */
|
|
466
|
+
readonly MAX_ROOM_SOLIDS: 49152;
|
|
467
|
+
/** Surfaces a piercing claim may walk: a wall of a thousand slabs costs what this many do. */
|
|
468
|
+
readonly MAX_CLAIM_WALKS: 8;
|
|
469
|
+
/** The least a ray is taken to face a surface: how far along a graze the tolerance reaches, at most four times itself. Swept on the corpus (world-shots.yml,
|
|
470
|
+
* run 42297695700, at each world's stated tolerance, 38 and 76 m, mean of 8 rows): from 1/2 to 1/4 honest claims refused or capped fall from 8.3% to 7.2% and a
|
|
471
|
+
* hostile reach past a real surface at p99 doubles to 17 units; from 1/4 to 1/16 honest gains .3 more, for a reach of 51 units and a shot through at 48 of 3.1%, 0 before. */
|
|
472
|
+
readonly MIN_CLAIM_FACING: number;
|
|
473
|
+
};
|
|
474
|
+
/** What a load counted of its shot world (InitOut's `shotWorld`). */
|
|
475
|
+
interface ShotWorldCount {
|
|
476
|
+
solids: number;
|
|
477
|
+
opsPerRay: number;
|
|
478
|
+
}
|
|
479
|
+
/** A claimed stop as `moveZ` in [-1, 1] (neither movement preset reads it, and every transport carries it, §17.7 *A claimed stop*):
|
|
480
|
+
* [0, range] across the axis, and the axis's top for a shot that flew on. */
|
|
481
|
+
declare function claimToAxis(dist: number | null, range: number): number;
|
|
482
|
+
/** `claimToAxis`'s other way: a distance, or null for a shot that flew on. */
|
|
483
|
+
declare function axisToClaim(axis: number, range: number): number | null;
|
|
484
|
+
|
|
485
|
+
export { resolvePresetParams as $, type VehicleParams as A, type VehicleStep as B, ClaimVerdict as C, type WorldBox as D, EMPTY_WORLD as E, type FirstpersonWorld as F, WorldError as G, type HullBody as H, WorldKey as I, WorldLimits as J, type WorldRamp as K, axisToClaim as L, MoveState as M, NO_POSED as N, claimToAxis as O, type PresetName as P, definitionOf as Q, firstpersonWorld as R, type ShotWorldCount as S, TOPDOWN_DEFAULTS as T, hullOps as U, VEHICLE_DEFAULTS as V, type WorldCostMeter as W, isPresetName as X, posedWorld as Y, presetParamsValid as Z, resolveFirstpersonParams as _, type PosedSolid as a, resolveTopdownParams as a0, resolveVehicleParams as a1, stepFirstperson as a2, stepPreset as a3, stepTopdown as a4, stepVehicle as a5, withWorldCostMeter as a6, worldTreeOrder as a7, type HullOps as b, type PosedWorld as c, type FirstpersonWorldSpec as d, EMPTY_WORLD_HASH as e, FIRSTPERSON_DEFAULTS as f, type FirstpersonBody as g, type FirstpersonInput as h, type FirstpersonParams as i, type FirstpersonStep as j, POSED_MAX as k, PRESETS as l, PRESET_MAX_DT_S as m, Preset as n, type PresetBody as o, type PresetDefinition as p, type PresetField as q, type PresetInput as r, type PresetParamRange as s, ShotWorldCost as t, TREE_KEY_RADIX as u, type TopdownBody as v, type TopdownInput as w, type TopdownParams as x, type VehicleBody as y, type VehicleInput as z };
|