@genex-ai/multiplayer 0.17.1 → 0.17.8
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 +761 -9
- package/README.md +285 -1
- package/WORLD-GLTF.md +109 -0
- package/WORLD-SCENE.md +135 -0
- package/dist/authority/fast-udp.d.ts +15 -0
- package/dist/authority/fast-udp.js +14 -0
- package/dist/authority/fast-webtransport.d.ts +67 -0
- package/dist/authority/fast-webtransport.js +21 -0
- package/dist/authority/index.d.ts +2671 -0
- package/dist/authority/index.js +958 -0
- package/dist/authority/module.d.ts +2 -0
- package/dist/authority/module.js +12 -0
- package/dist/bridge-authority.d.ts +101 -0
- package/dist/bridge-authority.global.js +15 -0
- package/dist/bridge-authority.js +291 -0
- package/dist/bridge-core-Dhc73GC8.d.ts +27 -0
- package/dist/bridge.d.ts +26 -20
- package/dist/bridge.global.js +7 -7
- package/dist/bridge.js +17 -48
- package/dist/chunk-2NGXXQDS.js +1916 -0
- package/dist/chunk-4R7C2TLH.js +68 -0
- package/dist/{chunk-C52XFIB6.js → chunk-CSQEEANB.js} +217 -4
- package/dist/chunk-FPWP22Y7.js +143 -0
- package/dist/chunk-NFMGIKFZ.js +2627 -0
- package/dist/chunk-OD6NRSX2.js +29 -0
- package/dist/{chunk-3ZUPU3GT.js → chunk-QY3QQNDJ.js} +13 -122
- package/dist/chunk-QZOCUQJT.js +6900 -0
- package/dist/chunk-TSYEWPVO.js +44 -0
- package/dist/chunk-TVTVIMIH.js +675 -0
- package/dist/chunk-YWQ3ALYY.js +69 -0
- package/dist/fast-client--A88q0kk.d.ts +546 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.js +3 -2
- package/dist/join-CGoInvUM.d.ts +6 -0
- package/dist/level-build-CbRqrYJq.d.ts +140 -0
- package/dist/module-CSpXrzFc.d.ts +1187 -0
- package/dist/physics-predict-C7ZB1gDG.d.ts +1223 -0
- package/dist/protocol.d.ts +222 -2
- package/dist/protocol.js +47 -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 +46 -4
|
@@ -0,0 +1,2671 @@
|
|
|
1
|
+
import { AuthorityCloseCode } from '../protocol.js';
|
|
2
|
+
export { AUTHORITY_ROOM_ENDED_TEXT, authorityCloseCodeOf } from '../protocol.js';
|
|
3
|
+
import * as _colyseus_schema from '@colyseus/schema';
|
|
4
|
+
import { SchemaType } from '@colyseus/schema';
|
|
5
|
+
import { T as TickHz, E as EntityData, J as Json, R as ResolvedModuleConfig, P as PlayerInfo, L as LeaveReason, I as InputData, a as PhysicsErrorCode, b as InputRepeat, c as LiftVec, C as ContactPolicy, d as Lift, e as LiftsPolicy, f as RemotePredict, S as StandRule, g as TopRule, h as PropSlide, i as ContactDrawing } from '../module-CSpXrzFc.js';
|
|
6
|
+
export { A as AuthorityLifetime, j as CONTACT_DEFAULTS, k as CONTACT_PAIRS_MAX, l as CONTACT_PASSES_MAX, m as CONTACT_PRESETS, n as CONTACT_TAG_MAX, o as CONTACT_VALUE_MAX, p as ContactConfigError, q as ContactDeclaration, r as ContactPreset, s as ContactPresetParams, t as ContactPush, u as ContactShape, v as ContactShapeKind, w as EntityApi, x as EntityInit, G as GenexRoomModule, H as HeadFriction, y as INPUTS_DEFAULT, z as INPUT_PRESETS, B as INPUT_SETTLE_MS, D as InitContext, F as InputConfigError, K as InputDeclaration, M as InputPolicy, N as LIFETIME_DEFAULT, O as LIFTS_MAX, Q as LIFT_ID_MAX, U as LIFT_POINTS_MAX, V as LIFT_SPIN_MIN_PERIOD, W as LIFT_TICKS_MAX, X as LIFT_VALUE_MAX, Y as LifetimeConfigError, Z as LifetimeDeclaration, _ as LifetimePolicy, $ as LiftEase, a0 as LiftImpart, a1 as LiftPath, a2 as LiftPathMode, a3 as LiftShape, a4 as LiftShapeKind, a5 as LiftSpin, a6 as LiftTooFast, a7 as LiftsApi, a8 as LiftsConfigError, a9 as MODULE_CONTRACT, aa as ModuleConfig, ab as NO_LIFTS, ac as PairRule, ad as PhysicsAnswer, ae as PhysicsApi, af as PhysicsBodyDesc, ag as PhysicsBodyState, ah as PhysicsBodyType, ai as PhysicsColliderDesc, aj as PhysicsCommandResult, ak as PhysicsCommands, al as PhysicsEvent, am as PhysicsGroups, an as PhysicsHit, ao as PhysicsJointDesc, ap as PhysicsLimits, aq as PhysicsMotor, ar as PhysicsOverlap, as as PhysicsPose, at as PhysicsQueryFilter, au as PhysicsRefusal, av as PhysicsRequest, aw as PhysicsSetPoseOptions, ax as PhysicsShape, ay as PresetSpec, az as ProjectileApi, aA as ProjectileField, aB as ProjectileFlight, aC as ProjectileHit, aD as ProjectileInit, aE as Quat, aF as ResolvedPhysics, aG as RewindApi, aH as RewoundPose, aI as RoomContext, aJ as SHOOTER_CENTER, aK as ShotWorldSpec, aL as SlideRule, aM as TopPolicy, aN as Vec3, aO as WorldApi, aP as WorldClaim, aQ as WorldClaimOptions, aR as WorldRayHit, aS as WorldRayOptions, aT as defineRoom, aU as isLiftId, aV as presetInputRepeat, aW as resolveContactConfig, aX as resolveInputConfig, aY as resolveLifetime, aZ as resolveLifts } from '../module-CSpXrzFc.js';
|
|
7
|
+
import { P as PhysicsCeiling, a as PhysEvRow, b as PhysAnswerRow, c as PhysBodyRow, d as PredictStatus, C as ContactBody, R as RemoteInput, A as AuthorityContactRule, e as AuthoritySeatRule, f as PredictCore, g as PredictBodyRule, h as PredictKinematicRule } from '../physics-predict-C7ZB1gDG.js';
|
|
8
|
+
export { i as AdoptReport, B as BODY_CORRECTION_TAU_MS, j as BODY_EXTRAPOLATE_BACK_TICKS, k as BODY_EXTRAPOLATE_MAX_MS, l as BODY_SNAP_METRES, m as BodyDrawing, n as BodyFields, o as BodyPose, p as BodyQuantization, q as BodySnap, r as BodyState, s as CONTACT_FIELDS, t as ContactField, D as DrawClock, u as DrawHandoff, v as DrawQuat, w as DrawVec3, H as HOST_BODY_FIELDS, I as ISLAND_MARGIN_METRES, x as IslandBody, K as KeyframeBody, y as KeyframeJoint, z as KeyframeOutside, E as KeyframeSeat, O as OwnPoseOf, F as PHYSICS_BODY_FIELDS, G as PHYSICS_CEILING_FACTOR, J as PHYSICS_CONTESTED_METRES, L as PHYSICS_CONTRACT, M as PHYSICS_DEFAULT_CEILING, N as PHYSICS_DEFAULT_LIMITS, Q as PHYSICS_DEFAULT_PATCH_HZ, S as PHYSICS_FULL_RATE_BODIES, T as PHYSICS_KEY_MAX_BYTES, U as PHYSICS_KIND_MAX_BYTES, V as PHYSICS_LIMIT_NAMES, W as PHYSICS_OVERLAP_MAX_KEYS, X as PHYSICS_PATCH_HZ, Y as PHYSICS_PREDICT_MAX_ANGULAR, Z as PHYSICS_PREDICT_MAX_BOXES, _ as PHYSICS_PREDICT_MAX_LINEAR, $ as PHYSICS_PREDICT_MAX_RAMPS, a0 as PHYSICS_PREDICT_MIN_ITERATIONS, a1 as PHYSICS_PRESET_LENGTH_UNITS, a2 as PHYSICS_REAL_LIMITS, a3 as PHYSICS_ROTATING_BODIES, a4 as PHYSICS_SCALED_LIMITS, a5 as PHYSICS_SHAPES_MAX, a6 as PHYSICS_SHAPE_MAX_CHARS, a7 as PHYSICS_STATIC_PIECE_BYTES, a8 as PHYSICS_STATIC_PREFIX, a9 as PHYSICS_SUBSTEPS, aa as PHYS_BUDGET_CALM_SHARE, ab as PHYS_BUDGET_MIN_SAMPLES, ac as PHYS_BUDGET_P90_FACTOR, ad as PHYS_BUDGET_WINDOW, ae as PHYS_CANARY_MAX_MISMATCH, af as PHYS_CANARY_MIN_SAMPLES, ag as PHYS_CANARY_WINDOW, ah as PHYS_CPU_CALM_PROBES, ai as PHYS_CPU_PROBE_MS, aj as PHYS_PREDICT_HASHES_KEPT, ak as PHYS_PREDICT_SET_SIZES, al as PHYS_RESIM_BUDGET_MS, am as PairPush, an as PhysDesc, ao as PhysDescPredict, ap as PhysEvContactBegin, aq as PhysEvKind, ar as PhysEvOther, as as PhysHitRow, at as PhysOverlapRow, au as PhysicsBodyField, av as PhysicsConfigRange, aw as PhysicsPredictRange, ax as PhysicsPredictor, ay as PhysicsResolution, az as PhysicsWorldDesc, aA as PredictKeyframe, aB as PredictLifts, aC as PredictResult, aD as PredictSmoothing, aE as PredictWorld, aF as PredictorOptions, aG as PresetBodyShape, aH as QuantizedRange, aI as RULED_SLEW, aJ as RULED_SNAP_TICKS, aK as RemoteStep, aL as RuleSeat, aM as RuleTick, aN as RuleVelocity, aO as SEAT_LIFT_MAX, aP as SEAT_PAIR_EASE, aQ as SEAT_ROUND_RATE, aR as SHAPE_REF_KINDS, aS as SeatContacts, aT as SeatSide, aU as WIRE_REST_MAX, aV as WIRE_ROW_STRIDE, aW as WireBodyState, aX as WireFields, aY as bodyRadiusOf, aZ as bodyStateOf, a_ as checkResolvedPhysics, a$ as clampedVelocity, b0 as correctionAt, b1 as correctionShare, b2 as correctionTauMs, b3 as decayedInput, b4 as dequantizeBodyValue, b5 as drawBody, b6 as effectivePatchHz, b7 as extrapolateBody, b8 as extrapolationSeconds, b9 as inlineShapes, ba as innerDtOf, bb as isPhysicsKey, bc as isPhysicsKind, bd as isPhysicsPatchHz, be as keyframeTicks, bf as liftOff, bg as motorText, bh as nextPredictSetSize, bi as parsePhysDesc, bj as physDescText, bk as physicsBudgetMs, bl as physicsCeilingValid, bm as physicsLimitsAt, bn as physicsLimitsForWorld, bo as physicsWorldDesc, bp as physicsWorldPredicts, bq as proximityIslands, br as quantizeBodyValue, bs as quatMul, bt as quatNormalize, bu as receiveBodyState, bv as remoteInputWeight, bw as resolvePhysicsConfig, bx as restStepsOf, by as ruledPoseAt, bz as sameBodyState, bA as seatPairKey, bB as seatRuleTick, bC as selfTestPredictCore, bD as separateAround, bE as separateDrawn, bF as separateSeats, bG as slerpFromIdentity, bH as snapMetresOf, bI as solverIterationsOf, bJ as wasmSimdSupported, bK as wireFieldsOf, bL as wireRowOfExport, bM as wireRowOfState, bN as writeWireRow } from '../physics-predict-C7ZB1gDG.js';
|
|
9
|
+
import { S as ShotWorldCount, W as WorldCostMeter, P as PresetName, H as HullBody, a as PosedSolid, b as HullOps, c as PosedWorld, F as FirstpersonWorld, d as FirstpersonWorldSpec } from '../shot-world-D22tqOUT.js';
|
|
10
|
+
export { C as ClaimVerdict, E as EMPTY_WORLD, e as EMPTY_WORLD_HASH, f as FIRSTPERSON_DEFAULTS, g as FirstpersonBody, h as FirstpersonInput, i as FirstpersonParams, j as FirstpersonStep, M as MoveState, N as NO_POSED, k as POSED_MAX, l as PRESETS, m as PRESET_MAX_DT_S, n as Preset, o as PresetBody, p as PresetDefinition, q as PresetField, r as PresetInput, s as PresetParamRange, t as ShotWorldCost, T as TOPDOWN_DEFAULTS, u as TREE_KEY_RADIX, v as TopdownBody, w as TopdownInput, x as TopdownParams, V as VEHICLE_DEFAULTS, y as VehicleBody, z as VehicleInput, A as VehicleParams, B as VehicleStep, D as WorldBox, G as WorldError, I as WorldKey, J as WorldLimits, K as WorldRamp, L as axisToClaim, O as claimToAxis, Q as definitionOf, R as firstpersonWorld, U as hullOps, X as isPresetName, Y as posedWorld, Z as presetParamsValid, _ as resolveFirstpersonParams, $ as resolvePresetParams, a0 as resolveTopdownParams, a1 as resolveVehicleParams, a2 as stepFirstperson, a3 as stepPreset, a4 as stepTopdown, a5 as stepVehicle, a6 as withWorldCostMeter, a7 as worldTreeOrder } from '../shot-world-D22tqOUT.js';
|
|
11
|
+
import { a as FastFallbackReason, F as FastSocketOpener } from '../fast-client--A88q0kk.js';
|
|
12
|
+
export { A as AcceptKind, c as AcceptOptions, d as AcceptResult, e as AcceptedInput, C as ClientRx, E as EntityMotion, f as FAST_ACK_EAGER_GAP_MS, g as FAST_ACK_EAGER_RECORDS, h as FAST_BIND_REV, i as FAST_CHALLENGE_JUMP, j as FAST_FRAME_GAP_MS, k as FAST_GAP_FILL_MS, l as FAST_HANDSHAKE_MS, m as FAST_KEEPALIVE_BIND_MS, n as FAST_KEEPALIVE_MS, o as FAST_KEY_BYTES, p as FAST_MAX_ACTIONS, q as FAST_MAX_DATAGRAM_BYTES, r as FAST_MAX_FRAGMENTS, s as FAST_MAX_RECORD_BYTES, t as FAST_OPEN_ROUND_TRIPS, u as FAST_REASSEMBLY_SLOTS, v as FAST_RETRY_BASE_MS, w as FAST_RETRY_MAX_MS, x as FAST_RETURN_PROOF, y as FAST_RETURN_STABLE_MS, z as FAST_SEQ_AHEAD_MS, B as FAST_SNAPSHOT_HISTORY, D as FAST_STALL_FALLBACK_MS, G as FAST_VERSION, b as FastBindMessage, H as FastBinding, I as FastClient, J as FastClientOptions, K as FastDatagramSocket, L as FastFault, M as FastInput, N as FastKind, O as FastMessage, P as FastOffMessage, Q as FastOnMessage, R as FastReceipt, S as FastResult, T as FastSnapshot, U as FastWebTransport, V as Fragment, W as HeldSnapshot, X as INPUT_REDUNDANCY_MAX, Y as INPUT_REDUNDANCY_MIN, Z as INPUT_REDUNDANCY_MS, _ as MotionRecord, $ as MotionRecordKind, a0 as PartialSnapshot, a1 as RECORD_ID_MAX_CHARS, a2 as ReceiveResult, a3 as Records, a4 as SeatEcho, a5 as SeatRx, a6 as SnapshotBody, a7 as SnapshotHead, a8 as Uplink, a9 as UplinkOptions, aa as acceptUplink, ab as applyBody, ac as blankEntityMotion, ad as blankSeatEcho, ae as decodeFragment, af as decodeRecord, ag as decodeUplink, ah as deltaBase, ai as dequantizeCode, aj as diffSnapshot, ak as emptyClientRx, al as encodeRecord, am as encodeSnapshot, an as encodeUplink, ao as fastRetryDelayMs, ap as fromHex, aq as gapFillMax, ar as heldInputs, as as inputRedundancyTicks, at as isFastBind, au as isPress, av as openFastClient, aw as parseBody, ax as quantizeCode, ay as receiveFragment, az as renderStamp, aA as seqAheadMax, aB as toHex, aC as uplinkFor, aD as uplinkMaxBytes } from '../fast-client--A88q0kk.js';
|
|
13
|
+
import { A as AuthSource } from '../join-CGoInvUM.js';
|
|
14
|
+
|
|
15
|
+
/** The Colyseus view tag on an entity's motion fields in a physics room's state (PROTOCOL.md §17.12
|
|
16
|
+
* *Downlink*): a client's view holds it on every entity it sees, except a fast seat's while its
|
|
17
|
+
* channel is live, whose motion comes by snapshot only. Server-side encoder metadata: no decoder reads
|
|
18
|
+
* it, and the handshake's type description is the same with or without it. */
|
|
19
|
+
declare const MOTION_VIEW_TAG = 1;
|
|
20
|
+
declare const AuthorityInput: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
21
|
+
moveX: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
22
|
+
moveY: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
23
|
+
moveZ: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
24
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
25
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
26
|
+
buttons: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
27
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
28
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
29
|
+
moveX: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
30
|
+
moveY: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
31
|
+
moveZ: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
32
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
33
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
34
|
+
buttons: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
35
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
36
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
37
|
+
type AuthorityInput = SchemaType<typeof AuthorityInput>;
|
|
38
|
+
declare const AuthorityEntity: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
39
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
40
|
+
owner: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
41
|
+
x: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
42
|
+
y: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
43
|
+
z: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
44
|
+
vx: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
45
|
+
vy: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
46
|
+
vz: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
47
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
48
|
+
hp: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
49
|
+
flags: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
50
|
+
epoch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
51
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
52
|
+
t0: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
53
|
+
g: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
54
|
+
src: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
55
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
56
|
+
duck: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
57
|
+
mstate: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
58
|
+
cap: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
59
|
+
spin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
60
|
+
fuel: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
61
|
+
qx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
62
|
+
qy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
63
|
+
qz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
64
|
+
qw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
65
|
+
lvx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
66
|
+
lvy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
67
|
+
lvz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
68
|
+
avx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
69
|
+
avy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
70
|
+
avz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
71
|
+
sleep: _colyseus_schema.FieldBuilder<boolean | undefined, false, true>;
|
|
72
|
+
rest: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
73
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
74
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
75
|
+
owner: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
76
|
+
x: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
77
|
+
y: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
78
|
+
z: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
79
|
+
vx: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
80
|
+
vy: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
81
|
+
vz: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
82
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
83
|
+
hp: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
84
|
+
flags: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
85
|
+
epoch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
86
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
87
|
+
t0: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
88
|
+
g: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
89
|
+
src: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
90
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
91
|
+
duck: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
92
|
+
mstate: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
93
|
+
cap: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
94
|
+
spin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
95
|
+
fuel: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
96
|
+
qx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
97
|
+
qy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
98
|
+
qz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
99
|
+
qw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
100
|
+
lvx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
101
|
+
lvy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
102
|
+
lvz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
103
|
+
avx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
104
|
+
avy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
105
|
+
avz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
106
|
+
sleep: _colyseus_schema.FieldBuilder<boolean | undefined, false, true>;
|
|
107
|
+
rest: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
108
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
109
|
+
type AuthorityEntity = SchemaType<typeof AuthorityEntity>;
|
|
110
|
+
declare const AuthorityPhysicsEntity: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
111
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
112
|
+
owner: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
113
|
+
x: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
114
|
+
y: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
115
|
+
z: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
116
|
+
vx: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
117
|
+
vy: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
118
|
+
vz: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
119
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
120
|
+
hp: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
121
|
+
flags: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
122
|
+
epoch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
123
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
124
|
+
t0: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
125
|
+
g: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
126
|
+
src: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
127
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
128
|
+
duck: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
129
|
+
mstate: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
130
|
+
cap: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
131
|
+
spin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
132
|
+
fuel: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
133
|
+
qx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
134
|
+
qy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
135
|
+
qz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
136
|
+
qw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
137
|
+
lvx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
138
|
+
lvy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
139
|
+
lvz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
140
|
+
avx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
141
|
+
avy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
142
|
+
avz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
143
|
+
sleep: _colyseus_schema.FieldBuilder<boolean | undefined, false, true>;
|
|
144
|
+
rest: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
145
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
146
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
147
|
+
owner: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
148
|
+
x: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
149
|
+
y: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
150
|
+
z: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
151
|
+
vx: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
152
|
+
vy: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
153
|
+
vz: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
154
|
+
yaw: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
155
|
+
hp: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
156
|
+
flags: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
157
|
+
epoch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
158
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
159
|
+
t0: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
160
|
+
g: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
161
|
+
src: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
162
|
+
pitch: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
163
|
+
duck: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
164
|
+
mstate: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
165
|
+
cap: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
166
|
+
spin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
167
|
+
fuel: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
168
|
+
qx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
169
|
+
qy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
170
|
+
qz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
171
|
+
qw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
172
|
+
lvx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
173
|
+
lvy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
174
|
+
lvz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
175
|
+
avx: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
176
|
+
avy: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
177
|
+
avz: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
178
|
+
sleep: _colyseus_schema.FieldBuilder<boolean | undefined, false, true>;
|
|
179
|
+
rest: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
180
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
181
|
+
type AuthorityPhysicsEntity = SchemaType<typeof AuthorityPhysicsEntity>;
|
|
182
|
+
declare const AuthorityPlayer: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
183
|
+
name: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
184
|
+
uid: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
185
|
+
team: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
186
|
+
connected: _colyseus_schema.FieldBuilder<boolean, true, false>;
|
|
187
|
+
avatarUrl: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
188
|
+
seqBase: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
189
|
+
inMoveX: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
190
|
+
inMoveY: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
191
|
+
inMoveZ: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
192
|
+
inYaw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
193
|
+
inPitch: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
194
|
+
inButtons: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
195
|
+
inRep: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
196
|
+
inStarve: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
197
|
+
inBuf: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
198
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
199
|
+
name: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
200
|
+
uid: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
201
|
+
team: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
202
|
+
connected: _colyseus_schema.FieldBuilder<boolean, true, false>;
|
|
203
|
+
avatarUrl: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
204
|
+
seqBase: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
205
|
+
inMoveX: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
206
|
+
inMoveY: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
207
|
+
inMoveZ: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
208
|
+
inYaw: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
209
|
+
inPitch: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
210
|
+
inButtons: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
211
|
+
inRep: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
212
|
+
inStarve: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
213
|
+
inBuf: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
214
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
215
|
+
type AuthorityPlayer = SchemaType<typeof AuthorityPlayer>;
|
|
216
|
+
declare const AuthorityBody: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
217
|
+
type: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
218
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
219
|
+
colliders: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
220
|
+
desc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
221
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
222
|
+
type: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
223
|
+
kind: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
224
|
+
colliders: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
225
|
+
desc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
226
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
227
|
+
type AuthorityBody = SchemaType<typeof AuthorityBody>;
|
|
228
|
+
declare const AuthorityShape: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
229
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
230
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
231
|
+
data: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
232
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
233
|
+
type AuthorityShape = SchemaType<typeof AuthorityShape>;
|
|
234
|
+
declare const AuthorityJoint: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
235
|
+
desc: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
236
|
+
motor: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
237
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
238
|
+
desc: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
239
|
+
motor: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
240
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
241
|
+
type AuthorityJoint = SchemaType<typeof AuthorityJoint>;
|
|
242
|
+
declare const AuthorityRoomState: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
243
|
+
players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
244
|
+
name: string;
|
|
245
|
+
uid: string;
|
|
246
|
+
team: string;
|
|
247
|
+
connected: boolean;
|
|
248
|
+
avatarUrl: string;
|
|
249
|
+
seqBase: number;
|
|
250
|
+
} & {
|
|
251
|
+
inMoveX?: number | undefined;
|
|
252
|
+
inMoveY?: number | undefined;
|
|
253
|
+
inMoveZ?: number | undefined;
|
|
254
|
+
inYaw?: number | undefined;
|
|
255
|
+
inPitch?: number | undefined;
|
|
256
|
+
inButtons?: number | undefined;
|
|
257
|
+
inRep?: number | undefined;
|
|
258
|
+
inStarve?: number | undefined;
|
|
259
|
+
inBuf?: number | undefined;
|
|
260
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
261
|
+
entities: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
262
|
+
kind: string;
|
|
263
|
+
owner: string;
|
|
264
|
+
x: number;
|
|
265
|
+
y: number;
|
|
266
|
+
z: number;
|
|
267
|
+
vx: number;
|
|
268
|
+
vy: number;
|
|
269
|
+
vz: number;
|
|
270
|
+
yaw: number;
|
|
271
|
+
hp: number;
|
|
272
|
+
flags: number;
|
|
273
|
+
epoch: number;
|
|
274
|
+
data: string;
|
|
275
|
+
t0: number;
|
|
276
|
+
g: number;
|
|
277
|
+
src: string;
|
|
278
|
+
pitch: number;
|
|
279
|
+
duck: number;
|
|
280
|
+
mstate: number;
|
|
281
|
+
cap: number;
|
|
282
|
+
spin: number;
|
|
283
|
+
fuel: number;
|
|
284
|
+
} & {
|
|
285
|
+
qx?: number | undefined;
|
|
286
|
+
qy?: number | undefined;
|
|
287
|
+
qz?: number | undefined;
|
|
288
|
+
qw?: number | undefined;
|
|
289
|
+
lvx?: number | undefined;
|
|
290
|
+
lvy?: number | undefined;
|
|
291
|
+
lvz?: number | undefined;
|
|
292
|
+
avx?: number | undefined;
|
|
293
|
+
avy?: number | undefined;
|
|
294
|
+
avz?: number | undefined;
|
|
295
|
+
sleep?: boolean | undefined;
|
|
296
|
+
rest?: number | undefined;
|
|
297
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
298
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
299
|
+
clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
300
|
+
preset: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
301
|
+
moduleSha: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
302
|
+
tickOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
303
|
+
physics: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
304
|
+
lengthUnit: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
305
|
+
bodies: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
306
|
+
type: string;
|
|
307
|
+
kind: string;
|
|
308
|
+
colliders: string;
|
|
309
|
+
} & {
|
|
310
|
+
desc?: string | undefined;
|
|
311
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
312
|
+
physDesc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
313
|
+
keyframe: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
314
|
+
shapes: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
315
|
+
data: string;
|
|
316
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
317
|
+
joints: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
318
|
+
desc: string;
|
|
319
|
+
motor: string;
|
|
320
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
321
|
+
lifts: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
322
|
+
matchKey: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
323
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
324
|
+
players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
325
|
+
name: string;
|
|
326
|
+
uid: string;
|
|
327
|
+
team: string;
|
|
328
|
+
connected: boolean;
|
|
329
|
+
avatarUrl: string;
|
|
330
|
+
seqBase: number;
|
|
331
|
+
} & {
|
|
332
|
+
inMoveX?: number | undefined;
|
|
333
|
+
inMoveY?: number | undefined;
|
|
334
|
+
inMoveZ?: number | undefined;
|
|
335
|
+
inYaw?: number | undefined;
|
|
336
|
+
inPitch?: number | undefined;
|
|
337
|
+
inButtons?: number | undefined;
|
|
338
|
+
inRep?: number | undefined;
|
|
339
|
+
inStarve?: number | undefined;
|
|
340
|
+
inBuf?: number | undefined;
|
|
341
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
342
|
+
entities: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
343
|
+
kind: string;
|
|
344
|
+
owner: string;
|
|
345
|
+
x: number;
|
|
346
|
+
y: number;
|
|
347
|
+
z: number;
|
|
348
|
+
vx: number;
|
|
349
|
+
vy: number;
|
|
350
|
+
vz: number;
|
|
351
|
+
yaw: number;
|
|
352
|
+
hp: number;
|
|
353
|
+
flags: number;
|
|
354
|
+
epoch: number;
|
|
355
|
+
data: string;
|
|
356
|
+
t0: number;
|
|
357
|
+
g: number;
|
|
358
|
+
src: string;
|
|
359
|
+
pitch: number;
|
|
360
|
+
duck: number;
|
|
361
|
+
mstate: number;
|
|
362
|
+
cap: number;
|
|
363
|
+
spin: number;
|
|
364
|
+
fuel: number;
|
|
365
|
+
} & {
|
|
366
|
+
qx?: number | undefined;
|
|
367
|
+
qy?: number | undefined;
|
|
368
|
+
qz?: number | undefined;
|
|
369
|
+
qw?: number | undefined;
|
|
370
|
+
lvx?: number | undefined;
|
|
371
|
+
lvy?: number | undefined;
|
|
372
|
+
lvz?: number | undefined;
|
|
373
|
+
avx?: number | undefined;
|
|
374
|
+
avy?: number | undefined;
|
|
375
|
+
avz?: number | undefined;
|
|
376
|
+
sleep?: boolean | undefined;
|
|
377
|
+
rest?: number | undefined;
|
|
378
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
379
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
380
|
+
clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
381
|
+
preset: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
382
|
+
moduleSha: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
383
|
+
tickOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
384
|
+
physics: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
385
|
+
lengthUnit: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
386
|
+
bodies: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
387
|
+
type: string;
|
|
388
|
+
kind: string;
|
|
389
|
+
colliders: string;
|
|
390
|
+
} & {
|
|
391
|
+
desc?: string | undefined;
|
|
392
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
393
|
+
physDesc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
394
|
+
keyframe: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
395
|
+
shapes: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
396
|
+
data: string;
|
|
397
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
398
|
+
joints: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
399
|
+
desc: string;
|
|
400
|
+
motor: string;
|
|
401
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
402
|
+
lifts: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
403
|
+
matchKey: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
404
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
405
|
+
type AuthorityRoomState = SchemaType<typeof AuthorityRoomState>;
|
|
406
|
+
declare const AuthorityPhysicsRoomState: _colyseus_schema.SchemaWithExtendsConstructor<{
|
|
407
|
+
entities: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
408
|
+
kind: string;
|
|
409
|
+
owner: string;
|
|
410
|
+
x: number;
|
|
411
|
+
y: number;
|
|
412
|
+
z: number;
|
|
413
|
+
vx: number;
|
|
414
|
+
vy: number;
|
|
415
|
+
vz: number;
|
|
416
|
+
yaw: number;
|
|
417
|
+
hp: number;
|
|
418
|
+
flags: number;
|
|
419
|
+
epoch: number;
|
|
420
|
+
data: string;
|
|
421
|
+
t0: number;
|
|
422
|
+
g: number;
|
|
423
|
+
src: string;
|
|
424
|
+
pitch: number;
|
|
425
|
+
duck: number;
|
|
426
|
+
mstate: number;
|
|
427
|
+
cap: number;
|
|
428
|
+
spin: number;
|
|
429
|
+
fuel: number;
|
|
430
|
+
} & {
|
|
431
|
+
qx?: number | undefined;
|
|
432
|
+
qy?: number | undefined;
|
|
433
|
+
qz?: number | undefined;
|
|
434
|
+
qw?: number | undefined;
|
|
435
|
+
lvx?: number | undefined;
|
|
436
|
+
lvy?: number | undefined;
|
|
437
|
+
lvz?: number | undefined;
|
|
438
|
+
avx?: number | undefined;
|
|
439
|
+
avy?: number | undefined;
|
|
440
|
+
avz?: number | undefined;
|
|
441
|
+
sleep?: boolean | undefined;
|
|
442
|
+
rest?: number | undefined;
|
|
443
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
444
|
+
players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
445
|
+
name: string;
|
|
446
|
+
uid: string;
|
|
447
|
+
team: string;
|
|
448
|
+
connected: boolean;
|
|
449
|
+
avatarUrl: string;
|
|
450
|
+
seqBase: number;
|
|
451
|
+
} & {
|
|
452
|
+
inMoveX?: number | undefined;
|
|
453
|
+
inMoveY?: number | undefined;
|
|
454
|
+
inMoveZ?: number | undefined;
|
|
455
|
+
inYaw?: number | undefined;
|
|
456
|
+
inPitch?: number | undefined;
|
|
457
|
+
inButtons?: number | undefined;
|
|
458
|
+
inRep?: number | undefined;
|
|
459
|
+
inStarve?: number | undefined;
|
|
460
|
+
inBuf?: number | undefined;
|
|
461
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
462
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
463
|
+
clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
464
|
+
preset: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
465
|
+
moduleSha: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
466
|
+
tickOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
467
|
+
physics: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
468
|
+
lengthUnit: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
469
|
+
bodies: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
470
|
+
type: string;
|
|
471
|
+
kind: string;
|
|
472
|
+
colliders: string;
|
|
473
|
+
} & {
|
|
474
|
+
desc?: string | undefined;
|
|
475
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
476
|
+
physDesc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
477
|
+
keyframe: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
478
|
+
shapes: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
479
|
+
data: string;
|
|
480
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
481
|
+
joints: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
482
|
+
desc: string;
|
|
483
|
+
motor: string;
|
|
484
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
485
|
+
lifts: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
486
|
+
matchKey: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
487
|
+
}, _colyseus_schema.BuilderInitProps<{
|
|
488
|
+
entities: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
489
|
+
kind: string;
|
|
490
|
+
owner: string;
|
|
491
|
+
x: number;
|
|
492
|
+
y: number;
|
|
493
|
+
z: number;
|
|
494
|
+
vx: number;
|
|
495
|
+
vy: number;
|
|
496
|
+
vz: number;
|
|
497
|
+
yaw: number;
|
|
498
|
+
hp: number;
|
|
499
|
+
flags: number;
|
|
500
|
+
epoch: number;
|
|
501
|
+
data: string;
|
|
502
|
+
t0: number;
|
|
503
|
+
g: number;
|
|
504
|
+
src: string;
|
|
505
|
+
pitch: number;
|
|
506
|
+
duck: number;
|
|
507
|
+
mstate: number;
|
|
508
|
+
cap: number;
|
|
509
|
+
spin: number;
|
|
510
|
+
fuel: number;
|
|
511
|
+
} & {
|
|
512
|
+
qx?: number | undefined;
|
|
513
|
+
qy?: number | undefined;
|
|
514
|
+
qz?: number | undefined;
|
|
515
|
+
qw?: number | undefined;
|
|
516
|
+
lvx?: number | undefined;
|
|
517
|
+
lvy?: number | undefined;
|
|
518
|
+
lvz?: number | undefined;
|
|
519
|
+
avx?: number | undefined;
|
|
520
|
+
avy?: number | undefined;
|
|
521
|
+
avz?: number | undefined;
|
|
522
|
+
sleep?: boolean | undefined;
|
|
523
|
+
rest?: number | undefined;
|
|
524
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
525
|
+
players: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
526
|
+
name: string;
|
|
527
|
+
uid: string;
|
|
528
|
+
team: string;
|
|
529
|
+
connected: boolean;
|
|
530
|
+
avatarUrl: string;
|
|
531
|
+
seqBase: number;
|
|
532
|
+
} & {
|
|
533
|
+
inMoveX?: number | undefined;
|
|
534
|
+
inMoveY?: number | undefined;
|
|
535
|
+
inMoveZ?: number | undefined;
|
|
536
|
+
inYaw?: number | undefined;
|
|
537
|
+
inPitch?: number | undefined;
|
|
538
|
+
inButtons?: number | undefined;
|
|
539
|
+
inRep?: number | undefined;
|
|
540
|
+
inStarve?: number | undefined;
|
|
541
|
+
inBuf?: number | undefined;
|
|
542
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string>, true, false>;
|
|
543
|
+
tick: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
544
|
+
clockOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
545
|
+
preset: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
546
|
+
moduleSha: _colyseus_schema.FieldBuilder<string, true, false>;
|
|
547
|
+
tickOrigin: _colyseus_schema.FieldBuilder<number, true, false>;
|
|
548
|
+
physics: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
549
|
+
lengthUnit: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
550
|
+
bodies: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
551
|
+
type: string;
|
|
552
|
+
kind: string;
|
|
553
|
+
colliders: string;
|
|
554
|
+
} & {
|
|
555
|
+
desc?: string | undefined;
|
|
556
|
+
} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
557
|
+
physDesc: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
558
|
+
keyframe: _colyseus_schema.FieldBuilder<number | undefined, false, true>;
|
|
559
|
+
shapes: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
560
|
+
data: string;
|
|
561
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
562
|
+
joints: _colyseus_schema.FieldBuilder<_colyseus_schema.MapSchema<{
|
|
563
|
+
desc: string;
|
|
564
|
+
motor: string;
|
|
565
|
+
} & {} & _colyseus_schema.Schema<any> & _colyseus_schema.Schema<unknown>, string> | undefined, true, true>;
|
|
566
|
+
lifts: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
567
|
+
matchKey: _colyseus_schema.FieldBuilder<string | undefined, false, true>;
|
|
568
|
+
}>, typeof _colyseus_schema.Schema>;
|
|
569
|
+
type AuthorityPhysicsRoomState = SchemaType<typeof AuthorityPhysicsRoomState>;
|
|
570
|
+
|
|
571
|
+
/** The guest's two entry points. */
|
|
572
|
+
declare const GuestGlobal: {
|
|
573
|
+
readonly INIT: "__genex_init";
|
|
574
|
+
readonly TICK: "__genex_tick";
|
|
575
|
+
/** A physics room's static world, called once after init (§17.10 *The static world*). */
|
|
576
|
+
readonly WORLD: "__genex_world";
|
|
577
|
+
/** The room's hand-off at the end of a drain (PROTOCOL.md §17.13), called once. */
|
|
578
|
+
readonly HANDOFF: "__genex_handoff";
|
|
579
|
+
};
|
|
580
|
+
/** Wire limits. Sizes are JS string lengths (UTF-16 code units), as everywhere in the protocol. */
|
|
581
|
+
declare const AuthorityLimits: {
|
|
582
|
+
/** Entities one tick may update, and separately remove. */
|
|
583
|
+
readonly MAX_ENTITIES: 256;
|
|
584
|
+
/** A room's hand-off (`onDrain`, PROTOCOL.md §17.13) as JSON text. Over it the successor starts clean. */
|
|
585
|
+
readonly MAX_HANDOFF_CHARS: number;
|
|
586
|
+
/** Entities one room may hold at once. The room state lives on the host, outside the sandbox's
|
|
587
|
+
* memory limit, so this cap is what bounds it (and every client's patches). */
|
|
588
|
+
readonly MAX_ROOM_ENTITIES: 1024;
|
|
589
|
+
/** One TickOut / InitOut as JSON text. */
|
|
590
|
+
readonly MAX_OUTPUT_BYTES: number;
|
|
591
|
+
readonly MAX_EVENTS_PER_TICK: 64;
|
|
592
|
+
/** One entity's `data` JSON text. */
|
|
593
|
+
readonly MAX_ENTITY_DATA_BYTES: 256;
|
|
594
|
+
readonly MAX_ENTITY_ID_CHARS: 64;
|
|
595
|
+
readonly MAX_KIND_CHARS: 64;
|
|
596
|
+
/** A session id (`owner`, an event's `to`). */
|
|
597
|
+
readonly MAX_SESSION_ID_CHARS: 64;
|
|
598
|
+
/** Every entity number's magnitude (float32 holds it without overflowing). */
|
|
599
|
+
readonly MAX_ABS: 1000000000;
|
|
600
|
+
/** `flags` is an integer below this. */
|
|
601
|
+
readonly MASK_LIMIT: number;
|
|
602
|
+
/** `epoch` is an integer in [0, MAX_EPOCH]. */
|
|
603
|
+
readonly MAX_EPOCH: number;
|
|
604
|
+
/** A projectile's launch tick `t0` is an integer in [0, MAX_PROJECTILE_TICK] (§17.9). */
|
|
605
|
+
readonly MAX_PROJECTILE_TICK: number;
|
|
606
|
+
/** A projectile's gravity `g` is in [0, MAX_PROJECTILE_G] units/s². */
|
|
607
|
+
readonly MAX_PROJECTILE_G: 1000;
|
|
608
|
+
/** The launches waiting to go out (since the last output the host applied) may hold at most this
|
|
609
|
+
* many entities and this much of the output's JSON (§17.9): a launch past either is refused in
|
|
610
|
+
* the sandbox, so a burst alone can never make an output the host must refuse (about a hundred
|
|
611
|
+
* new projectiles whose floats print in full). The rest of MAX_ENTITIES and MAX_OUTPUT_BYTES
|
|
612
|
+
* stays for everything else a tick writes. */
|
|
613
|
+
readonly MAX_LAUNCH_UPDATES: 224;
|
|
614
|
+
readonly MAX_LAUNCH_BYTES: number;
|
|
615
|
+
/** One event: its type, and its `data` as JSON text. */
|
|
616
|
+
readonly MAX_EVENT_TYPE_CHARS: 128;
|
|
617
|
+
readonly MAX_EVENT_BYTES: number;
|
|
618
|
+
readonly MAX_JSON_DEPTH: 32;
|
|
619
|
+
readonly MAX_JSON_NODES: 4096;
|
|
620
|
+
/** Seats one authority room may hold. */
|
|
621
|
+
readonly MAX_PLAYERS: 64;
|
|
622
|
+
/** A physics room's output (§17.10): at most this many `phys` commands, and `phys` plus `physQ`
|
|
623
|
+
* at most this much JSON, apart from the MAX_OUTPUT_BYTES the rest may hold, so the whole text is
|
|
624
|
+
* at most MAX_PHYSICS_OUTPUT_BYTES. */
|
|
625
|
+
readonly MAX_PHYS_COMMANDS: 256;
|
|
626
|
+
readonly MAX_PHYS_BYTES: number;
|
|
627
|
+
readonly MAX_PHYSICS_OUTPUT_BYTES: number;
|
|
628
|
+
/** The most a physics room's static world holds (§17.10 *The static world*): §17.7's caps, so any world a
|
|
629
|
+
* module may carry has its physics core. `limits.staticPieces` follows a world past its default. */
|
|
630
|
+
readonly MAX_PHYSICS_WORLD_BOXES: 32768;
|
|
631
|
+
readonly MAX_PHYSICS_WORLD_RAMPS: 4096;
|
|
632
|
+
/** `__genex_world()`'s text: base64 of the largest such world, 4 · ⌈(8 + 24 · 32768 + 36 · 4096) / 3⌉. */
|
|
633
|
+
readonly MAX_WORLD_TEXT_CHARS: 1245196;
|
|
634
|
+
};
|
|
635
|
+
/** Every tick rate a module may ask for; 120 only with physics (§17.11). */
|
|
636
|
+
declare const TICK_RATES: readonly TickHz[];
|
|
637
|
+
/** The tick rate only a physics room may run. */
|
|
638
|
+
declare const PHYSICS_ONLY_TICK_HZ: TickHz;
|
|
639
|
+
/** The fastest of {@link TICK_RATES}: an admission at it lets every module run at its own rate. */
|
|
640
|
+
declare const MAX_TICK_HZ: TickHz;
|
|
641
|
+
/** The rate validation and the local server run a module that asks for none at (their admission's
|
|
642
|
+
* `unaskedTickHz`): they admit at {@link MAX_TICK_HZ} so an asked rate stands. In production such a
|
|
643
|
+
* module runs at its admission's rate, the one its publisher declared (§17.4). */
|
|
644
|
+
declare const DEFAULT_TICK_HZ: TickHz;
|
|
645
|
+
/** Why guest output was refused. */
|
|
646
|
+
declare const TickOutFault: {
|
|
647
|
+
readonly NOT_JSON: "not_json";
|
|
648
|
+
readonly TOO_LARGE: "too_large";
|
|
649
|
+
readonly BAD_SHAPE: "bad_shape";
|
|
650
|
+
readonly NON_FINITE: "non_finite";
|
|
651
|
+
readonly OUT_OF_RANGE: "out_of_range";
|
|
652
|
+
readonly BAD_ID: "bad_id";
|
|
653
|
+
readonly DATA_TOO_LARGE: "data_too_large";
|
|
654
|
+
readonly TOO_MANY_ENTITIES: "too_many_entities";
|
|
655
|
+
readonly TOO_MANY_EVENTS: "too_many_events";
|
|
656
|
+
readonly RESERVED_EVENT: "reserved_event";
|
|
657
|
+
readonly BAD_CONFIG: "bad_config";
|
|
658
|
+
/** The module's maps leave a room without a shot world (§17.7 *The shot world*). */
|
|
659
|
+
readonly NO_SHOT_WORLD: "no_shot_world";
|
|
660
|
+
/** More `phys` commands than MAX_PHYS_COMMANDS, or more `physQ` queries than `queriesPerStep`. */
|
|
661
|
+
readonly TOO_MANY_COMMANDS: "too_many_commands";
|
|
662
|
+
};
|
|
663
|
+
type TickOutFault = (typeof TickOutFault)[keyof typeof TickOutFault];
|
|
664
|
+
/**
|
|
665
|
+
* How the host hands one input to the guest on a tick (PROTOCOL.md §17.11 *Input pacing*), which is
|
|
666
|
+
* also how each consumer of an input treats a starved tick's repeat. An input's move axes, aim and
|
|
667
|
+
* buttons are HELD state for the movement preset (it finds a press edge itself, from `mstate`'s
|
|
668
|
+
* jumpHeld, so a held jump never jumps twice); the module's `onInput` hears each real input exactly
|
|
669
|
+
* ONCE (a FIRE, a use, a sequenced command is never repeated). Absent = `STEP`.
|
|
670
|
+
*/
|
|
671
|
+
declare const InputUse: {
|
|
672
|
+
/** A real input: the preset steps it, then `onInput` hears it. */
|
|
673
|
+
readonly STEP: "step";
|
|
674
|
+
/** A starved tick: the preset steps the seat's last real input again; `onInput` never hears it. */
|
|
675
|
+
readonly REPEAT: "repeat";
|
|
676
|
+
/** A late real input a repeat already stepped for: `onInput` hears it (its one-shots happen exactly
|
|
677
|
+
* once), the preset does not step it again. Only an input whose buttons equal those the preset
|
|
678
|
+
* last stepped is absorbed, so no press edge is ever lost or made. */
|
|
679
|
+
readonly ABSORB: "absorb";
|
|
680
|
+
};
|
|
681
|
+
type InputUse = (typeof InputUse)[keyof typeof InputUse];
|
|
682
|
+
/** One input as the host hands it to the guest. `seq` is the host's own count of the seat's inputs
|
|
683
|
+
* fed to the module; `cseq` is the input's CLIENT sequence (Colyseus's `ackSeq` once the host has
|
|
684
|
+
* consumed it: the seat's inputs counted from 1, the number a client keys a predicted projectile
|
|
685
|
+
* by, §17.9). `seen` is the sender's lag-comp snapshot: entity id → [x, y, z] as that player saw it
|
|
686
|
+
* (present only for inputs that match `lagComp.buttons`). `seenPose` rides beside it: entity id →
|
|
687
|
+
* [yaw, duck] as that player saw it, for the entities that faced or ducked otherwise than they do
|
|
688
|
+
* now (`ctx.rewind.pose`); a snapshot without it reads every entity's as the tick began. `use` is how the tick uses it
|
|
689
|
+
* ({@link InputUse}; absent = `step`): a repeat carries the seat's last real input with that
|
|
690
|
+
* input's `seq` and `cseq`, never a `seen`. */
|
|
691
|
+
interface TickInput {
|
|
692
|
+
p: string;
|
|
693
|
+
seq: number;
|
|
694
|
+
cseq: number;
|
|
695
|
+
i: InputData;
|
|
696
|
+
seen?: Record<string, [number, number, number]>;
|
|
697
|
+
seenPose?: Record<string, [number, number]>;
|
|
698
|
+
use?: InputUse;
|
|
699
|
+
/** How many ticks later than its client meant the input is applied (negative: earlier), when its
|
|
700
|
+
* seat sends `tick@1` and the two differ (§17.11 *The input's tick*); absent: 0. */
|
|
701
|
+
lt?: number;
|
|
702
|
+
}
|
|
703
|
+
/** Host → guest, once per tick. In a physics room (§17.10) the `phys*` keys describe the world
|
|
704
|
+
* after the previous tick's step, each present only when non-empty (`physOverflow` only when
|
|
705
|
+
* true). Numbers are the core's float32 values, vectors are z up. */
|
|
706
|
+
interface TickIn {
|
|
707
|
+
t: number;
|
|
708
|
+
dt: number;
|
|
709
|
+
/** Seats that send `tick@1` and step none of their inputs this tick (§17.11 *The input's tick*): a
|
|
710
|
+
* firstperson view on a spinning lift turns with it (the input meant for this tick, a tick late,
|
|
711
|
+
* carries the turn back). Absent when none. */
|
|
712
|
+
vt?: string[];
|
|
713
|
+
joins?: PlayerInfo[];
|
|
714
|
+
leaves?: {
|
|
715
|
+
id: string;
|
|
716
|
+
reason: LeaveReason;
|
|
717
|
+
}[];
|
|
718
|
+
inputs: TickInput[];
|
|
719
|
+
/** [index into the `phys` array the host last applied, C§14 code]; the prelude maps the index to
|
|
720
|
+
* the command's number. */
|
|
721
|
+
physRefused?: [number, PhysicsErrorCode][];
|
|
722
|
+
/** The step's events in C§8.1's order. */
|
|
723
|
+
physEv?: PhysEvRow[];
|
|
724
|
+
physOverflow?: true;
|
|
725
|
+
/** One answer per query of the previous tick's `physQ`, in order. */
|
|
726
|
+
physAns?: PhysAnswerRow[];
|
|
727
|
+
/** Subscribed bodies changed since the previous export, in key order. */
|
|
728
|
+
physBodies?: PhysBodyRow[];
|
|
729
|
+
/** The entities whose module bodies escaped the world; the host removed them. */
|
|
730
|
+
physEsc?: string[];
|
|
731
|
+
}
|
|
732
|
+
/** One changed entity: its id plus only the fields that changed. `data` is JSON text ('' = none). */
|
|
733
|
+
type EntityOut = {
|
|
734
|
+
id: string;
|
|
735
|
+
} & Partial<Omit<EntityData, 'id' | 'data'>> & {
|
|
736
|
+
data?: string;
|
|
737
|
+
};
|
|
738
|
+
/** One game event to clients (all, or the seat `to`). */
|
|
739
|
+
interface EventOut {
|
|
740
|
+
type: string;
|
|
741
|
+
data?: Json;
|
|
742
|
+
to?: string;
|
|
743
|
+
}
|
|
744
|
+
/** One physics command or query in the contract's JSON form (C§7.3, C§13): one key, the verb, to
|
|
745
|
+
* its arguments, exactly as parsed from the guest's text. */
|
|
746
|
+
type PhysCommand = {
|
|
747
|
+
readonly [verb: string]: Json;
|
|
748
|
+
};
|
|
749
|
+
/** Guest → host, once per tick: changed entities, removed ids, events, and in a physics room the
|
|
750
|
+
* tick's physics commands and queries (present only when the room has physics). */
|
|
751
|
+
interface TickOut {
|
|
752
|
+
up: EntityOut[];
|
|
753
|
+
rm: string[];
|
|
754
|
+
ev: EventOut[];
|
|
755
|
+
phys?: PhysCommand[];
|
|
756
|
+
physQ?: PhysCommand[];
|
|
757
|
+
/** Every called lift's start tick (§17.11 *Lifts*), sent after a `ctx.lifts.call` until applied. */
|
|
758
|
+
lifts?: Record<string, number>;
|
|
759
|
+
}
|
|
760
|
+
/** Guest → host from `__genex_init`: the first output plus the config the module resolved. A
|
|
761
|
+
* physics room's carries `phys` (applied at load) and never `physQ`. */
|
|
762
|
+
interface InitOut extends TickOut {
|
|
763
|
+
config: ResolvedModuleConfig;
|
|
764
|
+
/** The names of the module's `worlds` map (§17.2 *Choosing a room*), when it has one. */
|
|
765
|
+
worlds?: string[];
|
|
766
|
+
/** What the load counted of the module's shot world (§17.7 *The shot world*), when it has one. */
|
|
767
|
+
shotWorld?: ShotWorldCount;
|
|
768
|
+
/** How the module's maps leave a room without a shot world: the validator refuses it as `no_shot_world`. */
|
|
769
|
+
noShotWorld?: string;
|
|
770
|
+
}
|
|
771
|
+
/** What the host passes `validateTickOut` in a physics room. */
|
|
772
|
+
interface PhysicsTickIndex {
|
|
773
|
+
/** The world's `queriesPerStep`: `physQ` holds at most this many. */
|
|
774
|
+
readonly queriesPerStep: number;
|
|
775
|
+
/** The module bodies' keys after the previous tick: the body entities, whose host fields (x y z
|
|
776
|
+
* and the body fields) the module may not write and which may not become projectiles. */
|
|
777
|
+
readonly bodies: {
|
|
778
|
+
has(key: string): boolean;
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
/** What the host passes `validateInitOut` for a room admitted with physics: its limit ceiling. */
|
|
782
|
+
interface PhysicsAdmission {
|
|
783
|
+
readonly ceiling: PhysicsCeiling;
|
|
784
|
+
}
|
|
785
|
+
/** The room's current entity ids, as the host holds them (a Set, or the state's MapSchema). With
|
|
786
|
+
* `get` (the state's MapSchema has it), the projectile rules are also checked against the fields an
|
|
787
|
+
* update leaves unchanged: an update that sets `owner` on a projectile is refused like one that
|
|
788
|
+
* launches an owned entity. */
|
|
789
|
+
interface EntityIndex {
|
|
790
|
+
readonly size: number;
|
|
791
|
+
has(id: string): boolean;
|
|
792
|
+
get?(id: string): {
|
|
793
|
+
readonly t0?: number;
|
|
794
|
+
readonly owner?: string;
|
|
795
|
+
} | undefined;
|
|
796
|
+
}
|
|
797
|
+
type WireResult<T> = {
|
|
798
|
+
ok: true;
|
|
799
|
+
value: T;
|
|
800
|
+
} | {
|
|
801
|
+
ok: false;
|
|
802
|
+
fault: TickOutFault;
|
|
803
|
+
path: string;
|
|
804
|
+
};
|
|
805
|
+
/** Sanitizes one raw input into {@link InputData}: axes float32 in [-1, 1] (non-finite → 0),
|
|
806
|
+
* yaw and pitch wrapped to [-π, π) (unusable → 0), buttons an integer mask below 2^24 (else 0). */
|
|
807
|
+
declare function sanitizeInput(raw: Record<string, unknown>): InputData;
|
|
808
|
+
/** Validates one `__genex_tick` result (JSON text, or an already parsed value). With `room`, the
|
|
809
|
+
* room's current entity ids, it also refuses a tick that would leave more than
|
|
810
|
+
* `MAX_ROOM_ENTITIES` entities in the room; the host always passes it. With `physics` (a physics
|
|
811
|
+
* room, §17.10) it reads `phys` and `physQ` and the body-entity rules; without, those keys are
|
|
812
|
+
* unknown and dropped. */
|
|
813
|
+
declare function validateTickOut(raw: unknown, room?: EntityIndex, physics?: PhysicsTickIndex): WireResult<TickOut>;
|
|
814
|
+
declare function validateInitOut(raw: unknown, physics?: PhysicsAdmission): WireResult<InitOut>;
|
|
815
|
+
|
|
816
|
+
/** Repeats owed at most, as time (shared/duration units: ms); {@link repeatMaxTicks} in ticks. */
|
|
817
|
+
declare const INPUT_REPEAT_MAX_MS: 100;
|
|
818
|
+
/** One starve run's repeats at most, as time (ms); {@link repeatRunTicks} in ticks. */
|
|
819
|
+
declare const INPUT_REPEAT_RUN_MS: 33;
|
|
820
|
+
/** {@link INPUT_REPEAT_RUN_MS} in whole ticks at `tickHz`, at least one. */
|
|
821
|
+
declare function repeatRunTicks(tickHz: number): number;
|
|
822
|
+
/** {@link INPUT_REPEAT_MAX_MS} in whole ticks at `tickHz`, at least one. */
|
|
823
|
+
declare function repeatMaxTicks(tickHz: number): number;
|
|
824
|
+
/** One seat's repeats: its last real input, the buttons the preset last stepped, the repeats no later
|
|
825
|
+
* input has paid back (`inRep`), its starve runs since its first input (`inStarve`: a run is starved
|
|
826
|
+
* ticks in a row) and whether the last tick was starved. */
|
|
827
|
+
interface SeatRepeats {
|
|
828
|
+
last: InputData | null;
|
|
829
|
+
steppedButtons: number;
|
|
830
|
+
owed: number;
|
|
831
|
+
starveRuns: number;
|
|
832
|
+
starving: boolean;
|
|
833
|
+
/** Repeats in the current starve run. */
|
|
834
|
+
runRepeats: number;
|
|
835
|
+
/** How many of the seat's latest real inputs in a row are the same held state (the last one counts). */
|
|
836
|
+
steady: number;
|
|
837
|
+
/** Diagnostics for the bench: by `steady` at the repeat (index capped at STEADY_BUCKETS − 1), the
|
|
838
|
+
* absorbed inputs, and those equal to the input their repeat stepped (a repeat that cost nothing). */
|
|
839
|
+
absorbsBySteady: number[];
|
|
840
|
+
exactBySteady: number[];
|
|
841
|
+
/** The input the owed repeats stepped, and the `steady` count they were stepped at. */
|
|
842
|
+
repeated: InputData | null;
|
|
843
|
+
repeatedSteady: number;
|
|
844
|
+
}
|
|
845
|
+
/** A starved seat is repeated only when at least this many of its latest real inputs in a row were
|
|
846
|
+
* alike (a steady stick: two 60 Hz frames' worth at 120 Hz); otherwise it holds, as before. Measured on
|
|
847
|
+
* car-ball (3 runs a profile, every repeat's absorbed input against the input it repeated): with 1-3
|
|
848
|
+
* alike, 0-7% of repeats stood in exactly; with 4 or more, 66-100%. */
|
|
849
|
+
declare const INPUT_REPEAT_STEADY = 4;
|
|
850
|
+
/** Buckets of the diagnostics' `steady` index. */
|
|
851
|
+
declare const STEADY_BUCKETS = 9;
|
|
852
|
+
/** Whether a room with setting `repeat` repeats a seat whose client joined with `caps`: the setting on
|
|
853
|
+
* and the client sent `repeat@1`. Off, the cap is ignored and the seat is paced as one without it. */
|
|
854
|
+
declare function repeatsSeat(repeat: InputRepeat, caps: readonly string[]): boolean;
|
|
855
|
+
/** A seat that has sent nothing yet. */
|
|
856
|
+
declare function seatRepeats(): SeatRepeats;
|
|
857
|
+
/** Two inputs the preset steps alike: every held field equal. */
|
|
858
|
+
declare function sameHeldInput(a: InputData, b: InputData): boolean;
|
|
859
|
+
/** A starved tick: the input the preset steps again (the seat's last real one, held), counted as owed;
|
|
860
|
+
* null when the seat has no input yet, its stick is not steady (fewer than `steadyMin` of its latest
|
|
861
|
+
* inputs in a row alike: a repeat would likely stand in wrongly, so the seat holds as before), this
|
|
862
|
+
* starve run already has `runMax` repeats, or it already owes `maxTicks` (it holds). */
|
|
863
|
+
declare function repeatStarved(seat: SeatRepeats, maxTicks: number, steadyMin?: number, runMax?: number): InputData | null;
|
|
864
|
+
/** Inputs this tick consumes: the pacer's `feed`, plus one more when a repeat is owed and the buffer
|
|
865
|
+
* holds more than `feed` (the late input a repeat stood in for, with one behind it), within `cap`. */
|
|
866
|
+
declare function feedWithPayback(seat: SeatRepeats, feed: number, buffered: number, cap: number): number;
|
|
867
|
+
/** How one consumed input is used, in sequence order; `more`: another input is consumed after it this
|
|
868
|
+
* tick (the tick's last input always steps). Records it as the seat's last real input. */
|
|
869
|
+
declare function consumedUse(seat: SeatRepeats, input: InputData, more: boolean): InputUse;
|
|
870
|
+
/** A new socket for the seat (a reconnect): its inputs count from 1 again and the client re-seeds from
|
|
871
|
+
* the state, so no repeat is owed to it. The last input stays, for the next starve. */
|
|
872
|
+
declare function forgiveRepeats(seat: SeatRepeats): void;
|
|
873
|
+
/**
|
|
874
|
+
* The client's side: the input the state's entity of yours was stepped through, `ack` (Colyseus's
|
|
875
|
+
* `ackSeq`) plus the room's `inRep` for your seat, never past `sent` (a tab that stopped sending while
|
|
876
|
+
* the server repeated for it). A replay from the state replays the inputs after it (your reconciler
|
|
877
|
+
* compares at {@link reconcileThrough}); the seat rule's tick of input `seq` is
|
|
878
|
+
* `tick + (seq − steppedThrough)`. In a room whose setting `repeat` is off, `inRep` is never read: the ack.
|
|
879
|
+
*/
|
|
880
|
+
declare function steppedThrough(ack: number, inRep: number | undefined, sent: number, repeat?: InputRepeat): number;
|
|
881
|
+
/**
|
|
882
|
+
* The input the state holds your entity stepped through: `ack + inRep` (a valid `inRep`, else none),
|
|
883
|
+
* not clamped to `sent` (a hitch steps it past the inputs you sent). In a room whose setting `repeat`
|
|
884
|
+
* is off: the ack. What {@link reconcilerAck} is handed.
|
|
885
|
+
*/
|
|
886
|
+
declare function stateThrough(ack: number, inRep: number | undefined, repeat?: InputRepeat): number;
|
|
887
|
+
/**
|
|
888
|
+
* The input your reconciler compares the state with your prediction at, given the one it compared at
|
|
889
|
+
* last (`held`), §17.11 *The reconciler's ack*, its hitch clause alone: `ack + inRep` once you have sent
|
|
890
|
+
* that input. While the state is stepped past the last input you sent (`ack + inRep > sent`: a hitch
|
|
891
|
+
* drained your seat's buffer and the room repeated for inputs you have not sent yet), no prediction of
|
|
892
|
+
* yours is at the state's input, so the reconcile waits at `held` (never past `sent`) until you send it.
|
|
893
|
+
* Compared at `sent` instead, a held throttle was pulled forward by the repeated steps, then back by as
|
|
894
|
+
* many once the next inputs went out. In a room whose setting `repeat` is off: the ack. A reconciler
|
|
895
|
+
* is told {@link reconcilerAck}, which applies this clause and then the ring's.
|
|
896
|
+
*/
|
|
897
|
+
declare function reconcileThrough(held: number, ack: number, inRep: number | undefined, sent: number, repeat?: InputRepeat): number;
|
|
898
|
+
/** The ack your reconciler was last told and the send count when it began holding one back (null:
|
|
899
|
+
* not holding), §17.11 *The reconciler's ack*. */
|
|
900
|
+
interface ReconcilerAckHold {
|
|
901
|
+
shown: number;
|
|
902
|
+
heldFrom: number | null;
|
|
903
|
+
}
|
|
904
|
+
/** A hold that has told the reconciler nothing yet. */
|
|
905
|
+
declare function reconcilerAckHold(): ReconcilerAckHold;
|
|
906
|
+
/**
|
|
907
|
+
* The ack your reconciler is told (§17.11 *The reconciler's ack*), from the input the state holds your
|
|
908
|
+
* entity stepped through (`through`, {@link stateThrough}: never clamped to `sent`). The hitch clause
|
|
909
|
+
* first: past `sent` it is the ack told last, never past `sent` ({@link reconcileThrough}). Then the
|
|
910
|
+
* ring's: that ack `stepped`, unless it advanced while input `stepped + 1` is in neither the replay ring
|
|
911
|
+
* (`ring` inputs back from `sent`) nor another copy (`kept`: the fast channel's). Then it stays the ack
|
|
912
|
+
* last told, so a state whose ack is still more than a ring behind your sends is not reconciled with its
|
|
913
|
+
* oldest inputs gone; at most a ring's length of sends from the first held ack, after which the
|
|
914
|
+
* reconciler is told `stepped` again and the hold is armed only by an ack within the ring or one that
|
|
915
|
+
* moved back. A hitch neither arms nor ends a hold.
|
|
916
|
+
*/
|
|
917
|
+
declare function reconcilerAck(hold: ReconcilerAckHold, through: number, sent: number, ring: number, kept: boolean): number;
|
|
918
|
+
/** How much faster a throttled client runs while it builds its cushion (a share of real time; RL's
|
|
919
|
+
* simulation time scaling is about 1%). At 3% a tick of lead takes 280 ms to build, and a frame never
|
|
920
|
+
* draws more than 3% of its time ahead of the frame before. */
|
|
921
|
+
declare const THROTTLE_DILATION = 0.03;
|
|
922
|
+
/** A starve with at most this many of the seat's inputs buffered at the keyframe asks the client for
|
|
923
|
+
* one more input of lead; a deeper buffer had the cushion, and the starve was a stall's. */
|
|
924
|
+
declare const THROTTLE_LOW_INPUTS = 1;
|
|
925
|
+
/** The share of the throttle's lead (`aheadMs`, and the part of an extra input still being paid,
|
|
926
|
+
* `accMs`) the other seats are drawn on: 1 draws them on your input clock, as your own car and the
|
|
927
|
+
* ball; 0 on the plain frame clock. Half: on car-ball at 200 ms (14 interleaved runs each), 1 drew other
|
|
928
|
+
* cars ~3 ms further ahead than the base and eased 5% more correction into them (p 0.001), 0 cost the
|
|
929
|
+
* ball (p 0.03); 0.5 kept both within the base (p 0.15, 0.21) and the loss-2 gain on how others see a
|
|
930
|
+
* starving car (hitches p 0.025, lurches p 0.000). */
|
|
931
|
+
declare const THROTTLE_SEAT_LEAD = 0.5;
|
|
932
|
+
/** A client's upstream throttle: the starve runs it has answered, the lead (ms) still to add, and the
|
|
933
|
+
* lead added so far (`aheadMs`: the client's clock runs this far ahead of real time, which whatever is
|
|
934
|
+
* drawn on your input clock adds too, so it never jumps when an extra input goes out). */
|
|
935
|
+
interface InputThrottle {
|
|
936
|
+
seenRuns: number | null;
|
|
937
|
+
owedMs: number;
|
|
938
|
+
accMs: number;
|
|
939
|
+
aheadMs: number;
|
|
940
|
+
}
|
|
941
|
+
/** A throttle that has seen no keyframe yet. */
|
|
942
|
+
declare function inputThrottle(): InputThrottle;
|
|
943
|
+
/** A state's `inStarve` and `inBuf` for your seat: a new starve run with at most THROTTLE_LOW_INPUTS
|
|
944
|
+
* buffered owes one step (`stepMs`) of lead, at most one step owed at a time. The first reading only
|
|
945
|
+
* takes the count. In a room whose setting `repeat` is off no reading is taken: nothing is ever owed. */
|
|
946
|
+
declare function throttleState(t: InputThrottle, inStarve: unknown, inBuf: unknown, stepMs: number, repeat?: InputRepeat): void;
|
|
947
|
+
/** The input clock other seats are drawn on (§17.11 *Input pacing*): the input `stepped` your entity
|
|
948
|
+
* in the state was stepped through, plus `drawn` inputs past it where your entity is drawn, plus
|
|
949
|
+
* THROTTLE_SEAT_LEAD of the throttle's part-paid extra input (`raw`), at THROTTLE_SEAT_LEAD of its lead
|
|
950
|
+
* past the frame's instant (`at`). */
|
|
951
|
+
declare function seatLeadClock(stepped: number, drawn: number, t: InputThrottle, stepMs: number, frameNow: number): {
|
|
952
|
+
raw: number;
|
|
953
|
+
at: number;
|
|
954
|
+
};
|
|
955
|
+
/** A frame `dtMs` long: the extra inputs it sends (0 or more), the owed lead paid THROTTLE_DILATION of
|
|
956
|
+
* real time at a time, each input sent once half of its step has been paid. */
|
|
957
|
+
declare function throttleSteps(t: InputThrottle, dtMs: number, stepMs: number): number;
|
|
958
|
+
|
|
959
|
+
/** The walk, and what it may cost. */
|
|
960
|
+
declare const WorldCost: {
|
|
961
|
+
/** What a step may average, in weighted operations: below the least count of any world that ended a room, ten seats on a c2-standard-4
|
|
962
|
+
* (micro 8,192 at 5,318, one run of two: integration cw/vm1). A warning to a creator, and a coarse one: bodies are walked from seeded
|
|
963
|
+
* solids, so a world that holds its cost where its module really spawns seats reads low (a cell 2.5 times, dense tiles 3), and one built to
|
|
964
|
+
* dodge the walk reads nothing. The sandbox's mean budget and CPU limits are what protect a host. */
|
|
965
|
+
readonly MAX_OPS_PER_STEP: 5000;
|
|
966
|
+
/** What each kind of operation costs against a tree entry, c2-standard-4, offline: an entry 4.9 ns, an exact test 36, a wedge's sweep test
|
|
967
|
+
* 382. A slab's sweep test has no weight of its own: it comes with exact tests in every world measured, three to one. */
|
|
968
|
+
readonly TEST_WEIGHT: 7;
|
|
969
|
+
readonly WEDGE_WEIGHT: 78;
|
|
970
|
+
/** The seats {@link WorldCost.MAX_OPS_PER_STEP} is sized for. */
|
|
971
|
+
readonly SEATS: 10;
|
|
972
|
+
/** Bodies walking, and the ticks each walks. */
|
|
973
|
+
readonly WALKERS: 16;
|
|
974
|
+
readonly TICKS: 120;
|
|
975
|
+
readonly SEED: 2026;
|
|
976
|
+
/** The step's dt: 30 Hz, the rate most rooms run. */
|
|
977
|
+
readonly DT: number;
|
|
978
|
+
/** Where a body starts above the top of the solid it is dropped on. */
|
|
979
|
+
readonly DROP: 1;
|
|
980
|
+
/** A body's chance a tick to turn, jump and duck. */
|
|
981
|
+
readonly TURN_CHANCE: 0.03;
|
|
982
|
+
readonly JUMP_CHANCE: 0.04;
|
|
983
|
+
readonly DUCK_CHANCE: 0.05;
|
|
984
|
+
};
|
|
985
|
+
/** What {@link worldCost} counted. */
|
|
986
|
+
interface WorldCostReport extends WorldCostMeter {
|
|
987
|
+
solids: number;
|
|
988
|
+
/** Steps walked. */
|
|
989
|
+
steps: number;
|
|
990
|
+
/** The operations, weighted by kind, a step on average, rounded down. */
|
|
991
|
+
opsPerStep: number;
|
|
992
|
+
/** Whether `opsPerStep` is within {@link WorldCost.MAX_OPS_PER_STEP}. */
|
|
993
|
+
accepted: boolean;
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* The cost of `spec` to a room of `preset` (firstperson's or vehicle's), with `params` as the module gives
|
|
997
|
+
* them. Bodies start on seeded solids, so a world cannot hide its dense part behind where it says bodies
|
|
998
|
+
* spawn, and a solid is as likely a start as any: where a bake spent its solids is where the bodies are.
|
|
999
|
+
*/
|
|
1000
|
+
declare function worldCost(spec: unknown, preset?: PresetName, params?: unknown): WorldCostReport;
|
|
1001
|
+
|
|
1002
|
+
/** The bounds of §17.2 *Choosing a room*. */
|
|
1003
|
+
declare const AuthorityRoomLimits: {
|
|
1004
|
+
/** A match key's longest length. */
|
|
1005
|
+
readonly MAX_MATCH_KEY_CHARS: 32;
|
|
1006
|
+
/** A room code's longest length (Colyseus's room ids are 9). */
|
|
1007
|
+
readonly MAX_CODE_CHARS: 32;
|
|
1008
|
+
/** The most named worlds one module's `worlds` map may hold. */
|
|
1009
|
+
readonly MAX_WORLDS: 16;
|
|
1010
|
+
};
|
|
1011
|
+
/** Whether `value` is a match key: 1 to 32 characters of a-z 0-9 . _ : -, a letter or digit first. */
|
|
1012
|
+
declare function validMatchKey(value: unknown): value is string;
|
|
1013
|
+
/** Whether `value` is a room code: 1 to 32 characters of A-Z a-z 0-9 _ -. A code goes into a url. */
|
|
1014
|
+
declare function validRoomCode(value: unknown): value is string;
|
|
1015
|
+
/** A join's `matchKey` option as the pool it names: '' for no key (absent or empty), null when it is
|
|
1016
|
+
* malformed (refused with 400). */
|
|
1017
|
+
declare function matchKeyOf(value: unknown): string | null;
|
|
1018
|
+
/** The ways into an authority room, by the Colyseus call that makes them. */
|
|
1019
|
+
declare const AuthorityJoinMethod: {
|
|
1020
|
+
readonly JoinOrCreate: "joinOrCreate";
|
|
1021
|
+
readonly Create: "create";
|
|
1022
|
+
readonly JoinById: "joinById";
|
|
1023
|
+
};
|
|
1024
|
+
type AuthorityJoinMethod = (typeof AuthorityJoinMethod)[keyof typeof AuthorityJoinMethod];
|
|
1025
|
+
/** Why a client refuses a target before anything reaches the network. */
|
|
1026
|
+
declare const AuthorityTargetRefusal: {
|
|
1027
|
+
readonly BadMatchKey: "bad_match_key";
|
|
1028
|
+
readonly BadCode: "bad_code";
|
|
1029
|
+
readonly Conflict: "conflict";
|
|
1030
|
+
};
|
|
1031
|
+
type AuthorityTargetRefusal = (typeof AuthorityTargetRefusal)[keyof typeof AuthorityTargetRefusal];
|
|
1032
|
+
/** Which room a client asks for: a pool (`matchKey`), a new private room, or a room by its code. */
|
|
1033
|
+
interface AuthorityRoomTarget {
|
|
1034
|
+
/** The pool to join, or the key of the private room to create. */
|
|
1035
|
+
matchKey?: string;
|
|
1036
|
+
/** Create a private room. */
|
|
1037
|
+
createPrivate?: boolean;
|
|
1038
|
+
/** Join the room with this code. */
|
|
1039
|
+
code?: string;
|
|
1040
|
+
}
|
|
1041
|
+
/** The Colyseus call a target makes, and the options it adds to the join's own. */
|
|
1042
|
+
type AuthorityJoinPlan = {
|
|
1043
|
+
method: AuthorityJoinMethod;
|
|
1044
|
+
roomId?: string;
|
|
1045
|
+
options: {
|
|
1046
|
+
matchKey?: string;
|
|
1047
|
+
private?: true;
|
|
1048
|
+
successorOf?: string;
|
|
1049
|
+
successorClosed?: true;
|
|
1050
|
+
};
|
|
1051
|
+
} | {
|
|
1052
|
+
refused: AuthorityTargetRefusal;
|
|
1053
|
+
};
|
|
1054
|
+
/** What `target` sends. Nothing asked sends nothing new, so a game that names no room joins as it
|
|
1055
|
+
* always has. A code names one room, whose key is its own: a key or a create beside it is a mistake. */
|
|
1056
|
+
declare function planAuthorityJoin(target: AuthorityRoomTarget): AuthorityJoinPlan;
|
|
1057
|
+
/** The region a join by code tries after refusal `error` on region `region` of `regions`, or null
|
|
1058
|
+
* when the refusal is final: only another region can hold a room this one refused as elsewhere. */
|
|
1059
|
+
declare function nextCodeRegion(error: unknown, region: number, regions: number): number | null;
|
|
1060
|
+
/** The world a room with match key `key` runs, as the sandbox picks it: the `worlds` entry the key
|
|
1061
|
+
* names, else `world` (absent: the empty world). A client calls this with the module's own map and
|
|
1062
|
+
* hands the result to `setWorld`, so its hash is the room's and prediction runs. */
|
|
1063
|
+
declare function selectMatchWorld<W>(worlds: Readonly<Record<string, W>> | undefined, world: W | undefined, key: string): W | undefined;
|
|
1064
|
+
|
|
1065
|
+
/** What `physicsPrediction` reports. */
|
|
1066
|
+
interface PhysicsPredictionStatus {
|
|
1067
|
+
status: PredictStatus;
|
|
1068
|
+
/** Keyframes adopted by skip-on-match and by replay. */
|
|
1069
|
+
matched: number;
|
|
1070
|
+
replayed: number;
|
|
1071
|
+
/** The slowest replay and the latest, ms (wall clock around one adoption's rebuild and replay). */
|
|
1072
|
+
peakResimMs: number;
|
|
1073
|
+
lastResimMs: number;
|
|
1074
|
+
/** Replays longer than RESIM_FRAME_MS: each held a 60 Hz frame back. */
|
|
1075
|
+
slowResims: number;
|
|
1076
|
+
/** How many times the replay budget turned prediction off (`cpu`), and on again. */
|
|
1077
|
+
fallbacks: number;
|
|
1078
|
+
recoveries: number;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
/** Largest launch tick (`t0` is an integer in [0, MAX_PROJECTILE_TICK]; 0 = not a projectile). */
|
|
1082
|
+
declare const MAX_PROJECTILE_TICK: number;
|
|
1083
|
+
/** Largest downward acceleration a projectile may carry, units/s² (`g` is in [0, MAX_PROJECTILE_G]). */
|
|
1084
|
+
declare const MAX_PROJECTILE_G = 1000;
|
|
1085
|
+
/** What a launch writes: the entity's float32 pose and velocity, its gravity and its launch tick. */
|
|
1086
|
+
interface ProjectileLaunch {
|
|
1087
|
+
x: number;
|
|
1088
|
+
y: number;
|
|
1089
|
+
z: number;
|
|
1090
|
+
vx: number;
|
|
1091
|
+
vy: number;
|
|
1092
|
+
vz: number;
|
|
1093
|
+
/** Downward acceleration along −z, units/s². */
|
|
1094
|
+
g: number;
|
|
1095
|
+
/** The launch tick. */
|
|
1096
|
+
t0: number;
|
|
1097
|
+
}
|
|
1098
|
+
/** A projectile at one instant. */
|
|
1099
|
+
interface ProjectileState {
|
|
1100
|
+
x: number;
|
|
1101
|
+
y: number;
|
|
1102
|
+
z: number;
|
|
1103
|
+
vx: number;
|
|
1104
|
+
vy: number;
|
|
1105
|
+
vz: number;
|
|
1106
|
+
}
|
|
1107
|
+
/** Whether an entity is a projectile: its launch tick is set (§17.9 `t0 > 0`). */
|
|
1108
|
+
declare const isProjectile: (entity: {
|
|
1109
|
+
t0?: unknown;
|
|
1110
|
+
}) => boolean;
|
|
1111
|
+
/**
|
|
1112
|
+
* Where a projectile launched as `launch` is at tick `T` (whole or fractional), in a room at
|
|
1113
|
+
* `tickHz`. Pure; float64 in the written order:
|
|
1114
|
+
* 1. s = (T − t0) / tickHz; non-finite or negative → 0 (before its launch it sits at its origin);
|
|
1115
|
+
* 2. x' = fround(x + vx·s), y' = fround(y + vy·s);
|
|
1116
|
+
* 3. z' = fround(((z + (vz·s)) − (((0.5·g)·s)·s)));
|
|
1117
|
+
* 4. vx' = vx, vy' = vy, vz' = fround(vz − g·s);
|
|
1118
|
+
* 5. a −0 result is written as 0.
|
|
1119
|
+
*/
|
|
1120
|
+
declare function projectileAt(launch: ProjectileLaunch, T: number, tickHz: number): ProjectileState;
|
|
1121
|
+
/** The room's tick at server time `serverNowMs` (the room clock, ms): `(serverNow − tickOrigin) ·
|
|
1122
|
+
* tickHz / 1000`, fractional. `tickOrigin` is `AuthorityRoomState.tickOrigin`. */
|
|
1123
|
+
declare function serverTick(serverNowMs: number, tickOrigin: number, tickHz: number): number;
|
|
1124
|
+
/** Tick `tick`'s nominal instant on the room clock, ms: `tickOrigin + tick · 1000 / tickHz`. */
|
|
1125
|
+
declare function tickInstant(tick: number, tickOrigin: number, tickHz: number): number;
|
|
1126
|
+
|
|
1127
|
+
/** A 3-vector, room units. */
|
|
1128
|
+
type V3 = readonly [number, number, number];
|
|
1129
|
+
/** One face of a grown solid: a point p is inside it when `n · p < e` (n of unit length). */
|
|
1130
|
+
type Plane = readonly [number, number, number, number];
|
|
1131
|
+
/**
|
|
1132
|
+
* A world compiled for one hull: every solid grown by it, and the clearance kept from a surface. Flat, so a
|
|
1133
|
+
* large world costs its numbers and no objects: `bounds` holds each solid's six (the grown footprint and
|
|
1134
|
+
* height: min x y z, max x y z; a ramp's box is its bound), boxes first. A box's six planes follow from
|
|
1135
|
+
* its bounds (see {@link planeInto}); a ramp's seven are in `rampPlanes`, four numbers each, the bottom last.
|
|
1136
|
+
*/
|
|
1137
|
+
interface ContactWorld {
|
|
1138
|
+
/** Solids, and how many of them are boxes. */
|
|
1139
|
+
readonly count: number;
|
|
1140
|
+
readonly boxCount: number;
|
|
1141
|
+
readonly bounds: Float64Array;
|
|
1142
|
+
readonly rampPlanes: Float64Array;
|
|
1143
|
+
/** A point is inside a solid only when it is more than this inside every plane (the preset's skin). */
|
|
1144
|
+
readonly skin: number;
|
|
1145
|
+
/** The solids by where they stand (compileContactWorld's; none: a query visits every solid). */
|
|
1146
|
+
readonly grid?: SolidGrid;
|
|
1147
|
+
}
|
|
1148
|
+
/**
|
|
1149
|
+
* A compiled world's solids on an x/y grid, so a cast or a point query visits the solids whose footprint
|
|
1150
|
+
* it can reach rather than every one (a dust2 map's 1500, about 0.5 ms a cast in QuickJS): cell (i, j) covers
|
|
1151
|
+
* [x0 + i·size, x0 + (i + 1)·size) on x (the edge cells reach on to the world's ends), and holds every
|
|
1152
|
+
* solid whose bounds grown by castWorld's margin meet it, ascending; a solid on more than GRID_WIDE
|
|
1153
|
+
* cells is on `wide` alone, which every query visits. Only where a cast visits solids changes, never
|
|
1154
|
+
* what it meets: a solid none of the cast's cells holds fails its bounds test at every length.
|
|
1155
|
+
*/
|
|
1156
|
+
interface SolidGrid {
|
|
1157
|
+
readonly x0: number;
|
|
1158
|
+
readonly y0: number;
|
|
1159
|
+
readonly size: number;
|
|
1160
|
+
readonly nx: number;
|
|
1161
|
+
readonly ny: number;
|
|
1162
|
+
/** Cell (i, j) is c = i + j·nx: its solids' indices are `cellSolids` from `cellStart[c]` up to
|
|
1163
|
+
* `cellStart[c + 1]`, ascending. */
|
|
1164
|
+
readonly cellStart: Int32Array;
|
|
1165
|
+
readonly cellSolids: Int32Array;
|
|
1166
|
+
/** The solids too wide for the cells (a floor, a map-long wall), ascending. */
|
|
1167
|
+
readonly wide: Int32Array;
|
|
1168
|
+
/** Each cell's solids and the wide ones as one list, kept once a query has asked for it: most queries are one cell's, and ask again. */
|
|
1169
|
+
readonly merged: (ArrayLike<number> | undefined)[];
|
|
1170
|
+
}
|
|
1171
|
+
/** A static world as a module gives it (§17.7): boxes `[x0 y0 z0 x1 y1 z1]`, then ramps
|
|
1172
|
+
* `[x0 y0 z0 x1 y1 z1 axis lo hi]`. */
|
|
1173
|
+
interface ContactWorldSpec {
|
|
1174
|
+
readonly boxes?: readonly (readonly number[])[];
|
|
1175
|
+
readonly ramps?: readonly (readonly number[])[];
|
|
1176
|
+
}
|
|
1177
|
+
/** Solids one push-out may move a body out of in turn (a corner is two walls and the floor). */
|
|
1178
|
+
declare const UNSTICK_SOLIDS = 4;
|
|
1179
|
+
/**
|
|
1180
|
+
* The world `spec` grown by a hull of half side `r` and height `h` (§17.7's `slab` and `wedge`): boxes
|
|
1181
|
+
* first, then ramps, each solid's bottom face last. A point closer than `skin` to a face is outside.
|
|
1182
|
+
*/
|
|
1183
|
+
declare function compileContactWorld(spec: ContactWorldSpec | null | undefined, r: number, h: number, skin: number): ContactWorld;
|
|
1184
|
+
/** Whether (x, y, z) is inside any solid of `world`. */
|
|
1185
|
+
declare function insideWorld(world: ContactWorld, x: number, y: number, z: number): boolean;
|
|
1186
|
+
/** Where a line first enters a solid: the distance along it and the face it crosses. */
|
|
1187
|
+
interface CastHit {
|
|
1188
|
+
t: number;
|
|
1189
|
+
face: Plane | null;
|
|
1190
|
+
}
|
|
1191
|
+
/** Faces a cast passes through: the surface a seat rides (its preset follows it), never a wall. */
|
|
1192
|
+
type FaceFilter = (face: Plane) => boolean;
|
|
1193
|
+
/** The faces a body whose support up is `up` rides: ground (a face whose z is at least `cos`, one a
|
|
1194
|
+
* body can stand on) within `cos` of its up. A wall is never ridden: it always stops a push. */
|
|
1195
|
+
declare const ridesOn: (up: V3, cos: number) => FaceFilter;
|
|
1196
|
+
/**
|
|
1197
|
+
* The first solid of `world` the segment from `p` along unit `d` meets within `len`: the distance to
|
|
1198
|
+
* where it comes within skin of it, and that face; `{ t: len, face: null }` when it is clear. Solids are
|
|
1199
|
+
* visited in order; a tie keeps the earlier. A solid `p` is already inside is skipped (the push-out, not
|
|
1200
|
+
* the cast, takes a body out of it), and so is one the segment would enter through a face `rides` passes.
|
|
1201
|
+
*/
|
|
1202
|
+
declare function castWorld(world: ContactWorld, p: V3, d: V3, len: number, rides?: FaceFilter): CastHit;
|
|
1203
|
+
/** How far a body's base at `p` can move along unit `d` before a grown solid, clamped to [0, len];
|
|
1204
|
+
* faces `rides` passes (the surface it rides) do not stop it. */
|
|
1205
|
+
declare function roomAlong(world: ContactWorld | null, p: V3, d: V3, len: number, rides?: FaceFilter): number;
|
|
1206
|
+
/**
|
|
1207
|
+
* The support up of a body whose base is at (x, y, z) (§17.11 *Contact policy* step 1): the normal of
|
|
1208
|
+
* the first face a cast straight down meets within `trace` (a ramp's top, a box's top), else world up
|
|
1209
|
+
* (in the air). A cast starting inside a solid ignores that solid.
|
|
1210
|
+
*/
|
|
1211
|
+
declare function surfaceUp(world: ContactWorld | null, x: number, y: number, z: number, trace: number): V3;
|
|
1212
|
+
/** The face a body at (x, y, z) is pushed out of the first solid it is inside through (§17.7
|
|
1213
|
+
* *Starting inside*), as [nx, ny, nz, depth]; null when it is clear. */
|
|
1214
|
+
declare function insideFace(world: ContactWorld, x: number, y: number, z: number): Plane | null;
|
|
1215
|
+
/** A body's base the contacts left inside the world, pushed back out with the skin's clearance (x y z
|
|
1216
|
+
* changed in place), up to UNSTICK_SOLIDS solids in turn; returns the deepest push (0: it was clear).
|
|
1217
|
+
* `onFace` hears each face it is pushed out through, with the depth. */
|
|
1218
|
+
declare function unstickBody(world: ContactWorld, body: {
|
|
1219
|
+
x: number;
|
|
1220
|
+
y: number;
|
|
1221
|
+
z: number;
|
|
1222
|
+
}, onFace?: (face: Plane) => void): number;
|
|
1223
|
+
|
|
1224
|
+
/** A lift's pose at a tick: its centre and yaw (float32). */
|
|
1225
|
+
interface LiftPose {
|
|
1226
|
+
readonly c: LiftVec;
|
|
1227
|
+
readonly yaw: number;
|
|
1228
|
+
}
|
|
1229
|
+
/** Lift `lift`'s pose at `tick`; `start` is a called lift's call tick (undefined: not called). */
|
|
1230
|
+
declare function liftPose(lift: Lift, tick: number, start?: number): LiftPose;
|
|
1231
|
+
/** Every lift's pose at `tick`, in declared order; `starts` holds called lifts' call ticks by id. */
|
|
1232
|
+
declare function liftPoses(policy: LiftsPolicy, tick: number, starts?: ReadonlyMap<string, number>): LiftPose[];
|
|
1233
|
+
/** A lift's turn per tick (0 for none). */
|
|
1234
|
+
declare const spinStep: (lift: Lift) => number;
|
|
1235
|
+
/** A firstperson view on lift `lift` applied `lag` ticks later than its client meant (`inputTickLag`,
|
|
1236
|
+
* §17.11 *The input's tick*): the view `yaw` carried by the lift's turn over those ticks, float32. */
|
|
1237
|
+
declare const viewOnLift: (lift: Lift, yaw: number, lag: number) => number;
|
|
1238
|
+
/** A rider's pose as the carry reads and writes it (float64; the caller writes float32). */
|
|
1239
|
+
interface RiderPose {
|
|
1240
|
+
readonly x: number;
|
|
1241
|
+
readonly y: number;
|
|
1242
|
+
readonly z: number;
|
|
1243
|
+
readonly yaw: number;
|
|
1244
|
+
}
|
|
1245
|
+
/** A carried rider: its pose at the next tick and its point's velocity over the tick (u/s). */
|
|
1246
|
+
interface Carried extends RiderPose {
|
|
1247
|
+
readonly v: LiftVec;
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* The carry of a rider on `lift` from `tick` to `tick + 1` (§17.11 *Lifts*, the carry slot): turned by
|
|
1251
|
+
* the lift's spin about its centre, moved with the centre, then by a conveyor's surface velocity in the
|
|
1252
|
+
* lift's frame at `tick + 1` over one tick; its yaw turned with the spin. `v` is the point's move over
|
|
1253
|
+
* the tick: what a rider keeps on leaving (`impart: all`).
|
|
1254
|
+
*/
|
|
1255
|
+
declare function carryOnLift(lift: Lift, rider: RiderPose, tick: number, tickHz: number, start?: number): Carried;
|
|
1256
|
+
/** Every lift as a posed solid (§17.7 *Posed solids*) at the poses given (`liftPoses` at a tick), in
|
|
1257
|
+
* declared order: a box that never spins is axis-aligned, one that spins an `obox`, a disc a disc. */
|
|
1258
|
+
declare function posedSolids(policy: LiftsPolicy, poses: readonly LiftPose[]): PosedSolid[];
|
|
1259
|
+
/** A seat as the slots read and write it (float32 writes). */
|
|
1260
|
+
interface LiftSeat extends HullBody {
|
|
1261
|
+
readonly id: string;
|
|
1262
|
+
x: number;
|
|
1263
|
+
y: number;
|
|
1264
|
+
z: number;
|
|
1265
|
+
vx: number;
|
|
1266
|
+
vy: number;
|
|
1267
|
+
vz: number;
|
|
1268
|
+
yaw: number;
|
|
1269
|
+
/** Its contact tags and flags (the pair rules match them), for the head slabs. */
|
|
1270
|
+
readonly tags?: readonly string[];
|
|
1271
|
+
readonly flags?: number;
|
|
1272
|
+
}
|
|
1273
|
+
/** A room's contact policy, for the slots' head slabs and the carry by a lower seat (§17.11 step 6
|
|
1274
|
+
* `stand` with `ride`). */
|
|
1275
|
+
interface HeadsContext {
|
|
1276
|
+
readonly policy: ContactPolicy;
|
|
1277
|
+
readonly env: ContactEnv;
|
|
1278
|
+
}
|
|
1279
|
+
/** Riders carried through a chain of seats at most (a seat on a seat on a seat on a lift). */
|
|
1280
|
+
declare const RIDE_CHAIN_MAX = 4;
|
|
1281
|
+
/** What the carry slot did: each seat's lift at the tick's start (−1 none) and its carry's velocity,
|
|
1282
|
+
* the seats a lift crushed against the world, and each seat's place as the slot left it. */
|
|
1283
|
+
interface CarryReport {
|
|
1284
|
+
readonly bases: readonly number[];
|
|
1285
|
+
/** The seat each rides at the tick's start (its pair rule `stand` with `ride`), else null. */
|
|
1286
|
+
readonly on: readonly (string | null)[];
|
|
1287
|
+
readonly v: readonly (LiftVec | null)[];
|
|
1288
|
+
readonly crushed: readonly {
|
|
1289
|
+
seat: string;
|
|
1290
|
+
lift: string;
|
|
1291
|
+
}[];
|
|
1292
|
+
/** Each seat's x y z after the carry slot: the ride slot reads a ridden seat's walk from it. */
|
|
1293
|
+
readonly from: readonly LiftVec[];
|
|
1294
|
+
}
|
|
1295
|
+
/** A tick's lifts as posed solids at its start (`tick`) and its end (`tick + 1`): computed once a tick
|
|
1296
|
+
* and handed to both slots and the inputs' steps. */
|
|
1297
|
+
interface TickSolids {
|
|
1298
|
+
readonly now: readonly PosedSolid[];
|
|
1299
|
+
readonly next: readonly PosedSolid[];
|
|
1300
|
+
}
|
|
1301
|
+
/** The lifts posed at `tick` and `tick + 1`. */
|
|
1302
|
+
declare function tickSolids(policy: LiftsPolicy, tick: number, starts?: ReadonlyMap<string, number>): TickSolids;
|
|
1303
|
+
/**
|
|
1304
|
+
* The carry slot of tick `tick`, before its inputs (§17.11 *Lifts*), on `seats` in their order (ids
|
|
1305
|
+
* ascending), each changed in place, every support and carry read from the seats as they were:
|
|
1306
|
+
* 1. its support: the lift it stands on among the lifts posed at `tick` (`ops.support`), or, with
|
|
1307
|
+
* `heads`, the seat whose head slab it stands on (ridden when their pair rule is `stand` with `ride`);
|
|
1308
|
+
* 2. on lift L: carried by L to `tick + 1` (`carryOnLift`; a vehicle's yaw, `turnYaw`, turned with it);
|
|
1309
|
+
* riding seat S: by S's carry, a chain base first (S's walk this tick follows in `rideSlot`, after
|
|
1310
|
+
* the steps);
|
|
1311
|
+
* 3. every other lift it is inside at `tick + 1`, in order: moved by that lift's move at its point,
|
|
1312
|
+
* then pushed out (`ops.pushOut`); still inside a solid: crushed by that lift.
|
|
1313
|
+
* Writes x y z (yaw) as float32; the report's `from` is each seat's place as the slot left it.
|
|
1314
|
+
*/
|
|
1315
|
+
declare function carrySlot(policy: LiftsPolicy, seats: LiftSeat[], tick: number, tickHz: number, starts: ReadonlyMap<string, number> | undefined, ops: HullOps, turnYaw: boolean, posed?: TickSolids, heads?: HeadsContext): CarryReport;
|
|
1316
|
+
/**
|
|
1317
|
+
* The ride slot of a tick, after its inputs' steps and before its contact pass (§17.11 *Lifts*): a seat
|
|
1318
|
+
* riding seat S (`report.on`) is moved in x y by S's walk this tick (S's place now less its place after
|
|
1319
|
+
* the carry slot, `report.from`: every step S's inputs took, none on a held starve) and by S's own ride,
|
|
1320
|
+
* base first, RIDE_CHAIN_MAX deep, so it keeps its place on S's head (no lag at a start or a stop). Its
|
|
1321
|
+
* carry's velocity gains that move (what it keeps on leaving S). `seats` are the carry slot's, in its
|
|
1322
|
+
* order, changed in place (x y as float32); returns the report with the riders' velocities.
|
|
1323
|
+
*/
|
|
1324
|
+
declare function rideSlot(seats: LiftSeat[], report: CarryReport, tickHz: number): CarryReport;
|
|
1325
|
+
/**
|
|
1326
|
+
* The impart slot of tick `tick`, after its contact pass: a seat that stood on lift L at the tick's
|
|
1327
|
+
* start (`report.bases`) and no longer stands on it among the lifts posed at `tick + 1` keeps L's
|
|
1328
|
+
* velocity at its point (`report.v`) when L imparts (`impart: all`); a seat that rode seat S
|
|
1329
|
+
* (`report.on`) and no longer stands on S's head keeps its carry's velocity. Writes vx vy vz as float32.
|
|
1330
|
+
*/
|
|
1331
|
+
declare function impartSlot(policy: LiftsPolicy, seats: LiftSeat[], report: CarryReport, tick: number, starts: ReadonlyMap<string, number> | undefined, ops: HullOps, next?: readonly PosedSolid[], heads?: HeadsContext): void;
|
|
1332
|
+
|
|
1333
|
+
/** A room's lifts as this client runs them: the policy (NO_LIFTS with heads only), the preset's hull
|
|
1334
|
+
* through this client's world, the heads (a declared policy with a stand rule) and the tick rate. */
|
|
1335
|
+
interface SeatLifts {
|
|
1336
|
+
readonly policy: LiftsPolicy;
|
|
1337
|
+
readonly ops: HullOps;
|
|
1338
|
+
readonly vehicle: boolean;
|
|
1339
|
+
readonly heads: HeadsContext | undefined;
|
|
1340
|
+
readonly tickHz: number;
|
|
1341
|
+
}
|
|
1342
|
+
/** The lifts the room's preset text declares (`{ name, params, lifts }`) and its heads, through
|
|
1343
|
+
* `world`; null when it has neither, or its preset carries no hull (topdown). */
|
|
1344
|
+
declare function seatLiftsOf(presetText: string, world: FirstpersonWorld, heads: HeadsContext | undefined, tickHz: number): SeatLifts | null;
|
|
1345
|
+
/** The called lifts' starts the state's `lifts` text holds (`{"id":tick,…}`), or undefined. */
|
|
1346
|
+
declare function liftStartsOf(text: string | undefined): ReadonlyMap<string, number> | undefined;
|
|
1347
|
+
/** One tick of the slots as a predicted step runs it: the lifts at its start and end, the carry's
|
|
1348
|
+
* report (the ride slot's once it ran), the seats (ids ascending) as the carry left them, and each
|
|
1349
|
+
* seat's posed world. */
|
|
1350
|
+
interface LiftTick {
|
|
1351
|
+
readonly tick: number;
|
|
1352
|
+
readonly solids: TickSolids;
|
|
1353
|
+
report: CarryReport;
|
|
1354
|
+
readonly seats: LiftSeat[];
|
|
1355
|
+
/** Seat id → the posed world its step runs through (the lifts at t + 1 and its head slabs). */
|
|
1356
|
+
readonly posed: ReadonlyMap<string, PosedWorld>;
|
|
1357
|
+
/** The lifts at t + 1 alone, for a seat with no head slab. */
|
|
1358
|
+
readonly next: PosedWorld;
|
|
1359
|
+
}
|
|
1360
|
+
/** A client's compiled lifts by tick, for one set of starts. */
|
|
1361
|
+
declare class LiftSolidsCache {
|
|
1362
|
+
private readonly kept;
|
|
1363
|
+
private startsText;
|
|
1364
|
+
/** Tick `tick`'s lifts at its start and end, and those at its end compiled for a step. */
|
|
1365
|
+
at(policy: LiftsPolicy, tick: number, starts: ReadonlyMap<string, number> | undefined): {
|
|
1366
|
+
solids: TickSolids;
|
|
1367
|
+
next: PosedWorld;
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
/**
|
|
1371
|
+
* The carry slot of tick `tick` on `seats` (ids ascending, changed in place, as float32), then each
|
|
1372
|
+
* seat's posed world for its input step: the lifts posed at `tick + 1` and, with heads, its head slabs
|
|
1373
|
+
* from the seats as the carry left them at their place plus velocity over `dt` (§17.11 *Lifts*, the
|
|
1374
|
+
* host's carryLifts).
|
|
1375
|
+
*/
|
|
1376
|
+
declare function carryTick(l: SeatLifts, seats: LiftSeat[], tick: number, starts: ReadonlyMap<string, number> | undefined, dt: number, cache: LiftSolidsCache): LiftTick;
|
|
1377
|
+
/** The ride slot of tick `t` (after the steps, before the contacts) on its seats, their places set to
|
|
1378
|
+
* where the steps left them (changed in place); its report becomes the ride slot's. */
|
|
1379
|
+
declare function rideTick(l: SeatLifts, t: LiftTick): void;
|
|
1380
|
+
/** Seat `k` of tick `t` moved by `move` (x y) in a ride slot run elsewhere (your seat: the seat
|
|
1381
|
+
* prediction runs the slot with the other seats): its carry's velocity gains the move over the tick. */
|
|
1382
|
+
declare function rodeBy(l: SeatLifts, t: LiftTick, k: number, move: readonly [number, number]): void;
|
|
1383
|
+
/** The posed world seat `id` steps through in tick `t`. */
|
|
1384
|
+
declare const posedFor: (t: LiftTick, id: string) => PosedWorld;
|
|
1385
|
+
/** The impart slot of tick `t` on its seats as they are after the contacts (changed in place). */
|
|
1386
|
+
declare function impartTick(l: SeatLifts, t: LiftTick, starts: ReadonlyMap<string, number> | undefined): void;
|
|
1387
|
+
/** Every lift's pose at fractional tick `f`: between the poses at its two ticks (a spin the short way,
|
|
1388
|
+
* its yaw unwrapped by the turn of one tick). */
|
|
1389
|
+
declare function liftPosesAt(policy: LiftsPolicy, f: number, starts: ReadonlyMap<string, number> | undefined): LiftPose[];
|
|
1390
|
+
/** The lift (its index) a hull drawn at `p` stands on at fractional tick `f`, else −1. */
|
|
1391
|
+
declare function liftUnder(l: SeatLifts, p: {
|
|
1392
|
+
x: number;
|
|
1393
|
+
y: number;
|
|
1394
|
+
z: number;
|
|
1395
|
+
duck?: number;
|
|
1396
|
+
}, f: number, starts: ReadonlyMap<string, number> | undefined): number;
|
|
1397
|
+
/** A drawn pose: place and heading. */
|
|
1398
|
+
interface DrawnPose {
|
|
1399
|
+
x: number;
|
|
1400
|
+
y: number;
|
|
1401
|
+
z: number;
|
|
1402
|
+
yaw: number;
|
|
1403
|
+
}
|
|
1404
|
+
/** A seat drawn at fractional tick `from` on lift `k`, carried in that lift's frame to tick `to`
|
|
1405
|
+
* (§17.11 *Client prediction*: `P_L(to) ∘ P_L(from)⁻¹ ∘ seat(from)`). Drawing only: Math's sine. */
|
|
1406
|
+
declare function inLiftFrame(policy: LiftsPolicy, k: number, p: DrawnPose, from: number, to: number, starts: ReadonlyMap<string, number> | undefined): DrawnPose;
|
|
1407
|
+
/** Lift `id`'s pose drawn at fractional tick `f` (centre and yaw), or undefined for no such lift. */
|
|
1408
|
+
declare function liftDrawnAt(policy: LiftsPolicy, id: string, f: number, starts: ReadonlyMap<string, number> | undefined): DrawnPose | undefined;
|
|
1409
|
+
/** Lift `k`'s top at fractional tick `f`. */
|
|
1410
|
+
declare function liftTopAt(policy: LiftsPolicy, k: number, f: number, starts: ReadonlyMap<string, number> | undefined): number;
|
|
1411
|
+
/**
|
|
1412
|
+
* One seat's step on tick `tick` with the room's lifts' slots round it, as the host runs them for a seat
|
|
1413
|
+
* alone (§17.11 *Lifts*): the carry, `step` through the lifts at t + 1 (its own head slabs left out: no
|
|
1414
|
+
* other seat is known), the impart. What a physics client world's replay steps another seat by (`hold`,
|
|
1415
|
+
* `inputDecay`); `body` (x y z, velocities, yaw, duck) is changed in place.
|
|
1416
|
+
*/
|
|
1417
|
+
declare function stepOnLifts(l: SeatLifts, starts: ReadonlyMap<string, number> | undefined, cache: LiftSolidsCache, step: (body: Record<string, number>, posed: PosedWorld) => void, body: Record<string, number>, tick: number, dt: number): void;
|
|
1418
|
+
/** A lift's body key in a physics room. */
|
|
1419
|
+
declare const liftBodyKey: (id: string) => string;
|
|
1420
|
+
/** A lift's collider as its kinematic body carries it: its box, or a disc's 16-sided prism (the
|
|
1421
|
+
* corners from the portable sine, so every SDK builds the same hull); a conveyor's is frictionless
|
|
1422
|
+
* (the conveyor rule, not friction, moves what it carries). */
|
|
1423
|
+
declare function liftCollider(lift: Lift): LiftCollider;
|
|
1424
|
+
/** A lift body's one collider. */
|
|
1425
|
+
interface LiftCollider {
|
|
1426
|
+
key: string;
|
|
1427
|
+
shape: {
|
|
1428
|
+
kind: 'box';
|
|
1429
|
+
half: [number, number, number];
|
|
1430
|
+
} | {
|
|
1431
|
+
kind: 'hull';
|
|
1432
|
+
points: [number, number, number][];
|
|
1433
|
+
};
|
|
1434
|
+
friction?: number;
|
|
1435
|
+
}
|
|
1436
|
+
/** A lift body's pose: its centre and its yaw as a quaternion about z. */
|
|
1437
|
+
interface LiftBodyPose {
|
|
1438
|
+
p: [number, number, number];
|
|
1439
|
+
q: [number, number, number, number];
|
|
1440
|
+
}
|
|
1441
|
+
/** A lift's body pose at `tick`: its centre and its yaw as a quaternion about z (portable sine). */
|
|
1442
|
+
declare function liftBodyPose(lift: Lift, tick: number, starts: ReadonlyMap<string, number> | undefined): LiftBodyPose;
|
|
1443
|
+
/** A lift's kinematic body as a physics room spawns it at `tick` (the host at load at P(1), a client
|
|
1444
|
+
* world at the keyframe's tick + 1). */
|
|
1445
|
+
declare function liftBodySpawn(lift: Lift, tick: number, starts: ReadonlyMap<string, number> | undefined): {
|
|
1446
|
+
key: string;
|
|
1447
|
+
type: 'kinematic';
|
|
1448
|
+
pose: LiftBodyPose;
|
|
1449
|
+
colliders: LiftCollider[];
|
|
1450
|
+
};
|
|
1451
|
+
/** How fast a conveyor brings a body on it to its surface velocity, per second: a tick's rule takes
|
|
1452
|
+
* this over the tick rate (at most all) of the difference, so a crate is at 95% of the belt's speed
|
|
1453
|
+
* in about 150 ms at any tick rate and in any length unit. */
|
|
1454
|
+
declare const CONVEYOR_RATE = 20;
|
|
1455
|
+
/** A dynamic body as the conveyor rule reads it after the last step: centre and velocity. */
|
|
1456
|
+
interface ConveyorBody {
|
|
1457
|
+
readonly key: string;
|
|
1458
|
+
readonly p: readonly number[];
|
|
1459
|
+
readonly v: readonly number[];
|
|
1460
|
+
}
|
|
1461
|
+
/** The conveyor a body centred at `p` is over at `tick`, as the conveyor rule reads it (inside its
|
|
1462
|
+
* footprint in its own frame, `0 < z − top ≤ reach`; the first in declared order): a test of the
|
|
1463
|
+
* body's place alone. */
|
|
1464
|
+
declare function conveyorUnder(policy: LiftsPolicy, tick: number, starts: ReadonlyMap<string, number> | undefined, reach: number): (p: readonly number[]) => Lift | undefined;
|
|
1465
|
+
/**
|
|
1466
|
+
* The conveyor rule of tick `tick` (before its physics step): each dynamic body (key order) whose
|
|
1467
|
+
* centre is over a conveyor's top at `tick` (inside its footprint in its own frame, above its top by at
|
|
1468
|
+
* most `reach`: the preset body's height; the first such conveyor in declared order) has its horizontal
|
|
1469
|
+
* velocity brought toward the carry velocity of its point from `tick` to `tick + 1` (the belt's surface
|
|
1470
|
+
* turned with the lift, plus the lift's own move) by the share `min(1, CONVEYOR_RATE / tickHz)` of the
|
|
1471
|
+
* difference; its vertical speed kept. Float64 on the float32 inputs; the velocities as the setVelocity commands carry them.
|
|
1472
|
+
*/
|
|
1473
|
+
declare function conveyorNudges(policy: LiftsPolicy, tick: number, starts: ReadonlyMap<string, number> | undefined, tickHz: number, bodies: readonly ConveyorBody[], reach: number): {
|
|
1474
|
+
key: string;
|
|
1475
|
+
v: [number, number, number];
|
|
1476
|
+
}[];
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
* A seat contact pass: what the room module does to every seat's entity after each tick's preset
|
|
1480
|
+
* steps (car-ball's pairs, pile passes and world passes), as a pure function of them all, ids
|
|
1481
|
+
* ascending, changing their fields in place. The module must run this very function. Without one, a
|
|
1482
|
+
* session runs the pair rule (`contacts`) once on every pair, ids ascending.
|
|
1483
|
+
*/
|
|
1484
|
+
type AuthoritySeatPass = (seats: ContactBody[]) => void;
|
|
1485
|
+
/** Another seat's entity in the latest state: its preset fields (`body`), its life, and its last
|
|
1486
|
+
* applied input (§17.11 *State*; undefined where the room writes none: moved by its velocity). */
|
|
1487
|
+
interface HeldSeat {
|
|
1488
|
+
id: string;
|
|
1489
|
+
epoch: number;
|
|
1490
|
+
body: Record<string, number>;
|
|
1491
|
+
input: RemoteInput | undefined;
|
|
1492
|
+
}
|
|
1493
|
+
/** How fast a predicted seat's pose moves at an input: room units and radians per ms. */
|
|
1494
|
+
interface SeatRate {
|
|
1495
|
+
vx: number;
|
|
1496
|
+
vy: number;
|
|
1497
|
+
vz: number;
|
|
1498
|
+
vyaw: number;
|
|
1499
|
+
}
|
|
1500
|
+
/** A predicted seat at an input: its pose there and how fast its predicted track moves there. */
|
|
1501
|
+
interface SeatMotion {
|
|
1502
|
+
pose: SeatPose;
|
|
1503
|
+
rate: SeatRate;
|
|
1504
|
+
}
|
|
1505
|
+
/** A seat in the pass it was drawn from (`before`) and in the pass after it (`after`), at one input
|
|
1506
|
+
* both passes stepped: what a new pass changed. */
|
|
1507
|
+
interface SeatChange {
|
|
1508
|
+
before: SeatMotion;
|
|
1509
|
+
after: SeatMotion;
|
|
1510
|
+
}
|
|
1511
|
+
/** One fixed step of a seat's entity under `input` (the room preset's own step), mutating `body`. */
|
|
1512
|
+
type SeatStep = (body: Record<string, number>, input: RemoteInput, dt: number, posed?: PosedWorld) => void;
|
|
1513
|
+
/** The room's lifts as the seat prediction runs them (§17.11 *Lifts*): the slots, the called lifts'
|
|
1514
|
+
* starts and the compiled solids. */
|
|
1515
|
+
interface SeatWorldLifts {
|
|
1516
|
+
lifts: SeatLifts;
|
|
1517
|
+
starts: ReadonlyMap<string, number> | undefined;
|
|
1518
|
+
cache: LiftSolidsCache;
|
|
1519
|
+
}
|
|
1520
|
+
/** A predicted seat after one tick: position, heading (radians) and velocity (room units, per second). */
|
|
1521
|
+
interface SeatPose {
|
|
1522
|
+
x: number;
|
|
1523
|
+
y: number;
|
|
1524
|
+
z: number;
|
|
1525
|
+
yaw: number;
|
|
1526
|
+
vx: number;
|
|
1527
|
+
vy: number;
|
|
1528
|
+
vz: number;
|
|
1529
|
+
}
|
|
1530
|
+
interface SeatWorldOptions {
|
|
1531
|
+
/** The room module's seat contact rule, on two seats (`a` the lower id). */
|
|
1532
|
+
rule: AuthorityContactRule;
|
|
1533
|
+
/** The room module's whole contact pass; absent: the rule once on every pair. */
|
|
1534
|
+
pass?: AuthoritySeatPass;
|
|
1535
|
+
/** Every other seat in the latest state. */
|
|
1536
|
+
others: () => readonly HeldSeat[];
|
|
1537
|
+
/** The room preset's step, or undefined when this client has none (seats are then extrapolated). */
|
|
1538
|
+
step: () => SeatStep | undefined;
|
|
1539
|
+
/** The room module's seat rule, run on each other seat before each of its steps. */
|
|
1540
|
+
seatRule?: AuthoritySeatRule;
|
|
1541
|
+
/** How other seats move between states (`physDesc.remotePredict`, `remoteDecayMs`). */
|
|
1542
|
+
remote: () => {
|
|
1543
|
+
predict: RemotePredict;
|
|
1544
|
+
decayMs: number;
|
|
1545
|
+
};
|
|
1546
|
+
/** The room's lifts and head slabs, run around each tick's steps as the host runs them; none: no carry. */
|
|
1547
|
+
lifts?: () => SeatWorldLifts | null;
|
|
1548
|
+
/** How far past a state other seats are predicted at most, ms (the lead cap and STALL_PREDICT_MS):
|
|
1549
|
+
* further on they hold where that left them. */
|
|
1550
|
+
maxAheadMs: () => number;
|
|
1551
|
+
}
|
|
1552
|
+
/** Other seats keep being predicted through a stall (no new state) this long past the lead cap, ms,
|
|
1553
|
+
* then hold. */
|
|
1554
|
+
declare const STALL_PREDICT_MS = 500;
|
|
1555
|
+
/** One pass: the seats stepped from one state, tick by tick, as your inputs ack + 1, ack + 2, … were. */
|
|
1556
|
+
interface SeatPass {
|
|
1557
|
+
readonly id: number;
|
|
1558
|
+
readonly ack: number;
|
|
1559
|
+
readonly stateTick: number;
|
|
1560
|
+
readonly tickHz: number;
|
|
1561
|
+
/** The last of your inputs applied, and the ticks the seats were stepped. */
|
|
1562
|
+
last: number;
|
|
1563
|
+
ticks: number;
|
|
1564
|
+
readonly seats: {
|
|
1565
|
+
id: string;
|
|
1566
|
+
epoch: number;
|
|
1567
|
+
body: Record<string, number>;
|
|
1568
|
+
input: RemoteInput | undefined;
|
|
1569
|
+
}[];
|
|
1570
|
+
/** Each seat's pose after the tick your input `seq` was applied on (seq `ack`: the state's). */
|
|
1571
|
+
readonly poses: Map<number, Map<string, SeatPose>>;
|
|
1572
|
+
/** The seats touching your entity in the tick of input `seq` (before the contact pass). */
|
|
1573
|
+
readonly touching: Map<number, Set<string>>;
|
|
1574
|
+
/** Your entity after the contact pass of the tick of input `seq`. */
|
|
1575
|
+
readonly own: Map<number, ContactBody>;
|
|
1576
|
+
/** Your entity as that tick's pass was given it (after your step, before any contact). */
|
|
1577
|
+
readonly ownIn: Map<number, ContactBody>;
|
|
1578
|
+
/** The seat your carry slot had you ride in the tick of input `seq` (null: none). */
|
|
1579
|
+
readonly ownOn: Map<number, string | null>;
|
|
1580
|
+
}
|
|
1581
|
+
/**
|
|
1582
|
+
* The other seats predicted from the latest state, as your own entity's prediction steps your inputs.
|
|
1583
|
+
* `apply` after your input `seq` was stepped into your entity: a new pass starts when the state's ack
|
|
1584
|
+
* or tick changed, or `seq` is not after the last input applied (a replay), and the other seats are
|
|
1585
|
+
* stepped to that input's tick, then the contact pass runs on all of them and yours.
|
|
1586
|
+
*/
|
|
1587
|
+
declare class SeatWorld {
|
|
1588
|
+
private readonly options;
|
|
1589
|
+
private serial;
|
|
1590
|
+
/** The current pass. */
|
|
1591
|
+
current: SeatPass | null;
|
|
1592
|
+
/** The passes before it, newest first (RECENT_PASSES): stepped on with the current one's ticks, so
|
|
1593
|
+
* a seat last drawn from one of them is compared with the current pass at the same input, both
|
|
1594
|
+
* stepped there (a bump or a turn the next tick brings is in both, not a correction). */
|
|
1595
|
+
private recent;
|
|
1596
|
+
/** The seats touching your entity in the tick each of your inputs was stepped live in (`apply`'s own
|
|
1597
|
+
* step, not a re-run), by input: what your prediction's contacts were stepped with. */
|
|
1598
|
+
private applied;
|
|
1599
|
+
/** The seats a pass found touching your entity in an input it was already stepped through that the
|
|
1600
|
+
* input's live step did not have touching it (`takeMissed`). */
|
|
1601
|
+
private missed;
|
|
1602
|
+
constructor(options: SeatWorldOptions);
|
|
1603
|
+
/**
|
|
1604
|
+
* After your input `seq` was stepped into `own` (the state of tick `stateTick` having consumed your
|
|
1605
|
+
* inputs through `ack`): the other seats stepped to that input's tick and the contact pass run on
|
|
1606
|
+
* every seat. Your fields the pass changed are written back as float32 (the entity's wire type).
|
|
1607
|
+
*/
|
|
1608
|
+
apply(seq: number, ack: number, stateTick: number, own: ContactBody, tickHz: number, rides?: string | null): readonly [number, number] | null;
|
|
1609
|
+
/**
|
|
1610
|
+
* The seats a pass found touching your entity that your prediction was not stepped with since the last
|
|
1611
|
+
* call, ids ascending (§17.11 *Seat contacts*), and forgets them: a state that put your inputs in
|
|
1612
|
+
* flight on later ticks (one that consumed none of them, then one that consumed several) re-runs
|
|
1613
|
+
* inputs your entity was already stepped through, and the other seats, run on from that state, can
|
|
1614
|
+
* reach yours in one of them. Your entity's changes in a re-run are not kept, so it would stand there
|
|
1615
|
+
* as a wall the other seat stops against: the session re-predicts your inputs from the state instead,
|
|
1616
|
+
* and draws these seats at your entity's input at once.
|
|
1617
|
+
*/
|
|
1618
|
+
takeMissed(): string[];
|
|
1619
|
+
/** Pass `pass`'s re-run of your input `seq`: each seat touching yours there that the input's live step
|
|
1620
|
+
* did not have touching it is missed (a live step with no record is not judged). */
|
|
1621
|
+
private noteMissed;
|
|
1622
|
+
/** Pass `old` stepped on to your input `seq` with your entity as `now` was given it at each tick. */
|
|
1623
|
+
private extend;
|
|
1624
|
+
/** Where seat `id` is at your input `seq` (fractional: between two inputs), in pass `pass` (default
|
|
1625
|
+
* the current one): between the two ticks around it, moved on by its velocity past the last one
|
|
1626
|
+
* stepped (the current pass at most a tick, which the next input steps; a pass before it as far as
|
|
1627
|
+
* asked: where it would have drawn the seat, which a new pass's correction is measured from).
|
|
1628
|
+
* Undefined for a seat the pass does not have. */
|
|
1629
|
+
poseAt(id: string, seq: number, pass?: SeatPass | null): SeatPose | undefined;
|
|
1630
|
+
/**
|
|
1631
|
+
* Seat `id` at your input `seq` in `pass` (default the current one): its pose and the slope of its
|
|
1632
|
+
* predicted track over the half inputs either side, per ms of your inputs' ticks. That slope is what
|
|
1633
|
+
* the drawn seat moves by (contact push-outs included, which the body's velocity leaves out).
|
|
1634
|
+
*/
|
|
1635
|
+
motionAt(id: string, seq: number, pass?: SeatPass | null): SeatMotion | undefined;
|
|
1636
|
+
/**
|
|
1637
|
+
* What the current pass changed for seat `id` from pass `from` (the one it was last drawn from): the
|
|
1638
|
+
* seat in both at your input `seq`, or at `from`'s last stepped input when `seq` is past it (the seat
|
|
1639
|
+
* clock can draw past your last input). Past its last tick the current pass moves a seat on by its
|
|
1640
|
+
* velocity, a tick at most, and `from` along its last steps: compared there, the drawing's own
|
|
1641
|
+
* advance read as a correction. A recent pass is stepped on with the current one, so both have that
|
|
1642
|
+
* input stepped; an older one goes on past its last tick along its last steps (`beyond`).
|
|
1643
|
+
* Undefined when `from` is the current pass.
|
|
1644
|
+
*/
|
|
1645
|
+
changeAt(id: string, seq: number, from: SeatPass): SeatChange | undefined;
|
|
1646
|
+
/**
|
|
1647
|
+
* How soon seat `id` touches your entity from your input `seq`, ms (§17.11 *Drawing other seats*,
|
|
1648
|
+
* *Touching*): 0 when the pass's own contact test had the two touching in the tick of an input from
|
|
1649
|
+
* `seq` to the one after it (a contact your predicted steps resolve); else the first of
|
|
1650
|
+
* SEAT_TOUCH_SAMPLES steps along SEAT_CLOCK_TAU_MS at which the room's contact rule touches your
|
|
1651
|
+
* entity there with the seat moved on from it at the two's relative velocity; undefined when it does
|
|
1652
|
+
* not within SEAT_CLOCK_TAU_MS (not touching).
|
|
1653
|
+
*/
|
|
1654
|
+
touchAheadMs(id: string, seq: number): number | undefined;
|
|
1655
|
+
/** Whether seat `id` touches your entity in the tick of your input nearest `seq`. */
|
|
1656
|
+
touchingAt(id: string, seq: number): boolean;
|
|
1657
|
+
/** How fast seat `id` moves in the latest state (the server's car, the pass's first pose), room units
|
|
1658
|
+
* per ms; undefined for a seat the current pass does not have. */
|
|
1659
|
+
stateRate(id: string): SeatRate | undefined;
|
|
1660
|
+
private start;
|
|
1661
|
+
/** Tick `i` of the pass (your input ack + i): every other seat stepped, the ride slot, then the
|
|
1662
|
+
* contact pass on every seat with yours (`own`, when known; `rides`: the seat your carry slot had
|
|
1663
|
+
* you ride); `write`: your fields the pass changed written back. Answers the move the ride gave you. */
|
|
1664
|
+
private tick;
|
|
1665
|
+
/**
|
|
1666
|
+
* Tick `i`'s ride slot (§17.11 *Lifts*, after the steps, before the contacts): the carry's seats set
|
|
1667
|
+
* to where the steps left the other seats and yours (`mine`), every rider moved by its ridden seat's
|
|
1668
|
+
* walk. Your entity rides as your carry slot had it (`rides`): the slot's move for it when this pass
|
|
1669
|
+
* knew you at the tick's start, else the ridden seat's walk and ride. Answers your move, or null.
|
|
1670
|
+
*/
|
|
1671
|
+
private ride;
|
|
1672
|
+
/** Tick `i`'s carry slot on every other seat (your entity as the tick before left it, when known),
|
|
1673
|
+
* their carried places written into them; null without lifts. */
|
|
1674
|
+
private carry;
|
|
1675
|
+
/** Tick `i`'s impart slot on every other seat, after the contact pass (`mine`: your entity after it). */
|
|
1676
|
+
private impart;
|
|
1677
|
+
/** One seat's tick `i`: the seat rule, then its step under its held (or decayed) input (through the
|
|
1678
|
+
* tick's lifts and its head slabs, `posed`), or its velocity when it has no input or this client no step. */
|
|
1679
|
+
private move;
|
|
1680
|
+
/** The room's pass on `all` (ids ascending), or its rule once on every pair. */
|
|
1681
|
+
private contactPass;
|
|
1682
|
+
/** Whether the rule changes your entity or seat `b` (copies of the two): they touch. */
|
|
1683
|
+
private touches;
|
|
1684
|
+
}
|
|
1685
|
+
/** The input other seats are drawn at (fractional) and the frame's time (ms). */
|
|
1686
|
+
interface SeatClock {
|
|
1687
|
+
seq: number;
|
|
1688
|
+
at: number;
|
|
1689
|
+
}
|
|
1690
|
+
/**
|
|
1691
|
+
* The input other seats are drawn at this frame (§17.11 *Drawing other seats*): last frame's moved on
|
|
1692
|
+
* by the time since at the room's tick rate, then pulled toward the input your entity is drawn at
|
|
1693
|
+
* (`raw`) by a share 1 − e^(−dt / SEAT_CLOCK_TAU_MS), never back; more than SEAT_CLOCK_SNAP_INPUTS off (a
|
|
1694
|
+
* reset, a stall), it is `raw`. Your entity's render fraction restarts at 0 on a frame that sends one
|
|
1695
|
+
* input more than the time asked for (Colyseus' Predict clamps its accumulator), so `raw` moved on by
|
|
1696
|
+
* most of a third input on one frame in four at 57 frames a second: drawn there, every other seat
|
|
1697
|
+
* stepped half a frame's travel at once.
|
|
1698
|
+
*/
|
|
1699
|
+
declare function seatClock(known: SeatClock | undefined, raw: number, at: number, tickHz: number): SeatClock;
|
|
1700
|
+
/**
|
|
1701
|
+
* A seat's share of the way from the seat clock's input to your entity's exact one this frame (§17.11
|
|
1702
|
+
* *Drawing other seats*, *Touching*): last frame's moved toward 1 while the seat is touching yours
|
|
1703
|
+
* (`touchAheadMs` has a time) and toward 0 when it is not, by dtMs / SEAT_CLOCK_TAU_MS, the seat clock's
|
|
1704
|
+
* own time to move other seats from one input clock to another; a seat without a share yet takes its
|
|
1705
|
+
* target. Only the clock is blended: a touching seat keeps its correction (a rival misprediction it
|
|
1706
|
+
* eases), and taking the share at once, or fading the correction with it, moved a car-ball car its
|
|
1707
|
+
* whole correction (~100 u at 200 ms) in a frame: remote snaps 5 to 24 a run.
|
|
1708
|
+
*/
|
|
1709
|
+
declare function seatTouchShare(known: number | undefined, touching: boolean, dtMs: number): number;
|
|
1710
|
+
/** A drawn seat's correction: the offset (room units, radians) from its predicted pose to where it is
|
|
1711
|
+
* drawn and how fast that offset is moving (per ms), the pass it was measured in and the seat's life;
|
|
1712
|
+
* the predicted position it was drawn from (`ax`, `ay`, `az`, in that pass); and the way the drawn
|
|
1713
|
+
* seat was last seen moving (`hx`, `hy`, `hz`, a unit vector, 0 before it moved) and how long it has
|
|
1714
|
+
* been drawn slower than SEAT_MOVING_UNITS_PER_MS since (`stillMs`); and whether a new pass found it
|
|
1715
|
+
* stopping late (`stopFound`: slower along that way, at the same input, than the pass it was drawn
|
|
1716
|
+
* from by more than SEAT_MOVING_UNITS_PER_MS; kept while it is drawn stopped, decided again by each
|
|
1717
|
+
* pass that arrives while it is drawn moving). */
|
|
1718
|
+
interface SeatOffset {
|
|
1719
|
+
pass: SeatPass | null;
|
|
1720
|
+
epoch: number;
|
|
1721
|
+
dx: number;
|
|
1722
|
+
dy: number;
|
|
1723
|
+
dz: number;
|
|
1724
|
+
dyaw: number;
|
|
1725
|
+
vx: number;
|
|
1726
|
+
vy: number;
|
|
1727
|
+
vz: number;
|
|
1728
|
+
vyaw: number;
|
|
1729
|
+
ax: number;
|
|
1730
|
+
ay: number;
|
|
1731
|
+
az: number;
|
|
1732
|
+
hx: number;
|
|
1733
|
+
hy: number;
|
|
1734
|
+
hz: number;
|
|
1735
|
+
stillMs: number;
|
|
1736
|
+
stopFound: boolean;
|
|
1737
|
+
}
|
|
1738
|
+
/** A shove's ease (`shoveEase`) is done once what is left of it is under this, world units. */
|
|
1739
|
+
declare const SHOVE_EASE_DONE = 0.01;
|
|
1740
|
+
/** What is left, `elapsedMs` after your inputs were predicted again from the state after a missed
|
|
1741
|
+
* contact, of the shift `from` (the drawn pose less the new prediction) that eases out at SEAT_TAU_MS:
|
|
1742
|
+
* `offset` is added to the predicted pose, and `done` once the largest axis is under SHOVE_EASE_DONE
|
|
1743
|
+
* (the ease is dropped and nothing is added). Pinned by `shoves` in carball-seat-predict.json. */
|
|
1744
|
+
declare function shoveEase(from: {
|
|
1745
|
+
dx: number;
|
|
1746
|
+
dy: number;
|
|
1747
|
+
dz: number;
|
|
1748
|
+
}, elapsedMs: number): {
|
|
1749
|
+
dx: number;
|
|
1750
|
+
dy: number;
|
|
1751
|
+
dz: number;
|
|
1752
|
+
done: boolean;
|
|
1753
|
+
};
|
|
1754
|
+
/** τ of a seat's correction (ms): SEAT_CONTACT_TAU_MS while it touches your entity in the prediction
|
|
1755
|
+
* (a bump lands where it is drawn), else SEAT_TAU_MS. */
|
|
1756
|
+
declare const seatTauMs: (touching: boolean) => number;
|
|
1757
|
+
/**
|
|
1758
|
+
* A seat's correction this frame (§17.11 *Drawing*): last frame's offset `known` brought `dtMs` closer
|
|
1759
|
+
* to 0 by a critically damped return at the seat's τ (no overshoot; a first-order decay moves a
|
|
1760
|
+
* correction C by C/τ at once, which reads as a one-frame jump), plus what a new pass changed (`change`,
|
|
1761
|
+
* `SeatWorld.changeAt`: the seat in the pass it was drawn from and in this one, at an input both
|
|
1762
|
+
* stepped). The offset takes the change of where it is, and its rate the change of how fast it moves,
|
|
1763
|
+
* so the drawn seat keeps both its place and its velocity on the frame a new pass arrives and turns
|
|
1764
|
+
* onto the new track over the next frames; the return never pulls it back against its drawn motion
|
|
1765
|
+
* (`keepCourse`), nor while the server's car (`server`, the seat's velocity in the latest state,
|
|
1766
|
+
* `SeatWorld.stateRate`) still moves that way. `now` is the seat in this pass at the drawn input. A new
|
|
1767
|
+
* life (epoch) or an offset over `snapUnits` starts at 0: drawn where it is predicted.
|
|
1768
|
+
*/
|
|
1769
|
+
declare function seatOffset(known: SeatOffset | undefined, pass: SeatPass, epoch: number, change: SeatChange | undefined, now: SeatMotion, dtMs: number, touching: boolean, snapUnits: number, server?: SeatRate): SeatOffset;
|
|
1770
|
+
|
|
1771
|
+
/** A seat as the policy sees it: its entity's fields, its tags (pair rules match them) and whether
|
|
1772
|
+
* its jump is held (a stomp's boost). `flags` bit k adds the tag `flag:k`. */
|
|
1773
|
+
interface PolicyBody extends ContactBody {
|
|
1774
|
+
tags?: readonly string[];
|
|
1775
|
+
flags?: number;
|
|
1776
|
+
jump?: number;
|
|
1777
|
+
}
|
|
1778
|
+
/** Whether a contact is between two sides or one seat over another's top. */
|
|
1779
|
+
declare const ContactKind: {
|
|
1780
|
+
readonly Side: "side";
|
|
1781
|
+
readonly Top: "top";
|
|
1782
|
+
};
|
|
1783
|
+
type ContactKind = (typeof ContactKind)[keyof typeof ContactKind];
|
|
1784
|
+
/** How a top contact's slide went: along the upper seat's free way, the lower seat's, or neither. */
|
|
1785
|
+
declare const SlideWay: {
|
|
1786
|
+
readonly Free: "free";
|
|
1787
|
+
readonly LowerYields: "lower-yields";
|
|
1788
|
+
readonly Pinned: "pinned";
|
|
1789
|
+
};
|
|
1790
|
+
type SlideWay = (typeof SlideWay)[keyof typeof SlideWay];
|
|
1791
|
+
/** What the module hears from the pass (a stomp's damage stays a server event, never predicted). */
|
|
1792
|
+
declare const ContactEvent: {
|
|
1793
|
+
readonly Stomp: "stomp";
|
|
1794
|
+
};
|
|
1795
|
+
type ContactEvent = (typeof ContactEvent)[keyof typeof ContactEvent];
|
|
1796
|
+
/** What the policy runs against: the world grown by the seats' hull, and optionally the module's own
|
|
1797
|
+
* support up (car-ball's `carUp`, a pure function of the base) and a listener for its events. */
|
|
1798
|
+
interface ContactEnv {
|
|
1799
|
+
readonly world: ContactWorld | null;
|
|
1800
|
+
readonly supportUp?: (x: number, y: number, z: number) => V3;
|
|
1801
|
+
/** Hears a pair's event: a stomp names the upper seat first. */
|
|
1802
|
+
readonly onContact?: (upper: PolicyBody, lower: PolicyBody, event: ContactEvent) => void;
|
|
1803
|
+
/** The id of a seat that never moves (a drawing's own entity, §17.11 *Drawing other seats*): the
|
|
1804
|
+
* other seat of its pair takes the whole push, its own way (along a wall, never into it). */
|
|
1805
|
+
readonly fixed?: string;
|
|
1806
|
+
/** A pass's memo of each seat's support up (see {@link contactPass}), by the place it was read at. */
|
|
1807
|
+
readonly supports?: Map<PolicyBody, {
|
|
1808
|
+
x: number;
|
|
1809
|
+
y: number;
|
|
1810
|
+
z: number;
|
|
1811
|
+
up: V3;
|
|
1812
|
+
}>;
|
|
1813
|
+
}
|
|
1814
|
+
/** One pair's contact: its kind, axis (unit, from `a` to `b`) and depth along it. */
|
|
1815
|
+
interface PairContact {
|
|
1816
|
+
kind: ContactKind;
|
|
1817
|
+
n: V3;
|
|
1818
|
+
depth: number;
|
|
1819
|
+
/** Whether `b` is the upper seat (top contacts; for side contacts the higher across the plane). */
|
|
1820
|
+
upperIsB: boolean;
|
|
1821
|
+
}
|
|
1822
|
+
/** What one pair step did: its contact, the impulse along the axis (a slide's change), and a top
|
|
1823
|
+
* contact's slide: how it went and the way taken (unit, the direction the sliding seat moves). */
|
|
1824
|
+
interface PairOutcome extends PairContact {
|
|
1825
|
+
j: number;
|
|
1826
|
+
way: SlideWay | null;
|
|
1827
|
+
w: V3 | null;
|
|
1828
|
+
}
|
|
1829
|
+
/** A seat's body for one pair test: its geometric up, support up, half extents, top and heading. */
|
|
1830
|
+
interface Frame {
|
|
1831
|
+
b: PolicyBody;
|
|
1832
|
+
up: V3;
|
|
1833
|
+
support: V3;
|
|
1834
|
+
hl: number;
|
|
1835
|
+
hw: number;
|
|
1836
|
+
top: number;
|
|
1837
|
+
s: number;
|
|
1838
|
+
c: number;
|
|
1839
|
+
}
|
|
1840
|
+
/** A seat's frame: a box turned with its heading and laid on its support up; a hull upright. */
|
|
1841
|
+
declare function frameOf(b: PolicyBody, policy: ContactPolicy, env: ContactEnv): Frame;
|
|
1842
|
+
/** A seat's tags: its own, and `flag:k` for each bit k set in its `flags`. */
|
|
1843
|
+
declare function tagsOf(b: PolicyBody): string[];
|
|
1844
|
+
/** The first pair rule matching the two seats' tags (either way round), else the policy's top. */
|
|
1845
|
+
declare function topRuleOf(policy: ContactPolicy, a: PolicyBody, b: PolicyBody): TopRule;
|
|
1846
|
+
/**
|
|
1847
|
+
* The contact of seats `a` and `b` under `policy` (§17.11 *Contact policy* steps 1-3): its kind, axis
|
|
1848
|
+
* (unit, from a to b), depth and which seat is upper; null when they do not touch.
|
|
1849
|
+
*/
|
|
1850
|
+
declare function contactOf(a: PolicyBody, b: PolicyBody, policy: ContactPolicy, env: ContactEnv): PairContact | null;
|
|
1851
|
+
/** Whether two seats' bases are too far apart for their bodies to touch, or one to rest on the other
|
|
1852
|
+
* (its ground trace and a unit over): no frame is laid for them (each a cast down the world). */
|
|
1853
|
+
declare function farApart(a: PolicyBody, b: PolicyBody, policy: ContactPolicy): boolean;
|
|
1854
|
+
/**
|
|
1855
|
+
* The shares of a side push of `depth` along `n` (from a to b) that `a` and `b` take (§17.11 step 4):
|
|
1856
|
+
* each the part of the push its way takes (straight to a wall, then along it in the plane it rides, its
|
|
1857
|
+
* support up `upA`, `upB`), `a` at most half (equal masses), `b` at most the rest, then `a` the rest of
|
|
1858
|
+
* what `b` could not take. Continuous in position. A face a seat rides (`ridesA`, `ridesB`: within
|
|
1859
|
+
* `supportCos` of its support up) does not stop its push: its preset follows that surface, so only
|
|
1860
|
+
* walls and ceilings take a share away.
|
|
1861
|
+
*/
|
|
1862
|
+
declare function yieldShares(a: PolicyBody, b: PolicyBody, n: V3, depth: number, world: ContactWorld | null, ridesA?: FaceFilter, ridesB?: FaceFilter, upA?: V3, upB?: V3, wantA?: number): [number, number];
|
|
1863
|
+
/** How far seat `upper`'s centre is off seat `lower`'s, as a share of the lower's half extent: the
|
|
1864
|
+
* larger of the two in the lower's heading frame (Chebyshev for a hull's square footprint). */
|
|
1865
|
+
declare function headOffset(upper: PolicyBody, lower: PolicyBody, policy: ContactPolicy): number;
|
|
1866
|
+
/** The least closing speed on a head that is a landing (u/s): above one tick of gravity at any tick
|
|
1867
|
+
* rate from 10 Hz (800 u/s² × 0.1 s), so a released seat falling back onto the top is not one, and
|
|
1868
|
+
* below a fall from 6 u (√(2 · 800 · 6.25)). */
|
|
1869
|
+
declare const HEAD_LANDING_SPEED = 100;
|
|
1870
|
+
/** How a seat over a `stand` head is held (§17.11 step 6 `stand`): it stands (and gets the head's slab);
|
|
1871
|
+
* it is released (no slab, no kick: it is already leaving); or it slides off by the stand's slide. */
|
|
1872
|
+
declare const HeadHold: {
|
|
1873
|
+
readonly Stand: "stand";
|
|
1874
|
+
readonly Release: "release";
|
|
1875
|
+
readonly Slide: "slide";
|
|
1876
|
+
};
|
|
1877
|
+
type HeadHold = (typeof HeadHold)[keyof typeof HeadHold];
|
|
1878
|
+
/**
|
|
1879
|
+
* The stand test (§17.11 step 6 `stand`, and the head slabs): how seat `upper`, over seat `lower` whose
|
|
1880
|
+
* pair rule is the stand `rule`, is held. `center` null: it stands. Else a seat within `center` of the
|
|
1881
|
+
* lower's half extent (headOffset) stands; a landing (closing on it faster than HEAD_LANDING_SPEED)
|
|
1882
|
+
* beyond it slides; a resting seat beyond it whose lower moves away from under it (leavingOf) at half
|
|
1883
|
+
* its slide's step (the slide's speed when the step is null) or more is released (it is leaving: the
|
|
1884
|
+
* lower walked away under it); else it slides once its centre is past the footprint and stands until then.
|
|
1885
|
+
*/
|
|
1886
|
+
declare function headHold(upper: PolicyBody, lower: PolicyBody, rule: StandRule, policy: ContactPolicy): HeadHold;
|
|
1887
|
+
/** Whether seat `upper` stands on seat `lower` under `rule` (a stand that holds it: it gets the slab). */
|
|
1888
|
+
declare const headStands: (upper: PolicyBody, lower: PolicyBody, rule: TopRule, policy: ContactPolicy) => boolean;
|
|
1889
|
+
/**
|
|
1890
|
+
* Two seats `a` and `b` (`a` the lower id) under `policy` (§17.11 *Contact policy* steps 1-6), changed
|
|
1891
|
+
* in place: a ghost pair or two that do not touch are left as they are (null); a side contact is pushed
|
|
1892
|
+
* apart; a top contact is set on the lower seat's top and runs its pair's top policy. `cooling` holds a
|
|
1893
|
+
* side contact's impulse back (the release-1 room's pair cooldown). `others`: the rest of the pass's
|
|
1894
|
+
* seats, whose tops an upper seat also rests on (its free way clears them all).
|
|
1895
|
+
*/
|
|
1896
|
+
declare function contactPair(a: PolicyBody, b: PolicyBody, policy: ContactPolicy, env: ContactEnv, cooling?: boolean, others?: readonly PolicyBody[]): PairOutcome | null;
|
|
1897
|
+
/** What a contact pass did. */
|
|
1898
|
+
interface ContactReport {
|
|
1899
|
+
/** Passes that touched a pair. */
|
|
1900
|
+
passes: number;
|
|
1901
|
+
/** Each seat's deepest push out of the world, by id. */
|
|
1902
|
+
pushed: Map<string, number>;
|
|
1903
|
+
/** Each seat's deepest push out through a wall (a face it could not stand on: its z under
|
|
1904
|
+
* `supportCos`), by id: what the contacts drove into a wall for the push-out to undo. */
|
|
1905
|
+
walls: Map<string, number>;
|
|
1906
|
+
/** Top contacts that stood pinned (no free way for either seat). */
|
|
1907
|
+
pinned: number;
|
|
1908
|
+
}
|
|
1909
|
+
/** Options of a pass: the release-1 room's pair cooldown, a module's own rule for the first pass's
|
|
1910
|
+
* pairs (car-ball's release-1 sweep over its 60 Hz tick: a pair it answers, null or an outcome, is not
|
|
1911
|
+
* run through the policy; undefined leaves it to the policy), and a listener for every pair touched. */
|
|
1912
|
+
interface ContactPassOptions {
|
|
1913
|
+
cooling?: (a: PolicyBody, b: PolicyBody) => boolean;
|
|
1914
|
+
first?: (a: PolicyBody, b: PolicyBody, cooling: boolean) => PairOutcome | null | undefined;
|
|
1915
|
+
onPair?: (a: PolicyBody, b: PolicyBody, outcome: PairOutcome) => void;
|
|
1916
|
+
}
|
|
1917
|
+
/**
|
|
1918
|
+
* The contact pass (§17.11 *Contact policy* step 7) over `seats` (ids ascending, changed in place): every
|
|
1919
|
+
* pair in id order, then a pile's further passes, up to `policy.passes`, on the pairs still more than
|
|
1920
|
+
* `slop` inside each other; after every pass that touched, every seat the contacts drove into the world
|
|
1921
|
+
* pushed back out (§17.7 *Starting inside*). The server's seat contact pass and the client's replay.
|
|
1922
|
+
*/
|
|
1923
|
+
declare function contactPass(seats: PolicyBody[], policy: ContactPolicy, env: ContactEnv, options?: ContactPassOptions): ContactReport;
|
|
1924
|
+
/** The policy as a seat contact rule on two seats (`connectAuthority({ contacts })`, `separateSeats`'
|
|
1925
|
+
* drawing guard): one pair step. */
|
|
1926
|
+
declare const contactRuleOf: (policy: ContactPolicy, env: ContactEnv) => AuthorityContactRule;
|
|
1927
|
+
/** The policy as a whole seat contact pass (`connectAuthority({ contactPass })`). */
|
|
1928
|
+
declare const contactPassOf: (policy: ContactPolicy, env: ContactEnv) => AuthoritySeatPass;
|
|
1929
|
+
/** A kinematic-rule body a seat may stand on: its box at the tick and how far it moves to the next. */
|
|
1930
|
+
interface KinematicSupport {
|
|
1931
|
+
key: string;
|
|
1932
|
+
min: V3;
|
|
1933
|
+
max: V3;
|
|
1934
|
+
/** Its move from this tick to the next (`kinematicRule(t + 1) − kinematicRule(t)`). */
|
|
1935
|
+
dp: V3;
|
|
1936
|
+
}
|
|
1937
|
+
/** What one seat stands on: another seat or a kinematic body, and the base velocity it gives. */
|
|
1938
|
+
interface Ride {
|
|
1939
|
+
id: string;
|
|
1940
|
+
on: string;
|
|
1941
|
+
v: V3;
|
|
1942
|
+
}
|
|
1943
|
+
/**
|
|
1944
|
+
* The `stand` ride (§17.11 *Contact policy* step 6, run in the seat-rule slot before the tick's preset
|
|
1945
|
+
* steps): each seat standing on a kinematic body or on a seat whose pair rule is `stand` is carried by
|
|
1946
|
+
* its support's velocity for the tick (`1 / tickHz`; a kinematic body's move to the next tick); a seat
|
|
1947
|
+
* leaving it upward (`vz > 0`) keeps that velocity. Every ride is found from the seats as they were
|
|
1948
|
+
* before any moved (ids ascending). Changes x y (vx vy on leaving) in place; returns the rides.
|
|
1949
|
+
*/
|
|
1950
|
+
declare function rideStep(seats: PolicyBody[], supports: readonly KinematicSupport[], policy: ContactPolicy, env: ContactEnv, tickHz: number): Ride[];
|
|
1951
|
+
|
|
1952
|
+
/** A declared policy as the session runs it: the pair rule and the whole pass. */
|
|
1953
|
+
interface DeclaredContacts {
|
|
1954
|
+
policy: ContactPolicy;
|
|
1955
|
+
rule: AuthorityContactRule;
|
|
1956
|
+
pass: AuthoritySeatPass;
|
|
1957
|
+
/** The static world the policy runs through (for the head slabs' stand test). */
|
|
1958
|
+
env: ContactEnv;
|
|
1959
|
+
/** The pair rule a drawing runs against your entity `you` (its id): yours fixed, the other seat
|
|
1960
|
+
* taking the whole push its way allows (§17.11 *Drawing other seats*). */
|
|
1961
|
+
drawRule: (you: string) => AuthorityContactRule;
|
|
1962
|
+
}
|
|
1963
|
+
/**
|
|
1964
|
+
* The policy the room's preset text declares (`{ name, params, contacts }`), run through `world` (the
|
|
1965
|
+
* static world this client steps the preset through); null when the text declares none.
|
|
1966
|
+
*/
|
|
1967
|
+
declare function declaredContacts(presetText: string, world: ContactWorldSpec): DeclaredContacts | null;
|
|
1968
|
+
|
|
1969
|
+
/** The field's range: the tick modulo this (a uint16 on the wire). */
|
|
1970
|
+
declare const INPUT_TICK_MOD = 65536;
|
|
1971
|
+
/** The farthest an input's applied tick may be from the tick it carries, in seconds of ticks: past it
|
|
1972
|
+
* the field is ignored (an input that old, or that far ahead, was not re-timed by pacing). */
|
|
1973
|
+
declare const INPUT_TICK_SLACK_S = 0.5;
|
|
1974
|
+
/** The field a client writes for an input it predicts at server tick `tick` (an integer): `tick`
|
|
1975
|
+
* modulo INPUT_TICK_MOD, in [0, INPUT_TICK_MOD). A tick that is not a finite integer writes 0. */
|
|
1976
|
+
declare function inputTickField(tick: number): number;
|
|
1977
|
+
/** The most ticks an input's applied tick may be off the tick it carries at `tickHz` (at least 1). */
|
|
1978
|
+
declare const inputTickSlack: (tickHz: number) => number;
|
|
1979
|
+
/**
|
|
1980
|
+
* How many ticks later than the client meant an input is applied (negative: earlier): the input
|
|
1981
|
+
* carries `field` (the tick it was predicted for, modulo INPUT_TICK_MOD) and is applied at server tick
|
|
1982
|
+
* `applied`. The carried tick is the one congruent to `field` nearest `applied`; 0 when `field` is not
|
|
1983
|
+
* an integer in [0, INPUT_TICK_MOD), when `applied` is not a safe integer, or when the two are more
|
|
1984
|
+
* than {@link inputTickSlack} apart (a hostile or stale field changes nothing).
|
|
1985
|
+
*/
|
|
1986
|
+
declare function inputTickLag(field: unknown, applied: number, tickHz: number): number;
|
|
1987
|
+
|
|
1988
|
+
/** One seat's head slabs: the posed solids and, by the same index, the id of the seat each is the top of. */
|
|
1989
|
+
interface HeadSlabs {
|
|
1990
|
+
readonly solids: PosedSolid[];
|
|
1991
|
+
readonly lowers: string[];
|
|
1992
|
+
}
|
|
1993
|
+
/** Whether a policy has any `stand` rule (its top or a pair's): a room without one has no head slabs. */
|
|
1994
|
+
declare function hasStand(policy: ContactPolicy): boolean;
|
|
1995
|
+
/** Seat `lower`'s top as a slab at its place plus its velocity over `dt`: `groundTrace` thick under the
|
|
1996
|
+
* top, a hull's square footprint, a box turned with its heading. */
|
|
1997
|
+
declare function headSlab(lower: PolicyBody, policy: ContactPolicy, dt: number): PosedSolid;
|
|
1998
|
+
/** Whether any seat could get any other's slab moved by up to `dt` of its velocity (the height band
|
|
1999
|
+
* and the reach alone): false lets a tick skip the heads altogether, with the same result. */
|
|
2000
|
+
declare function mayStand(seats: readonly PolicyBody[], policy: ContactPolicy, dt?: number): boolean;
|
|
2001
|
+
/**
|
|
2002
|
+
* Every seat's head slabs (ids ascending in `seats`, read as they are): for seat i, the slab of each
|
|
2003
|
+
* other seat it may stand on, in order, at its place plus its velocity over `dt` (0 at the tick's start
|
|
2004
|
+
* for the carry slot's support; the tick's dt for the input steps).
|
|
2005
|
+
*/
|
|
2006
|
+
declare function headSlabs(seats: readonly PolicyBody[], policy: ContactPolicy, env: ContactEnv, dt: number): HeadSlabs[];
|
|
2007
|
+
/** A seat as the prop rule reads it: its feet and velocity (room units, per second). */
|
|
2008
|
+
interface PropSeat {
|
|
2009
|
+
readonly key: string;
|
|
2010
|
+
readonly x: number;
|
|
2011
|
+
readonly y: number;
|
|
2012
|
+
readonly z: number;
|
|
2013
|
+
readonly vx: number;
|
|
2014
|
+
readonly vy: number;
|
|
2015
|
+
}
|
|
2016
|
+
/** A dynamic module body as the prop rule reads it after the last step: centre and velocity. */
|
|
2017
|
+
interface PropBody {
|
|
2018
|
+
readonly key: string;
|
|
2019
|
+
readonly p: readonly number[];
|
|
2020
|
+
readonly v: readonly number[];
|
|
2021
|
+
}
|
|
2022
|
+
/** A velocity the prop rule sets (room units per second). */
|
|
2023
|
+
interface PropNudge {
|
|
2024
|
+
key: string;
|
|
2025
|
+
v: [number, number, number];
|
|
2026
|
+
}
|
|
2027
|
+
/** The first seat (in the order given) whose top a body centred at `p` is over, as the prop rule reads
|
|
2028
|
+
* it (within its preset body's footprint `half`, above its top by at most the seat's height): a test
|
|
2029
|
+
* of the body's place alone. */
|
|
2030
|
+
declare function seatUnderProp(seats: readonly PropSeat[], half: readonly number[], p: readonly number[]): PropSeat | undefined;
|
|
2031
|
+
/**
|
|
2032
|
+
* The prop rule under `headFriction: slide` (after the module's body rule, before the physics step):
|
|
2033
|
+
* each dynamic body (key order) whose centre is over a seat's top (within its preset body's footprint
|
|
2034
|
+
* `half`, above its top by at most the seat's height; the first such seat in key order) has its
|
|
2035
|
+
* parting from that seat, along the way from the seat's centre to its own (+x when centred), brought
|
|
2036
|
+
* up to `slide.speed` by at most `slide.step`; vertical speed kept. Float64 on float32 inputs.
|
|
2037
|
+
*/
|
|
2038
|
+
declare function propSlideNudges(seats: readonly PropSeat[], half: readonly number[], bodies: readonly PropBody[], slide: PropSlide): PropNudge[];
|
|
2039
|
+
|
|
2040
|
+
/** `[psin(a), pcos(a)]` in one reduction (§17.7's steps 1–7; steps 2–5 are shared). */
|
|
2041
|
+
declare function psincos(a: number): [number, number];
|
|
2042
|
+
/** The portable sine of a float64 angle (§17.7): the same bits in every engine. A non-finite angle,
|
|
2043
|
+
* or one past ±1e9, is read as 0. */
|
|
2044
|
+
declare const psin: (a: number) => number;
|
|
2045
|
+
/** The portable cosine of a float64 angle (§17.7): the same bits in every engine. A non-finite
|
|
2046
|
+
* angle, or one past ±1e9, is read as 0 (cosine 1). */
|
|
2047
|
+
declare const pcos: (a: number) => number;
|
|
2048
|
+
|
|
2049
|
+
/** Which transport a seat's motion and inputs are on. */
|
|
2050
|
+
declare const FastTransport: {
|
|
2051
|
+
readonly Udp: "udp";
|
|
2052
|
+
readonly WebSocket: "websocket";
|
|
2053
|
+
};
|
|
2054
|
+
type FastTransport = (typeof FastTransport)[keyof typeof FastTransport];
|
|
2055
|
+
/** Why a seat that never had the channel is on the WebSocket. A fallback's reason is `FastFallbackReason`. */
|
|
2056
|
+
declare const FastNotAsked: {
|
|
2057
|
+
/** The game turned it off (`fast: false`, `bFastChannel = false`, ...). */
|
|
2058
|
+
readonly Off: "off";
|
|
2059
|
+
/** This runtime has no UDP socket (WebGL, a browser with no opener). */
|
|
2060
|
+
readonly NoUdp: "no_udp";
|
|
2061
|
+
/** The seat asked and the room sent no binding. */
|
|
2062
|
+
readonly NotOffered: "not_offered";
|
|
2063
|
+
};
|
|
2064
|
+
type FastNotAsked = (typeof FastNotAsked)[keyof typeof FastNotAsked];
|
|
2065
|
+
/** How long after a socket's first state a seat waits for its binding before it says the room offered
|
|
2066
|
+
* none: the binding follows the state on one ordered stream, so any wait covers it; the handshake's. */
|
|
2067
|
+
declare const FAST_OFFER_WAIT_MS = 1000;
|
|
2068
|
+
/** The line for a seat on UDP to `url`. */
|
|
2069
|
+
declare const udpLine: (url: string) => string;
|
|
2070
|
+
/** The line for a seat on the WebSocket because of `reason` (a {@link FastNotAsked} or a fallback reason). */
|
|
2071
|
+
declare const webSocketLine: (reason: string) => string;
|
|
2072
|
+
/** What a seat knows of its channel at one instant. */
|
|
2073
|
+
interface FastLineObservation {
|
|
2074
|
+
/** The game left the channel on. */
|
|
2075
|
+
asked: boolean;
|
|
2076
|
+
/** This runtime has a UDP socket to open. */
|
|
2077
|
+
udp: boolean;
|
|
2078
|
+
/** Milliseconds since this socket's first state; null before it. */
|
|
2079
|
+
joinedMs: number | null;
|
|
2080
|
+
/** The binding's url; null before one came. */
|
|
2081
|
+
url: string | null;
|
|
2082
|
+
/** Snapshots applied on this socket. */
|
|
2083
|
+
snapshots: number;
|
|
2084
|
+
/** Why this socket fell back; null if it has not. */
|
|
2085
|
+
fallback: string | null;
|
|
2086
|
+
}
|
|
2087
|
+
/** Says each line once per socket. */
|
|
2088
|
+
interface FastLineAnnouncer {
|
|
2089
|
+
/** The line this instant owes, or null. */
|
|
2090
|
+
observe(o: FastLineObservation): string | null;
|
|
2091
|
+
/** A new socket: everything may be said again. */
|
|
2092
|
+
reset(): void;
|
|
2093
|
+
}
|
|
2094
|
+
/** A seat's announcer. */
|
|
2095
|
+
declare function fastLineAnnouncer(): FastLineAnnouncer;
|
|
2096
|
+
|
|
2097
|
+
/** What the session reads of a seat's fast channel. */
|
|
2098
|
+
interface FastSeatStatus {
|
|
2099
|
+
/** Snapshots are flowing and inputs go by datagram. */
|
|
2100
|
+
readonly live: boolean;
|
|
2101
|
+
/** Snapshots applied on this session. */
|
|
2102
|
+
readonly snapshots: number;
|
|
2103
|
+
/** Why this seat is on the WebSocket, else null (on the channel, connecting, or the game turned it
|
|
2104
|
+
* off): {@link FastFallbackReason}. */
|
|
2105
|
+
readonly fallback: FastFallbackReason | null;
|
|
2106
|
+
/** Times this session fell back. */
|
|
2107
|
+
readonly fallbacks: number;
|
|
2108
|
+
/** Times this session came back to the channel after a fallback. */
|
|
2109
|
+
readonly returns: number;
|
|
2110
|
+
/** The transport as last said: UDP once a snapshot came over it, the WebSocket before that and after a fallback. */
|
|
2111
|
+
readonly transport: FastTransport;
|
|
2112
|
+
/** The newest transport line (fast-line.ts), once there is one: names the transport and why. */
|
|
2113
|
+
readonly line: string | null;
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
/** One latency sample of `url` in ms; rejects (or never settles) when the relay doesn't answer. */
|
|
2117
|
+
type RelayProbe = (url: string, timeoutMs: number) => Promise<number>;
|
|
2118
|
+
type RelaySelectOptions = {
|
|
2119
|
+
/** Default: one Colyseus ping (`Client.getLatency`) on a fresh socket. */
|
|
2120
|
+
probe?: RelayProbe;
|
|
2121
|
+
/** Samples per relay, taken concurrently. */
|
|
2122
|
+
samples?: number;
|
|
2123
|
+
/** A sample still unanswered after this is a failed sample; also the whole selection's ceiling. */
|
|
2124
|
+
timeoutMs?: number;
|
|
2125
|
+
/** Once any relay has answered, how much longer the others get before the choice is made. */
|
|
2126
|
+
graceMs?: number;
|
|
2127
|
+
};
|
|
2128
|
+
|
|
2129
|
+
/** One region of the authority cluster: its name and the servers a join may enter it through. */
|
|
2130
|
+
type AuthorityRegion = {
|
|
2131
|
+
region: string;
|
|
2132
|
+
urls: string[];
|
|
2133
|
+
};
|
|
2134
|
+
/** A region as a join enters it: through one of its urls. */
|
|
2135
|
+
type AuthorityRegionPick = {
|
|
2136
|
+
region: string;
|
|
2137
|
+
url: string;
|
|
2138
|
+
};
|
|
2139
|
+
/** One attempt of a join: the region (an index into the ranked list) and the wait before it, ms. */
|
|
2140
|
+
type CapacityAttempt = {
|
|
2141
|
+
region: number;
|
|
2142
|
+
waitMs: number;
|
|
2143
|
+
};
|
|
2144
|
+
/** Refusals (503) in a row on one region before the next attempt goes to the next-best region. */
|
|
2145
|
+
declare const AUTHORITY_REFUSALS_PER_REGION = 2;
|
|
2146
|
+
/** The regions a client uses, read leniently from `colyseus.authorityRegions`, else one per flat url. */
|
|
2147
|
+
declare function normalizeAuthorityRegions(regions: unknown, urls: unknown): AuthorityRegion[];
|
|
2148
|
+
/** The url each probe sample of a region goes to: sample n to url n modulo the url count. */
|
|
2149
|
+
declare function regionProbePlan(urls: readonly string[], samples: number): string[];
|
|
2150
|
+
/** The order regions are tried in, from each url's best sample (`best[region][url]`; anything but a
|
|
2151
|
+
* finite number ≥ 0 is no answer). */
|
|
2152
|
+
declare function rankAuthorityRegions(regions: readonly AuthorityRegion[], best: readonly (readonly unknown[] | undefined)[]): AuthorityRegionPick[];
|
|
2153
|
+
/** Every attempt of a join that every server refuses 503, over `regionCount` ranked regions and the
|
|
2154
|
+
* capacity schedule `delays`: a prefix of it is the walk of a join that is seated. */
|
|
2155
|
+
declare function capacityWalk(regionCount: number, delays: readonly number[]): CapacityAttempt[];
|
|
2156
|
+
/** What a refused join does next (§17.1 *Regions*). */
|
|
2157
|
+
declare const RefusalKind: {
|
|
2158
|
+
/** A full region, or a process shutting down that a sibling answers: the schedule, on this region. */
|
|
2159
|
+
readonly Capacity: "capacity";
|
|
2160
|
+
/** A dead path, with other regions healthy: the next region at once. */
|
|
2161
|
+
readonly NextRegion: "next_region";
|
|
2162
|
+
/** The server's answer: final. */
|
|
2163
|
+
readonly Final: "final";
|
|
2164
|
+
};
|
|
2165
|
+
type RefusalKind = (typeof RefusalKind)[keyof typeof RefusalKind];
|
|
2166
|
+
/** What a join refused with `code` does next; no number at all is a network that failed. */
|
|
2167
|
+
declare function refusalKind(code: unknown): RefusalKind;
|
|
2168
|
+
/** Probes every region (relay-select.ts's tolerant samples, one url per sample) and answers the order
|
|
2169
|
+
* to try them in. One region is not probed; none answers []. Never rejects on a probe. */
|
|
2170
|
+
declare function selectAuthorityRegions(regions: readonly AuthorityRegion[], options?: RelaySelectOptions): Promise<AuthorityRegionPick[]>;
|
|
2171
|
+
|
|
2172
|
+
/** The rejoin's schedule and windows, ms. */
|
|
2173
|
+
declare const REJOIN: {
|
|
2174
|
+
/** Waits before each attempt; past the end the last one repeats. */
|
|
2175
|
+
readonly scheduleMs: readonly [0, 250, 500, 1000, 2000, 4000];
|
|
2176
|
+
/** Each wait adds up to this much, by chance, so a room's seats do not arrive at once. */
|
|
2177
|
+
readonly jitterMs: 250;
|
|
2178
|
+
/** How long a seat keeps trying: long enough for a roll's next process to come up on a full node. */
|
|
2179
|
+
readonly budgetMs: 180000;
|
|
2180
|
+
/** How long a seat stays with its own region before it tries the next one. */
|
|
2181
|
+
readonly regionStayMs: 60000;
|
|
2182
|
+
/** How long a public seat looks for its room's successor before it joins the game's pool. */
|
|
2183
|
+
readonly successorMs: 90000;
|
|
2184
|
+
};
|
|
2185
|
+
/** How long a successor room stays closed to the game's pool. Longer than `REJOIN.successorMs`, so a
|
|
2186
|
+
* late seat of the lost room still reaches it; then it serves the pool like any room. */
|
|
2187
|
+
declare const SUCCESSOR_OPEN_MS = 120000;
|
|
2188
|
+
/** The ways back: the lost room by its id (a socket drop, where it may still live), its successor, or
|
|
2189
|
+
* the game's pool. */
|
|
2190
|
+
declare const RejoinWay: {
|
|
2191
|
+
readonly Room: "room";
|
|
2192
|
+
readonly Successor: "successor";
|
|
2193
|
+
readonly Pool: "pool";
|
|
2194
|
+
};
|
|
2195
|
+
type RejoinWay = (typeof RejoinWay)[keyof typeof RejoinWay];
|
|
2196
|
+
/** Why a rejoin stopped. */
|
|
2197
|
+
declare const RejoinStop: {
|
|
2198
|
+
readonly Final: "final";
|
|
2199
|
+
readonly Budget: "budget";
|
|
2200
|
+
};
|
|
2201
|
+
type RejoinStop = (typeof RejoinStop)[keyof typeof RejoinStop];
|
|
2202
|
+
/** What an attempt is decided from. */
|
|
2203
|
+
interface RejoinInput {
|
|
2204
|
+
/** Attempts already made. */
|
|
2205
|
+
attempt: number;
|
|
2206
|
+
/** Since the close. */
|
|
2207
|
+
elapsedMs: number;
|
|
2208
|
+
/** What the last attempt was refused with; null for none yet or a failed network. */
|
|
2209
|
+
refusal: number | null;
|
|
2210
|
+
/** The close that started this rejoin. */
|
|
2211
|
+
lostCode: number;
|
|
2212
|
+
/** The lost room was private: its seats keep to its successor. */
|
|
2213
|
+
closed: boolean;
|
|
2214
|
+
/** How many regions the client knows. */
|
|
2215
|
+
regions: number;
|
|
2216
|
+
/** A number in [0, 1): the attempt's share of the jitter window. */
|
|
2217
|
+
jitter: number;
|
|
2218
|
+
}
|
|
2219
|
+
type RejoinStep = {
|
|
2220
|
+
stop: RejoinStop;
|
|
2221
|
+
} | {
|
|
2222
|
+
waitMs: number;
|
|
2223
|
+
region: number;
|
|
2224
|
+
way: RejoinWay;
|
|
2225
|
+
};
|
|
2226
|
+
/** Whether a seat closed with `code` goes back into play by itself. */
|
|
2227
|
+
declare function comesBackAfter(code: number): boolean;
|
|
2228
|
+
/** The next attempt of a rejoin, or why there is none. */
|
|
2229
|
+
declare function rejoinStep(input: RejoinInput): RejoinStep;
|
|
2230
|
+
/** Whether `value` can name a lost room: a room code, so nothing else reaches a room filter. */
|
|
2231
|
+
declare function validSuccessorOf(value: unknown): value is string;
|
|
2232
|
+
/** The options a seat's successor join adds to the join's own. */
|
|
2233
|
+
declare function planSuccessorJoin(input: {
|
|
2234
|
+
lostRoomId: string;
|
|
2235
|
+
matchKey: string;
|
|
2236
|
+
closed: boolean;
|
|
2237
|
+
}): {
|
|
2238
|
+
matchKey?: string;
|
|
2239
|
+
successorOf: string;
|
|
2240
|
+
successorClosed?: true;
|
|
2241
|
+
};
|
|
2242
|
+
|
|
2243
|
+
/** `draining`: the server closes this room in `closesInMs`, -1 when an older server does not say. Play
|
|
2244
|
+
* on: the seat moves by itself at the close. */
|
|
2245
|
+
type AuthorityDraining = {
|
|
2246
|
+
closesInMs: number;
|
|
2247
|
+
};
|
|
2248
|
+
/** `rejoining`: the room is gone and attempt `attempt` (from 1) of finding the next one starts in
|
|
2249
|
+
* `waitMs`. `code` is the close that lost it. Show "reconnecting"; there is nothing to do. */
|
|
2250
|
+
type AuthorityRejoining = {
|
|
2251
|
+
attempt: number;
|
|
2252
|
+
code: number;
|
|
2253
|
+
waitMs: number;
|
|
2254
|
+
};
|
|
2255
|
+
/** `rejoined`: back in play, as a new seat in a new room (the invite `code` is new too). */
|
|
2256
|
+
type AuthorityRejoined = {
|
|
2257
|
+
code: string;
|
|
2258
|
+
url: string;
|
|
2259
|
+
};
|
|
2260
|
+
|
|
2261
|
+
/** The own-entity fields a prediction step may read and write: the pose and velocity always, and
|
|
2262
|
+
* firstperson's `pitch`, `duck`, `mstate` and `cap` and vehicle's `spin` and `fuel` when a step
|
|
2263
|
+
* lists them in `fields`. */
|
|
2264
|
+
type PredictedBody = Pick<EntityData, 'x' | 'y' | 'z' | 'vx' | 'vy' | 'vz' | 'yaw'> & Partial<Pick<EntityData, 'pitch' | 'duck' | 'mstate' | 'cap' | 'spin' | 'fuel'>>;
|
|
2265
|
+
type PredictedField = keyof PredictedBody;
|
|
2266
|
+
/** A game's own prediction step: advance `body` by one fixed step of `dt` seconds under `input`
|
|
2267
|
+
* (already sanitized like the server's). It must be the step the room module runs. */
|
|
2268
|
+
type AuthorityStep = (body: PredictedBody, input: InputData, dt: number, posed?: PosedWorld) => void;
|
|
2269
|
+
/** How the own entity is predicted: with your step, mirroring `fields` (default: all of them). */
|
|
2270
|
+
type AuthorityPrediction = {
|
|
2271
|
+
step: AuthorityStep;
|
|
2272
|
+
fields?: readonly PredictedField[];
|
|
2273
|
+
};
|
|
2274
|
+
type AuthorityConnectOptions = {
|
|
2275
|
+
/** Authority cluster urls (pass `getAuthorityUrls()` from @genex-ai/embed-sdk). Without `regions`,
|
|
2276
|
+
* each is a region of its own (§17.1 *Regions*): several are probed for latency like the relay's;
|
|
2277
|
+
* one connects straight to it. */
|
|
2278
|
+
urls: string[];
|
|
2279
|
+
/** The cluster's regions (pass `getAuthorityRegions()` from @genex-ai/embed-sdk), §17.1 *Regions*:
|
|
2280
|
+
* one url per sample of each region is probed, the nearest region is joined, and a join refused 503
|
|
2281
|
+
* twice there moves to the next-best one. Each region is its own matchmaking pool. Omitted or with
|
|
2282
|
+
* nothing usable, `urls` are the regions. */
|
|
2283
|
+
regions?: readonly AuthorityRegion[];
|
|
2284
|
+
/** Override: connect to THIS exact url, skipping latency selection: an invitee passes the inviter's
|
|
2285
|
+
* `session.url` and lands in the inviter's region (a party plays in its leader's region). */
|
|
2286
|
+
url?: string;
|
|
2287
|
+
/** One latency sample of a url (relay-select.ts `RelayProbe`). Default: one Colyseus ping. For tests
|
|
2288
|
+
* and benches; a game leaves it unset. */
|
|
2289
|
+
probe?: RelayProbe;
|
|
2290
|
+
/** Game id (your project slug): everyone who passes the same id shares a room. */
|
|
2291
|
+
room: string;
|
|
2292
|
+
/** Display-name fallback when the token carries none. */
|
|
2293
|
+
name?: string;
|
|
2294
|
+
/** Verified identity, as for `connect()`: pass `() => genexEmbed.getColyseusAuth()` after
|
|
2295
|
+
* `await genexEmbed.waitForPlayer()`. Read fresh at every join attempt. NEVER log it. */
|
|
2296
|
+
auth?: AuthSource;
|
|
2297
|
+
/** Own-entity prediction. Omitted: predict with the room's movement preset when it runs one, and
|
|
2298
|
+
* render the server's state otherwise. `false`: never predict. An object: predict with your step. */
|
|
2299
|
+
predict?: false | AuthorityPrediction;
|
|
2300
|
+
/** How far in the past other entities render, ms. Default `AuthorityTiming.RENDER_DELAY_MS`. */
|
|
2301
|
+
renderDelayMs?: number;
|
|
2302
|
+
/** How other entities' samples are timed in a predicting room (§17.11 *Drawing other seats*):
|
|
2303
|
+
* `tick` (default) by their keyframe's tick, `patch` by the patch's server stamp (every other room's
|
|
2304
|
+
* way, kept for comparison). */
|
|
2305
|
+
remoteSamples?: 'tick' | 'patch';
|
|
2306
|
+
/** How other seats are drawn when the room has a seat contact rule (`contacts`, §17.11 *Drawing other
|
|
2307
|
+
* seats*): `predicted` (default, the Rocket League model) on your own entity's clock, every other
|
|
2308
|
+
* seat stepped from the latest state by the room preset under its last input (`remotePredict`) with
|
|
2309
|
+
* the room's contact pass run on every seat, yours included, so a bump is predicted where it is
|
|
2310
|
+
* drawn, each correction drawn as a decaying offset; `separate` on the render timeline like every
|
|
2311
|
+
* other entity, then moved out of your drawn entity by the rule and taken round it, never across it
|
|
2312
|
+
* (draw-only); `timeline` on the render timeline only, where a seat that missed yours on the server
|
|
2313
|
+
* can be drawn through it. Both `predicted` and `separate` keep every seat out of yours and out of
|
|
2314
|
+
* each other on screen (`separateSeats`). */
|
|
2315
|
+
seatDrawing?: SeatDrawing;
|
|
2316
|
+
/** The pool to join (§17.2 *Choosing a room*): players with one key share rooms, and the room module
|
|
2317
|
+
* reads it at init to choose a world or mode. At most 32 of a-z 0-9 . _ : -; absent: the game's one
|
|
2318
|
+
* pool. Give the world the key picks to `world` (`selectMatchWorld`). */
|
|
2319
|
+
matchKey?: string;
|
|
2320
|
+
/** The `firstperson` or `vehicle` collision world, as the room module exports it (`setWorld` later, too):
|
|
2321
|
+
* your own entity is predicted only while its hash equals the room's `params.world`. */
|
|
2322
|
+
world?: FirstpersonWorldSpec | FirstpersonWorld;
|
|
2323
|
+
/** The physicsHash of a physics world this client runs a copy of (`setPhysics` later, too). A
|
|
2324
|
+
* mismatch is reported (`physics`); prediction checks the room's hash itself. */
|
|
2325
|
+
physics?: string;
|
|
2326
|
+
/** Loads the physics core that predicts a predicting room's bodies (§17.11): `@genex-ai/physics`
|
|
2327
|
+
* (contract 1.1) after its `init()`, e.g. `async () => { const p = await import('@genex-ai/physics');
|
|
2328
|
+
* await p.init(); return p; }`. Called only once a room sends keyframes; omitted, bodies are drawn
|
|
2329
|
+
* from the server (§17.10) everywhere. The room's static world is the one given to `world`. */
|
|
2330
|
+
physicsCore?: () => Promise<PredictCore>;
|
|
2331
|
+
/** `false` never predicts physics bodies, even with `physicsCore` (the client's kill switch). */
|
|
2332
|
+
predictPhysics?: boolean;
|
|
2333
|
+
/** A replay budget, ms, that overrides the device's (§17.11 *Budgets*: 4 desktop, 5 mobile) when it
|
|
2334
|
+
* is a finite number over 0; anything else is ignored. For benches and CI that hold every client
|
|
2335
|
+
* to one budget on a slow host; a game leaves it unset. */
|
|
2336
|
+
physicsBudgetMs?: number;
|
|
2337
|
+
/** The clock replays are timed on, ms (default `performance.now`), for the replay budget
|
|
2338
|
+
* (§17.11 *Budgets*). Tests and conformance runs whose point is not CPU speed hand it a fixed
|
|
2339
|
+
* clock so a slow host can never turn prediction off (`cpu`); a game leaves it unset. */
|
|
2340
|
+
physicsClock?: () => number;
|
|
2341
|
+
/** The room module's seat contact rule (§17.11 *Seat contacts*), run in your own entity's
|
|
2342
|
+
* prediction; omitted, a contact between seats arrives as a correction. */
|
|
2343
|
+
contacts?: AuthorityContactRule;
|
|
2344
|
+
/** The room module's whole seat contact pass (§17.11 *Seat contacts*: car-ball's pairs, pile passes
|
|
2345
|
+
* and world passes), which `seatDrawing: 'predicted'` runs on every seat after each predicted tick;
|
|
2346
|
+
* omitted, `contacts` runs once on every pair. */
|
|
2347
|
+
contactPass?: AuthoritySeatPass;
|
|
2348
|
+
/** The room module's seat rule (§17.11 *Seat rules*), run on your own entity before each predicted
|
|
2349
|
+
* input (with that input's tick and sequence) and, in an `inputDecay` room, on other seats' bodies
|
|
2350
|
+
* before each of their steps. */
|
|
2351
|
+
seatRule?: AuthoritySeatRule;
|
|
2352
|
+
/** The room module's body rule (§17.11 *Body rules*), run before every step of the client world;
|
|
2353
|
+
* omitted, what the module does to its bodies arrives as a correction. */
|
|
2354
|
+
bodyRule?: PredictBodyRule;
|
|
2355
|
+
/** The room module's kinematic rule (§17.11 *Kinematic rules*): where it poses its kinematic bodies
|
|
2356
|
+
* (a door, a platform, a moving floor) at each tick, so the client world moves them as the room does
|
|
2357
|
+
* and draws them as predicted bodies; omitted, they hold each keyframe's pose and are drawn from the
|
|
2358
|
+
* server's states. */
|
|
2359
|
+
kinematicRule?: PredictKinematicRule;
|
|
2360
|
+
/** The fast channel (PROTOCOL.md §17.12): on by default wherever this runtime can reach it, UDP in Node and
|
|
2361
|
+
* WebTransport in a browser whose room's server runs the relay. Your inputs and the room's motion go by
|
|
2362
|
+
* datagram, everything else stays on the WebSocket, and the seat falls back to the WebSocket and returns by
|
|
2363
|
+
* itself (`session.fast` says when and why, and one line says so). An opener is the socket to use instead.
|
|
2364
|
+
* `false` keeps the seat on the WebSocket. */
|
|
2365
|
+
fast?: FastSocketOpener | false;
|
|
2366
|
+
/** Where the transport line goes (fast-line.ts). Default: stderr in Node, else `console.info`. */
|
|
2367
|
+
fastLog?: (line: string) => void;
|
|
2368
|
+
/** The millisecond clock the fast channel's deadlines and round trips run on (default
|
|
2369
|
+
* `performance.now`). */
|
|
2370
|
+
fastClock?: () => number;
|
|
2371
|
+
/** Waits before each retry of a join refused for capacity (503). Default 1 s, 2 s, 4 s; `[]` never
|
|
2372
|
+
* retries. No other refusal is retried. */
|
|
2373
|
+
capacityRetryMs?: readonly number[];
|
|
2374
|
+
/** Whether a seat whose room ended for a deploy, or whose socket no reconnect restored, goes back into
|
|
2375
|
+
* play by itself (§17.13 *Drain and rejoin*). Default true; false makes that close final. */
|
|
2376
|
+
rejoin?: boolean;
|
|
2377
|
+
/** Every message the server sends, in order, by type: the room module's events and the server's
|
|
2378
|
+
* own (`server:restart` before a drain), with no name withheld. For a facade that forwards them
|
|
2379
|
+
* all, such as the engine bridge; a game subscribes with `on(type)`. */
|
|
2380
|
+
onEvent?: (type: string, data: unknown) => void;
|
|
2381
|
+
};
|
|
2382
|
+
/** An entity as this client renders it. */
|
|
2383
|
+
type AuthorityEntityView = {
|
|
2384
|
+
id: string;
|
|
2385
|
+
kind: string;
|
|
2386
|
+
/** Owning seat's session id, or ''. */
|
|
2387
|
+
owner: string;
|
|
2388
|
+
/** Rendered: interpolated for other entities, predicted for your own. */
|
|
2389
|
+
x: number;
|
|
2390
|
+
y: number;
|
|
2391
|
+
z: number;
|
|
2392
|
+
/** Rendered heading, radians in [-π, π). */
|
|
2393
|
+
yaw: number;
|
|
2394
|
+
vx: number;
|
|
2395
|
+
vy: number;
|
|
2396
|
+
vz: number;
|
|
2397
|
+
hp: number;
|
|
2398
|
+
flags: number;
|
|
2399
|
+
epoch: number;
|
|
2400
|
+
/** The entity's JSON text, '' = none. */
|
|
2401
|
+
data: string;
|
|
2402
|
+
/** A projectile's launch tick (§17.9), 0 = not a projectile. A projectile's x..vz are drawn from
|
|
2403
|
+
* its flight; your own prediction's is the (fractional) tick it was fired at. */
|
|
2404
|
+
t0: number;
|
|
2405
|
+
/** A projectile's downward acceleration, units/s². */
|
|
2406
|
+
g: number;
|
|
2407
|
+
/** The seat that fired a projectile, '' = none. */
|
|
2408
|
+
src: string;
|
|
2409
|
+
/** A firstperson body's aim pitch, radians: predicted for yours, interpolated for others, within
|
|
2410
|
+
* the preset's ±pitchLimit. */
|
|
2411
|
+
pitch: number;
|
|
2412
|
+
/** A firstperson body's duck amount, 0 standing to 1 fully ducked: predicted or interpolated. */
|
|
2413
|
+
duck: number;
|
|
2414
|
+
/** A firstperson body's movement bits (1 onGround, 2 ducking, 4 jumpHeld): predicted for yours,
|
|
2415
|
+
* the server's latest for others. */
|
|
2416
|
+
mstate: number;
|
|
2417
|
+
/** A firstperson body's speed multiplier, or a vehicle's top-speed multiplier, as the server last
|
|
2418
|
+
* wrote it (default 1). */
|
|
2419
|
+
cap: number;
|
|
2420
|
+
/** A vehicle body's yaw rate, rad/s, positive toward +yaw: predicted for yours, the server's
|
|
2421
|
+
* latest for others (for wheels and skids; the heading itself is `yaw`). */
|
|
2422
|
+
spin: number;
|
|
2423
|
+
/** A vehicle body's boost fuel, [0, 1]: predicted for yours, the server's latest for others. */
|
|
2424
|
+
fuel: number;
|
|
2425
|
+
/** A physics body (§17.10): drawn at the server's present from its body state, extrapolated and
|
|
2426
|
+
* eased (x, y, z and the orientation below), never interpolated behind. False for every other
|
|
2427
|
+
* entity. A body out of this client's view is still listed, held where its last state left it. */
|
|
2428
|
+
body: boolean;
|
|
2429
|
+
/** A physics body's drawn orientation, a unit quaternion (z up, the server's axes); the identity
|
|
2430
|
+
* for every other entity, whose heading is `yaw`. */
|
|
2431
|
+
qx: number;
|
|
2432
|
+
qy: number;
|
|
2433
|
+
qz: number;
|
|
2434
|
+
qw: number;
|
|
2435
|
+
/** The server put this physics body to sleep (it is drawn where it is). False for other entities. */
|
|
2436
|
+
sleep: boolean;
|
|
2437
|
+
/** This physics body is predicted (§17.11) rather than drawn from the server's states; or this other
|
|
2438
|
+
* seat is drawn predicted on your clock (`seatDrawing: 'predicted'`). */
|
|
2439
|
+
predicted?: boolean;
|
|
2440
|
+
/** A seat drawn predicted: how far it is drawn from its predicted pose (room units), the correction
|
|
2441
|
+
* still being eased in plus any push out of another drawn seat. */
|
|
2442
|
+
correction?: number;
|
|
2443
|
+
};
|
|
2444
|
+
/** Whether your own entity is predicted, and why not when it is not:
|
|
2445
|
+
* - `off`: `predict: false`;
|
|
2446
|
+
* - `no_entity`: you own no entity (yet);
|
|
2447
|
+
* - `no_preset`: the room runs no movement preset this client knows, and you gave no step;
|
|
2448
|
+
* - `world_mismatch`: the room's firstperson or vehicle world is not the one given to `setWorld` (its hash is
|
|
2449
|
+
* `world`, the room's `roomWorld`): your entity renders from the server's state, unpredicted. */
|
|
2450
|
+
type AuthorityPredictionStatus = {
|
|
2451
|
+
predicting: boolean;
|
|
2452
|
+
reason: '' | 'off' | 'no_entity' | 'no_preset' | 'world_mismatch';
|
|
2453
|
+
/** The hash of this client's world (the empty world's until `setWorld`). */
|
|
2454
|
+
world: number;
|
|
2455
|
+
/** The world the room's preset steps through (`params.world`), or null when it has none. */
|
|
2456
|
+
roomWorld: number | null;
|
|
2457
|
+
};
|
|
2458
|
+
/** Whether this client's copy of the room's physics world is the room's (§17.10 *The resolved
|
|
2459
|
+
* config*): `physics_mismatch` when the room runs physics (`roomPhysics` is not '') and its hash is
|
|
2460
|
+
* not the one given to `setPhysics` (''), as `world_mismatch` is for presets. Such a client never
|
|
2461
|
+
* steps its copy from the room's state. */
|
|
2462
|
+
type AuthorityPhysicsStatus = {
|
|
2463
|
+
reason: '' | 'physics_mismatch';
|
|
2464
|
+
/** The hash given to `setPhysics`, '' until then. */
|
|
2465
|
+
physics: string;
|
|
2466
|
+
/** The room's `physics` (its world's physicsHash), '' in a room without physics. */
|
|
2467
|
+
roomPhysics: string;
|
|
2468
|
+
};
|
|
2469
|
+
/** A projectile your game fires, as it predicts it (`predictProjectile`): where it starts, its
|
|
2470
|
+
* velocity and its gravity, in world units — the values the room module launches it with. */
|
|
2471
|
+
type ProjectilePrediction = {
|
|
2472
|
+
kind: string;
|
|
2473
|
+
x: number;
|
|
2474
|
+
y: number;
|
|
2475
|
+
z: number;
|
|
2476
|
+
vx: number;
|
|
2477
|
+
vy: number;
|
|
2478
|
+
vz: number;
|
|
2479
|
+
/** Downward acceleration along −z, units/s², [0, 1000]. Default 0. */
|
|
2480
|
+
g?: number;
|
|
2481
|
+
};
|
|
2482
|
+
/** A seated player. */
|
|
2483
|
+
type AuthorityPlayerView = {
|
|
2484
|
+
id: string;
|
|
2485
|
+
name: string;
|
|
2486
|
+
uid: string;
|
|
2487
|
+
team: string;
|
|
2488
|
+
connected: boolean;
|
|
2489
|
+
avatarUrl: string;
|
|
2490
|
+
};
|
|
2491
|
+
/** What the session measured. Counters only grow. */
|
|
2492
|
+
type AuthorityTelemetry = {
|
|
2493
|
+
/** Inputs transmitted. */
|
|
2494
|
+
inputsSent: number;
|
|
2495
|
+
/** Input steps that came due while the socket was down, and were not sent (never queued). */
|
|
2496
|
+
inputsDropped: number;
|
|
2497
|
+
/** Server acks the reconciler checked its prediction against. */
|
|
2498
|
+
reconciles: number;
|
|
2499
|
+
/** Reconciles that moved the own entity's place by more than 5 cm (0.05 × the room's units per metre). */
|
|
2500
|
+
visibleCorrections: number;
|
|
2501
|
+
/** The visible corrections by size, metres: under 0.5, 0.5-1, 1-5, 5-20 and over 20
|
|
2502
|
+
* (CORRECTION_BUCKET_METRES); they sum to `visibleCorrections`. */
|
|
2503
|
+
correctionBuckets: number[];
|
|
2504
|
+
/** Largest correction of the own entity's place seen, and the latest one: the length of the move, in
|
|
2505
|
+
* room units. Velocity and angles are never in it. */
|
|
2506
|
+
peakCorrection: number;
|
|
2507
|
+
lastCorrection: number;
|
|
2508
|
+
/** Largest correction of any other mirrored field (velocity, heading, pitch, duck), each in its own
|
|
2509
|
+
* unit, so only zero or not says anything: with `peakCorrection`, whether the prediction was exact. */
|
|
2510
|
+
peakStateCorrection: number;
|
|
2511
|
+
/** Times the prediction was re-seeded from the server: an epoch bump on your own entity (a respawn
|
|
2512
|
+
* or teleport, snapped to the server's new pose and never counted as a correction) or a reconnect. */
|
|
2513
|
+
reseeds: number;
|
|
2514
|
+
/** Physics body states received (§17.10), and how many of them snapped instead of easing in
|
|
2515
|
+
* (the first state of a body, an epoch change, or an offset over one metre). */
|
|
2516
|
+
bodyStates: number;
|
|
2517
|
+
bodySnaps: number;
|
|
2518
|
+
/** Largest correction a body state started, room units (eased away, never drawn as a jump). */
|
|
2519
|
+
peakBodyCorrection: number;
|
|
2520
|
+
/** Projectiles `predictProjectile` drew before the server had them. */
|
|
2521
|
+
projectilesPredicted: number;
|
|
2522
|
+
/** Predictions the server's projectile of the same id confirmed. */
|
|
2523
|
+
projectilesConfirmed: number;
|
|
2524
|
+
/** Predictions no server projectile confirmed, and dropped: the server refused the shot, or removed
|
|
2525
|
+
* it before any state patch carried it (a point-blank hit), or its input was lost in a drop. Found
|
|
2526
|
+
* once the server acknowledges the firing input or the reconnect's first state lacks it, else
|
|
2527
|
+
* after max(2·RTT, 600 ms), a stalled link's silence not counted. */
|
|
2528
|
+
projectilesRejected: number;
|
|
2529
|
+
/** The latest confirmation's input lead, ms: the server's launch instant minus the prediction's. */
|
|
2530
|
+
lastProjectileLeadMs: number;
|
|
2531
|
+
};
|
|
2532
|
+
type AuthoritySession = {
|
|
2533
|
+
/** This seat's session id: the `owner` of your entity. */
|
|
2534
|
+
readonly id: string;
|
|
2535
|
+
/** The server this session joined through (its region's, §17.1 *Regions*). An invite carries it:
|
|
2536
|
+
* an invitee passes it as `url` and plays in this session's region. */
|
|
2537
|
+
readonly url: string;
|
|
2538
|
+
/** The input sent on each step. Mutate it any time; `frame()` sends it. */
|
|
2539
|
+
readonly input: InputData;
|
|
2540
|
+
/** Call once per render frame, before reading positions. Sends one input per due fixed step and
|
|
2541
|
+
* advances prediction and interpolation. Returns how many inputs it sent. */
|
|
2542
|
+
frame(now?: number): number;
|
|
2543
|
+
/** Your own entity (the first one you own that is not a projectile), predicted. */
|
|
2544
|
+
me(): AuthorityEntityView | undefined;
|
|
2545
|
+
/**
|
|
2546
|
+
* The `firstperson` or `vehicle` collision world: the same `{ boxes, ramps }` the room module exports. Validated
|
|
2547
|
+
* by §17.7's rules (a refused world throws a `WorldError` and changes nothing) and hashed; your
|
|
2548
|
+
* own entity is predicted while that hash equals the room's `params.world`, and rendered from the
|
|
2549
|
+
* server's state otherwise (`prediction` says which). Returns the hash. Call it before the first
|
|
2550
|
+
* `frame()`, or pass `world` to `connectAuthority`; a later call re-seeds the prediction.
|
|
2551
|
+
*/
|
|
2552
|
+
setWorld(world: FirstpersonWorldSpec | FirstpersonWorld): number;
|
|
2553
|
+
/** The room's invite code (§17.2 *Choosing a room*): friends pass it to `joinPrivateAuthority()`. */
|
|
2554
|
+
readonly code: string;
|
|
2555
|
+
/** The room's match key, '' for none. A friend who joined by code reads it here once the first state
|
|
2556
|
+
* has landed, to hand the room's world to `setWorld`; until then its entity is unpredicted. */
|
|
2557
|
+
readonly matchKey: string;
|
|
2558
|
+
/** Whether your own entity is predicted right now, and why not. */
|
|
2559
|
+
readonly prediction: AuthorityPredictionStatus;
|
|
2560
|
+
/** Hands the SDK the physicsHash (16 hex digits) of the physics world your client runs a copy of
|
|
2561
|
+
* (§17.10). When the room runs physics with another hash, `physics` reports `physics_mismatch`
|
|
2562
|
+
* (and a console warning explains it once). Returns the hash. */
|
|
2563
|
+
setPhysics(hash: string): string;
|
|
2564
|
+
/** Whether your physics copy matches the room's. */
|
|
2565
|
+
readonly physics: AuthorityPhysicsStatus;
|
|
2566
|
+
/** Whether the room's bodies are predicted (§17.11), why not, and how keyframes were adopted. */
|
|
2567
|
+
readonly physicsPrediction: Readonly<PhysicsPredictionStatus>;
|
|
2568
|
+
/** The tick other seats were last drawn at (`seatDrawing: 'predicted'`): the state after that tick,
|
|
2569
|
+
* fractional between two, on your own entity's clock; NaN when they are drawn on the render
|
|
2570
|
+
* timeline (another drawing, or nothing to predict from yet). */
|
|
2571
|
+
drawTick(): number;
|
|
2572
|
+
/** How far ahead of the server's present (ms, on this client's estimate of the room clock) other
|
|
2573
|
+
* seats were last drawn: `drawTick` as an instant; NaN when it is. */
|
|
2574
|
+
drawLead(): number;
|
|
2575
|
+
/** Where declared lift `id` is drawn now (§17.11 *Lifts*): its centre and yaw on your entity's clock
|
|
2576
|
+
* (between your drawn input's ticks at the same alpha), else on the render timeline; undefined for
|
|
2577
|
+
* a room without that lift. */
|
|
2578
|
+
liftPose(id: string): {
|
|
2579
|
+
x: number;
|
|
2580
|
+
y: number;
|
|
2581
|
+
z: number;
|
|
2582
|
+
yaw: number;
|
|
2583
|
+
} | undefined;
|
|
2584
|
+
/** The turn (radians) your view owes the lift your entity stands on since your last call: the
|
|
2585
|
+
* lift's turn between the ticks the server applies your newest input at then and now, as the
|
|
2586
|
+
* latest state maps your inputs to ticks; 0 off one, and on the call that finds you on it. A
|
|
2587
|
+
* firstperson game adds it to its view yaw once a frame, after `frame(now)`, so your view turns with
|
|
2588
|
+
* a spinner tick for tick, also across a tick the server stepped two of your inputs or none
|
|
2589
|
+
* (§17.11 *Lifts*, *Input pacing*). */
|
|
2590
|
+
viewCarry(): number;
|
|
2591
|
+
/**
|
|
2592
|
+
* Predict a projectile you fire (§17.9): call it while staging the input that fires, before the
|
|
2593
|
+
* `frame()` that sends it. It is drawn at once from this launch, under the id the room gives it
|
|
2594
|
+
* (`<seat>.<seq>.<n>`: the input's sequence and your launches during it), and `entities()` keeps
|
|
2595
|
+
* that id when the server's projectile arrives, drawn on from where the prediction was. One the
|
|
2596
|
+
* state never shows (a cooldown, a dead shooter, or a hit before any patch carried it) is dropped
|
|
2597
|
+
* as soon as the server acknowledges the input that fired it, one whose input a drop lost at the
|
|
2598
|
+
* reconnect's first state, and any at the latest after max(2·RTT, 600 ms) (a stall in which no
|
|
2599
|
+
* state arrives, the socket up, is not counted). Returns the id, or
|
|
2600
|
+
* `''` (and predicts nothing) while the socket is down: from a drop until the reconnect's first
|
|
2601
|
+
* state, and after the session ends.
|
|
2602
|
+
*/
|
|
2603
|
+
predictProjectile(projectile: ProjectilePrediction): string;
|
|
2604
|
+
entity(id: string): AuthorityEntityView | undefined;
|
|
2605
|
+
/** Every entity, rendered, your predicted projectiles included. A fresh map per call. */
|
|
2606
|
+
entities(): Map<string, AuthorityEntityView>;
|
|
2607
|
+
/** Every seated player. A fresh map per call. */
|
|
2608
|
+
players(): Map<string, AuthorityPlayerView>;
|
|
2609
|
+
/** The fixed-step tick the server last wrote. */
|
|
2610
|
+
readonly tick: number;
|
|
2611
|
+
/** False from a drop until the reconnect's first state lands, and after the session ends. */
|
|
2612
|
+
readonly connected: boolean;
|
|
2613
|
+
readonly telemetry: Readonly<AuthorityTelemetry>;
|
|
2614
|
+
/** The fast channel (§17.12): whether it is live, snapshots applied, and why it fell back. */
|
|
2615
|
+
readonly fast: FastSeatStatus;
|
|
2616
|
+
on(event: 'reconnecting', handler: (info: {
|
|
2617
|
+
code: number;
|
|
2618
|
+
}) => void): () => void;
|
|
2619
|
+
on(event: 'reconnected', handler: () => void): () => void;
|
|
2620
|
+
/** The session is over: a close nothing comes back from, or a rejoin that ran out (§17.13). `reason` is why an authority room
|
|
2621
|
+
* ended, for you, the game's creator: show players AUTHORITY_ROOM_ENDED_TEXT, not the code. Null with no such reason. */
|
|
2622
|
+
on(event: 'disconnect', handler: (code: number, reason: AuthorityCloseCode | null) => void): () => void;
|
|
2623
|
+
/** The server closes this room soon, for a deploy (§17.13). Play on: the seat moves by itself. */
|
|
2624
|
+
on(event: 'draining', handler: (info: AuthorityDraining) => void): () => void;
|
|
2625
|
+
/** The room is gone and the seat is on its way back. Say so; there is nothing to do. */
|
|
2626
|
+
on(event: 'rejoining', handler: (info: AuthorityRejoining) => void): () => void;
|
|
2627
|
+
/** Back in play: a new seat (`id`) in a new room (`code`). */
|
|
2628
|
+
on(event: 'rejoined', handler: (info: AuthorityRejoined) => void): () => void;
|
|
2629
|
+
/** A game event the room module emitted. */
|
|
2630
|
+
on(event: string, handler: (data: unknown) => void): () => void;
|
|
2631
|
+
/** Leave on purpose. Never reconnects. */
|
|
2632
|
+
leave(): Promise<void>;
|
|
2633
|
+
};
|
|
2634
|
+
/** How other seats are drawn with a seat contact rule (`seatDrawing`). */
|
|
2635
|
+
declare const SEAT_DRAWINGS: readonly ["predicted", "separate", "timeline"];
|
|
2636
|
+
type SeatDrawing = ContactDrawing;
|
|
2637
|
+
/** The drawing a session with a seat contact rule uses when `seatDrawing` is not given: the Rocket
|
|
2638
|
+
* League model (the car-ball owner's reference), every seat predicted on your clock. */
|
|
2639
|
+
declare const DEFAULT_SEAT_DRAWING: SeatDrawing;
|
|
2640
|
+
/**
|
|
2641
|
+
* Join a server-authoritative room (PROTOCOL.md §17) and return its session.
|
|
2642
|
+
*
|
|
2643
|
+
* ```ts
|
|
2644
|
+
* const s = await connectAuthority({ urls: genexEmbed.getAuthorityUrls(), room: 'my-game',
|
|
2645
|
+
* auth: () => genexEmbed.getColyseusAuth() });
|
|
2646
|
+
* function loop(now) {
|
|
2647
|
+
* s.input.moveX = right - left; s.input.moveY = up - down; s.input.yaw = aim;
|
|
2648
|
+
* s.frame(now); // send due inputs, predict, interpolate
|
|
2649
|
+
* draw(s.me(), s.entities());
|
|
2650
|
+
* requestAnimationFrame(loop);
|
|
2651
|
+
* }
|
|
2652
|
+
* ```
|
|
2653
|
+
*
|
|
2654
|
+
* A refused join rejects with the server's error; its `code` is a {@link JoinError}. 402
|
|
2655
|
+
* (`NOT_ENTITLED`), 424, 429 and 426 are not retried; 503 is retried per `capacityRetryMs`.
|
|
2656
|
+
*/
|
|
2657
|
+
declare function connectAuthority(opts: AuthorityConnectOptions): Promise<AuthoritySession>;
|
|
2658
|
+
/**
|
|
2659
|
+
* Creates a private authority room (§17.2 *Choosing a room*) and returns its session: `session.code`
|
|
2660
|
+
* is the invite, which friends pass to `joinPrivateAuthority()`. No matchmaking ever reaches the room.
|
|
2661
|
+
* `matchKey` chooses its world or mode as it does a pool's.
|
|
2662
|
+
*/
|
|
2663
|
+
declare function createPrivateAuthority(opts: AuthorityConnectOptions): Promise<AuthoritySession>;
|
|
2664
|
+
/**
|
|
2665
|
+
* Joins the private authority room with invite `code`, walking the regions until one holds it. The
|
|
2666
|
+
* room's key is its own (`session.matchKey`, once the first state lands): hand its world to `setWorld`
|
|
2667
|
+
* with `selectMatchWorld`. `opts.matchKey` must be unset.
|
|
2668
|
+
*/
|
|
2669
|
+
declare function joinPrivateAuthority(code: string, opts: AuthorityConnectOptions): Promise<AuthoritySession>;
|
|
2670
|
+
|
|
2671
|
+
export { AUTHORITY_REFUSALS_PER_REGION, AuthorityBody, AuthorityCloseCode, type AuthorityConnectOptions, AuthorityContactRule, type AuthorityDraining, AuthorityEntity, type AuthorityEntityView, AuthorityInput, AuthorityJoinMethod, type AuthorityJoinPlan, AuthorityJoint, AuthorityLimits, AuthorityPhysicsEntity, AuthorityPhysicsRoomState, type AuthorityPhysicsStatus, AuthorityPlayer, type AuthorityPlayerView, type AuthorityPrediction, type AuthorityPredictionStatus, type AuthorityRegion, type AuthorityRegionPick, type AuthorityRejoined, type AuthorityRejoining, AuthorityRoomLimits, AuthorityRoomState, type AuthorityRoomTarget, type AuthoritySeatPass, AuthoritySeatRule, type AuthoritySession, AuthorityShape, type AuthorityStep, AuthorityTargetRefusal, type AuthorityTelemetry, CONVEYOR_RATE, type Carried, type CarryReport, type CastHit, ContactBody, ContactDrawing, type ContactEnv, ContactEvent, ContactKind, type ContactPassOptions, ContactPolicy, type ContactReport, type ContactWorld, type ContactWorldSpec, type ConveyorBody, DEFAULT_SEAT_DRAWING, DEFAULT_TICK_HZ, type DeclaredContacts, type DrawnPose, EntityData, type EntityIndex, type EntityOut, type EventOut, FAST_OFFER_WAIT_MS, type FaceFilter, FastFallbackReason, type FastLineAnnouncer, type FastLineObservation, FastNotAsked, type FastSeatStatus, FastSocketOpener, FastTransport, FirstpersonWorld, FirstpersonWorldSpec, type Frame, GuestGlobal, HEAD_LANDING_SPEED, HeadHold, type HeadSlabs, type HeadsContext, type HeldSeat, HullBody, HullOps, INPUT_REPEAT_MAX_MS, INPUT_REPEAT_RUN_MS, INPUT_REPEAT_STEADY, INPUT_TICK_MOD, INPUT_TICK_SLACK_S, type InitOut, InputData, InputRepeat, type InputThrottle, InputUse, Json, type KinematicSupport, LeaveReason, Lift, type LiftBodyPose, type LiftCollider, type LiftPose, type LiftSeat, LiftSolidsCache, type LiftTick, LiftVec, LiftsPolicy, MAX_PROJECTILE_G, MAX_PROJECTILE_TICK, MAX_TICK_HZ, MOTION_VIEW_TAG, PHYSICS_ONLY_TICK_HZ, type PairContact, type PairOutcome, PhysAnswerRow, PhysBodyRow, type PhysCommand, PhysEvRow, type PhysicsAdmission, PhysicsCeiling, PhysicsErrorCode, type PhysicsPredictionStatus, type PhysicsTickIndex, type Plane, PlayerInfo, type PolicyBody, PosedSolid, PosedWorld, PredictBodyRule, PredictCore, PredictKinematicRule, PredictStatus, type PredictedBody, type PredictedField, PresetName, type ProjectileLaunch, type ProjectilePrediction, type ProjectileState, type PropBody, type PropNudge, type PropSeat, PropSlide, REJOIN, RIDE_CHAIN_MAX, type ReconcilerAckHold, RefusalKind, type RejoinInput, type RejoinStep, RejoinStop, RejoinWay, RemoteInput, RemotePredict, ResolvedModuleConfig, type Ride, type RiderPose, SEAT_DRAWINGS, SHOVE_EASE_DONE, STALL_PREDICT_MS, STEADY_BUCKETS, SUCCESSOR_OPEN_MS, type SeatChange, type SeatClock, type SeatDrawing, type SeatLifts, type SeatMotion, type SeatOffset, type SeatPass, type SeatPose, type SeatRate, type SeatRepeats, type SeatStep, SeatWorld, type SeatWorldLifts, type SeatWorldOptions, ShotWorldCount, SlideWay, type SolidGrid, StandRule, THROTTLE_DILATION, THROTTLE_LOW_INPUTS, THROTTLE_SEAT_LEAD, TICK_RATES, TickHz, type TickIn, type TickInput, type TickOut, TickOutFault, type TickSolids, TopRule, UNSTICK_SOLIDS, type V3, type WireResult, WorldCost, WorldCostMeter, type WorldCostReport, capacityWalk, carryOnLift, carrySlot, carryTick, castWorld, comesBackAfter, compileContactWorld, connectAuthority, consumedUse, contactOf, contactPair, contactPass, contactPassOf, contactRuleOf, conveyorNudges, conveyorUnder, createPrivateAuthority, declaredContacts, farApart, fastLineAnnouncer, feedWithPayback, forgiveRepeats, frameOf, hasStand, headHold, headOffset, headSlab, headSlabs, headStands, impartSlot, impartTick, inLiftFrame, inputThrottle, inputTickField, inputTickLag, inputTickSlack, insideFace, insideWorld, isProjectile, joinPrivateAuthority, liftBodyKey, liftBodyPose, liftBodySpawn, liftCollider, liftDrawnAt, liftPose, liftPoses, liftPosesAt, liftStartsOf, liftTopAt, liftUnder, matchKeyOf, mayStand, nextCodeRegion, normalizeAuthorityRegions, pcos, planAuthorityJoin, planSuccessorJoin, posedFor, posedSolids, projectileAt, propSlideNudges, psin, psincos, rankAuthorityRegions, reconcileThrough, reconcilerAck, reconcilerAckHold, refusalKind, regionProbePlan, rejoinStep, repeatMaxTicks, repeatRunTicks, repeatStarved, repeatsSeat, rideSlot, rideStep, rideTick, ridesOn, rodeBy, roomAlong, sameHeldInput, sanitizeInput, seatClock, seatLeadClock, seatLiftsOf, seatOffset, seatRepeats, seatTauMs, seatTouchShare, seatUnderProp, selectAuthorityRegions, selectMatchWorld, serverTick, shoveEase, spinStep, stateThrough, stepOnLifts, steppedThrough, surfaceUp, tagsOf, throttleState, throttleSteps, tickInstant, tickSolids, topRuleOf, udpLine, unstickBody, validMatchKey, validRoomCode, validSuccessorOf, validateInitOut, validateTickOut, viewOnLift, webSocketLine, worldCost, yieldShares };
|