@jgengine/core 0.6.0 → 0.8.0

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.
Files changed (330) hide show
  1. package/CHANGELOG.md +214 -2
  2. package/README.md +2 -0
  3. package/dist/ai/crowd.d.ts +36 -0
  4. package/dist/ai/crowd.js +213 -0
  5. package/dist/ai/jobBoard.d.ts +49 -0
  6. package/dist/ai/jobBoard.js +155 -0
  7. package/dist/ai/spawnDirector.d.ts +61 -0
  8. package/dist/ai/spawnDirector.js +162 -0
  9. package/dist/ai/threat.d.ts +25 -0
  10. package/dist/ai/threat.js +67 -0
  11. package/dist/anim/easing.d.ts +14 -0
  12. package/dist/anim/easing.js +55 -0
  13. package/dist/audio/audioFalloff.d.ts +38 -0
  14. package/dist/audio/audioFalloff.js +32 -0
  15. package/dist/behaviour/behaviour.d.ts +136 -0
  16. package/dist/behaviour/behaviour.js +388 -0
  17. package/dist/board/laneBoard.d.ts +63 -0
  18. package/dist/board/laneBoard.js +114 -0
  19. package/dist/board/timelineBoard.d.ts +36 -0
  20. package/dist/board/timelineBoard.js +70 -0
  21. package/dist/cards/cardPile.d.ts +64 -0
  22. package/dist/cards/cardPile.js +175 -0
  23. package/dist/cards/modifierPipeline.d.ts +33 -0
  24. package/dist/cards/modifierPipeline.js +48 -0
  25. package/dist/combat/abilityKit.d.ts +47 -0
  26. package/dist/combat/abilityKit.js +139 -0
  27. package/dist/combat/animationState.d.ts +47 -0
  28. package/dist/combat/animationState.js +101 -0
  29. package/dist/combat/attackTags.d.ts +14 -0
  30. package/dist/combat/attackTags.js +26 -0
  31. package/dist/combat/breakMeters.d.ts +32 -0
  32. package/dist/combat/breakMeters.js +51 -0
  33. package/dist/combat/comboString.d.ts +35 -0
  34. package/dist/combat/comboString.js +59 -0
  35. package/dist/combat/death.d.ts +8 -0
  36. package/dist/combat/death.js +5 -2
  37. package/dist/combat/defensiveWindow.d.ts +34 -0
  38. package/dist/combat/defensiveWindow.js +66 -0
  39. package/dist/combat/downed.d.ts +35 -0
  40. package/dist/combat/downed.js +104 -0
  41. package/dist/combat/effects.d.ts +12 -1
  42. package/dist/combat/effects.js +31 -19
  43. package/dist/combat/hitReaction.d.ts +23 -0
  44. package/dist/combat/hitReaction.js +20 -0
  45. package/dist/combat/projectiles.d.ts +42 -5
  46. package/dist/combat/projectiles.js +98 -12
  47. package/dist/combat/resistance.d.ts +13 -0
  48. package/dist/combat/resistance.js +46 -0
  49. package/dist/combat/telegraph.d.ts +31 -0
  50. package/dist/combat/telegraph.js +51 -0
  51. package/dist/commands/commandRegistry.d.ts +1 -1
  52. package/dist/commands/commandRegistry.js +2 -1
  53. package/dist/crafting/crop.d.ts +59 -0
  54. package/dist/crafting/crop.js +181 -0
  55. package/dist/crafting/production.d.ts +64 -0
  56. package/dist/crafting/production.js +130 -0
  57. package/dist/crafting/recipe.d.ts +62 -0
  58. package/dist/crafting/recipe.js +101 -0
  59. package/dist/data/dataSource.d.ts +26 -0
  60. package/dist/data/dataSource.js +93 -0
  61. package/dist/data/devProxy.d.ts +11 -0
  62. package/dist/data/devProxy.js +38 -0
  63. package/dist/data/fetchJson.d.ts +20 -0
  64. package/dist/data/fetchJson.js +43 -0
  65. package/dist/data/jsonDataSource.d.ts +4 -0
  66. package/dist/data/jsonDataSource.js +6 -0
  67. package/dist/devtools/devtools.d.ts +157 -0
  68. package/dist/devtools/devtools.js +484 -0
  69. package/dist/devtools/transformTunables.d.ts +14 -0
  70. package/dist/devtools/transformTunables.js +38 -0
  71. package/dist/economy/sharedWallet.d.ts +28 -0
  72. package/dist/economy/sharedWallet.js +62 -0
  73. package/dist/economy/techTree.d.ts +40 -0
  74. package/dist/economy/techTree.js +66 -0
  75. package/dist/game/chat.d.ts +66 -0
  76. package/dist/game/chat.js +165 -0
  77. package/dist/game/cosmetics.d.ts +25 -0
  78. package/dist/game/cosmetics.js +51 -0
  79. package/dist/game/defineGame.d.ts +10 -2
  80. package/dist/game/defineGame.js +2 -1
  81. package/dist/game/events.d.ts +87 -0
  82. package/dist/game/levelSequence.d.ts +44 -0
  83. package/dist/game/levelSequence.js +78 -0
  84. package/dist/game/lootFilter.d.ts +33 -0
  85. package/dist/game/lootFilter.js +48 -0
  86. package/dist/game/ping.d.ts +67 -0
  87. package/dist/game/ping.js +86 -0
  88. package/dist/game/playableGame.d.ts +516 -8
  89. package/dist/game/playableGame.js +6 -1
  90. package/dist/game/progression.d.ts +1 -0
  91. package/dist/game/progression.js +23 -2
  92. package/dist/game/race.d.ts +100 -0
  93. package/dist/game/race.js +236 -0
  94. package/dist/game/runDraft.d.ts +34 -0
  95. package/dist/game/runDraft.js +97 -0
  96. package/dist/game/social.d.ts +69 -0
  97. package/dist/game/social.js +138 -0
  98. package/dist/game/spawnPoints.d.ts +19 -0
  99. package/dist/game/spawnPoints.js +23 -0
  100. package/dist/game/worldItem.d.ts +95 -0
  101. package/dist/game/worldItem.js +138 -0
  102. package/dist/input/actionBindings.d.ts +10 -0
  103. package/dist/input/actionBindings.js +14 -0
  104. package/dist/input/axisInput.d.ts +43 -0
  105. package/dist/input/axisInput.js +70 -0
  106. package/dist/input/gestureSurface.d.ts +31 -0
  107. package/dist/input/gestureSurface.js +120 -0
  108. package/dist/input/pointer.d.ts +69 -0
  109. package/dist/input/pointer.js +65 -0
  110. package/dist/input/touchScheme.d.ts +83 -0
  111. package/dist/input/touchScheme.js +115 -0
  112. package/dist/interaction/contextMenu.d.ts +30 -0
  113. package/dist/interaction/contextMenu.js +22 -0
  114. package/dist/interaction/qte.d.ts +20 -0
  115. package/dist/interaction/qte.js +24 -0
  116. package/dist/interaction/skillCheck.d.ts +20 -0
  117. package/dist/interaction/skillCheck.js +26 -0
  118. package/dist/inventory/shapedGrid.d.ts +56 -0
  119. package/dist/inventory/shapedGrid.js +176 -0
  120. package/dist/inventory/storageTier.d.ts +52 -0
  121. package/dist/inventory/storageTier.js +77 -0
  122. package/dist/item/affix.d.ts +54 -0
  123. package/dist/item/affix.js +115 -0
  124. package/dist/item/durability.d.ts +51 -0
  125. package/dist/item/durability.js +78 -0
  126. package/dist/item/modularItem.d.ts +46 -0
  127. package/dist/item/modularItem.js +75 -0
  128. package/dist/meta/changelog.d.ts +1 -1
  129. package/dist/meta/changelog.js +71 -1
  130. package/dist/movement/dash.d.ts +37 -0
  131. package/dist/movement/dash.js +65 -0
  132. package/dist/movement/movementModel.d.ts +36 -3
  133. package/dist/movement/movementModel.js +81 -5
  134. package/dist/movement/voxelController.d.ts +61 -0
  135. package/dist/movement/voxelController.js +229 -0
  136. package/dist/multiplayer/chatContract.d.ts +42 -0
  137. package/dist/multiplayer/chatContract.js +57 -0
  138. package/dist/multiplayer/combatSnapshot.d.ts +45 -0
  139. package/dist/multiplayer/combatSnapshot.js +89 -0
  140. package/dist/multiplayer/identity.d.ts +13 -0
  141. package/dist/multiplayer/identity.js +20 -0
  142. package/dist/multiplayer/lagCompensation.d.ts +43 -0
  143. package/dist/multiplayer/lagCompensation.js +154 -0
  144. package/dist/multiplayer/matchmaking.d.ts +33 -0
  145. package/dist/multiplayer/matchmaking.js +60 -0
  146. package/dist/multiplayer/poseSyncGate.d.ts +1 -0
  147. package/dist/multiplayer/poseSyncGate.js +13 -1
  148. package/dist/multiplayer/presenceModel.d.ts +3 -0
  149. package/dist/multiplayer/presenceModel.js +15 -1
  150. package/dist/multiplayer/simultaneousCommit.d.ts +34 -0
  151. package/dist/multiplayer/simultaneousCommit.js +53 -0
  152. package/dist/multiplayer/voiceContract.d.ts +44 -0
  153. package/dist/multiplayer/voiceContract.js +108 -0
  154. package/dist/nav/navConstrain.d.ts +14 -0
  155. package/dist/nav/navConstrain.js +26 -0
  156. package/dist/nav/navFromEnvironment.d.ts +11 -0
  157. package/dist/nav/navFromEnvironment.js +16 -0
  158. package/dist/nav/navGrid.d.ts +56 -0
  159. package/dist/nav/navGrid.js +265 -0
  160. package/dist/nav/pathFollow.d.ts +31 -0
  161. package/dist/nav/pathFollow.js +69 -0
  162. package/dist/physics/ballisticSweep.d.ts +18 -0
  163. package/dist/physics/ballisticSweep.js +49 -0
  164. package/dist/physics/buoyancy.d.ts +49 -0
  165. package/dist/physics/buoyancy.js +112 -0
  166. package/dist/physics/carryable.d.ts +46 -0
  167. package/dist/physics/carryable.js +110 -0
  168. package/dist/physics/damageZones.d.ts +56 -0
  169. package/dist/physics/damageZones.js +107 -0
  170. package/dist/physics/forceVolume.d.ts +48 -0
  171. package/dist/physics/forceVolume.js +119 -0
  172. package/dist/physics/physicsWorld.d.ts +124 -2
  173. package/dist/physics/physicsWorld.js +493 -41
  174. package/dist/physics/ragdoll.d.ts +49 -0
  175. package/dist/physics/ragdoll.js +103 -0
  176. package/dist/physics/spatialGrid.d.ts +41 -0
  177. package/dist/physics/spatialGrid.js +143 -0
  178. package/dist/physics/structure.d.ts +83 -0
  179. package/dist/physics/structure.js +0 -0
  180. package/dist/physics/traversal.d.ts +75 -0
  181. package/dist/physics/traversal.js +138 -0
  182. package/dist/physics/vehicleBody.d.ts +99 -0
  183. package/dist/physics/vehicleBody.js +233 -0
  184. package/dist/puzzle/cellGrid.d.ts +26 -0
  185. package/dist/puzzle/cellGrid.js +110 -0
  186. package/dist/puzzle/fallingPiece.d.ts +24 -0
  187. package/dist/puzzle/fallingPiece.js +51 -0
  188. package/dist/random/nameGen.d.ts +18 -0
  189. package/dist/random/nameGen.js +35 -0
  190. package/dist/random/rng.d.ts +2 -0
  191. package/dist/random/rng.js +23 -0
  192. package/dist/runtime/adapter.d.ts +35 -0
  193. package/dist/runtime/adapter.js +37 -1
  194. package/dist/runtime/cameraDirector.d.ts +10 -0
  195. package/dist/runtime/cameraDirector.js +25 -0
  196. package/dist/runtime/gameContext.d.ts +107 -3
  197. package/dist/runtime/gameContext.js +253 -7
  198. package/dist/runtime/hostPersistence.d.ts +39 -0
  199. package/dist/runtime/hostPersistence.js +54 -0
  200. package/dist/runtime/inputSnapshot.d.ts +7 -0
  201. package/dist/runtime/inputSnapshot.js +12 -0
  202. package/dist/runtime/motionIntents.d.ts +25 -0
  203. package/dist/runtime/motionIntents.js +25 -0
  204. package/dist/runtime/persistenceScope.d.ts +32 -0
  205. package/dist/runtime/persistenceScope.js +64 -0
  206. package/dist/runtime/transport.d.ts +32 -0
  207. package/dist/scene/autoTarget.d.ts +15 -0
  208. package/dist/scene/autoTarget.js +54 -0
  209. package/dist/scene/behaviors.d.ts +13 -1
  210. package/dist/scene/behaviors.js +3 -0
  211. package/dist/scene/captureCheck.d.ts +7 -0
  212. package/dist/scene/captureCheck.js +11 -0
  213. package/dist/scene/entityStore.d.ts +9 -1
  214. package/dist/scene/entityStore.js +25 -2
  215. package/dist/scene/form.d.ts +40 -0
  216. package/dist/scene/form.js +56 -0
  217. package/dist/scene/mount.d.ts +62 -0
  218. package/dist/scene/mount.js +107 -0
  219. package/dist/scene/movementSpeed.d.ts +35 -0
  220. package/dist/scene/movementSpeed.js +20 -0
  221. package/dist/scene/objectQuery.d.ts +18 -0
  222. package/dist/scene/objectQuery.js +108 -0
  223. package/dist/scene/objectStore.d.ts +11 -0
  224. package/dist/scene/objectStore.js +109 -4
  225. package/dist/scene/paintLayer.d.ts +15 -0
  226. package/dist/scene/paintLayer.js +53 -0
  227. package/dist/scene/possession.d.ts +30 -0
  228. package/dist/scene/possession.js +51 -0
  229. package/dist/scene/roster.d.ts +25 -0
  230. package/dist/scene/roster.js +57 -0
  231. package/dist/scene/selection.d.ts +30 -0
  232. package/dist/scene/selection.js +38 -0
  233. package/dist/scene/spatial.d.ts +21 -0
  234. package/dist/scene/spatial.js +63 -1
  235. package/dist/scene/stationClaim.d.ts +43 -0
  236. package/dist/scene/stationClaim.js +109 -0
  237. package/dist/sensor/concealment.d.ts +21 -0
  238. package/dist/sensor/concealment.js +63 -0
  239. package/dist/sensor/freezeMonitor.d.ts +17 -0
  240. package/dist/sensor/freezeMonitor.js +35 -0
  241. package/dist/sensor/frustumSensor.d.ts +60 -0
  242. package/dist/sensor/frustumSensor.js +104 -0
  243. package/dist/sensor/hiddenStateProbe.d.ts +31 -0
  244. package/dist/sensor/hiddenStateProbe.js +40 -0
  245. package/dist/sensor/recordingBuffer.d.ts +29 -0
  246. package/dist/sensor/recordingBuffer.js +61 -0
  247. package/dist/sensor/revealQuery.d.ts +22 -0
  248. package/dist/sensor/revealQuery.js +36 -0
  249. package/dist/session/contestedChannel.d.ts +36 -0
  250. package/dist/session/contestedChannel.js +100 -0
  251. package/dist/session/extraction.d.ts +54 -0
  252. package/dist/session/extraction.js +108 -0
  253. package/dist/session/ring.d.ts +36 -0
  254. package/dist/session/ring.js +88 -0
  255. package/dist/session/roles.d.ts +6 -0
  256. package/dist/session/roles.js +32 -0
  257. package/dist/session/roundState.d.ts +79 -0
  258. package/dist/session/roundState.js +158 -0
  259. package/dist/stats/accumulatorMeter.d.ts +31 -0
  260. package/dist/stats/accumulatorMeter.js +81 -0
  261. package/dist/stats/eventMeter.d.ts +34 -0
  262. package/dist/stats/eventMeter.js +76 -0
  263. package/dist/stats/rollCheck.d.ts +15 -0
  264. package/dist/stats/rollCheck.js +15 -0
  265. package/dist/survival/decayMeter.d.ts +59 -0
  266. package/dist/survival/decayMeter.js +95 -0
  267. package/dist/survival/moodle.d.ts +48 -0
  268. package/dist/survival/moodle.js +91 -0
  269. package/dist/survival/regionHealth.d.ts +72 -0
  270. package/dist/survival/regionHealth.js +129 -0
  271. package/dist/tactics/fallingGrid.d.ts +62 -0
  272. package/dist/tactics/fallingGrid.js +158 -0
  273. package/dist/tactics/predictiveQuery.d.ts +34 -0
  274. package/dist/tactics/predictiveQuery.js +44 -0
  275. package/dist/tactics/snapshot.d.ts +18 -0
  276. package/dist/tactics/snapshot.js +65 -0
  277. package/dist/tactics/surface.d.ts +52 -0
  278. package/dist/tactics/surface.js +135 -0
  279. package/dist/tactics/tacticalGrid.d.ts +68 -0
  280. package/dist/tactics/tacticalGrid.js +261 -0
  281. package/dist/time/beatClock.d.ts +40 -0
  282. package/dist/time/beatClock.js +73 -0
  283. package/dist/time/simClock.d.ts +25 -1
  284. package/dist/time/simClock.js +28 -3
  285. package/dist/turn/commit.d.ts +27 -0
  286. package/dist/turn/commit.js +72 -0
  287. package/dist/turn/intent.d.ts +14 -0
  288. package/dist/turn/intent.js +29 -0
  289. package/dist/turn/turnLoop.d.ts +60 -0
  290. package/dist/turn/turnLoop.js +223 -0
  291. package/dist/world/buildPermissions.d.ts +47 -0
  292. package/dist/world/buildPermissions.js +134 -0
  293. package/dist/world/carve.d.ts +105 -0
  294. package/dist/world/carve.js +175 -0
  295. package/dist/world/connectors.d.ts +40 -0
  296. package/dist/world/connectors.js +67 -0
  297. package/dist/world/envField.d.ts +71 -0
  298. package/dist/world/envField.js +96 -0
  299. package/dist/world/environmentSummary.d.ts +53 -0
  300. package/dist/world/environmentSummary.js +129 -0
  301. package/dist/world/features.d.ts +87 -6
  302. package/dist/world/features.js +52 -2
  303. package/dist/world/fog.d.ts +40 -0
  304. package/dist/world/fog.js +137 -0
  305. package/dist/world/gridInstances.d.ts +13 -0
  306. package/dist/world/gridInstances.js +22 -0
  307. package/dist/world/markers.d.ts +52 -0
  308. package/dist/world/markers.js +96 -0
  309. package/dist/world/minimap.d.ts +42 -0
  310. package/dist/world/minimap.js +72 -0
  311. package/dist/world/placedStructureStore.d.ts +39 -0
  312. package/dist/world/placedStructureStore.js +95 -0
  313. package/dist/world/placementController.d.ts +69 -0
  314. package/dist/world/placementController.js +153 -0
  315. package/dist/world/realm.d.ts +61 -0
  316. package/dist/world/realm.js +66 -0
  317. package/dist/world/support.d.ts +27 -0
  318. package/dist/world/support.js +75 -0
  319. package/dist/world/terraform.d.ts +54 -0
  320. package/dist/world/terraform.js +186 -0
  321. package/dist/world/terrain.d.ts +23 -1
  322. package/dist/world/terrain.js +64 -1
  323. package/dist/world/voxelField.d.ts +54 -0
  324. package/dist/world/voxelField.js +241 -0
  325. package/dist/world/walls.d.ts +61 -0
  326. package/dist/world/walls.js +221 -0
  327. package/dist/world/weather.d.ts +92 -0
  328. package/dist/world/weather.js +169 -0
  329. package/llms.txt +4102 -0
  330. package/package.json +3 -2
@@ -0,0 +1,99 @@
1
+ import type { PhysicsWorld } from "./physicsWorld.js";
2
+ import type { AxisInput } from "../input/axisInput.js";
3
+ export interface GripCurve {
4
+ points: readonly (readonly [number, number])[];
5
+ }
6
+ /**
7
+ * Piecewise-linear tire-grip curve: normalized lateral slip → available grip (0..1). Grip peaks near
8
+ * the breakaway slip then falls off as the tire slides — the shape that separates a planted corner
9
+ * from a drift. Points are read in ascending slip order; ends clamp.
10
+ */
11
+ export declare function sampleGripCurve(curve: GripCurve, slip: number): number;
12
+ export declare const DEFAULT_GRIP_CURVE: GripCurve;
13
+ export interface WheelSpec {
14
+ offset: readonly [number, number, number];
15
+ radius?: number;
16
+ restLength?: number;
17
+ steered?: boolean;
18
+ powered?: boolean;
19
+ handbrakeLocks?: boolean;
20
+ }
21
+ export interface WheelState {
22
+ worldX: number;
23
+ worldY: number;
24
+ worldZ: number;
25
+ grounded: boolean;
26
+ compression: number;
27
+ steerAngle: number;
28
+ }
29
+ export interface VehicleBodyConfig {
30
+ position: readonly [number, number, number];
31
+ heading?: number;
32
+ chassisHalfExtents?: readonly [number, number, number];
33
+ mass?: number;
34
+ wheels?: readonly WheelSpec[];
35
+ engineAccel?: number;
36
+ brakeAccel?: number;
37
+ topSpeed?: number;
38
+ reverseSpeed?: number;
39
+ turnRate?: number;
40
+ turnSpeedRef?: number;
41
+ grip?: GripCurve;
42
+ gripStrength?: number;
43
+ handbrakeGrip?: number;
44
+ rollingResistance?: number;
45
+ suspensionRest?: number;
46
+ suspensionStiffness?: number;
47
+ suspensionDamping?: number;
48
+ groundHeight?: (x: number, z: number) => number;
49
+ surfaceFriction?: (x: number, z: number) => number;
50
+ }
51
+ /**
52
+ * Arcade vehicle over the {@link PhysicsWorld} rigid-body sim. The chassis is a single box body driven
53
+ * by an {@link AxisInput}: per-wheel suspension is a spring-damper held with G3's `springJoint` against
54
+ * the sampled ground, drive/brake push along the heading, and a tire-grip curve bleeds lateral velocity
55
+ * (cornering, and drift under handbrake). Because the chassis is a physics body it still collides — that
56
+ * contact feeds crash damage. Call `update(dt, input)` before the shared `world.step(dt)`.
57
+ */
58
+ export declare class VehicleBody {
59
+ heading: number;
60
+ readonly chassis: number;
61
+ private readonly world;
62
+ private readonly wheels;
63
+ private readonly springs;
64
+ private readonly wheelStates;
65
+ private readonly engineAccel;
66
+ private readonly brakeAccel;
67
+ private readonly topSpeed;
68
+ private readonly reverseSpeed;
69
+ private readonly turnRate;
70
+ private readonly turnSpeedRef;
71
+ private readonly grip;
72
+ private readonly gripStrength;
73
+ private readonly handbrakeGrip;
74
+ private readonly rollingResistance;
75
+ private readonly suspensionRest;
76
+ private readonly groundHeight;
77
+ private readonly surfaceFriction;
78
+ private groundedCount;
79
+ constructor(world: PhysicsWorld, config: VehicleBodyConfig);
80
+ /**
81
+ * A wheel's local offset rotated by the current heading — the ground-side mount and the
82
+ * chassis-side spring anchor both derive from this, so the suspension axis stays vertical (not a
83
+ * mix of rotated and unrotated ends) as the chassis turns.
84
+ */
85
+ private rotateOffset;
86
+ private wheelMount;
87
+ get position(): [number, number, number];
88
+ get forward(): [number, number];
89
+ /** Signed forward speed along the heading (negative = reversing). */
90
+ get speed(): number;
91
+ get grounded(): boolean;
92
+ wheelState(index: number): WheelState | null;
93
+ get wheelCount(): number;
94
+ resetTo(position: readonly [number, number, number], heading: number): void;
95
+ update(dt: number, input: AxisInput): void;
96
+ private updateSuspension;
97
+ remove(): void;
98
+ }
99
+ export declare function createVehicleBody(world: PhysicsWorld, config: VehicleBodyConfig): VehicleBody;
@@ -0,0 +1,233 @@
1
+ /**
2
+ * Piecewise-linear tire-grip curve: normalized lateral slip → available grip (0..1). Grip peaks near
3
+ * the breakaway slip then falls off as the tire slides — the shape that separates a planted corner
4
+ * from a drift. Points are read in ascending slip order; ends clamp.
5
+ */
6
+ export function sampleGripCurve(curve, slip) {
7
+ const pts = curve.points;
8
+ if (pts.length === 0)
9
+ return 1;
10
+ const s = Math.abs(slip);
11
+ if (s <= pts[0][0])
12
+ return pts[0][1];
13
+ for (let i = 1; i < pts.length; i += 1) {
14
+ const [x1, y1] = pts[i];
15
+ if (s <= x1) {
16
+ const [x0, y0] = pts[i - 1];
17
+ const span = x1 - x0;
18
+ const t = span <= 0 ? 0 : (s - x0) / span;
19
+ return y0 + (y1 - y0) * t;
20
+ }
21
+ }
22
+ return pts[pts.length - 1][1];
23
+ }
24
+ export const DEFAULT_GRIP_CURVE = {
25
+ points: [
26
+ [0, 1],
27
+ [0.2, 1],
28
+ [0.45, 0.78],
29
+ [1, 0.55],
30
+ ],
31
+ };
32
+ function cornerWheels(half, rest, radius) {
33
+ const x = half[0];
34
+ const z = half[2];
35
+ const y = -half[1];
36
+ return [
37
+ { offset: [-x, y, z], steered: true, restLength: rest, radius },
38
+ { offset: [x, y, z], steered: true, restLength: rest, radius },
39
+ { offset: [-x, y, -z], powered: true, handbrakeLocks: true, restLength: rest, radius },
40
+ { offset: [x, y, -z], powered: true, handbrakeLocks: true, restLength: rest, radius },
41
+ ];
42
+ }
43
+ /**
44
+ * Arcade vehicle over the {@link PhysicsWorld} rigid-body sim. The chassis is a single box body driven
45
+ * by an {@link AxisInput}: per-wheel suspension is a spring-damper held with G3's `springJoint` against
46
+ * the sampled ground, drive/brake push along the heading, and a tire-grip curve bleeds lateral velocity
47
+ * (cornering, and drift under handbrake). Because the chassis is a physics body it still collides — that
48
+ * contact feeds crash damage. Call `update(dt, input)` before the shared `world.step(dt)`.
49
+ */
50
+ export class VehicleBody {
51
+ heading;
52
+ chassis;
53
+ world;
54
+ wheels;
55
+ springs;
56
+ wheelStates;
57
+ engineAccel;
58
+ brakeAccel;
59
+ topSpeed;
60
+ reverseSpeed;
61
+ turnRate;
62
+ turnSpeedRef;
63
+ grip;
64
+ gripStrength;
65
+ handbrakeGrip;
66
+ rollingResistance;
67
+ suspensionRest;
68
+ groundHeight;
69
+ surfaceFriction;
70
+ groundedCount = 0;
71
+ constructor(world, config) {
72
+ this.world = world;
73
+ this.heading = config.heading ?? 0;
74
+ const half = config.chassisHalfExtents ?? [0.9, 0.35, 1.8];
75
+ this.suspensionRest = config.suspensionRest ?? 0.55;
76
+ const radius = 0.35;
77
+ this.wheels = config.wheels ?? cornerWheels(half, this.suspensionRest, radius);
78
+ this.engineAccel = config.engineAccel ?? 18;
79
+ this.brakeAccel = config.brakeAccel ?? 26;
80
+ this.topSpeed = config.topSpeed ?? 28;
81
+ this.reverseSpeed = config.reverseSpeed ?? 10;
82
+ this.turnRate = config.turnRate ?? 1.6;
83
+ this.turnSpeedRef = config.turnSpeedRef ?? 8;
84
+ this.grip = config.grip ?? DEFAULT_GRIP_CURVE;
85
+ this.gripStrength = config.gripStrength ?? 8;
86
+ this.handbrakeGrip = config.handbrakeGrip ?? 0.35;
87
+ this.rollingResistance = config.rollingResistance ?? 0.6;
88
+ const stiffness = config.suspensionStiffness ?? 60;
89
+ const damping = config.suspensionDamping ?? 8;
90
+ this.groundHeight = config.groundHeight ?? (() => 0);
91
+ this.surfaceFriction = config.surfaceFriction ?? (() => 1);
92
+ this.chassis = world.addBody({
93
+ position: config.position,
94
+ halfExtents: half,
95
+ mass: config.mass ?? 4,
96
+ });
97
+ this.springs = [];
98
+ this.wheelStates = [];
99
+ for (const wheel of this.wheels) {
100
+ const worldPos = this.wheelMount(wheel);
101
+ const rest = wheel.restLength ?? this.suspensionRest;
102
+ const id = world.springJoint({
103
+ bodyA: this.chassis,
104
+ anchorA: this.rotateOffset(wheel.offset),
105
+ anchorB: [worldPos[0], worldPos[1] - rest, worldPos[2]],
106
+ restLength: rest,
107
+ stiffness,
108
+ damping,
109
+ });
110
+ this.springs.push(id);
111
+ this.wheelStates.push({
112
+ worldX: worldPos[0],
113
+ worldY: worldPos[1],
114
+ worldZ: worldPos[2],
115
+ grounded: false,
116
+ compression: 0,
117
+ steerAngle: 0,
118
+ });
119
+ }
120
+ }
121
+ /**
122
+ * A wheel's local offset rotated by the current heading — the ground-side mount and the
123
+ * chassis-side spring anchor both derive from this, so the suspension axis stays vertical (not a
124
+ * mix of rotated and unrotated ends) as the chassis turns.
125
+ */
126
+ rotateOffset(offset) {
127
+ const sin = Math.sin(this.heading);
128
+ const cos = Math.cos(this.heading);
129
+ const [ox, oy, oz] = offset;
130
+ return [ox * cos + oz * sin, oy, -ox * sin + oz * cos];
131
+ }
132
+ wheelMount(wheel) {
133
+ const [dx, dy, dz] = this.rotateOffset(wheel.offset);
134
+ return [this.world.posX[this.chassis] + dx, this.world.posY[this.chassis] + dy, this.world.posZ[this.chassis] + dz];
135
+ }
136
+ get position() {
137
+ return [this.world.posX[this.chassis], this.world.posY[this.chassis], this.world.posZ[this.chassis]];
138
+ }
139
+ get forward() {
140
+ return [Math.sin(this.heading), Math.cos(this.heading)];
141
+ }
142
+ /** Signed forward speed along the heading (negative = reversing). */
143
+ get speed() {
144
+ const [fx, fz] = this.forward;
145
+ return this.world.velX[this.chassis] * fx + this.world.velZ[this.chassis] * fz;
146
+ }
147
+ get grounded() {
148
+ return this.groundedCount > 0;
149
+ }
150
+ wheelState(index) {
151
+ return this.wheelStates[index] ?? null;
152
+ }
153
+ get wheelCount() {
154
+ return this.wheels.length;
155
+ }
156
+ resetTo(position, heading) {
157
+ this.world.teleport(this.chassis, position[0], position[1], position[2]);
158
+ this.heading = heading;
159
+ }
160
+ update(dt, input) {
161
+ const w = this.world;
162
+ const c = this.chassis;
163
+ this.updateSuspension(input.steer);
164
+ const speed = this.speed;
165
+ const grounded = this.groundedCount > 0;
166
+ if (grounded) {
167
+ const steerScale = Math.min(1, Math.abs(speed) / this.turnSpeedRef);
168
+ const dir = speed >= 0 ? 1 : -1;
169
+ this.heading += input.steer * this.turnRate * steerScale * dir * dt;
170
+ }
171
+ const [fx, fz] = this.forward;
172
+ if (grounded) {
173
+ let accel = 0;
174
+ if (input.throttle > 0 && speed < this.topSpeed)
175
+ accel += input.throttle * this.engineAccel;
176
+ if (input.brake > 0) {
177
+ if (speed > 0.2)
178
+ accel -= input.brake * this.brakeAccel;
179
+ else if (speed > -this.reverseSpeed)
180
+ accel -= input.brake * this.engineAccel;
181
+ }
182
+ w.velX[c] += fx * accel * dt;
183
+ w.velZ[c] += fz * accel * dt;
184
+ const roll = Math.max(0, 1 - this.rollingResistance * dt * (input.throttle > 0 ? 0 : 1));
185
+ const forwardSpeed = w.velX[c] * fx + w.velZ[c] * fz;
186
+ const rolled = forwardSpeed * roll;
187
+ const lateralSpeed = -w.velX[c] * fz + w.velZ[c] * fx;
188
+ const surface = this.surfaceFriction(w.posX[c], w.posZ[c]);
189
+ const slip = Math.abs(lateralSpeed) / (Math.abs(forwardSpeed) + 1);
190
+ const handbrake = 1 - input.handbrake * (1 - this.handbrakeGrip);
191
+ const grip = sampleGripCurve(this.grip, slip) * surface * handbrake;
192
+ const keep = Math.max(0, 1 - grip * this.gripStrength * dt);
193
+ const newLateral = lateralSpeed * keep;
194
+ w.velX[c] = fx * rolled - fz * newLateral;
195
+ w.velZ[c] = fz * rolled + fx * newLateral;
196
+ w.wake(c);
197
+ }
198
+ }
199
+ updateSuspension(steer) {
200
+ this.groundedCount = 0;
201
+ const w = this.world;
202
+ for (let i = 0; i < this.wheels.length; i += 1) {
203
+ const wheel = this.wheels[i];
204
+ const state = this.wheelStates[i];
205
+ const mount = this.wheelMount(wheel);
206
+ const radius = wheel.radius ?? 0.35;
207
+ const rest = wheel.restLength ?? this.suspensionRest;
208
+ const groundY = this.groundHeight(mount[0], mount[2]);
209
+ const gap = mount[1] - (groundY + radius);
210
+ const maxTravel = rest + radius;
211
+ const grounded = gap <= maxTravel;
212
+ const anchorA = this.rotateOffset(wheel.offset);
213
+ w.setJointAnchorA(this.springs[i], anchorA[0], anchorA[1], anchorA[2]);
214
+ w.setJointAnchor(this.springs[i], mount[0], groundY + radius, mount[2]);
215
+ state.worldX = mount[0];
216
+ state.worldY = groundY + radius;
217
+ state.worldZ = mount[2];
218
+ state.grounded = grounded;
219
+ state.compression = Math.max(0, rest - gap);
220
+ state.steerAngle = wheel.steered === true ? steer : 0;
221
+ if (grounded)
222
+ this.groundedCount += 1;
223
+ }
224
+ }
225
+ remove() {
226
+ for (const id of this.springs)
227
+ this.world.removeJoint(id);
228
+ this.springs.length = 0;
229
+ }
230
+ }
231
+ export function createVehicleBody(world, config) {
232
+ return new VehicleBody(world, config);
233
+ }
@@ -0,0 +1,26 @@
1
+ export interface CellGrid<T> {
2
+ readonly width: number;
3
+ readonly height: number;
4
+ readonly cells: readonly (T | null)[];
5
+ }
6
+ export interface CellRun<T> {
7
+ readonly value: T;
8
+ readonly cells: readonly {
9
+ readonly x: number;
10
+ readonly y: number;
11
+ }[];
12
+ readonly direction: "row" | "column";
13
+ }
14
+ export declare function createCellGrid<T>(width: number, height: number): CellGrid<T>;
15
+ export declare function inGridBounds<T>(grid: CellGrid<T>, x: number, y: number): boolean;
16
+ export declare function cellAt<T>(grid: CellGrid<T>, x: number, y: number): T | null;
17
+ export declare function withCell<T>(grid: CellGrid<T>, x: number, y: number, value: T | null): CellGrid<T>;
18
+ export declare function withCells<T>(grid: CellGrid<T>, entries: readonly {
19
+ readonly x: number;
20
+ readonly y: number;
21
+ readonly value: T | null;
22
+ }[]): CellGrid<T>;
23
+ export declare function fullRows<T>(grid: CellGrid<T>): number[];
24
+ export declare function clearRows<T>(grid: CellGrid<T>, rows: readonly number[]): CellGrid<T>;
25
+ export declare function collapseColumns<T>(grid: CellGrid<T>): CellGrid<T>;
26
+ export declare function findRuns<T>(grid: CellGrid<T>, minLength: number, matches?: (a: T, b: T) => boolean): CellRun<T>[];
@@ -0,0 +1,110 @@
1
+ export function createCellGrid(width, height) {
2
+ return { width, height, cells: new Array(width * height).fill(null) };
3
+ }
4
+ export function inGridBounds(grid, x, y) {
5
+ return x >= 0 && x < grid.width && y >= 0 && y < grid.height;
6
+ }
7
+ export function cellAt(grid, x, y) {
8
+ if (!inGridBounds(grid, x, y))
9
+ return null;
10
+ return grid.cells[y * grid.width + x] ?? null;
11
+ }
12
+ export function withCell(grid, x, y, value) {
13
+ if (!inGridBounds(grid, x, y))
14
+ return grid;
15
+ const cells = grid.cells.slice();
16
+ cells[y * grid.width + x] = value;
17
+ return { width: grid.width, height: grid.height, cells };
18
+ }
19
+ export function withCells(grid, entries) {
20
+ const cells = grid.cells.slice();
21
+ for (const entry of entries) {
22
+ if (inGridBounds(grid, entry.x, entry.y))
23
+ cells[entry.y * grid.width + entry.x] = entry.value;
24
+ }
25
+ return { width: grid.width, height: grid.height, cells };
26
+ }
27
+ export function fullRows(grid) {
28
+ const rows = [];
29
+ for (let y = 0; y < grid.height; y += 1) {
30
+ let full = true;
31
+ for (let x = 0; x < grid.width; x += 1) {
32
+ if (cellAt(grid, x, y) === null) {
33
+ full = false;
34
+ break;
35
+ }
36
+ }
37
+ if (full)
38
+ rows.push(y);
39
+ }
40
+ return rows;
41
+ }
42
+ export function clearRows(grid, rows) {
43
+ const removed = new Set(rows);
44
+ const kept = [];
45
+ for (let y = 0; y < grid.height; y += 1) {
46
+ if (removed.has(y))
47
+ continue;
48
+ kept.push(grid.cells.slice(y * grid.width, y * grid.width + grid.width));
49
+ }
50
+ const clearedCount = grid.height - kept.length;
51
+ const cells = [];
52
+ for (let i = 0; i < clearedCount; i += 1)
53
+ cells.push(...new Array(grid.width).fill(null));
54
+ for (const row of kept)
55
+ cells.push(...row);
56
+ return { width: grid.width, height: grid.height, cells };
57
+ }
58
+ export function collapseColumns(grid) {
59
+ const cells = grid.cells.slice();
60
+ for (let x = 0; x < grid.width; x += 1) {
61
+ const values = [];
62
+ for (let y = 0; y < grid.height; y += 1) {
63
+ const value = cellAt(grid, x, y);
64
+ if (value !== null)
65
+ values.push(value);
66
+ }
67
+ const emptyCount = grid.height - values.length;
68
+ for (let y = 0; y < grid.height; y += 1) {
69
+ cells[y * grid.width + x] = y < emptyCount ? null : values[y - emptyCount];
70
+ }
71
+ }
72
+ return { width: grid.width, height: grid.height, cells };
73
+ }
74
+ function scanRuns(length, cellAtIndex, minLength, matches) {
75
+ const runs = [];
76
+ let start = 0;
77
+ for (let i = 1; i <= length; i += 1) {
78
+ const prev = cellAtIndex(i - 1);
79
+ const cur = i < length ? cellAtIndex(i) : null;
80
+ const continues = prev !== null && cur !== null && matches(prev, cur);
81
+ if (!continues) {
82
+ const runLength = i - start;
83
+ const value = cellAtIndex(start);
84
+ if (runLength >= minLength && value !== null)
85
+ runs.push({ value, start, end: i });
86
+ start = i;
87
+ }
88
+ }
89
+ return runs;
90
+ }
91
+ export function findRuns(grid, minLength, matches = (a, b) => a === b) {
92
+ const runs = [];
93
+ for (let y = 0; y < grid.height; y += 1) {
94
+ for (const run of scanRuns(grid.width, (x) => cellAt(grid, x, y), minLength, matches)) {
95
+ const cells = [];
96
+ for (let x = run.start; x < run.end; x += 1)
97
+ cells.push({ x, y });
98
+ runs.push({ value: run.value, cells, direction: "row" });
99
+ }
100
+ }
101
+ for (let x = 0; x < grid.width; x += 1) {
102
+ for (const run of scanRuns(grid.height, (y) => cellAt(grid, x, y), minLength, matches)) {
103
+ const cells = [];
104
+ for (let y = run.start; y < run.end; y += 1)
105
+ cells.push({ x, y });
106
+ runs.push({ value: run.value, cells, direction: "column" });
107
+ }
108
+ }
109
+ return runs;
110
+ }
@@ -0,0 +1,24 @@
1
+ import { type CellGrid } from "./cellGrid.js";
2
+ export interface FallingPiece<TShape extends string = string> {
3
+ readonly shape: TShape;
4
+ readonly rotation: number;
5
+ readonly x: number;
6
+ readonly y: number;
7
+ }
8
+ export type ShapeTable<TShape extends string = string> = Record<TShape, readonly (readonly (readonly [number, number])[])[]>;
9
+ export declare function pieceCells<TShape extends string>(table: ShapeTable<TShape>, piece: FallingPiece<TShape>): readonly (readonly [number, number])[];
10
+ export declare function pieceCollides<T, TShape extends string>(grid: CellGrid<T>, table: ShapeTable<TShape>, piece: FallingPiece<TShape>): boolean;
11
+ export declare function mergePiece<T, TShape extends string>(grid: CellGrid<T>, table: ShapeTable<TShape>, piece: FallingPiece<TShape>, value: T): CellGrid<T>;
12
+ export declare function dropDistance<T, TShape extends string>(grid: CellGrid<T>, table: ShapeTable<TShape>, piece: FallingPiece<TShape>): number;
13
+ export declare function gravityInterval(level: number, base?: number, perLevel?: number, min?: number): number;
14
+ export declare function levelForLines(lines: number, linesPerLevel?: number): number;
15
+ export declare function lineScore(cleared: number, level: number, table?: readonly number[]): number;
16
+ export interface LockDelayState {
17
+ readonly delaySeconds: number;
18
+ readonly elapsed: number;
19
+ }
20
+ export declare function createLockDelay(delaySeconds: number): LockDelayState;
21
+ export declare function stepLockDelay(state: LockDelayState, grounded: boolean, dt: number): {
22
+ state: LockDelayState;
23
+ locked: boolean;
24
+ };
@@ -0,0 +1,51 @@
1
+ import { cellAt } from "./cellGrid.js";
2
+ export function pieceCells(table, piece) {
3
+ const rotations = table[piece.shape];
4
+ const index = ((piece.rotation % rotations.length) + rotations.length) % rotations.length;
5
+ const state = rotations[index];
6
+ return state.map(([ox, oy]) => [piece.x + ox, piece.y + oy]);
7
+ }
8
+ export function pieceCollides(grid, table, piece) {
9
+ for (const [x, y] of pieceCells(table, piece)) {
10
+ if (x < 0 || x >= grid.width || y >= grid.height)
11
+ return true;
12
+ if (y >= 0 && cellAt(grid, x, y) !== null)
13
+ return true;
14
+ }
15
+ return false;
16
+ }
17
+ export function mergePiece(grid, table, piece, value) {
18
+ const cells = grid.cells.slice();
19
+ for (const [x, y] of pieceCells(table, piece)) {
20
+ if (x >= 0 && x < grid.width && y >= 0 && y < grid.height)
21
+ cells[y * grid.width + x] = value;
22
+ }
23
+ return { width: grid.width, height: grid.height, cells };
24
+ }
25
+ export function dropDistance(grid, table, piece) {
26
+ let distance = 0;
27
+ while (!pieceCollides(grid, table, { ...piece, y: piece.y + distance + 1 }))
28
+ distance += 1;
29
+ return distance;
30
+ }
31
+ export function gravityInterval(level, base = 0.8, perLevel = 0.07, min = 0.05) {
32
+ return Math.max(min, base - level * perLevel);
33
+ }
34
+ export function levelForLines(lines, linesPerLevel = 10) {
35
+ return Math.floor(lines / linesPerLevel);
36
+ }
37
+ const CLASSIC_LINE_SCORE = [0, 40, 100, 300, 1200];
38
+ export function lineScore(cleared, level, table = CLASSIC_LINE_SCORE) {
39
+ return (table[cleared] ?? 0) * (level + 1);
40
+ }
41
+ export function createLockDelay(delaySeconds) {
42
+ return { delaySeconds, elapsed: 0 };
43
+ }
44
+ export function stepLockDelay(state, grounded, dt) {
45
+ if (!grounded)
46
+ return { state: { ...state, elapsed: 0 }, locked: false };
47
+ const elapsed = state.elapsed + dt;
48
+ if (elapsed >= state.delaySeconds)
49
+ return { state: { ...state, elapsed: 0 }, locked: true };
50
+ return { state: { ...state, elapsed }, locked: false };
51
+ }
@@ -0,0 +1,18 @@
1
+ export interface SyllableBank {
2
+ onset?: readonly string[];
3
+ nucleus: readonly string[];
4
+ coda?: readonly string[];
5
+ }
6
+ export interface NameGeneratorOptions {
7
+ rng: () => number;
8
+ syllables: SyllableBank;
9
+ minSyllables?: number;
10
+ maxSyllables?: number;
11
+ capitalize?: boolean;
12
+ }
13
+ export interface NameGenerator {
14
+ name(): string;
15
+ }
16
+ export declare function pickFrom(rng: () => number, bank: readonly string[]): string;
17
+ export declare function createNameGenerator(options: NameGeneratorOptions): NameGenerator;
18
+ export declare function fillTemplate(template: string, vars: Record<string, () => string> | Record<string, string>): string;
@@ -0,0 +1,35 @@
1
+ export function pickFrom(rng, bank) {
2
+ if (bank.length === 0)
3
+ throw new Error("pickFrom: bank must not be empty");
4
+ return bank[Math.floor(rng() * bank.length)];
5
+ }
6
+ export function createNameGenerator(options) {
7
+ const { rng, syllables } = options;
8
+ const minSyllables = Math.max(1, options.minSyllables ?? 2);
9
+ const maxSyllables = Math.max(minSyllables, options.maxSyllables ?? minSyllables);
10
+ const capitalize = options.capitalize ?? true;
11
+ function syllable() {
12
+ const onset = syllables.onset === undefined || syllables.onset.length === 0 ? "" : pickFrom(rng, syllables.onset);
13
+ const nucleus = pickFrom(rng, syllables.nucleus);
14
+ const coda = syllables.coda === undefined || syllables.coda.length === 0 ? "" : pickFrom(rng, syllables.coda);
15
+ return `${onset}${nucleus}${coda}`;
16
+ }
17
+ return {
18
+ name() {
19
+ const span = maxSyllables - minSyllables;
20
+ const count = minSyllables + (span === 0 ? 0 : Math.floor(rng() * (span + 1)));
21
+ let result = "";
22
+ for (let i = 0; i < count; i++)
23
+ result += syllable();
24
+ return capitalize && result.length > 0 ? result.charAt(0).toUpperCase() + result.slice(1) : result;
25
+ },
26
+ };
27
+ }
28
+ export function fillTemplate(template, vars) {
29
+ return template.replace(/\{(\w+)\}/g, (match, key) => {
30
+ if (!(key in vars))
31
+ return match;
32
+ const value = vars[key];
33
+ return typeof value === "function" ? value() : value;
34
+ });
35
+ }
@@ -0,0 +1,2 @@
1
+ export declare function seededRng(seed: string | number): () => number;
2
+ export declare function seededStreams(seed: string | number): (stream: string) => () => number;
@@ -0,0 +1,23 @@
1
+ function hashSeed(seed) {
2
+ const text = typeof seed === "number" ? seed.toString() : seed;
3
+ let h = 2166136261 >>> 0;
4
+ for (let i = 0; i < text.length; i++) {
5
+ h ^= text.charCodeAt(i);
6
+ h = Math.imul(h, 16777619);
7
+ }
8
+ return h >>> 0;
9
+ }
10
+ export function seededRng(seed) {
11
+ let a = hashSeed(seed) >>> 0;
12
+ return () => {
13
+ a = (a + 0x6d2b79f5) >>> 0;
14
+ let t = a;
15
+ t = Math.imul(t ^ (t >>> 15), t | 1);
16
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
17
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
18
+ };
19
+ }
20
+ export function seededStreams(seed) {
21
+ const base = typeof seed === "number" ? seed.toString() : seed;
22
+ return (stream) => seededRng(`${base}:${stream}`);
23
+ }
@@ -5,6 +5,20 @@ export type MultiplayerAdapterConfig = {
5
5
  } | {
6
6
  kind: "ws";
7
7
  topology?: MultiplayerTopology;
8
+ url?: string;
9
+ } | {
10
+ kind: "socketio";
11
+ topology?: MultiplayerTopology;
12
+ url?: string;
13
+ } | {
14
+ kind: "p2p";
15
+ topology?: MultiplayerTopology;
16
+ room?: string;
17
+ } | {
18
+ kind: "lan";
19
+ topology?: MultiplayerTopology;
20
+ port?: number;
21
+ path?: string;
8
22
  } | {
9
23
  kind: "offline";
10
24
  };
@@ -13,8 +27,29 @@ export declare function convex(config?: {
13
27
  }): MultiplayerAdapterConfig;
14
28
  export declare function ws(config?: {
15
29
  topology?: MultiplayerTopology;
30
+ url?: string;
31
+ }): MultiplayerAdapterConfig;
32
+ export declare function fly(config: {
33
+ app: string;
34
+ topology?: MultiplayerTopology;
35
+ path?: string;
36
+ }): MultiplayerAdapterConfig;
37
+ export declare function socketIo(config?: {
38
+ topology?: MultiplayerTopology;
39
+ url?: string;
40
+ }): MultiplayerAdapterConfig;
41
+ export declare function p2p(config?: {
42
+ topology?: MultiplayerTopology;
43
+ room?: string;
44
+ }): MultiplayerAdapterConfig;
45
+ export declare function lan(config?: {
46
+ topology?: MultiplayerTopology;
47
+ port?: number;
48
+ path?: string;
16
49
  }): MultiplayerAdapterConfig;
17
50
  export declare function offline(): MultiplayerAdapterConfig;
51
+ export declare function adapterOf(multiplayer: unknown): MultiplayerAdapterConfig | null;
52
+ export declare function multiplayerAdapterKind(multiplayer: unknown): string | null;
18
53
  export type ServersPoolConfig = {
19
54
  maxServers: number;
20
55
  slotsPerServer: number;