@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
@@ -1,14 +1,21 @@
1
- import { createDeathSystem, deathReasonFromEffect } from "../combat/death.js";
1
+ import { createCardPile } from "../cards/cardPile.js";
2
+ import { createDeathSystem, deathReasonFromEffect, normalizeOnDeath } from "../combat/death.js";
2
3
  import { createEffectSystem, } from "../combat/effects.js";
3
4
  import { createProjectileSystem } from "../combat/projectiles.js";
5
+ import { resolveHitReaction, } from "../combat/hitReaction.js";
6
+ import { pointInTelegraph, } from "../combat/telegraph.js";
4
7
  import { createCommandRegistry, } from "../commands/commandRegistry.js";
5
8
  import { balance as walletBalance, canAfford as walletCanAfford, charge as walletCharge, chargeAll as walletChargeAll, createEmptyWallet, grant as walletGrant, } from "../economy/wallet.js";
9
+ import { createCosmetics } from "../game/cosmetics.js";
10
+ import { groundFieldFor } from "../world/terrain.js";
6
11
  import { createGameEvents } from "../game/events.js";
7
12
  import { createGameFeed } from "../game/feed.js";
8
13
  import { createLeaderboard } from "../game/leaderboard.js";
9
14
  import { createLoadouts } from "../game/loadout.js";
10
15
  import { createLootRegistry, grantDrops } from "../game/lootTable.js";
11
16
  import { createQuestJournal } from "../game/quest.js";
17
+ import { createWorldItemStore, resolveDeathDrops, DEFAULT_RARITY, WORLD_ITEM_ENTITY_NAME, } from "../game/worldItem.js";
18
+ import { createChat } from "../game/chat.js";
12
19
  import { createSocial } from "../game/social.js";
13
20
  import { createTradeSystem } from "../game/trade.js";
14
21
  import { createUnlocks } from "../game/unlocks.js";
@@ -16,18 +23,29 @@ import { createInventorySet, putItem, } from "../inventory/inventoryModel.js";
16
23
  import { createItemUse, } from "../item/use.js";
17
24
  import { createWeaponStats } from "../item/weapon.js";
18
25
  import { createPoseState } from "../movement/poseState.js";
26
+ import { createPaintLayer } from "../scene/paintLayer.js";
19
27
  import { createEntityStatsApi, seedStatValues, setStatValue, } from "../scene/entityStats.js";
28
+ import { createForms } from "../scene/form.js";
29
+ import { raycastObjects, raycastObjectsAll } from "../scene/objectQuery.js";
20
30
  import { createObjectStore } from "../scene/objectStore.js";
31
+ import { createRoster } from "../scene/roster.js";
32
+ import { createPossession } from "../scene/possession.js";
21
33
  import { createSpatialApi } from "../scene/spatial.js";
22
34
  import { createTargeting } from "../scene/targeting.js";
23
35
  import { createStats } from "../stats/statModifiers.js";
24
36
  import { createChangeSignal, notifyAfter } from "../store/changeSignal.js";
37
+ import { createObservableKeyedStore } from "../store/observableKeyedStore.js";
25
38
  import { createSimClock } from "../time/simClock.js";
39
+ import { createTurnLoop } from "../turn/turnLoop.js";
40
+ import { createCameraDirector } from "./cameraDirector.js";
41
+ import { createInputSnapshot } from "./inputSnapshot.js";
42
+ import { createMotionIntents } from "./motionIntents.js";
26
43
  export function createGameContext(options) {
27
44
  const { definition, content, player } = options;
28
45
  const now = options.now ?? Date.now;
29
46
  const signal = createChangeSignal();
30
47
  const time = createSimClock({ config: definition.time, onChange: signal.notify });
48
+ const ground = groundFieldFor(definition.world);
31
49
  const entities = definition.scene;
32
50
  const objects = createObjectStore();
33
51
  entities.subscribe(signal.notify);
@@ -77,20 +95,44 @@ export function createGameContext(options) {
77
95
  signal.notify();
78
96
  },
79
97
  };
80
- const feed = createGameFeed();
98
+ const feed = createGameFeed(definition.feed);
81
99
  const lootRegistry = createLootRegistry();
82
100
  const unlocks = notifyAfter(createUnlocks(), ["grant", "hydrate"], signal.notify);
83
- const rawSocial = createSocial({ events, now });
101
+ const rawSocial = createSocial({
102
+ events,
103
+ now,
104
+ emotes: {
105
+ entities: { get: (id) => entities.get(id) },
106
+ spatial: { inRadius: (center, radius, filter) => spatial.inRadius(center, radius, filter) },
107
+ },
108
+ });
84
109
  const social = {
85
- friends: notifyAfter(rawSocial.friends, ["request", "accept", "remove", "block", "hydrate"], signal.notify),
86
- party: notifyAfter(rawSocial.party, ["invite", "accept", "kick", "leave", "promote"], signal.notify),
110
+ friends: notifyAfter(rawSocial.friends, ["request", "accept", "decline", "remove", "block", "hydrate"], signal.notify),
111
+ party: notifyAfter(rawSocial.party, ["invite", "accept", "decline", "kick", "leave", "promote"], signal.notify),
87
112
  presence: rawSocial.presence,
113
+ emotes: rawSocial.emotes,
114
+ worldInvites: notifyAfter(rawSocial.worldInvites, ["invite", "accept", "decline"], signal.notify),
88
115
  };
116
+ const chat = notifyAfter(createChat({
117
+ events,
118
+ now,
119
+ party: rawSocial.party,
120
+ proximity: {
121
+ entities: { get: (id) => entities.get(id) },
122
+ spatial: { inRadius: (center, radius, filter) => spatial.inRadius(center, radius, filter) },
123
+ },
124
+ blockedBy: (userId) => rawSocial.friends.snapshot(userId).blocked,
125
+ }), ["register", "send", "whisper", "hydrate"], signal.notify);
89
126
  const leaderboard = notifyAfter(createLeaderboard(), ["increment", "hydrate"], signal.notify);
127
+ const roster = notifyAfter(createRoster({ now }), ["capture", "release", "setEquipped", "hydrate"], signal.notify);
90
128
  const playerStats = createStats({});
91
129
  const pose = createPoseState((instanceId) => catalogEntry(instanceId)?.movement);
92
130
  const commandRegistry = createCommandRegistry();
93
131
  const itemUse = createItemUse((itemId) => content.itemById?.(itemId)?.use);
132
+ const possession = notifyAfter(createPossession({ entities, events }), ["possess", "own", "disown"], signal.notify);
133
+ const forms = notifyAfter(createForms({ entities, time, events }), ["shapeshift", "revert"], signal.notify);
134
+ const cosmetics = notifyAfter(createCosmetics({ events }), ["apply", "equip", "hydrate"], signal.notify);
135
+ const paintLayer = notifyAfter(createPaintLayer(), ["paint", "clear"], signal.notify);
94
136
  const inventoryDeclarations = definition.inventories ?? {};
95
137
  const inventoryIds = Object.keys(inventoryDeclarations);
96
138
  const layouts = {};
@@ -242,6 +284,47 @@ export function createGameContext(options) {
242
284
  pose.clear(instanceId);
243
285
  return existed;
244
286
  }
287
+ function resetAllToSpawn(filter) {
288
+ let count = 0;
289
+ for (const entity of entities.list()) {
290
+ if (filter !== undefined && !filter(entity))
291
+ continue;
292
+ if (entities.resetToSpawn(entity.id))
293
+ count += 1;
294
+ }
295
+ return count;
296
+ }
297
+ const worldItems = notifyAfter(createWorldItemStore({
298
+ spawnEntity: (position) => entities.spawn(WORLD_ITEM_ENTITY_NAME, { position, role: "prop" }),
299
+ despawnEntity,
300
+ resolvePosition: (instanceId) => entities.get(instanceId)?.position,
301
+ }), ["spawn", "take", "remove"], signal.notify);
302
+ function spawnWorldItem(input) {
303
+ const record = worldItems.spawn(input);
304
+ events.emit("worldItem.dropped", {
305
+ instanceId: record.instanceId,
306
+ itemId: record.itemId,
307
+ rarity: record.rarity,
308
+ count: record.count,
309
+ position: [input.position[0], input.position[1], input.position[2]],
310
+ ...(record.source !== undefined ? { source: record.source } : {}),
311
+ });
312
+ return record;
313
+ }
314
+ function pickupWorldItem(instanceId, userId) {
315
+ const record = worldItems.take(instanceId);
316
+ if (record === null)
317
+ return { status: "rejected", reason: "not-found" };
318
+ loot.grantToPlayer(userId, [{ item: record.itemId, count: record.count }], "worldItem.pickup");
319
+ events.emit("worldItem.picked_up", {
320
+ instanceId,
321
+ userId,
322
+ itemId: record.itemId,
323
+ rarity: record.rarity,
324
+ count: record.count,
325
+ });
326
+ return { status: "ok", record };
327
+ }
245
328
  const death = createDeathSystem({
246
329
  resolveOnDeath: (instanceId) => catalogEntry(instanceId)?.onDeath,
247
330
  resolveIdentity(instanceId) {
@@ -268,7 +351,10 @@ export function createGameContext(options) {
268
351
  getStat: weapon.getStat,
269
352
  spatial: combatSpatial,
270
353
  onLethal(instanceId, lethalCtx) {
271
- const catalogId = entities.get(instanceId)?.name;
354
+ const dyingEntity = entities.get(instanceId);
355
+ const catalogId = dyingEntity?.name;
356
+ const position = dyingEntity?.position;
357
+ const normalizedOnDeath = normalizeOnDeath(catalogEntry(instanceId)?.onDeath);
272
358
  const reason = deathReasonFromEffect({
273
359
  ...lethalCtx,
274
360
  userIdOf: (id) => (id === player.userId ? player.userId : undefined),
@@ -278,7 +364,23 @@ export function createGameContext(options) {
278
364
  resolution.drops.length > 0 &&
279
365
  reason.kind === "player_kill" &&
280
366
  reason.killerUserId === player.userId) {
281
- loot.grantToPlayer(player.userId, resolution.drops, catalogId);
367
+ if (normalizedOnDeath.dropMode === "world" && position !== undefined) {
368
+ const resolved = resolveDeathDrops(resolution.drops, {
369
+ mode: "world",
370
+ origin: position,
371
+ resolveRarity: (itemId) => content.itemById?.(itemId)?.rarity ?? DEFAULT_RARITY,
372
+ resolveBaseType: (itemId) => content.itemById?.(itemId)?.baseType ?? itemId,
373
+ scatter: normalizedOnDeath.scatter,
374
+ ...(catalogId !== undefined ? { source: catalogId } : {}),
375
+ });
376
+ for (const spawn of resolved.worldSpawns)
377
+ spawnWorldItem(spawn);
378
+ if (resolved.grants.length > 0)
379
+ loot.grantToPlayer(player.userId, resolved.grants, catalogId);
380
+ }
381
+ else {
382
+ loot.grantToPlayer(player.userId, resolution.drops, catalogId);
383
+ }
282
384
  }
283
385
  },
284
386
  }), ["applyEffect"], signal.notify);
@@ -297,8 +399,76 @@ export function createGameContext(options) {
297
399
  event.instanceId = input.instanceId;
298
400
  if (input.amount !== undefined)
299
401
  event.amount = input.amount;
402
+ if (input.hitType !== undefined)
403
+ event.hitType = input.hitType;
404
+ if (input.element !== undefined)
405
+ event.element = input.element;
406
+ if (input.crit !== undefined)
407
+ event.crit = input.crit;
408
+ if (input.scale !== undefined)
409
+ event.scale = input.scale;
300
410
  events.emit("entity.floatText", event);
301
411
  }
412
+ let telegraphSeq = 0;
413
+ function fireTelegraph(input) {
414
+ const id = telegraphSeq++;
415
+ const telegraphEvent = {
416
+ id,
417
+ shape: input.shape,
418
+ position: [input.at[0], input.at[1], input.at[2]],
419
+ windupMs: input.windupMs,
420
+ kind: input.kind ?? "danger",
421
+ };
422
+ if (input.dir !== undefined)
423
+ telegraphEvent.dir = input.dir;
424
+ events.emit("combat.telegraph", telegraphEvent);
425
+ const bound = input.effect;
426
+ if (bound === undefined)
427
+ return () => { };
428
+ const config = { shape: input.shape, at: input.at, windupMs: input.windupMs };
429
+ if (input.dir !== undefined)
430
+ config.dir = input.dir;
431
+ return time.after(input.windupMs / 1000, () => {
432
+ const targets = entities.list().filter((entity) => pointInTelegraph(config, entity.position));
433
+ for (const target of targets) {
434
+ applyEffectAndFloat({
435
+ from: input.from,
436
+ to: target.id,
437
+ effect: bound.effect,
438
+ ...(bound.via === undefined ? {} : { via: bound.via }),
439
+ });
440
+ }
441
+ });
442
+ }
443
+ function applyHitReaction(input) {
444
+ const attacker = entities.get(input.from);
445
+ const target = entities.get(input.to);
446
+ if (target === null)
447
+ return null;
448
+ const attackerPos = attacker?.position ?? target.position;
449
+ const reaction = resolveHitReaction(input.config, {
450
+ attackerPos,
451
+ targetPos: target.position,
452
+ ...(input.power === undefined ? {} : { power: input.power }),
453
+ });
454
+ entities.setPose(input.to, {
455
+ position: [
456
+ target.position[0] + reaction.impulse[0],
457
+ target.position[1] + reaction.impulse[1],
458
+ target.position[2] + reaction.impulse[2],
459
+ ],
460
+ rotationY: target.rotationY,
461
+ });
462
+ const reactionEvent = {
463
+ instanceId: input.to,
464
+ position: [target.position[0], target.position[1], target.position[2]],
465
+ hitstopMs: reaction.hitstopMs,
466
+ };
467
+ if (reaction.shake !== null)
468
+ reactionEvent.shake = reaction.shake;
469
+ events.emit("combat.hitReaction", reactionEvent);
470
+ return reaction;
471
+ }
302
472
  function applyEffectAndFloat(input) {
303
473
  const positionsBefore = new Map();
304
474
  for (const entity of entities.list())
@@ -347,18 +517,70 @@ export function createGameContext(options) {
347
517
  const sceneObjects = {
348
518
  ...objects,
349
519
  catalog: (instanceId) => catalogObject(instanceId) ?? null,
520
+ raycast: (input) => raycastObjects(objects.list(), input),
521
+ raycastAll: (input) => raycastObjectsAll(objects.list(), input),
350
522
  };
523
+ const store = notifyAfter(createObservableKeyedStore(), ["set", "delete"], signal.notify);
524
+ const cardPiles = new Map();
525
+ function pile(id, config) {
526
+ const existing = cardPiles.get(id);
527
+ if (existing !== undefined)
528
+ return existing;
529
+ if (config === undefined) {
530
+ throw new Error(`cardPile "${id}" has not been created yet; pass a config on first access`);
531
+ }
532
+ const created = notifyAfter(createCardPile(config), ["shuffle", "draw", "discard", "exhaust", "move", "reset"], signal.notify);
533
+ cardPiles.set(id, created);
534
+ return created;
535
+ }
536
+ const turnLoops = new Map();
537
+ function loop(id, config) {
538
+ const existing = turnLoops.get(id);
539
+ if (existing !== undefined)
540
+ return existing;
541
+ if (config === undefined) {
542
+ throw new Error(`turn loop "${id}" has not been created yet; pass a config on first access`);
543
+ }
544
+ const raw = createTurnLoop(config);
545
+ const wrappedCommit = notifyAfter(raw.commit, ["submit", "expected", "commit", "rewind", "clear"], signal.notify);
546
+ const wrapped = {
547
+ ...notifyAfter(raw, [
548
+ "setOrder",
549
+ "addParticipant",
550
+ "removeParticipant",
551
+ "advancePhase",
552
+ "advanceTurn",
553
+ "advanceRound",
554
+ "spend",
555
+ "gain",
556
+ "refill",
557
+ "restore",
558
+ ], signal.notify),
559
+ commit: wrappedCommit,
560
+ };
561
+ turnLoops.set(id, wrapped);
562
+ return wrapped;
563
+ }
564
+ const camera = notifyAfter(createCameraDirector(), ["follow", "setCinematic"], signal.notify);
565
+ const input = createInputSnapshot();
566
+ const motion = createMotionIntents();
351
567
  const ctx = {
352
568
  scene: {
353
569
  object: sceneObjects,
354
570
  entity: {
355
571
  spawn: spawnEntity,
356
572
  despawn: despawnEntity,
573
+ update: entities.update,
357
574
  setPose: entities.setPose,
358
575
  get: entities.get,
359
576
  list: entities.list,
577
+ spawnPoseOf: entities.spawnPoseOf,
578
+ resetToSpawn: entities.resetToSpawn,
579
+ resetAllToSpawn,
360
580
  stats: entityStats,
361
581
  floatText: emitFloatText,
582
+ telegraph: fireTelegraph,
583
+ hitReaction: applyHitReaction,
362
584
  setTarget: targeting.setTarget,
363
585
  getTarget: targeting.getTarget,
364
586
  cycleTarget: targeting.cycleTarget,
@@ -373,8 +595,22 @@ export function createGameContext(options) {
373
595
  hasLineOfSight: spatial.hasLineOfSight,
374
596
  queryArc: spatial.queryArc,
375
597
  moveToward: spatial.moveToward,
598
+ form: forms,
599
+ paint: paintLayer,
600
+ },
601
+ worldItem: {
602
+ spawn: spawnWorldItem,
603
+ get: worldItems.get,
604
+ list: worldItems.list,
605
+ nearestInRadius: worldItems.nearestInRadius,
606
+ pickup: pickupWorldItem,
607
+ consume: worldItems.remove,
376
608
  },
377
609
  },
610
+ world: {
611
+ ground,
612
+ groundHeightAt: ground.sampleHeight,
613
+ },
378
614
  game: {
379
615
  commands: {
380
616
  define: commandRegistry.define,
@@ -405,9 +641,14 @@ export function createGameContext(options) {
405
641
  trade,
406
642
  quest,
407
643
  social,
644
+ chat,
408
645
  unlocks,
409
646
  economy,
410
647
  leaderboard,
648
+ roster,
649
+ store,
650
+ cards: { pile },
651
+ turn: { loop },
411
652
  },
412
653
  player: {
413
654
  userId: player.userId,
@@ -417,6 +658,9 @@ export function createGameContext(options) {
417
658
  loadout: loadouts,
418
659
  applyLoadout: loadouts.applyLoadout,
419
660
  movement: pose,
661
+ possession,
662
+ cosmetics,
663
+ motion,
420
664
  },
421
665
  item: {
422
666
  use: {
@@ -432,6 +676,8 @@ export function createGameContext(options) {
432
676
  weapon,
433
677
  },
434
678
  time,
679
+ camera,
680
+ input,
435
681
  subscribe: signal.subscribe,
436
682
  version: signal.version,
437
683
  };
@@ -1,13 +1,26 @@
1
1
  import type { LeaderboardScope } from "../game/leaderboard.js";
2
+ import type { NormalizedScenarioReset } from "./persistenceScope.js";
2
3
  import type { SaveConfig } from "./save.js";
3
4
  import type { GameRuntimeSnapshot, RuntimeChunkRow, RuntimePlayerRow, RuntimeServerRow } from "./snapshot.js";
4
5
  export type GameServerStatus = "open" | "running" | "closed";
6
+ export type SessionVisibility = "public" | "private";
7
+ export type SessionAttributes = {
8
+ label?: string;
9
+ mode?: string;
10
+ visibility?: SessionVisibility;
11
+ joinCode?: string;
12
+ tags?: string[];
13
+ };
5
14
  export type GameServerRecord = {
6
15
  serverId: string;
7
16
  gameId: string;
8
17
  status: GameServerStatus;
9
18
  mode?: string;
10
19
  modeConfig?: unknown;
20
+ label?: string;
21
+ visibility?: SessionVisibility;
22
+ joinCode?: string;
23
+ tags?: string[];
11
24
  memberUserIds: string[];
12
25
  slotsPerServer: number;
13
26
  save: SaveConfig;
@@ -49,6 +62,26 @@ export declare function drainPendingLeaderboardIncrements(session: Record<string
49
62
  increments: LeaderboardIncrement[];
50
63
  session: Record<string, unknown>;
51
64
  };
65
+ export declare const LEADERBOARD_TOP_LIMIT = 100;
66
+ export type LeaderboardRow = {
67
+ gameId: string;
68
+ stat: string;
69
+ scope: LeaderboardScope;
70
+ serverId?: string;
71
+ userId: string;
72
+ value: number;
73
+ updatedAt: number;
74
+ };
75
+ export declare function leaderboardRowKey(row: Omit<LeaderboardRow, "value" | "updatedAt">): string;
76
+ export declare function applyLeaderboardRows(rows: Map<string, LeaderboardRow>, gameId: string, entries: LeaderboardIncrement[], now: number): void;
77
+ export declare function topLeaderboardRows(rows: Iterable<LeaderboardRow>, args: {
78
+ gameId: string;
79
+ stat: string;
80
+ scope: LeaderboardScope;
81
+ serverId?: string;
82
+ limit?: number;
83
+ }): LeaderboardEntry[];
84
+ export declare function profileLeaderboardStats(rows: Iterable<LeaderboardRow>, gameId: string, userId: string): Record<string, number>;
52
85
  export declare const FEED_RING_LIMIT = 20;
53
86
  export declare function trimFeedEntries<T>(entries: T[], limit?: number): T[];
54
87
  export declare function shouldAutoSave(save: SaveConfig, dirtyAt: number | undefined, lastSavedAt: number | undefined, now: number): boolean;
@@ -58,11 +91,17 @@ export type ServerListing = {
58
91
  memberCount: number;
59
92
  slotsPerServer: number;
60
93
  mode?: string;
94
+ label?: string;
95
+ visibility?: SessionVisibility;
96
+ joinCode?: string;
97
+ tags?: string[];
61
98
  updatedAt: number;
62
99
  };
63
100
  export declare function toServerListing(record: GameServerRecord): ServerListing;
101
+ export declare function toOpenServerListings(listings: Iterable<ServerListing>, limit?: number): ServerListing[];
64
102
  export type HostPersistence = {
65
103
  savePlan?: (plan: ServerPersistPlan) => Promise<void>;
104
+ resetScenario?: (reset: NormalizedScenarioReset) => Promise<void>;
66
105
  loadServer: (serverId: string) => Promise<GameServerRecord | null>;
67
106
  saveServer: (record: GameServerRecord) => Promise<void>;
68
107
  listServers: (gameId: string) => Promise<GameServerRecord[]>;
@@ -20,6 +20,50 @@ export function drainPendingLeaderboardIncrements(session) {
20
20
  delete rest[LEADERBOARD_PENDING_KEY];
21
21
  return { increments: raw.filter(isLeaderboardIncrement), session: rest };
22
22
  }
23
+ export const LEADERBOARD_TOP_LIMIT = 100;
24
+ export function leaderboardRowKey(row) {
25
+ return [row.gameId, row.scope, row.stat, row.serverId ?? "", row.userId].join("|");
26
+ }
27
+ export function applyLeaderboardRows(rows, gameId, entries, now) {
28
+ for (const entry of entries) {
29
+ const key = leaderboardRowKey({ ...entry, gameId });
30
+ const existing = rows.get(key);
31
+ if (existing) {
32
+ rows.set(key, { ...existing, value: existing.value + entry.by, updatedAt: now });
33
+ }
34
+ else {
35
+ rows.set(key, {
36
+ gameId,
37
+ stat: entry.stat,
38
+ scope: entry.scope,
39
+ serverId: entry.serverId,
40
+ userId: entry.userId,
41
+ value: entry.by,
42
+ updatedAt: now,
43
+ });
44
+ }
45
+ }
46
+ }
47
+ export function topLeaderboardRows(rows, args) {
48
+ const limit = Math.min(Math.max(args.limit ?? LEADERBOARD_TOP_LIMIT, 1), LEADERBOARD_TOP_LIMIT);
49
+ return [...rows]
50
+ .filter((row) => row.gameId === args.gameId &&
51
+ row.stat === args.stat &&
52
+ row.scope === args.scope &&
53
+ (args.serverId === undefined || row.serverId === args.serverId))
54
+ .sort((a, b) => b.value - a.value)
55
+ .slice(0, limit)
56
+ .map((row) => ({ userId: row.userId, value: row.value }));
57
+ }
58
+ export function profileLeaderboardStats(rows, gameId, userId) {
59
+ const profile = {};
60
+ for (const row of rows) {
61
+ if (row.gameId === gameId && row.userId === userId && row.scope === "profile") {
62
+ profile[row.stat] = row.value;
63
+ }
64
+ }
65
+ return profile;
66
+ }
23
67
  export const FEED_RING_LIMIT = 20;
24
68
  export function trimFeedEntries(entries, limit = FEED_RING_LIMIT) {
25
69
  if (entries.length <= limit)
@@ -42,9 +86,19 @@ export function toServerListing(record) {
42
86
  memberCount: record.memberUserIds.length,
43
87
  slotsPerServer: record.slotsPerServer,
44
88
  mode: record.mode,
89
+ label: record.label,
90
+ visibility: record.visibility,
91
+ joinCode: record.joinCode,
92
+ tags: record.tags,
45
93
  updatedAt: record.updatedAt,
46
94
  };
47
95
  }
96
+ export function toOpenServerListings(listings, limit = 20) {
97
+ return [...listings]
98
+ .filter((listing) => listing.status === "running")
99
+ .sort((a, b) => b.updatedAt - a.updatedAt)
100
+ .slice(0, limit);
101
+ }
48
102
  export function buildHydratePlayers(server, profiles) {
49
103
  const players = {};
50
104
  for (const userId of server.memberUserIds) {
@@ -0,0 +1,7 @@
1
+ export interface InputSnapshot {
2
+ /** Replaces the held-action set for this frame. Called by the shell before `onTick` each frame; does not bump `ctx.version()` or notify `ctx.subscribe` listeners — per-frame publishes would storm subscribers. */
3
+ publish(held: readonly string[]): void;
4
+ isDown(action: string): boolean;
5
+ held(): readonly string[];
6
+ }
7
+ export declare function createInputSnapshot(): InputSnapshot;
@@ -0,0 +1,12 @@
1
+ export function createInputSnapshot() {
2
+ let heldSet = new Set();
3
+ let heldList = [];
4
+ return {
5
+ publish(held) {
6
+ heldList = held;
7
+ heldSet = new Set(held);
8
+ },
9
+ isDown: (action) => heldSet.has(action),
10
+ held: () => heldList,
11
+ };
12
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Seam for game code to reach the vertical motion the shell's FrameDriver
3
+ * otherwise owns privately (#162.4). Game code calls `impulse`,
4
+ * `setVerticalVelocity`, and/or `setY` from `onTick` or commands; the shell
5
+ * calls `takePending()` once per frame, before integrating gravity, to drain
6
+ * what accumulated. `setY` wins over physics for that frame; impulses add to
7
+ * the vertical velocity the driver is about to integrate; a later
8
+ * `setVerticalVelocity` replaces that velocity outright.
9
+ *
10
+ * Intentionally not `ctx.version()`/`ctx.subscribe` wired: these fire at
11
+ * most once per frame and would otherwise storm subscribers with per-frame
12
+ * churn (same rationale as `InputSnapshot.publish`).
13
+ */
14
+ export interface MotionIntents {
15
+ impulse(velocityY: number): void;
16
+ setVerticalVelocity(velocityY: number): void;
17
+ setY(y: number): void;
18
+ takePending(): MotionIntentBatch | null;
19
+ }
20
+ export interface MotionIntentBatch {
21
+ impulses: readonly number[];
22
+ verticalVelocity: number | null;
23
+ y: number | null;
24
+ }
25
+ export declare function createMotionIntents(): MotionIntents;
@@ -0,0 +1,25 @@
1
+ export function createMotionIntents() {
2
+ let impulses = [];
3
+ let verticalVelocity = null;
4
+ let y = null;
5
+ return {
6
+ impulse(velocityY) {
7
+ impulses.push(velocityY);
8
+ },
9
+ setVerticalVelocity(velocityY) {
10
+ verticalVelocity = velocityY;
11
+ },
12
+ setY(nextY) {
13
+ y = nextY;
14
+ },
15
+ takePending() {
16
+ if (impulses.length === 0 && verticalVelocity === null && y === null)
17
+ return null;
18
+ const batch = { impulses, verticalVelocity, y };
19
+ impulses = [];
20
+ verticalVelocity = null;
21
+ y = null;
22
+ return batch;
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,32 @@
1
+ import type { PlayerProfileRecord } from "./hostPersistence.js";
2
+ import type { RuntimePlayerRow } from "./snapshot.js";
3
+ export type PersistenceScope = "run" | "meta";
4
+ export interface ScopeSchema {
5
+ run: readonly string[];
6
+ }
7
+ export interface ScopedState<T = Record<string, unknown>> {
8
+ meta: Partial<T>;
9
+ run: Partial<T>;
10
+ }
11
+ export declare function partitionScopes<T extends Record<string, unknown>>(state: T, schema: ScopeSchema): ScopedState<T>;
12
+ export declare function resetRun<T extends Record<string, unknown>>(scoped: ScopedState<T>): ScopedState<T>;
13
+ export declare function mergeScopes<T extends Record<string, unknown>>(scoped: ScopedState<T>): Partial<T>;
14
+ export declare function clearRunFields(player: RuntimePlayerRow, runFields: readonly string[]): RuntimePlayerRow;
15
+ export declare function applyRunReset(profile: PlayerProfileRecord, runFields: readonly string[], now: number): PlayerProfileRecord;
16
+ export interface ScenarioReset {
17
+ gameId: string;
18
+ serverId?: string;
19
+ wipeChunks?: boolean;
20
+ wipeServerSession?: boolean;
21
+ resetPlayers?: PersistenceScope | "none";
22
+ runFields?: readonly string[];
23
+ }
24
+ export interface NormalizedScenarioReset {
25
+ gameId: string;
26
+ serverId: string | null;
27
+ wipeChunks: boolean;
28
+ wipeServerSession: boolean;
29
+ resetPlayers: "run" | "none";
30
+ runFields: readonly string[];
31
+ }
32
+ export declare function planScenarioReset(reset: ScenarioReset): NormalizedScenarioReset;