@v12-engine/engine 0.1.0 → 0.4.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.
- package/dist/abilities/amounts.d.ts +28 -0
- package/dist/abilities/amounts.js +74 -0
- package/dist/abilities/amounts.js.map +1 -0
- package/dist/abilities/buffs.d.ts +106 -6
- package/dist/abilities/buffs.js +443 -0
- package/dist/abilities/buffs.js.map +1 -0
- package/dist/abilities/castTold.d.ts +2 -0
- package/dist/abilities/castTold.js +66 -0
- package/dist/abilities/castTold.js.map +1 -0
- package/dist/abilities/chance.d.ts +38 -0
- package/dist/abilities/chance.js +77 -0
- package/dist/abilities/chance.js.map +1 -0
- package/dist/abilities/charges.d.ts +18 -0
- package/dist/abilities/charges.js +101 -0
- package/dist/abilities/charges.js.map +1 -0
- package/dist/abilities/control.d.ts +28 -0
- package/dist/abilities/control.js +113 -0
- package/dist/abilities/control.js.map +1 -0
- package/dist/abilities/dispel.js +51 -0
- package/dist/abilities/dispel.js.map +1 -0
- package/dist/abilities/effectFields.d.ts +1 -1
- package/dist/abilities/effectFields.js +676 -0
- package/dist/abilities/effectFields.js.map +1 -0
- package/dist/abilities/effectIndex.d.ts +27 -0
- package/dist/abilities/effectIndex.js +64 -0
- package/dist/abilities/effectIndex.js.map +1 -0
- package/dist/abilities/effects/buff.d.ts +9 -3
- package/dist/abilities/effects/buff.js +84 -0
- package/dist/abilities/effects/buff.js.map +1 -0
- package/dist/abilities/effects/conditions.d.ts +2 -0
- package/dist/abilities/effects/conditions.js +41 -0
- package/dist/abilities/effects/conditions.js.map +1 -0
- package/dist/abilities/effects/core.js +54 -0
- package/dist/abilities/effects/core.js.map +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -1
- package/dist/abilities/effects/damage.js +43 -0
- package/dist/abilities/effects/damage.js.map +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -2
- package/dist/abilities/effects/heal.js +51 -0
- package/dist/abilities/effects/heal.js.map +1 -0
- package/dist/abilities/effects/missile.d.ts +13 -1
- package/dist/abilities/effects/missile.js +104 -0
- package/dist/abilities/effects/missile.js.map +1 -0
- package/dist/abilities/effects/morph.d.ts +5 -0
- package/dist/abilities/effects/morph.js +43 -0
- package/dist/abilities/effects/morph.js.map +1 -0
- package/dist/abilities/effects/moves.d.ts +16 -4
- package/dist/abilities/effects/moves.js +212 -0
- package/dist/abilities/effects/moves.js.map +1 -0
- package/dist/abilities/effects/passives.d.ts +19 -9
- package/dist/abilities/effects/passives.js +131 -0
- package/dist/abilities/effects/passives.js.map +1 -0
- package/dist/abilities/effects/proxy.d.ts +5 -0
- package/dist/abilities/effects/proxy.js +60 -0
- package/dist/abilities/effects/proxy.js.map +1 -0
- package/dist/abilities/effects/sight.d.ts +2 -2
- package/dist/abilities/effects/sight.js +39 -0
- package/dist/abilities/effects/sight.js.map +1 -0
- package/dist/abilities/effects/spawn.d.ts +5 -2
- package/dist/abilities/effects/spawn.js +40 -0
- package/dist/abilities/effects/spawn.js.map +1 -0
- package/dist/abilities/effects/timed.d.ts +2 -2
- package/dist/abilities/effects/timed.js +96 -0
- package/dist/abilities/effects/timed.js.map +1 -0
- package/dist/abilities/effects/trade.d.ts +1 -1
- package/dist/abilities/effects/trade.js +25 -0
- package/dist/abilities/effects/trade.js.map +1 -0
- package/dist/abilities/effects.d.ts +97 -23
- package/dist/abilities/effects.js +860 -0
- package/dist/abilities/effects.js.map +1 -0
- package/dist/abilities/land.d.ts +38 -4
- package/dist/abilities/land.js +189 -0
- package/dist/abilities/land.js.map +1 -0
- package/dist/abilities/recast.d.ts +45 -0
- package/dist/abilities/recast.js +118 -0
- package/dist/abilities/recast.js.map +1 -0
- package/dist/abilities/scaled.js +40 -0
- package/dist/abilities/scaled.js.map +1 -0
- package/dist/abilities/screen.d.ts +6 -0
- package/dist/abilities/screen.js +83 -0
- package/dist/abilities/screen.js.map +1 -0
- package/dist/abilities/shapes.d.ts +66 -0
- package/dist/abilities/shapes.js +122 -0
- package/dist/abilities/shapes.js.map +1 -0
- package/dist/abilities/text.d.ts +14 -2
- package/dist/abilities/text.js +204 -0
- package/dist/abilities/text.js.map +1 -0
- package/dist/abilities/triggers.d.ts +98 -0
- package/dist/abilities/triggers.js +351 -0
- package/dist/abilities/triggers.js.map +1 -0
- package/dist/abilityChanges.d.ts +131 -0
- package/dist/abilityChanges.js +345 -0
- package/dist/abilityChanges.js.map +1 -0
- package/dist/ai/area.d.ts +4 -1
- package/dist/ai/brain.d.ts +4 -1
- package/dist/ai/brain.js +844 -0
- package/dist/ai/brain.js.map +1 -0
- package/dist/ai/budget.js +74 -0
- package/dist/ai/budget.js.map +1 -0
- package/dist/ai/checks.d.ts +9 -1
- package/dist/ai/checks.js +242 -0
- package/dist/ai/checks.js.map +1 -0
- package/dist/ai/computer.d.ts +11 -4
- package/dist/ai/computer.js +251 -0
- package/dist/ai/computer.js.map +1 -0
- package/dist/ai/defence.d.ts +4 -0
- package/dist/ai/defence.js +430 -0
- package/dist/ai/defence.js.map +1 -0
- package/dist/ai/define.d.ts +3 -2
- package/dist/ai/define.js +31 -0
- package/dist/ai/define.js.map +1 -0
- package/dist/ai/economy.d.ts +10 -7
- package/dist/ai/economy.js +780 -0
- package/dist/ai/economy.js.map +1 -0
- package/dist/ai/geometry.js +38 -0
- package/dist/ai/geometry.js.map +1 -0
- package/dist/ai/goals.d.ts +1 -0
- package/dist/ai/goals.js +560 -0
- package/dist/ai/goals.js.map +1 -0
- package/dist/ai/knowledge.d.ts +72 -7
- package/dist/ai/knowledge.js +804 -0
- package/dist/ai/knowledge.js.map +1 -0
- package/dist/ai/lanes.d.ts +10 -2
- package/dist/ai/lanes.js +715 -0
- package/dist/ai/lanes.js.map +1 -0
- package/dist/ai/melee/build.js +264 -0
- package/dist/ai/melee/build.js.map +1 -0
- package/dist/ai/melee/goals.d.ts +7 -0
- package/dist/ai/melee/goals.js +720 -0
- package/dist/ai/melee/goals.js.map +1 -0
- package/dist/ai/melee/heroes.js +68 -0
- package/dist/ai/melee/heroes.js.map +1 -0
- package/dist/ai/melee/index.d.ts +1 -1
- package/dist/ai/melee/index.js +51 -0
- package/dist/ai/melee/index.js.map +1 -0
- package/dist/ai/melee/production.js +29 -0
- package/dist/ai/melee/production.js.map +1 -0
- package/dist/ai/melee/surrender.js +64 -0
- package/dist/ai/melee/surrender.js.map +1 -0
- package/dist/ai/micro.d.ts +9 -0
- package/dist/ai/micro.js +1316 -0
- package/dist/ai/micro.js.map +1 -0
- package/dist/ai/mission.d.ts +9 -2
- package/dist/ai/mission.js +538 -0
- package/dist/ai/mission.js.map +1 -0
- package/dist/ai/missionRules.d.ts +1 -1
- package/dist/ai/missionRules.js +26 -0
- package/dist/ai/missionRules.js.map +1 -0
- package/dist/ai/module.d.ts +6 -2
- package/dist/ai/module.js +37 -0
- package/dist/ai/module.js.map +1 -0
- package/dist/ai/options.d.ts +3 -3
- package/dist/ai/plans/build.d.ts +20 -1
- package/dist/ai/plans/build.js +608 -0
- package/dist/ai/plans/build.js.map +1 -0
- package/dist/ai/plans/placement.d.ts +4 -1
- package/dist/ai/plans/placement.js +295 -0
- package/dist/ai/plans/placement.js.map +1 -0
- package/dist/ai/plans/plans.d.ts +9 -0
- package/dist/ai/plans/plans.js +110 -0
- package/dist/ai/plans/plans.js.map +1 -0
- package/dist/ai/plans/production.d.ts +14 -2
- package/dist/ai/plans/production.js +434 -0
- package/dist/ai/plans/production.js.map +1 -0
- package/dist/ai/plans/purse.d.ts +6 -3
- package/dist/ai/plans/purse.js +139 -0
- package/dist/ai/plans/purse.js.map +1 -0
- package/dist/ai/plans/tech.d.ts +6 -0
- package/dist/ai/plans/tech.js +122 -0
- package/dist/ai/plans/tech.js.map +1 -0
- package/dist/ai/profiles.d.ts +4 -4
- package/dist/{profiles-B3NS9jwk.js → ai/profiles.js} +3 -98
- package/dist/ai/profiles.js.map +1 -0
- package/dist/ai/reach.js +54 -0
- package/dist/ai/reach.js.map +1 -0
- package/dist/ai/report.d.ts +8 -0
- package/dist/ai/report.js +87 -0
- package/dist/ai/report.js.map +1 -0
- package/dist/ai/roles.d.ts +4 -0
- package/dist/ai/roles.js +207 -0
- package/dist/ai/roles.js.map +1 -0
- package/dist/ai/rules.d.ts +8 -2
- package/dist/ai/rules.js +416 -0
- package/dist/ai/rules.js.map +1 -0
- package/dist/ai/scouting.d.ts +6 -0
- package/dist/ai/scouting.js +324 -0
- package/dist/ai/scouting.js.map +1 -0
- package/dist/ai/settings.js +99 -0
- package/dist/ai/settings.js.map +1 -0
- package/dist/ai/squads.d.ts +21 -2
- package/dist/ai/squads.js +916 -0
- package/dist/ai/squads.js.map +1 -0
- package/dist/ai/strength.js +320 -0
- package/dist/ai/strength.js.map +1 -0
- package/dist/ai/task.d.ts +3 -1
- package/dist/ai/task.js +17 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tasks/attack.js +24 -0
- package/dist/ai/tasks/attack.js.map +1 -0
- package/dist/ai/tasks/capture.d.ts +3 -3
- package/dist/ai/tasks/capture.js +37 -0
- package/dist/ai/tasks/capture.js.map +1 -0
- package/dist/ai/tasks/creep.js +29 -0
- package/dist/ai/tasks/creep.js.map +1 -0
- package/dist/ai/tasks/defend.js +61 -0
- package/dist/ai/tasks/defend.js.map +1 -0
- package/dist/ai/tasks/drop.js +81 -0
- package/dist/ai/tasks/drop.js.map +1 -0
- package/dist/ai/tasks/escort.js +59 -0
- package/dist/ai/tasks/escort.js.map +1 -0
- package/dist/ai/tasks/gather.js +48 -0
- package/dist/ai/tasks/gather.js.map +1 -0
- package/dist/ai/tasks/harass.js +39 -0
- package/dist/ai/tasks/harass.js.map +1 -0
- package/dist/ai/tasks/hold.js +32 -0
- package/dist/ai/tasks/hold.js.map +1 -0
- package/dist/ai/tasks/index.js +34 -0
- package/dist/ai/tasks/index.js.map +1 -0
- package/dist/ai/tasks/move.js +26 -0
- package/dist/ai/tasks/move.js.map +1 -0
- package/dist/ai/tasks/patrol.js +59 -0
- package/dist/ai/tasks/patrol.js.map +1 -0
- package/dist/ai/tasks/retreat.js +28 -0
- package/dist/ai/tasks/retreat.js.map +1 -0
- package/dist/ai/tasks/scout.js +73 -0
- package/dist/ai/tasks/scout.js.map +1 -0
- package/dist/ai/tasks/shared.d.ts +1 -1
- package/dist/ai/tasks/shared.js +137 -0
- package/dist/ai/tasks/shared.js.map +1 -0
- package/dist/ai/team.d.ts +18 -1
- package/dist/ai/team.js +492 -0
- package/dist/ai/team.js.map +1 -0
- package/dist/ai/threat.d.ts +6 -0
- package/dist/ai/threat.js +206 -0
- package/dist/ai/threat.js.map +1 -0
- package/dist/ai/view.d.ts +21 -7
- package/dist/ai/view.js +677 -0
- package/dist/ai/view.js.map +1 -0
- package/dist/ai/waves.d.ts +6 -0
- package/dist/ai/waves.js +410 -0
- package/dist/ai/waves.js.map +1 -0
- package/dist/ai.js +54 -6239
- package/dist/aiTesting.d.ts +6 -3
- package/dist/aiTesting.js +229 -0
- package/dist/aiTesting.js.map +1 -0
- package/dist/areas.d.ts +4 -1
- package/dist/areas.js +295 -0
- package/dist/areas.js.map +1 -0
- package/dist/attacks.d.ts +3 -3
- package/dist/attacks.js +127 -0
- package/dist/attacks.js.map +1 -0
- package/dist/burning.d.ts +267 -0
- package/dist/burning.js +795 -0
- package/dist/burning.js.map +1 -0
- package/dist/bytes.js +21 -0
- package/dist/bytes.js.map +1 -0
- package/dist/callings.d.ts +71 -0
- package/dist/callings.js +157 -0
- package/dist/callings.js.map +1 -0
- package/dist/cameraOrders.d.ts +78 -0
- package/dist/cameraOrders.js +114 -0
- package/dist/cameraOrders.js.map +1 -0
- package/dist/camps.d.ts +70 -4
- package/dist/camps.js +501 -0
- package/dist/camps.js.map +1 -0
- package/dist/capture.d.ts +15 -3
- package/dist/capture.js +304 -0
- package/dist/capture.js.map +1 -0
- package/dist/cellLayers.d.ts +78 -13
- package/dist/cellLayers.js +275 -0
- package/dist/cellLayers.js.map +1 -0
- package/dist/cellPatches.d.ts +24 -0
- package/dist/cellPatches.js +73 -0
- package/dist/cellPatches.js.map +1 -0
- package/dist/cinematics.d.ts +10 -5
- package/dist/cinematics.js +161 -0
- package/dist/cinematics.js.map +1 -0
- package/dist/clock.d.ts +2 -2
- package/dist/clock.js +78 -0
- package/dist/clock.js.map +1 -0
- package/dist/commands.d.ts +36 -4
- package/dist/commands.js +636 -0
- package/dist/commands.js.map +1 -0
- package/dist/components.d.ts +31 -10
- package/dist/components.js +74 -0
- package/dist/components.js.map +1 -0
- package/dist/computers.d.ts +4 -4
- package/dist/computers.js +194 -0
- package/dist/computers.js.map +1 -0
- package/dist/concealment.d.ts +25 -2
- package/dist/concealment.js +409 -0
- package/dist/concealment.js.map +1 -0
- package/dist/coreComponents.js +130 -0
- package/dist/coreComponents.js.map +1 -0
- package/dist/createGame.d.ts +306 -0
- package/dist/createGame.js +405 -0
- package/dist/createGame.js.map +1 -0
- package/dist/dashing.d.ts +18 -2
- package/dist/dashing.js +41 -0
- package/dist/dashing.js.map +1 -0
- package/dist/debug.d.ts +8 -0
- package/dist/debug.js +5 -3
- package/dist/debug2.js +76 -0
- package/dist/debug2.js.map +1 -0
- package/dist/debugCommands.d.ts +6 -6
- package/dist/debugCommands.js +537 -0
- package/dist/debugCommands.js.map +1 -0
- package/dist/debugging.d.ts +1 -0
- package/dist/defaultSets.d.ts +183 -0
- package/dist/defaultSets.js +216 -0
- package/dist/defaultSets.js.map +1 -0
- package/dist/definitions.d.ts +6 -0
- package/dist/definitions.js +78 -0
- package/dist/definitions.js.map +1 -0
- package/dist/defs.d.ts +1895 -165
- package/dist/defs.js +380 -0
- package/dist/defs.js.map +1 -0
- package/dist/denying.d.ts +4 -4
- package/dist/denying.js +106 -0
- package/dist/denying.js.map +1 -0
- package/dist/destructibles.d.ts +2 -2
- package/dist/destructibles.js +36 -0
- package/dist/destructibles.js.map +1 -0
- package/dist/determinism.d.ts +4 -4
- package/dist/determinism.js +247 -0
- package/dist/determinism.js.map +1 -0
- package/dist/dialog.d.ts +17 -2
- package/dist/dialog.js +108 -0
- package/dist/dialog.js.map +1 -0
- package/dist/effectRefs.js +28 -0
- package/dist/effectRefs.js.map +1 -0
- package/dist/effects.d.ts +27 -11
- package/dist/effects.js +110 -0
- package/dist/effects.js.map +1 -0
- package/dist/endings.d.ts +1 -1
- package/dist/endings.js +78 -0
- package/dist/endings.js.map +1 -0
- package/dist/engagement.d.ts +40 -6
- package/dist/engagement.js +530 -0
- package/dist/engagement.js.map +1 -0
- package/dist/engineEvents.d.ts +72 -9
- package/dist/engineEvents.js +520 -0
- package/dist/engineEvents.js.map +1 -0
- package/dist/entity.d.ts +275 -26
- package/dist/entity.js +441 -0
- package/dist/entity.js.map +1 -0
- package/dist/entityIndex.d.ts +10 -3
- package/dist/entityIndex.js +149 -0
- package/dist/entityIndex.js.map +1 -0
- package/dist/errors.d.ts +6 -2
- package/dist/errors.js +59 -0
- package/dist/errors.js.map +1 -0
- package/dist/events.d.ts +11 -5
- package/dist/events.js +158 -0
- package/dist/events.js.map +1 -0
- package/dist/exactMath.js +273 -0
- package/dist/exactMath.js.map +1 -0
- package/dist/features.d.ts +1 -1
- package/dist/features.js +127 -0
- package/dist/features.js.map +1 -0
- package/dist/fields.d.ts +25 -5
- package/dist/fields.js +140 -0
- package/dist/fields.js.map +1 -0
- package/dist/fixture.d.ts +3 -3
- package/dist/fixture.js +512 -0
- package/dist/fixture.js.map +1 -0
- package/dist/fog.d.ts +26 -3
- package/dist/fog.js +333 -0
- package/dist/fog.js.map +1 -0
- package/dist/foliage.d.ts +476 -0
- package/dist/foliage.js +1478 -0
- package/dist/foliage.js.map +1 -0
- package/dist/foliageDebug.d.ts +57 -0
- package/dist/foliageDebug.js +172 -0
- package/dist/foliageDebug.js.map +1 -0
- package/dist/foliageRegrowth.d.ts +20 -0
- package/dist/foliageRegrowth.js +332 -0
- package/dist/foliageRegrowth.js.map +1 -0
- package/dist/formState.d.ts +67 -0
- package/dist/formState.js +65 -0
- package/dist/formState.js.map +1 -0
- package/dist/formation.d.ts +46 -8
- package/dist/formation.js +297 -0
- package/dist/formation.js.map +1 -0
- package/dist/forms.d.ts +58 -0
- package/dist/forms.js +146 -0
- package/dist/forms.js.map +1 -0
- package/dist/friendlyFire.d.ts +2 -2
- package/dist/friendlyFire.js +37 -0
- package/dist/friendlyFire.js.map +1 -0
- package/dist/game.d.ts +141 -48
- package/dist/game.js +834 -0
- package/dist/game.js.map +1 -0
- package/dist/gameData.d.ts +96 -22
- package/dist/gameData.js +1690 -0
- package/dist/gameData.js.map +1 -0
- package/dist/gameFiles.d.ts +3 -3
- package/dist/gameFiles.js +14 -0
- package/dist/gameFiles.js.map +1 -0
- package/dist/gates.js +92 -0
- package/dist/gates.js.map +1 -0
- package/dist/generate.d.ts +28 -1
- package/dist/generate.js +1062 -0
- package/dist/generate.js.map +1 -0
- package/dist/generateWorker.d.ts +7 -3
- package/dist/generateWorker.js +86 -0
- package/dist/generateWorker.js.map +1 -0
- package/dist/grid.d.ts +9 -0
- package/dist/grid.js +102 -0
- package/dist/grid.js.map +1 -0
- package/dist/ground.d.ts +17 -1
- package/dist/ground.js +375 -0
- package/dist/ground.js.map +1 -0
- package/dist/groundObjects.d.ts +70 -0
- package/dist/groundObjects.js +371 -0
- package/dist/groundObjects.js.map +1 -0
- package/dist/groundSpeed.d.ts +20 -3
- package/dist/groundSpeed.js +117 -0
- package/dist/groundSpeed.js.map +1 -0
- package/dist/hero.d.ts +126 -10
- package/dist/hero.js +432 -0
- package/dist/hero.js.map +1 -0
- package/dist/holds.d.ts +94 -0
- package/dist/holds.js +305 -0
- package/dist/holds.js.map +1 -0
- package/dist/home.d.ts +1 -1
- package/dist/home.js +30 -0
- package/dist/home.js.map +1 -0
- package/dist/hooks.d.ts +339 -57
- package/dist/hooks.js +105 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hotReload.d.ts +6 -5
- package/dist/hotReload.js +145 -0
- package/dist/hotReload.js.map +1 -0
- package/dist/ids.d.ts +3 -3
- package/dist/ids.js +30 -0
- package/dist/ids.js.map +1 -0
- package/dist/idsFile.d.ts +36 -0
- package/dist/idsFile.js +134 -0
- package/dist/idsFile.js.map +1 -0
- package/dist/index.d.ts +105 -68
- package/dist/index.js +194 -4701
- package/dist/inspect.d.ts +29 -2
- package/dist/{inspect-D9dWHmZ0.js → inspect.js} +21 -12
- package/dist/inspect.js.map +1 -0
- package/dist/inventory.d.ts +14 -1
- package/dist/inventory.js +84 -0
- package/dist/inventory.js.map +1 -0
- package/dist/items.d.ts +136 -8
- package/dist/items.js +585 -0
- package/dist/items.js.map +1 -0
- package/dist/lanes.d.ts +12 -3
- package/dist/lanes.js +496 -0
- package/dist/lanes.js.map +1 -0
- package/dist/life.d.ts +6 -2
- package/dist/life.js +287 -0
- package/dist/life.js.map +1 -0
- package/dist/log.d.ts +26 -3
- package/dist/log.js +192 -0
- package/dist/log.js.map +1 -0
- package/dist/manaBurn.d.ts +2 -2
- package/dist/manaBurn.js +75 -0
- package/dist/manaBurn.js.map +1 -0
- package/dist/map/file.d.ts +56 -3
- package/dist/map/file.js +264 -0
- package/dist/map/file.js.map +1 -0
- package/dist/map/images.js +61 -0
- package/dist/map/images.js.map +1 -0
- package/dist/map/look.d.ts +1 -1
- package/dist/map/look.js +30 -0
- package/dist/map/look.js.map +1 -0
- package/dist/map/pathProfile.js +183 -0
- package/dist/map/pathProfile.js.map +1 -0
- package/dist/map/resize.d.ts +4 -0
- package/dist/map/resize.js +136 -0
- package/dist/map/resize.js.map +1 -0
- package/dist/map/schema.js +257 -0
- package/dist/map/schema.js.map +1 -0
- package/dist/map/terrain.js +214 -0
- package/dist/map/terrain.js.map +1 -0
- package/dist/map/types.d.ts +92 -13
- package/dist/map/types.js +251 -0
- package/dist/map/types.js.map +1 -0
- package/dist/mapCheck/cells.js +94 -0
- package/dist/mapCheck/cells.js.map +1 -0
- package/dist/mapCheck/rules/foliage.d.ts +9 -0
- package/dist/mapCheck/rules/foliage.js +83 -0
- package/dist/mapCheck/rules/foliage.js.map +1 -0
- package/dist/mapCheck/rules/names.js +39 -0
- package/dist/mapCheck/rules/names.js.map +1 -0
- package/dist/mapCheck/rules/objects.d.ts +1 -1
- package/dist/mapCheck/rules/objects.js +56 -0
- package/dist/mapCheck/rules/objects.js.map +1 -0
- package/dist/mapCheck/rules/paths.js +32 -0
- package/dist/mapCheck/rules/paths.js.map +1 -0
- package/dist/mapCheck/rules/players.js +20 -0
- package/dist/mapCheck/rules/players.js.map +1 -0
- package/dist/mapCheck/rules/races.js +56 -0
- package/dist/mapCheck/rules/races.js.map +1 -0
- package/dist/mapCheck/rules/random.js +47 -0
- package/dist/mapCheck/rules/random.js.map +1 -0
- package/dist/mapCheck/rules/regions.js +30 -0
- package/dist/mapCheck/rules/regions.js.map +1 -0
- package/dist/mapCheck/rules/targets.js +31 -0
- package/dist/mapCheck/rules/targets.js.map +1 -0
- package/dist/mapCheck/rules/walking.js +45 -0
- package/dist/mapCheck/rules/walking.js.map +1 -0
- package/dist/mapCheck.d.ts +2 -2
- package/dist/mapCheck.js +63 -0
- package/dist/mapCheck.js.map +1 -0
- package/dist/mapFields.d.ts +25 -2
- package/dist/mapFields.js +134 -0
- package/dist/mapFields.js.map +1 -0
- package/dist/mapFile.js +176 -0
- package/dist/mapFile.js.map +1 -0
- package/dist/mapMeasure.d.ts +8 -0
- package/dist/mapMeasure.js +283 -0
- package/dist/mapMeasure.js.map +1 -0
- package/dist/mapMerge.d.ts +1 -0
- package/dist/mapMerge.js +172 -0
- package/dist/mapMerge.js.map +1 -0
- package/dist/mapObjectives.js +138 -0
- package/dist/mapObjectives.js.map +1 -0
- package/dist/mapObjects.js +80 -0
- package/dist/mapObjects.js.map +1 -0
- package/dist/math.d.ts +37 -7
- package/dist/math.js +155 -0
- package/dist/math.js.map +1 -0
- package/dist/messages.d.ts +71 -4
- package/dist/messages.js +29 -0
- package/dist/messages.js.map +1 -0
- package/dist/missionRules.d.ts +10 -2
- package/dist/{missionRules-C-bGxm0Q.js → missionRules.js} +30 -150
- package/dist/missionRules.js.map +1 -0
- package/dist/mods.d.ts +39 -20
- package/dist/mods.js +271 -0
- package/dist/mods.js.map +1 -0
- package/dist/moves.d.ts +87 -0
- package/dist/moves.js +539 -0
- package/dist/moves.js.map +1 -0
- package/dist/names.d.ts +7 -0
- package/dist/names.js +122 -0
- package/dist/names.js.map +1 -0
- package/dist/navigation/agentParams.js +14 -0
- package/dist/navigation/agentParams.js.map +1 -0
- package/dist/navigation/air.d.ts +7 -3
- package/dist/navigation/air.js +401 -0
- package/dist/navigation/air.js.map +1 -0
- package/dist/navigation/builds.d.ts +34 -2
- package/dist/navigation/builds.js +287 -0
- package/dist/navigation/builds.js.map +1 -0
- package/dist/navigation/groundAreas.d.ts +59 -1
- package/dist/navigation/groundAreas.js +407 -0
- package/dist/navigation/groundAreas.js.map +1 -0
- package/dist/navigation/navigation.d.ts +98 -9
- package/dist/navigation/recast.d.ts +194 -18
- package/dist/navigation/recast.js +1379 -0
- package/dist/navigation/recast.js.map +1 -0
- package/dist/navigation/sidePaths.d.ts +8 -3
- package/dist/navigation/sidePaths.js +241 -0
- package/dist/navigation/sidePaths.js.map +1 -0
- package/dist/navigation/sized.js +243 -0
- package/dist/navigation/sized.js.map +1 -0
- package/dist/nearest.js +32 -0
- package/dist/nearest.js.map +1 -0
- package/dist/noise.js +59 -0
- package/dist/noise.js.map +1 -0
- package/dist/objectives.d.ts +12 -3
- package/dist/objectives.js +144 -0
- package/dist/objectives.js.map +1 -0
- package/dist/orders/basic.d.ts +5 -5
- package/dist/orders/basic.js +417 -0
- package/dist/orders/basic.js.map +1 -0
- package/dist/orders/build.js +278 -0
- package/dist/orders/build.js.map +1 -0
- package/dist/orders/cast.d.ts +13 -3
- package/dist/orders/cast.js +558 -0
- package/dist/orders/cast.js.map +1 -0
- package/dist/orders/facts.js +16 -0
- package/dist/orders/facts.js.map +1 -0
- package/dist/orders/harvest.d.ts +21 -5
- package/dist/orders/harvest.js +540 -0
- package/dist/orders/harvest.js.map +1 -0
- package/dist/orders/idle.d.ts +3 -1
- package/dist/orders/idle.js +234 -0
- package/dist/orders/idle.js.map +1 -0
- package/dist/orders/items.js +92 -0
- package/dist/orders/items.js.map +1 -0
- package/dist/orders/queue.js +108 -0
- package/dist/orders/queue.js.map +1 -0
- package/dist/orders/waiting.d.ts +39 -0
- package/dist/orders/waiting.js +149 -0
- package/dist/orders/waiting.js.map +1 -0
- package/dist/pack.schema.js +13 -0
- package/dist/pack.schema.js.map +1 -0
- package/dist/pack.schema.json +7622 -841
- package/dist/packs/director/index.d.ts +13 -5
- package/dist/packs/director/index.js +204 -0
- package/dist/packs/director/index.js.map +1 -0
- package/dist/packs/heroes/campaign.d.ts +3 -2
- package/dist/packs/heroes/campaign.js +241 -0
- package/dist/packs/heroes/campaign.js.map +1 -0
- package/dist/packs/heroes/carry.d.ts +6 -0
- package/dist/packs/heroes/carry.js +112 -0
- package/dist/packs/heroes/carry.js.map +1 -0
- package/dist/packs/heroes/commands.js +115 -0
- package/dist/packs/heroes/commands.js.map +1 -0
- package/dist/packs/heroes/fallen.d.ts +43 -0
- package/dist/packs/heroes/fallen.js +61 -0
- package/dist/packs/heroes/fallen.js.map +1 -0
- package/dist/packs/heroes/hire.js +60 -0
- package/dist/packs/heroes/hire.js.map +1 -0
- package/dist/packs/heroes/index.d.ts +7 -6
- package/dist/packs/heroes/index.js +130 -0
- package/dist/packs/heroes/index.js.map +1 -0
- package/dist/packs/heroes/loop.d.ts +95 -0
- package/dist/packs/heroes/loop.js +250 -0
- package/dist/packs/heroes/loop.js.map +1 -0
- package/dist/packs/heroes/making.d.ts +6 -3
- package/dist/packs/heroes/making.js +55 -0
- package/dist/packs/heroes/making.js.map +1 -0
- package/dist/packs/heroes/respawn.d.ts +3 -3
- package/dist/packs/heroes/respawn.js +87 -0
- package/dist/packs/heroes/respawn.js.map +1 -0
- package/dist/packs/heroes/sets.d.ts +32 -0
- package/dist/packs/heroes/sets.js +51 -0
- package/dist/packs/heroes/sets.js.map +1 -0
- package/dist/packs/heroes/spells.d.ts +16 -0
- package/dist/packs/heroes/spells.js +269 -0
- package/dist/packs/heroes/spells.js.map +1 -0
- package/dist/packs/items/defaults.d.ts +43 -0
- package/dist/packs/items/defaults.js +1504 -0
- package/dist/packs/items/defaults.js.map +1 -0
- package/dist/packs/items/index.d.ts +27 -0
- package/dist/packs/items/index.js +214 -0
- package/dist/packs/items/index.js.map +1 -0
- package/dist/packs/moba/index.d.ts +3 -3
- package/dist/packs/moba/index.js +174 -0
- package/dist/packs/moba/index.js.map +1 -0
- package/dist/packs/pack.d.ts +15 -15
- package/dist/packs/pack.js +14 -0
- package/dist/packs/pack.js.map +1 -0
- package/dist/packs.d.ts +15 -7
- package/dist/packs.js +222 -0
- package/dist/packs.js.map +1 -0
- package/dist/paths.d.ts +2 -0
- package/dist/paths.js +109 -0
- package/dist/paths.js.map +1 -0
- package/dist/plain.js +57 -0
- package/dist/plain.js.map +1 -0
- package/dist/player.d.ts +33 -10
- package/dist/player.js +159 -0
- package/dist/player.js.map +1 -0
- package/dist/portals.d.ts +1 -1
- package/dist/portals.js +194 -0
- package/dist/portals.js.map +1 -0
- package/dist/prefabs.d.ts +25 -2
- package/dist/prefabs.js +239 -0
- package/dist/prefabs.js.map +1 -0
- package/dist/presetBuildings.js +58 -0
- package/dist/presetBuildings.js.map +1 -0
- package/dist/presetFoliage.d.ts +27 -0
- package/dist/presetFoliage.js +98 -0
- package/dist/presetFoliage.js.map +1 -0
- package/dist/presetGround.js +65 -0
- package/dist/presetGround.js.map +1 -0
- package/dist/proxies.d.ts +12 -0
- package/dist/proxies.js +79 -0
- package/dist/proxies.js.map +1 -0
- package/dist/query.d.ts +56 -0
- package/dist/query.js +88 -0
- package/dist/query.js.map +1 -0
- package/dist/races.d.ts +15 -14
- package/dist/races.js +172 -0
- package/dist/races.js.map +1 -0
- package/dist/randomGroups.js +91 -0
- package/dist/randomGroups.js.map +1 -0
- package/dist/registry.d.ts +117 -53
- package/dist/registry.js +323 -0
- package/dist/registry.js.map +1 -0
- package/dist/remains.d.ts +11 -9
- package/dist/remains.js +188 -0
- package/dist/remains.js.map +1 -0
- package/dist/replication.d.ts +12 -7
- package/dist/replication.js +100 -0
- package/dist/replication.js.map +1 -0
- package/dist/rng.d.ts +2 -0
- package/dist/rng.js +40 -0
- package/dist/rng.js.map +1 -0
- package/dist/rules.d.ts +186 -99
- package/dist/rules.js +179 -0
- package/dist/rules.js.map +1 -0
- package/dist/rulesCheck.d.ts +5 -4
- package/dist/rulesCheck.js +693 -0
- package/dist/rulesCheck.js.map +1 -0
- package/dist/runes.d.ts +2 -2
- package/dist/runes.js +80 -0
- package/dist/runes.js.map +1 -0
- package/dist/save.d.ts +37 -12
- package/dist/save.js +532 -0
- package/dist/save.js.map +1 -0
- package/dist/scenario.d.ts +2 -2
- package/dist/scenario.js +99 -0
- package/dist/scenario.js.map +1 -0
- package/dist/scheduler.d.ts +3 -0
- package/dist/scheduler.js +156 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/score.d.ts +19 -19
- package/dist/score.js +709 -0
- package/dist/score.js.map +1 -0
- package/dist/sequences.d.ts +10 -6
- package/dist/sequences.js +206 -0
- package/dist/sequences.js.map +1 -0
- package/dist/server/doorman.js +154 -0
- package/dist/server/doorman.js.map +1 -0
- package/dist/server/gameServer.d.ts +16 -1
- package/dist/server/gameServer.js +643 -0
- package/dist/server/gameServer.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/lobby.js +199 -0
- package/dist/server/lobby.js.map +1 -0
- package/dist/server/log.js +18 -0
- package/dist/server/log.js.map +1 -0
- package/dist/server/match.js +267 -0
- package/dist/server/match.js.map +1 -0
- package/dist/server/mode.d.ts +18 -9
- package/dist/server/mode.js +220 -0
- package/dist/server/mode.js.map +1 -0
- package/dist/{navigation-worker.js → server/navigation-worker.js} +1 -1
- package/dist/server/navigation-worker.js.map +1 -0
- package/dist/server/navigation.js +39 -0
- package/dist/server/navigation.js.map +1 -0
- package/dist/server/ops.d.ts +4 -0
- package/dist/server/ops.js +137 -0
- package/dist/server/ops.js.map +1 -0
- package/dist/server/packs.d.ts +3 -3
- package/dist/server/packs.js +32 -0
- package/dist/server/packs.js.map +1 -0
- package/dist/server/ratings.d.ts +5 -0
- package/dist/server/ratings.js +104 -0
- package/dist/server/ratings.js.map +1 -0
- package/dist/server/relay.d.ts +12 -2
- package/dist/server/relay.js +144 -0
- package/dist/server/relay.js.map +1 -0
- package/dist/server/rooms.d.ts +9 -2
- package/dist/server/rooms.js +442 -0
- package/dist/server/rooms.js.map +1 -0
- package/dist/server/seat.js +116 -0
- package/dist/server/seat.js.map +1 -0
- package/dist/server/seatSettings.d.ts +3 -3
- package/dist/server/seatSettings.js +63 -0
- package/dist/server/seatSettings.js.map +1 -0
- package/dist/server/secret.js +13 -0
- package/dist/server/secret.js.map +1 -0
- package/dist/server/start.d.ts +13 -6
- package/dist/server/start.js +76 -0
- package/dist/server/start.js.map +1 -0
- package/dist/server/websocket.d.ts +9 -1
- package/dist/server/websocket.js +306 -0
- package/dist/server/websocket.js.map +1 -0
- package/dist/server.js +15 -2861
- package/dist/session/can.js +26 -0
- package/dist/session/can.js.map +1 -0
- package/dist/session/commandReplay.d.ts +8 -2
- package/dist/session/commandReplay.js +293 -0
- package/dist/session/commandReplay.js.map +1 -0
- package/dist/session/debug.js +151 -0
- package/dist/session/debug.js.map +1 -0
- package/dist/session/delay.js +62 -0
- package/dist/session/delay.js.map +1 -0
- package/dist/session/delta.d.ts +14 -1
- package/dist/session/delta.js +407 -0
- package/dist/session/delta.js.map +1 -0
- package/dist/session/entityState.js +415 -0
- package/dist/session/entityState.js.map +1 -0
- package/dist/session/local.d.ts +47 -5
- package/dist/session/local.js +670 -0
- package/dist/session/local.js.map +1 -0
- package/dist/session/memory.d.ts +20 -2
- package/dist/session/memory.js +131 -0
- package/dist/session/memory.js.map +1 -0
- package/dist/session/protocol.d.ts +325 -31
- package/dist/session/protocol.js +55 -0
- package/dist/session/protocol.js.map +1 -0
- package/dist/session/remote.d.ts +74 -12
- package/dist/session/remote.js +1394 -0
- package/dist/session/remote.js.map +1 -0
- package/dist/session/replay.d.ts +11 -2
- package/dist/session/replay.js +160 -0
- package/dist/session/replay.js.map +1 -0
- package/dist/session/seed.js +12 -0
- package/dist/session/seed.js.map +1 -0
- package/dist/session/share.d.ts +5 -1
- package/dist/session/share.js +94 -0
- package/dist/session/share.js.map +1 -0
- package/dist/session/socket.d.ts +1 -1
- package/dist/session/socket.js +29 -0
- package/dist/session/socket.js.map +1 -0
- package/dist/session/wire.d.ts +5 -0
- package/dist/session/wire.js +84 -0
- package/dist/session/wire.js.map +1 -0
- package/dist/session/worker.d.ts +77 -12
- package/dist/session/worker.js +499 -0
- package/dist/session/worker.js.map +1 -0
- package/dist/shared.d.ts +31 -5
- package/dist/shared.js +166 -0
- package/dist/shared.js.map +1 -0
- package/dist/sides.d.ts +9 -3
- package/dist/sides.js +149 -0
- package/dist/sides.js.map +1 -0
- package/dist/sight.js +85 -0
- package/dist/sight.js.map +1 -0
- package/dist/simulate-worker.js +1 -1
- package/dist/simulate.d.ts +12 -8
- package/dist/{simulate-oXBiw1Ff.js → simulate.js} +10 -11
- package/dist/simulate.js.map +1 -0
- package/dist/smart.js +77 -0
- package/dist/smart.js.map +1 -0
- package/dist/spatial.d.ts +32 -16
- package/dist/spatial.js +234 -0
- package/dist/spatial.js.map +1 -0
- package/dist/spawning.d.ts +1 -0
- package/dist/spawning.js +224 -0
- package/dist/spawning.js.map +1 -0
- package/dist/stances.d.ts +6 -3
- package/dist/stances.js +169 -0
- package/dist/stances.js.map +1 -0
- package/dist/start.d.ts +10 -10
- package/dist/start.js +75 -0
- package/dist/start.js.map +1 -0
- package/dist/stats.d.ts +42 -16
- package/dist/stats.js +290 -0
- package/dist/stats.js.map +1 -0
- package/dist/summoned.d.ts +52 -0
- package/dist/summoned.js +38 -0
- package/dist/summoned.js.map +1 -0
- package/dist/summons.d.ts +10 -13
- package/dist/summons.js +271 -0
- package/dist/summons.js.map +1 -0
- package/dist/systems/abilities.js +224 -0
- package/dist/systems/abilities.js.map +1 -0
- package/dist/systems/combat.d.ts +35 -1
- package/dist/systems/combat.js +677 -0
- package/dist/systems/combat.js.map +1 -0
- package/dist/systems/combatTold.d.ts +3 -1
- package/dist/systems/combatTold.js +85 -0
- package/dist/systems/combatTold.js.map +1 -0
- package/dist/systems/construction.js +80 -0
- package/dist/systems/construction.js.map +1 -0
- package/dist/systems/economy.d.ts +0 -6
- package/dist/systems/economy.js +128 -0
- package/dist/systems/economy.js.map +1 -0
- package/dist/systems/fog.d.ts +1 -1
- package/dist/systems/fog.js +120 -0
- package/dist/systems/fog.js.map +1 -0
- package/dist/systems/life.js +32 -0
- package/dist/systems/life.js.map +1 -0
- package/dist/systems/movement.d.ts +24 -12
- package/dist/systems/movement.js +1247 -0
- package/dist/systems/movement.js.map +1 -0
- package/dist/systems/orders.js +64 -0
- package/dist/systems/orders.js.map +1 -0
- package/dist/systems/production.js +322 -0
- package/dist/systems/production.js.map +1 -0
- package/dist/systems/productionQueue.js +120 -0
- package/dist/systems/productionQueue.js.map +1 -0
- package/dist/systems/victory.d.ts +1 -1
- package/dist/systems/victory.js +56 -0
- package/dist/systems/victory.js.map +1 -0
- package/dist/talk.d.ts +6 -6
- package/dist/talk.js +153 -0
- package/dist/talk.js.map +1 -0
- package/dist/targeting.d.ts +142 -0
- package/dist/targeting.js +49 -0
- package/dist/targeting.js.map +1 -0
- package/dist/tech.d.ts +20 -3
- package/dist/tech.js +239 -0
- package/dist/tech.js.map +1 -0
- package/dist/techTree.d.ts +7 -0
- package/dist/techTree.js +90 -0
- package/dist/techTree.js.map +1 -0
- package/dist/terrain.d.ts +59 -7
- package/dist/terrain.js +389 -0
- package/dist/terrain.js.map +1 -0
- package/dist/terrainSave.d.ts +6 -0
- package/dist/terrainSave.js +74 -0
- package/dist/terrainSave.js.map +1 -0
- package/dist/testing.d.ts +8 -7
- package/dist/testing.js +13 -739
- package/dist/testing.js.map +1 -1
- package/dist/tiles.d.ts +1 -1
- package/dist/tiles.js +43 -0
- package/dist/tiles.js.map +1 -0
- package/dist/timers.d.ts +29 -4
- package/dist/timers.js +242 -0
- package/dist/timers.js.map +1 -0
- package/dist/tomes.d.ts +4 -4
- package/dist/tomes.js +94 -0
- package/dist/tomes.js.map +1 -0
- package/dist/trade.js +103 -0
- package/dist/trade.js.map +1 -0
- package/dist/transport.d.ts +6 -1
- package/dist/transport.js +281 -0
- package/dist/transport.js.map +1 -0
- package/dist/tunables.d.ts +10 -3
- package/dist/tunables.js +56 -0
- package/dist/tunables.js.map +1 -0
- package/dist/unitResources.d.ts +67 -0
- package/dist/unitResources.js +266 -0
- package/dist/unitResources.js.map +1 -0
- package/dist/upkeep.d.ts +6 -1
- package/dist/upkeep.js +26 -0
- package/dist/upkeep.js.map +1 -0
- package/dist/veterancy.d.ts +8 -3
- package/dist/veterancy.js +131 -0
- package/dist/veterancy.js.map +1 -0
- package/dist/vision.d.ts +36 -0
- package/dist/vision.js +133 -0
- package/dist/vision.js.map +1 -0
- package/dist/walls.d.ts +1 -1
- package/dist/walls.js +278 -0
- package/dist/walls.js.map +1 -0
- package/dist/world.d.ts +606 -88
- package/dist/world.js +1263 -0
- package/dist/world.js.map +1 -0
- package/package.json +2 -2
- package/dist/ai.js.map +0 -1
- package/dist/attributes.d.ts +0 -66
- package/dist/brain-BvVdUhX8.js +0 -7659
- package/dist/brain-BvVdUhX8.js.map +0 -1
- package/dist/builds-C6LfgvEU.js +0 -460
- package/dist/builds-C6LfgvEU.js.map +0 -1
- package/dist/coreComponents-syuh2fPG.js +0 -5149
- package/dist/coreComponents-syuh2fPG.js.map +0 -1
- package/dist/debugCommands-CzjrSm66.js +0 -14739
- package/dist/debugCommands-CzjrSm66.js.map +0 -1
- package/dist/determinism-BCymQwiE.js +0 -518
- package/dist/determinism-BCymQwiE.js.map +0 -1
- package/dist/game-DiJEN-Ks.js +0 -5800
- package/dist/game-DiJEN-Ks.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/inspect-D9dWHmZ0.js.map +0 -1
- package/dist/local-Dkovq42k.js +0 -1379
- package/dist/local-Dkovq42k.js.map +0 -1
- package/dist/missionRules-C-bGxm0Q.js.map +0 -1
- package/dist/navigation-worker.js.map +0 -1
- package/dist/packs-g5thvmGn.js +0 -3199
- package/dist/packs-g5thvmGn.js.map +0 -1
- package/dist/profiles-B3NS9jwk.js.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/simulate-oXBiw1Ff.js.map +0 -1
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { checkpoint } from "../engineEvents.js";
|
|
2
|
+
import { Logger, errorFields, rootLogger } from "../log.js";
|
|
3
|
+
import { navigationData } from "../navigation/builds.js";
|
|
4
|
+
import { saveWorld } from "../save.js";
|
|
5
|
+
import { createWorldFromMap, loadWorld } from "../game.js";
|
|
6
|
+
import { paceOf, savesOf } from "./can.js";
|
|
7
|
+
import { RemoteSession, SessionHost, connectAs } from "./remote.js";
|
|
8
|
+
import { reloadGame } from "../hotReload.js";
|
|
9
|
+
import { randomSeed } from "./seed.js";
|
|
10
|
+
//#region src/session/worker.ts
|
|
11
|
+
/** Milliseconds between two words of where the time went */
|
|
12
|
+
var TIMING_EVERY = 1e3;
|
|
13
|
+
var firstOfMap = (map) => (map.players.find((player) => player.start) ?? map.players[0])?.id;
|
|
14
|
+
function firstOfWorld(world) {
|
|
15
|
+
for (const player of world.players.values()) if (!player.neutral && !player.creeps) return player.id;
|
|
16
|
+
throw new Error("The world has no player to play: every one of its players is neutral");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What a game's worker file does: `serveWorld(game, { onStart })`. It waits for the page to say what to play (a map, a
|
|
20
|
+
* save, or nothing for a world made here in code), makes the world, runs it by the clock, and seats the page's player
|
|
21
|
+
* at it. A new game asked for ends the one before: a restart is the same worker, its navigation built already
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
function serveWorld(first, options = {}) {
|
|
26
|
+
/** The game's version now: the one it began with, or the one it took last (`reload`) */
|
|
27
|
+
let game = first;
|
|
28
|
+
const port = options.port ?? globalThis;
|
|
29
|
+
const post = (message, transfer) => port.postMessage(message, transfer);
|
|
30
|
+
/** The game running now, and what ends it */
|
|
31
|
+
let running;
|
|
32
|
+
/** Whether the systems are measured, as the page's stats ask: off until they do */
|
|
33
|
+
let profiling = false;
|
|
34
|
+
/** Each start has a number: one overtaken while its world was made is let go */
|
|
35
|
+
let starts = 0;
|
|
36
|
+
const start = async (asked) => {
|
|
37
|
+
const mine = ++starts;
|
|
38
|
+
running?.end();
|
|
39
|
+
running = void 0;
|
|
40
|
+
const log = new Logger();
|
|
41
|
+
const stopLog = log.to((entry) => post({
|
|
42
|
+
vg: "log",
|
|
43
|
+
entry
|
|
44
|
+
}));
|
|
45
|
+
let world;
|
|
46
|
+
try {
|
|
47
|
+
const seed = asked.seed ?? randomSeed();
|
|
48
|
+
world = asked.from ? await loadWorld(asked.from, {
|
|
49
|
+
rules: game,
|
|
50
|
+
log
|
|
51
|
+
}) : asked.map ? await createWorldFromMap({
|
|
52
|
+
map: asked.map,
|
|
53
|
+
rules: game,
|
|
54
|
+
seed,
|
|
55
|
+
log
|
|
56
|
+
}) : options.world ? await options.world({
|
|
57
|
+
rules: game,
|
|
58
|
+
seed,
|
|
59
|
+
args: asked.args,
|
|
60
|
+
log
|
|
61
|
+
}) : void 0;
|
|
62
|
+
if (!world) throw new Error("A game in a worker needs a map, a save to go on from, or a world made in the worker (serveWorld world)");
|
|
63
|
+
if (mine !== starts) return world.dispose();
|
|
64
|
+
world.errorPolicy ??= "end";
|
|
65
|
+
const player = asked.player ?? options.player?.(world, asked.map) ?? (asked.map && firstOfMap(asked.map)) ?? firstOfWorld(world);
|
|
66
|
+
const context = {
|
|
67
|
+
player,
|
|
68
|
+
map: asked.map,
|
|
69
|
+
args: asked.args,
|
|
70
|
+
tell: (data) => {
|
|
71
|
+
if (mine === starts) post({
|
|
72
|
+
vg: "told",
|
|
73
|
+
data
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
if (!asked.from) await options.onStart?.(world, context);
|
|
78
|
+
if (mine !== starts) return world.dispose();
|
|
79
|
+
await options.beforePlay?.(world, {
|
|
80
|
+
...context,
|
|
81
|
+
fresh: !asked.from
|
|
82
|
+
});
|
|
83
|
+
if (mine !== starts) return world.dispose();
|
|
84
|
+
if (asked.reveal) world.fog.setRevealed(world.player(player).team, true);
|
|
85
|
+
if (asked.debug) world.debugPlayers.add(player);
|
|
86
|
+
const made = world;
|
|
87
|
+
const host = new SessionHost(made, {
|
|
88
|
+
ownsWorld: true,
|
|
89
|
+
sendRate: made.tickRate,
|
|
90
|
+
dropSilentAfter: Infinity
|
|
91
|
+
});
|
|
92
|
+
let hear = () => {};
|
|
93
|
+
const transport = {
|
|
94
|
+
send: (text) => post(text),
|
|
95
|
+
onMessage: (handler) => hear = handler,
|
|
96
|
+
onClose: () => {},
|
|
97
|
+
close: () => {}
|
|
98
|
+
};
|
|
99
|
+
const stopCheckpoint = made.events.on(checkpoint, ({ label }) => {
|
|
100
|
+
setTimeout(() => {
|
|
101
|
+
if (running?.host === host) post({
|
|
102
|
+
vg: "checkpoint",
|
|
103
|
+
label,
|
|
104
|
+
save: saveWorld(made)
|
|
105
|
+
});
|
|
106
|
+
}, 0);
|
|
107
|
+
});
|
|
108
|
+
made.scheduler.profiling = profiling;
|
|
109
|
+
const timingTimer = setInterval(() => {
|
|
110
|
+
const timing = host.takeTiming();
|
|
111
|
+
post({
|
|
112
|
+
vg: "timing",
|
|
113
|
+
tick: timing.ticks ? timing.tickTime / timing.ticks : 0,
|
|
114
|
+
tickMax: timing.tickMax,
|
|
115
|
+
send: timing.sends ? timing.sendTime / timing.sends : 0,
|
|
116
|
+
systems: made.scheduler.timing()
|
|
117
|
+
});
|
|
118
|
+
}, TIMING_EVERY);
|
|
119
|
+
running = {
|
|
120
|
+
host,
|
|
121
|
+
hear: (text) => hear(text),
|
|
122
|
+
end: () => {
|
|
123
|
+
clearInterval(timingTimer);
|
|
124
|
+
stopCheckpoint();
|
|
125
|
+
stopLog();
|
|
126
|
+
host.dispose();
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
post({
|
|
130
|
+
vg: "ready",
|
|
131
|
+
player,
|
|
132
|
+
about: options.about?.(made, {
|
|
133
|
+
player,
|
|
134
|
+
map: asked.map,
|
|
135
|
+
args: asked.args
|
|
136
|
+
})
|
|
137
|
+
});
|
|
138
|
+
host.connect(player, transport, { inOrder: true });
|
|
139
|
+
host.start();
|
|
140
|
+
} catch (error) {
|
|
141
|
+
stopLog();
|
|
142
|
+
world?.dispose();
|
|
143
|
+
if (mine === starts) post({
|
|
144
|
+
vg: "refused",
|
|
145
|
+
message: error instanceof Error ? error.message : String(error),
|
|
146
|
+
stack: error instanceof Error ? error.stack : void 0
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const heard = (message) => {
|
|
151
|
+
if (typeof message === "string") return running?.hear(message);
|
|
152
|
+
const said = message;
|
|
153
|
+
if (typeof said !== "object" || said === null) return;
|
|
154
|
+
switch (said.vg) {
|
|
155
|
+
case "start":
|
|
156
|
+
start(said);
|
|
157
|
+
return;
|
|
158
|
+
case "reload":
|
|
159
|
+
(async () => {
|
|
160
|
+
const world = running?.host.world;
|
|
161
|
+
if (!options.reload) {
|
|
162
|
+
world?.log.warn("game", `${game.id} in a worker has no reload (serveWorld reload): it keeps the version it began with`);
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const next = await options.reload(Date.now());
|
|
167
|
+
if (!next) return;
|
|
168
|
+
game = next;
|
|
169
|
+
if (world && running?.host.world === world) reloadGame(world, next);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
world?.log.error("game", `${game.id}'s new version could not be taken in the worker: ${error instanceof Error ? error.message : String(error)}`);
|
|
172
|
+
}
|
|
173
|
+
})();
|
|
174
|
+
return;
|
|
175
|
+
case "stop":
|
|
176
|
+
starts++;
|
|
177
|
+
running?.end();
|
|
178
|
+
running = void 0;
|
|
179
|
+
return;
|
|
180
|
+
case "speed":
|
|
181
|
+
if (running) running.host.speed = said.speed;
|
|
182
|
+
return;
|
|
183
|
+
case "advance": return running?.host.advance(said.ticks);
|
|
184
|
+
case "save":
|
|
185
|
+
try {
|
|
186
|
+
if (!running) throw new Error("There is no game to save");
|
|
187
|
+
post({
|
|
188
|
+
vg: "saved",
|
|
189
|
+
id: said.id,
|
|
190
|
+
save: saveWorld(running.host.world)
|
|
191
|
+
});
|
|
192
|
+
} catch (error) {
|
|
193
|
+
post({
|
|
194
|
+
vg: "saved",
|
|
195
|
+
id: said.id,
|
|
196
|
+
error: error instanceof Error ? error.message : String(error)
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
return;
|
|
200
|
+
case "navigation":
|
|
201
|
+
navigationData(said.build).then((data) => post({
|
|
202
|
+
vg: "built",
|
|
203
|
+
id: said.id,
|
|
204
|
+
data
|
|
205
|
+
}), (error) => post({
|
|
206
|
+
vg: "built",
|
|
207
|
+
id: said.id,
|
|
208
|
+
error: error instanceof Error ? error.message : String(error)
|
|
209
|
+
}));
|
|
210
|
+
return;
|
|
211
|
+
case "profile":
|
|
212
|
+
profiling = said.on;
|
|
213
|
+
if (running) running.host.world.scheduler.profiling = said.on;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
if (port.on) port.on("message", heard);
|
|
218
|
+
else port.addEventListener?.("message", (event) => heard(event.data));
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* A seat at a game run in a worker of this page (`workerSession`): a `RemoteSession` whose host is a message away,
|
|
222
|
+
* with what a game played in the page has besides: its pace held and stepped (`speed`, `advance`), a save of it
|
|
223
|
+
* (`save`), the checkpoint to start again from, what it says in its log, the debug tools' view, and where its time went
|
|
224
|
+
*
|
|
225
|
+
* @beta
|
|
226
|
+
*/
|
|
227
|
+
var WorkerSession = class extends RemoteSession {
|
|
228
|
+
/** What the world says (`World.log`), said again here: the page shows it with its own */
|
|
229
|
+
log;
|
|
230
|
+
/** The label and save of the last checkpoint the worker's game took, to retry from */
|
|
231
|
+
checkpoint;
|
|
232
|
+
/** What the worker's file said of the world as the game started (`ServeWorldOptions.about`): plain data, none where it says nothing */
|
|
233
|
+
about;
|
|
234
|
+
/** The debug tools' view of the world, where they are on: over the session's own words, as a server's is */
|
|
235
|
+
get debug() {
|
|
236
|
+
return this.debugView;
|
|
237
|
+
}
|
|
238
|
+
/** Its pace held and stepped, saves of it, the debug tools' view where they are on, and where its time went and in which systems */
|
|
239
|
+
can = {
|
|
240
|
+
pace: paceOf(this),
|
|
241
|
+
saves: savesOf(this),
|
|
242
|
+
inspect: this.debugView,
|
|
243
|
+
timing: {
|
|
244
|
+
timing: () => this.timing(),
|
|
245
|
+
profile: (on) => this.postToWorker({
|
|
246
|
+
vg: "profile",
|
|
247
|
+
on
|
|
248
|
+
})
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
pace = 1;
|
|
252
|
+
timed;
|
|
253
|
+
/** Milliseconds the page took to take in what the worker sent, each time, evened out: its share of a game run there */
|
|
254
|
+
received = 0;
|
|
255
|
+
postToWorker = () => {};
|
|
256
|
+
saves = /* @__PURE__ */ new Map();
|
|
257
|
+
nextSave = 0;
|
|
258
|
+
stopHearing = () => {};
|
|
259
|
+
/** Who hears what the worker's code tells (`onTold`), and what it told before anyone listened */
|
|
260
|
+
listening = /* @__PURE__ */ new Set();
|
|
261
|
+
toldBefore = [];
|
|
262
|
+
/** What `workerSession` gives it once it is made: the way to the worker, and what stops hearing it */
|
|
263
|
+
wire(post, log, stop) {
|
|
264
|
+
this.postToWorker = post;
|
|
265
|
+
this.log = log;
|
|
266
|
+
this.stopHearing = stop;
|
|
267
|
+
}
|
|
268
|
+
/** What the worker said that is not the session's own text */
|
|
269
|
+
heard(said) {
|
|
270
|
+
if (said.vg === "checkpoint") this.checkpoint = {
|
|
271
|
+
label: said.label,
|
|
272
|
+
save: said.save
|
|
273
|
+
};
|
|
274
|
+
else if (said.vg === "told") {
|
|
275
|
+
if (this.listening.size) for (const listener of this.listening) listener(said.data);
|
|
276
|
+
else this.toldBefore.push(said.data);
|
|
277
|
+
} else if (said.vg === "timing") this.timed = {
|
|
278
|
+
tick: said.tick,
|
|
279
|
+
tickMax: said.tickMax,
|
|
280
|
+
send: said.send,
|
|
281
|
+
systems: said.systems
|
|
282
|
+
};
|
|
283
|
+
else if (said.vg === "saved") {
|
|
284
|
+
const waiting = this.saves.get(said.id);
|
|
285
|
+
this.saves.delete(said.id);
|
|
286
|
+
if (said.save) waiting?.done(said.save);
|
|
287
|
+
else waiting?.failed(new Error(said.error ?? "The game could not be saved"));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Hears what the worker's code tells the page (`WorkerGameContext.tell`): plain data, in order with the ticks. What
|
|
292
|
+
* it told before anyone listened is heard by the first listener, at once. Gives back what stops hearing it
|
|
293
|
+
*/
|
|
294
|
+
onTold(listener) {
|
|
295
|
+
this.listening.add(listener);
|
|
296
|
+
for (const data of this.toldBefore.splice(0)) listener(data);
|
|
297
|
+
return () => this.listening.delete(listener);
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* How far behind the newest tick the screen is shown, in ticks: one, and room for how unevenly they come (a tick
|
|
301
|
+
* that took long comes late). Less than over a wire, where two are kept in hand: there is no line to stall here
|
|
302
|
+
*/
|
|
303
|
+
get delay() {
|
|
304
|
+
return this.interval + Math.min(this.jitter, this.limits.maxJitter ?? .2) * this.tickRate * 2;
|
|
305
|
+
}
|
|
306
|
+
/** The simulation speed multiplier the worker's game runs at, 0 pauses; setting it tells the worker */
|
|
307
|
+
get speed() {
|
|
308
|
+
return this.pace;
|
|
309
|
+
}
|
|
310
|
+
set speed(speed) {
|
|
311
|
+
this.pace = speed;
|
|
312
|
+
this.postToWorker({
|
|
313
|
+
vg: "speed",
|
|
314
|
+
speed
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
/** Asks the worker to step the held game by this many ticks */
|
|
318
|
+
advance(ticks = 1) {
|
|
319
|
+
this.postToWorker({
|
|
320
|
+
vg: "advance",
|
|
321
|
+
ticks
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Asks the worker to take a new version of the game (hot reload): it loads the game again itself, as its file says
|
|
326
|
+
* (`serveWorld` `reload`), and puts it into its world
|
|
327
|
+
*/
|
|
328
|
+
reloadGame() {
|
|
329
|
+
this.postToWorker({ vg: "reload" });
|
|
330
|
+
}
|
|
331
|
+
/** Asks the worker for a save of its world and resolves with it; rejects if the game ends first */
|
|
332
|
+
save() {
|
|
333
|
+
return new Promise((done, failed) => {
|
|
334
|
+
const id = ++this.nextSave;
|
|
335
|
+
this.saves.set(id, {
|
|
336
|
+
done,
|
|
337
|
+
failed
|
|
338
|
+
});
|
|
339
|
+
this.postToWorker({
|
|
340
|
+
vg: "save",
|
|
341
|
+
id
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/** Where the worker's time went (tick, send and receive milliseconds and each system's), or undefined until it has said */
|
|
346
|
+
timing() {
|
|
347
|
+
return this.timed && {
|
|
348
|
+
...this.timed,
|
|
349
|
+
receive: this.received
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
/** Ends the game in the worker. The worker is the page's: it stays, for the next game, until the page ends it */
|
|
353
|
+
dispose() {
|
|
354
|
+
this.postToWorker({ vg: "stop" });
|
|
355
|
+
this.stopHearing();
|
|
356
|
+
for (const waiting of this.saves.values()) waiting.failed(/* @__PURE__ */ new Error("The game ended"));
|
|
357
|
+
this.saves.clear();
|
|
358
|
+
super.dispose();
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
/** What cuts off the seat at the game a worker plays now, by the worker: a new game there ends it */
|
|
362
|
+
var lines = /* @__PURE__ */ new WeakMap();
|
|
363
|
+
/**
|
|
364
|
+
* Plays a game in a worker, and seats this page's player at it: the worker's file calls `serveWorld` with the same
|
|
365
|
+
* game. Settles once the world is made there and its welcome is in; fails with what the worker said went wrong
|
|
366
|
+
*
|
|
367
|
+
* const session = await workerSession(new Worker(new URL('./game.worker.ts', import.meta.url), { type: 'module' }), { rules: game, map })
|
|
368
|
+
*
|
|
369
|
+
* @beta
|
|
370
|
+
*/
|
|
371
|
+
async function workerSession(worker, options) {
|
|
372
|
+
const { rules: game, navigation, maps, log: under, ...asked } = options;
|
|
373
|
+
let toSession = () => {};
|
|
374
|
+
let closed = () => {};
|
|
375
|
+
let session;
|
|
376
|
+
const builds = /* @__PURE__ */ new Map();
|
|
377
|
+
let nextBuild = 0;
|
|
378
|
+
/** What the worker said of its world as it was ready, before there is a session to keep it */
|
|
379
|
+
let about;
|
|
380
|
+
/** What the worker's code told before there is a session to hear it */
|
|
381
|
+
const early = [];
|
|
382
|
+
let saying;
|
|
383
|
+
const log = (under ?? rootLogger).child({ context: () => ({
|
|
384
|
+
game: saying?.game,
|
|
385
|
+
tick: saying?.tick
|
|
386
|
+
}) });
|
|
387
|
+
lines.get(worker)?.();
|
|
388
|
+
let cut = false;
|
|
389
|
+
const post = (message) => {
|
|
390
|
+
if (!cut) worker.postMessage(message);
|
|
391
|
+
};
|
|
392
|
+
let refuse = () => {};
|
|
393
|
+
const refused = new Promise((_, reject) => refuse = reject);
|
|
394
|
+
refused.catch(() => {});
|
|
395
|
+
const heard = (message) => {
|
|
396
|
+
if (typeof message === "string") {
|
|
397
|
+
const began = performance.now();
|
|
398
|
+
toSession(message);
|
|
399
|
+
if (session) session.received += (performance.now() - began - session.received) * .1;
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const said = message;
|
|
403
|
+
if (typeof said !== "object" || said === null) return;
|
|
404
|
+
if (said.vg === "refused") {
|
|
405
|
+
const error = new Error(said.message);
|
|
406
|
+
if (said.stack) error.stack = said.stack;
|
|
407
|
+
refuse(error);
|
|
408
|
+
} else if (said.vg === "log") {
|
|
409
|
+
saying = said.entry;
|
|
410
|
+
log.log(said.entry.level, said.entry.category, said.entry.message, said.entry.fields);
|
|
411
|
+
saying = void 0;
|
|
412
|
+
} else if (said.vg === "built") {
|
|
413
|
+
const waiting = builds.get(said.id);
|
|
414
|
+
builds.delete(said.id);
|
|
415
|
+
if (said.data) waiting?.done(said.data);
|
|
416
|
+
else waiting?.failed(new Error(said.error ?? "The navigation could not be built"));
|
|
417
|
+
} else if (said.vg === "ready") about = said.about;
|
|
418
|
+
else if (!session && said.vg === "told") early.push(said);
|
|
419
|
+
else session?.heard(said);
|
|
420
|
+
};
|
|
421
|
+
const broke = (error) => {
|
|
422
|
+
const reason = /* @__PURE__ */ new Error(`The game's worker stopped: ${error instanceof Error ? error.message : String(error?.message ?? error)}`);
|
|
423
|
+
log.error("game", reason.message, { error: errorFields(error) });
|
|
424
|
+
refuse(reason);
|
|
425
|
+
closed();
|
|
426
|
+
};
|
|
427
|
+
const onMessage = (event) => heard(event.data);
|
|
428
|
+
if (worker.on) {
|
|
429
|
+
worker.on("message", heard);
|
|
430
|
+
worker.on("error", broke);
|
|
431
|
+
} else {
|
|
432
|
+
worker.addEventListener?.("message", onMessage);
|
|
433
|
+
worker.addEventListener?.("error", broke);
|
|
434
|
+
}
|
|
435
|
+
const stop = () => {
|
|
436
|
+
if (worker.off) {
|
|
437
|
+
worker.off("message", heard);
|
|
438
|
+
worker.off("error", broke);
|
|
439
|
+
} else {
|
|
440
|
+
worker.removeEventListener?.("message", onMessage);
|
|
441
|
+
worker.removeEventListener?.("error", broke);
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
lines.set(worker, () => {
|
|
445
|
+
cut = true;
|
|
446
|
+
stop();
|
|
447
|
+
});
|
|
448
|
+
const transport = {
|
|
449
|
+
send: (text) => post(text),
|
|
450
|
+
onMessage: (handler) => toSession = handler,
|
|
451
|
+
onClose: (handler) => closed = handler,
|
|
452
|
+
close: () => {}
|
|
453
|
+
};
|
|
454
|
+
post({
|
|
455
|
+
vg: "start",
|
|
456
|
+
...asked
|
|
457
|
+
});
|
|
458
|
+
try {
|
|
459
|
+
session = await Promise.race([connectAs(transport, {
|
|
460
|
+
rules: game,
|
|
461
|
+
maps,
|
|
462
|
+
navigation: {
|
|
463
|
+
...navigation,
|
|
464
|
+
builds: { builder: (build) => new Promise((done, failed) => {
|
|
465
|
+
const id = ++nextBuild;
|
|
466
|
+
builds.set(id, {
|
|
467
|
+
done,
|
|
468
|
+
failed
|
|
469
|
+
});
|
|
470
|
+
post({
|
|
471
|
+
vg: "navigation",
|
|
472
|
+
id,
|
|
473
|
+
build: {
|
|
474
|
+
positions: build.positions.slice(),
|
|
475
|
+
indices: build.indices.slice(),
|
|
476
|
+
config: build.config,
|
|
477
|
+
...build.speeds && { speeds: {
|
|
478
|
+
...build.speeds,
|
|
479
|
+
values: build.speeds.values.slice()
|
|
480
|
+
} }
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}) }
|
|
484
|
+
}
|
|
485
|
+
}, (...made) => new WorkerSession(...made)), refused]);
|
|
486
|
+
} catch (error) {
|
|
487
|
+
post({ vg: "stop" });
|
|
488
|
+
stop();
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
session.wire(post, log, stop);
|
|
492
|
+
session.about = about;
|
|
493
|
+
for (const said of early.splice(0)) session.heard(said);
|
|
494
|
+
return session;
|
|
495
|
+
}
|
|
496
|
+
//#endregion
|
|
497
|
+
export { WorkerSession, serveWorld, workerSession };
|
|
498
|
+
|
|
499
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","names":["checkpointEvent"],"sources":["../../src/session/worker.ts"],"sourcesContent":["import { checkpoint as checkpointEvent } from '#engine/engineEvents'\nimport { reloadGame } from '#engine/hotReload'\nimport { randomSeed } from '#engine/session/seed'\nimport { paceOf, savesOf } from './can'\nimport type { PlayerId } from '#engine/entity'\nimport { createWorldFromMap, type Rules, loadWorld } from '#engine/game'\nimport { errorFields, type LogEntry, Logger, rootLogger } from '#engine/log'\nimport type { GameMap } from '#engine/map'\nimport type { Message } from '#engine/messages'\nimport { type NavigationBuild, navigationData } from '#engine/navigation/builds'\nimport { saveWorld, type WorldSave } from '#engine/save'\nimport type { World } from '#engine/world'\nimport type { SystemTiming } from '#engine/scheduler'\nimport type { SessionCan, SessionDebug } from './protocol'\nimport { type ConnectOptions, connectAs, MAX_JITTER, RemoteSession, SessionHost, type Transport } from './remote'\n\n/*\n * The simulation off the page's thread (S54). A game played alone steps its world on the thread that draws: a tick that\n * takes long is a frame that is late. Here the world runs in a worker the page gives, and the page has a seat at it as\n * it would at a server's game: snapshots one way, commands the other, over the worker's messages. The game's code has to\n * be in the worker, and only the game's developer can put it there: the worker's file is theirs, one call\n * (`serveWorld(game, { onStart })`), made into a worker the way their bundler wants it; the library makes none. What\n * the page did by reaching into the world (holding the game for a menu, a step, a save, the checkpoint to retry from,\n * the debug tools' view, what the game says in its log) goes over the same messages.\n */\n\n/**\n * What a worker is, as far as a game goes: a page's `Worker`, or Node's `worker_threads` one\n *\n * @beta\n */\nexport interface WorldWorkerLike {\n\t/** Sends a message to the worker, with objects to transfer rather than copy */\n\tpostMessage(message: unknown, transfer?: unknown[]): void\n\t/** Listens for the worker's messages or errors, where the worker is a page's `Worker` */\n\taddEventListener?(type: 'message' | 'error', listener: (event: { data?: unknown; message?: string }) => void): void\n\t/** Stops a listener added with `addEventListener` */\n\tremoveEventListener?(type: 'message' | 'error', listener: (event: { data?: unknown; message?: string }) => void): void\n\t/** Listens for the worker's messages or errors, where the worker is Node's `worker_threads` one */\n\ton?(type: 'message' | 'error', listener: (value: unknown) => void): void\n\t/** Stops a listener added with `on` */\n\toff?(type: 'message' | 'error', listener: (value: unknown) => void): void\n}\n\n/**\n * Where a worker hears and answers: a page's worker scope, or Node's `parentPort`\n *\n * @beta\n */\nexport interface WorldPort {\n\t/** Sends a message to the page, with objects to transfer rather than copy */\n\tpostMessage(message: unknown, transfer?: unknown[]): void\n\t/** Listens for the page's messages, where the port is a worker scope */\n\taddEventListener?(type: 'message', listener: (event: { data: unknown }) => void): void\n\t/** Listens for the page's messages, where the port is Node's `parentPort` */\n\ton?(type: 'message', listener: (value: unknown) => void): void\n}\n\n/**\n * What the page says a game in a worker is made from: plain data, which is all that crosses\n *\n * @beta\n */\nexport interface WorkerGame {\n\t/** A map of the game: the world is made from it. Or a save to go on from (`from`); or neither, where the worker makes its world in code */\n\tmap?: GameMap\n\t/** A save to continue the game from, in place of a map */\n\tfrom?: WorldSave\n\t/** Who the player at the screen is: as the worker says (`ServeWorldOptions.player`), then the map's first with a start, when left out */\n\tplayer?: PlayerId\n\t/** The seed the world's random generator starts with */\n\tseed?: number\n\t/** Whether the player may use the debug tools, and sees everything from the start */\n\tdebug?: boolean\n\t/** Whether the player sees the whole map from the start */\n\treveal?: boolean\n\t/** Anything else the worker's own code is to know (`start`, `world`): plain data */\n\targs?: unknown\n}\n\n/**\n * What the worker's code that runs on a world is given (`ServeWorldOptions.onStart`, `beforePlay`): the player at the\n * screen, the map, what the page sent (`WorkerGame.args`), and a way to tell the page something\n *\n * @beta\n */\nexport interface WorkerGameContext {\n\t/** The player at the screen */\n\tplayer: PlayerId\n\t/** The map the world was made from, where it was made from one (or sent with a save) */\n\tmap?: GameMap\n\t/** What the page sent for the worker's own code (`WorkerGame.args`): plain data */\n\targs: unknown\n\t/**\n\t * Tells the page something, while this game lasts: plain data, as it crosses (a mission won and what it carries on).\n\t * The page hears it on its session (`WorkerSession.onTold`), in order with the game's ticks: what is told in a tick\n\t * is heard before the snapshot of that tick. Said for nothing once the game has ended\n\t */\n\ttell(data: unknown): void\n}\n\n/**\n * What the worker's file gives besides the game: its code that runs on the world, which cannot be sent\n *\n * @beta\n */\nexport interface ServeWorldOptions {\n\t/** A world made in code, where the page gives neither a map nor a save: generated ground, players of its own */\n\tworld?: (context: { rules: Rules; seed: number; args: unknown; log: Logger }) => World | Promise<World>\n\t/** What the game does once a new world is made, before anyone plays: as `launch`'s `start`, which a worker's game has here */\n\tonStart?: (world: World, context: WorkerGameContext) => void | Promise<void>\n\t/**\n\t * What the game does before anyone plays, a new world or one loaded from a save (`fresh`), after `onStart`: as\n\t * `prepareGame`'s `beforePlay`, which a worker's game has here. What it listens to on the world it listens to for\n\t * this game alone, as a loaded game has none of what the game before listened to\n\t */\n\tbeforePlay?: (world: World, context: WorkerGameContext & { fresh: boolean }) => void | Promise<void>\n\t/** Who the player at the screen is, where the page does not say */\n\tplayer?: (world: World, map?: GameMap) => PlayerId\n\t/**\n\t * What the page is told of the world as the game starts, which it cannot reach into: where the player's base is, who\n\t * the other side is. Plain data, as it crosses; the page reads it on its session (`WorkerSession.about`). Asked once\n\t * the world is made and started (`onStart`), for a new game and for one loaded\n\t */\n\tabout?: (world: World, context: { player: PlayerId; map?: GameMap; args: unknown }) => unknown\n\t/** Where it hears: the worker's own scope when left out (a page's worker); Node's `parentPort` in a worker thread */\n\tport?: WorldPort\n\t/**\n\t * A new version of the game, loaded again in the worker as the page asks (hot reload: the page's game took one, and\n\t * a worker has no hot reload of its own). The game's module imported anew, so that the dev server gives it as it is\n\t * now: `(version) => import(/* @vite-ignore *\\/ `./index.ts?t=${version}`).then((module) => module.myGame)` (a path\n\t * from the worker's file). Only ever asked for in the dev server. Without it, a game in the worker keeps the version it began with\n\t */\n\treload?: (version: number) => Promise<Rules | undefined> | Rules | undefined\n}\n\n/** What goes between the page and the worker besides the session's own text */\ntype ToWorker =\n\t| ({ vg: 'start' } & WorkerGame)\n\t| { vg: 'stop' }\n\t| { vg: 'reload' }\n\t| { vg: 'speed'; speed: number }\n\t| { vg: 'advance'; ticks: number }\n\t| { vg: 'save'; id: number }\n\t| { vg: 'navigation'; id: number; build: NavigationBuild }\n\t| { vg: 'profile'; on: boolean }\n\ntype FromWorker =\n\t| { vg: 'ready'; player: PlayerId; about?: unknown }\n\t| { vg: 'refused'; message: string; stack?: string }\n\t| { vg: 'saved'; id: number; save?: WorldSave; error?: string }\n\t| { vg: 'built'; id: number; data?: Uint8Array; error?: string }\n\t| { vg: 'checkpoint'; label: Message; save: WorldSave }\n\t| { vg: 'log'; entry: LogEntry }\n\t| { vg: 'timing'; tick: number; tickMax: number; send: number; systems: SystemTiming[] }\n\t| { vg: 'told'; data: unknown }\n\n/** Milliseconds between two words of where the time went */\nconst TIMING_EVERY = 1000\n\nconst firstOfMap = (map: GameMap): PlayerId | undefined => (map.players.find((player) => player.start) ?? map.players[0])?.id\n\nfunction firstOfWorld(world: World): PlayerId {\n\tfor (const player of world.players.values()) if (!player.neutral && !player.creeps) return player.id\n\tthrow new Error('The world has no player to play: every one of its players is neutral')\n}\n\n/**\n * What a game's worker file does: `serveWorld(game, { onStart })`. It waits for the page to say what to play (a map, a\n * save, or nothing for a world made here in code), makes the world, runs it by the clock, and seats the page's player\n * at it. A new game asked for ends the one before: a restart is the same worker, its navigation built already\n *\n * @public\n */\nexport function serveWorld(first: Rules, options: ServeWorldOptions = {}): void {\n\t/** The game's version now: the one it began with, or the one it took last (`reload`) */\n\tlet game = first\n\tconst port = options.port ?? (globalThis as unknown as WorldPort)\n\tconst post = (message: FromWorker | string, transfer?: unknown[]) => port.postMessage(message, transfer)\n\t/** The game running now, and what ends it */\n\tlet running: { host: SessionHost; hear: (text: string) => void; end: () => void } | undefined\n\t/** Whether the systems are measured, as the page's stats ask: off until they do */\n\tlet profiling = false\n\t/** Each start has a number: one overtaken while its world was made is let go */\n\tlet starts = 0\n\n\tconst start = async (asked: WorkerGame) => {\n\t\tconst mine = ++starts\n\t\trunning?.end()\n\t\trunning = undefined\n\t\t// what the world says goes to the page, which says it where it says its own: not twice, here too\n\t\tconst log = new Logger()\n\t\tconst stopLog = log.to((entry) => post({ vg: 'log', entry }))\n\t\tlet world: World | undefined\n\t\ttry {\n\t\t\tconst seed = asked.seed ?? randomSeed()\n\t\t\tworld = asked.from\n\t\t\t\t? await loadWorld(asked.from, { rules: game, log })\n\t\t\t\t: asked.map\n\t\t\t\t\t? await createWorldFromMap({ map: asked.map, rules: game, seed, log })\n\t\t\t\t\t: options.world\n\t\t\t\t\t\t? await options.world({ rules: game, seed, args: asked.args, log })\n\t\t\t\t\t\t: undefined\n\t\t\tif (!world) throw new Error('A game in a worker needs a map, a save to go on from, or a world made in the worker (serveWorld world)')\n\t\t\tif (mine !== starts) return world.dispose()\n\t\t\tworld.errorPolicy ??= 'end'\n\t\t\tconst player = asked.player ?? options.player?.(world, asked.map) ?? (asked.map && firstOfMap(asked.map)) ?? firstOfWorld(world)\n\t\t\t// what the game's code tells the page, while this game is the one played\n\t\t\tconst context: WorkerGameContext = {\n\t\t\t\tplayer,\n\t\t\t\tmap: asked.map,\n\t\t\t\targs: asked.args,\n\t\t\t\ttell: (data) => {\n\t\t\t\t\tif (mine === starts) post({ vg: 'told', data })\n\t\t\t\t}\n\t\t\t}\n\t\t\t// only a new game is started: one loaded goes on as it was\n\t\t\tif (!asked.from) await options.onStart?.(world, context)\n\t\t\tif (mine !== starts) return world.dispose()\n\t\t\tawait options.beforePlay?.(world, { ...context, fresh: !asked.from })\n\t\t\tif (mine !== starts) return world.dispose()\n\t\t\tif (asked.reveal) world.fog.setRevealed(world.player(player).team, true)\n\t\t\tif (asked.debug) world.debugPlayers.add(player)\n\n\t\t\tconst made = world\n\t\t\t// every tick goes to the page: there is no wire to spare, and the screen is as close to the world as it gets\n\t\t\tconst host = new SessionHost(made, { ownsWorld: true, sendRate: made.tickRate, dropSilentAfter: Infinity })\n\t\t\tlet hear: (text: string) => void = () => {}\n\t\t\tconst transport: Transport = { send: (text) => post(text), onMessage: (handler) => (hear = handler), onClose: () => {}, close: () => {} }\n\t\t\t// the checkpoint to start again from, as the world stood at the end of the tick that marked it\n\t\t\tconst stopCheckpoint = made.events.on(checkpointEvent, ({ label }) => {\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (running?.host === host) post({ vg: 'checkpoint', label, save: saveWorld(made) })\n\t\t\t\t}, 0)\n\t\t\t})\n\t\t\t// measured as the page's stats ask (`profile`): the next game as the one before\n\t\t\tmade.scheduler.profiling = profiling\n\t\t\tconst timingTimer = setInterval(() => {\n\t\t\t\tconst timing = host.takeTiming()\n\t\t\t\tpost({\n\t\t\t\t\tvg: 'timing',\n\t\t\t\t\ttick: timing.ticks ? timing.tickTime / timing.ticks : 0,\n\t\t\t\t\ttickMax: timing.tickMax,\n\t\t\t\t\tsend: timing.sends ? timing.sendTime / timing.sends : 0,\n\t\t\t\t\tsystems: made.scheduler.timing()\n\t\t\t\t})\n\t\t\t}, TIMING_EVERY)\n\t\t\trunning = {\n\t\t\t\thost,\n\t\t\t\thear: (text) => hear(text),\n\t\t\t\tend: () => {\n\t\t\t\t\tclearInterval(timingTimer)\n\t\t\t\t\tstopCheckpoint()\n\t\t\t\t\tstopLog()\n\t\t\t\t\thost.dispose()\n\t\t\t\t}\n\t\t\t}\n\t\t\tpost({ vg: 'ready', player, about: options.about?.(made, { player, map: asked.map, args: asked.args }) })\n\t\t\t// a worker's messages are never lost nor reordered: each frame is the base of the next as it goes\n\t\t\thost.connect(player, transport, { inOrder: true })\n\t\t\thost.start()\n\t\t} catch (error) {\n\t\t\tstopLog()\n\t\t\tworld?.dispose()\n\t\t\tif (mine === starts)\n\t\t\t\tpost({\n\t\t\t\t\tvg: 'refused',\n\t\t\t\t\tmessage: error instanceof Error ? error.message : String(error),\n\t\t\t\t\tstack: error instanceof Error ? error.stack : undefined\n\t\t\t\t})\n\t\t}\n\t}\n\n\tconst heard = (message: unknown) => {\n\t\t// the session's own words are text; everything else is said as an object\n\t\tif (typeof message === 'string') return running?.hear(message)\n\t\tconst said = message as ToWorker\n\t\tif (typeof said !== 'object' || said === null) return\n\t\tswitch (said.vg) {\n\t\t\tcase 'start':\n\t\t\t\treturn void start(said)\n\t\t\tcase 'reload':\n\t\t\t\treturn void (async () => {\n\t\t\t\t\tconst world = running?.host.world\n\t\t\t\t\tif (!options.reload) {\n\t\t\t\t\t\tworld?.log.warn('game', `${game.id} in a worker has no reload (serveWorld reload): it keeps the version it began with`)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst next = await options.reload(Date.now())\n\t\t\t\t\t\tif (!next) return\n\t\t\t\t\t\tgame = next\n\t\t\t\t\t\tif (world && running?.host.world === world) reloadGame(world, next)\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tworld?.log.error(\n\t\t\t\t\t\t\t'game',\n\t\t\t\t\t\t\t`${game.id}'s new version could not be taken in the worker: ${error instanceof Error ? error.message : String(error)}`\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t})()\n\t\t\tcase 'stop':\n\t\t\t\tstarts++\n\t\t\t\trunning?.end()\n\t\t\t\trunning = undefined\n\t\t\t\treturn\n\t\t\tcase 'speed':\n\t\t\t\tif (running) running.host.speed = said.speed\n\t\t\t\treturn\n\t\t\tcase 'advance':\n\t\t\t\treturn running?.host.advance(said.ticks)\n\t\t\tcase 'save':\n\t\t\t\ttry {\n\t\t\t\t\tif (!running) throw new Error('There is no game to save')\n\t\t\t\t\tpost({ vg: 'saved', id: said.id, save: saveWorld(running.host.world) })\n\t\t\t\t} catch (error) {\n\t\t\t\t\tpost({ vg: 'saved', id: said.id, error: error instanceof Error ? error.message : String(error) })\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\tcase 'navigation':\n\t\t\t\t// the page's own navigation (the ways it shows): built here, where the world's was, or kept from it\n\t\t\t\treturn void navigationData(said.build).then(\n\t\t\t\t\t(data) => post({ vg: 'built', id: said.id, data }),\n\t\t\t\t\t(error: unknown) => post({ vg: 'built', id: said.id, error: error instanceof Error ? error.message : String(error) })\n\t\t\t\t)\n\t\t\tcase 'profile':\n\t\t\t\tprofiling = said.on\n\t\t\t\tif (running) running.host.world.scheduler.profiling = said.on\n\t\t\t\treturn\n\t\t}\n\t}\n\tif (port.on) port.on('message', heard)\n\telse port.addEventListener?.('message', (event) => heard(event.data))\n}\n\n/**\n * A seat at a game run in a worker of this page (`workerSession`): a `RemoteSession` whose host is a message away,\n * with what a game played in the page has besides: its pace held and stepped (`speed`, `advance`), a save of it\n * (`save`), the checkpoint to start again from, what it says in its log, the debug tools' view, and where its time went\n *\n * @beta\n */\nexport class WorkerSession extends RemoteSession {\n\t/** What the world says (`World.log`), said again here: the page shows it with its own */\n\tlog!: Logger\n\t/** The label and save of the last checkpoint the worker's game took, to retry from */\n\tcheckpoint?: { label: Message; save: WorldSave }\n\t/** What the worker's file said of the world as the game started (`ServeWorldOptions.about`): plain data, none where it says nothing */\n\tabout?: unknown\n\t/** The debug tools' view of the world, where they are on: over the session's own words, as a server's is */\n\tget debug(): SessionDebug | undefined {\n\t\treturn this.debugView\n\t}\n\t/** Its pace held and stepped, saves of it, the debug tools' view where they are on, and where its time went and in which systems */\n\toverride readonly can: SessionCan = {\n\t\tpace: paceOf(this),\n\t\tsaves: savesOf(this),\n\t\tinspect: this.debugView,\n\t\ttiming: { timing: () => this.timing(), profile: (on) => this.postToWorker({ vg: 'profile', on }) }\n\t}\n\tprivate pace = 1\n\tprivate timed?: { tick: number; tickMax: number; send: number; systems: SystemTiming[] }\n\t/** Milliseconds the page took to take in what the worker sent, each time, evened out: its share of a game run there */\n\treceived = 0\n\tprivate postToWorker: (message: ToWorker) => void = () => {}\n\tprivate readonly saves = new Map<number, { done: (save: WorldSave) => void; failed: (error: Error) => void }>()\n\tprivate nextSave = 0\n\tprivate stopHearing: () => void = () => {}\n\t/** Who hears what the worker's code tells (`onTold`), and what it told before anyone listened */\n\tprivate readonly listening = new Set<(data: unknown) => void>()\n\tprivate readonly toldBefore: unknown[] = []\n\n\t/** What `workerSession` gives it once it is made: the way to the worker, and what stops hearing it */\n\twire(post: (message: ToWorker) => void, log: Logger, stop: () => void): void {\n\t\tthis.postToWorker = post\n\t\tthis.log = log\n\t\tthis.stopHearing = stop\n\t}\n\n\t/** What the worker said that is not the session's own text */\n\theard(said: FromWorker): void {\n\t\tif (said.vg === 'checkpoint') this.checkpoint = { label: said.label, save: said.save }\n\t\telse if (said.vg === 'told') {\n\t\t\tif (this.listening.size) for (const listener of this.listening) listener(said.data)\n\t\t\telse this.toldBefore.push(said.data)\n\t\t} else if (said.vg === 'timing') this.timed = { tick: said.tick, tickMax: said.tickMax, send: said.send, systems: said.systems }\n\t\telse if (said.vg === 'saved') {\n\t\t\tconst waiting = this.saves.get(said.id)\n\t\t\tthis.saves.delete(said.id)\n\t\t\tif (said.save) waiting?.done(said.save)\n\t\t\telse waiting?.failed(new Error(said.error ?? 'The game could not be saved'))\n\t\t}\n\t}\n\n\t/**\n\t * Hears what the worker's code tells the page (`WorkerGameContext.tell`): plain data, in order with the ticks. What\n\t * it told before anyone listened is heard by the first listener, at once. Gives back what stops hearing it\n\t */\n\tonTold(listener: (data: unknown) => void): () => void {\n\t\tthis.listening.add(listener)\n\t\tfor (const data of this.toldBefore.splice(0)) listener(data)\n\t\treturn () => this.listening.delete(listener)\n\t}\n\n\t/**\n\t * How far behind the newest tick the screen is shown, in ticks: one, and room for how unevenly they come (a tick\n\t * that took long comes late). Less than over a wire, where two are kept in hand: there is no line to stall here\n\t */\n\toverride get delay(): number {\n\t\treturn this.interval + Math.min(this.jitter, this.limits.maxJitter ?? MAX_JITTER) * this.tickRate * 2\n\t}\n\n\t/** The simulation speed multiplier the worker's game runs at, 0 pauses; setting it tells the worker */\n\tget speed(): number {\n\t\treturn this.pace\n\t}\n\n\tset speed(speed: number) {\n\t\tthis.pace = speed\n\t\tthis.postToWorker({ vg: 'speed', speed })\n\t}\n\n\t/** Asks the worker to step the held game by this many ticks */\n\tadvance(ticks = 1): void {\n\t\tthis.postToWorker({ vg: 'advance', ticks })\n\t}\n\n\t/**\n\t * Asks the worker to take a new version of the game (hot reload): it loads the game again itself, as its file says\n\t * (`serveWorld` `reload`), and puts it into its world\n\t */\n\treloadGame(): void {\n\t\tthis.postToWorker({ vg: 'reload' })\n\t}\n\n\t/** Asks the worker for a save of its world and resolves with it; rejects if the game ends first */\n\tsave(): Promise<WorldSave> {\n\t\treturn new Promise((done, failed) => {\n\t\t\tconst id = ++this.nextSave\n\t\t\tthis.saves.set(id, { done, failed })\n\t\t\tthis.postToWorker({ vg: 'save', id })\n\t\t})\n\t}\n\n\t/** Where the worker's time went (tick, send and receive milliseconds and each system's), or undefined until it has said */\n\ttiming(): { tick: number; tickMax: number; send: number; receive: number; systems: SystemTiming[] } | undefined {\n\t\treturn this.timed && { ...this.timed, receive: this.received }\n\t}\n\n\t/** Ends the game in the worker. The worker is the page's: it stays, for the next game, until the page ends it */\n\toverride dispose(): void {\n\t\tthis.postToWorker({ vg: 'stop' })\n\t\tthis.stopHearing()\n\t\tfor (const waiting of this.saves.values()) waiting.failed(new Error('The game ended'))\n\t\tthis.saves.clear()\n\t\tsuper.dispose()\n\t}\n}\n\n/**\n * What a seat at a worker's game is asked for: what to play (`WorkerGame`), and what `connect` takes\n *\n * @beta\n */\nexport interface WorkerSessionOptions extends WorkerGame, Pick<ConnectOptions, 'navigation' | 'maps'> {\n\t/** The game module's rules the worker's game runs, which the page needs the data of */\n\trules: Rules\n\t/** The logger what the world says is said under, in the page: the root one when left out */\n\tlog?: Logger\n}\n\n/** What cuts off the seat at the game a worker plays now, by the worker: a new game there ends it */\nconst lines = new WeakMap<object, () => void>()\n\n/**\n * Plays a game in a worker, and seats this page's player at it: the worker's file calls `serveWorld` with the same\n * game. Settles once the world is made there and its welcome is in; fails with what the worker said went wrong\n *\n * const session = await workerSession(new Worker(new URL('./game.worker.ts', import.meta.url), { type: 'module' }), { rules: game, map })\n *\n * @beta\n */\nexport async function workerSession(worker: WorldWorkerLike, options: WorkerSessionOptions): Promise<WorkerSession> {\n\tconst { rules: game, navigation, maps, log: under, ...asked } = options\n\tlet toSession: (text: string) => void = () => {}\n\tlet closed: () => void = () => {}\n\tlet session: WorkerSession | undefined\n\tconst builds = new Map<number, { done: (data: Uint8Array) => void; failed: (error: Error) => void }>()\n\tlet nextBuild = 0\n\t/** What the worker said of its world as it was ready, before there is a session to keep it */\n\tlet about: unknown\n\t/** What the worker's code told before there is a session to hear it */\n\tconst early: FromWorker[] = []\n\t// what the world says, with the game and the tick it said it in\n\tlet saying: LogEntry | undefined\n\tconst log = (under ?? rootLogger).child({ context: () => ({ game: saying?.game, tick: saying?.tick }) })\n\t// the game before on this worker is over as this one starts (`start` ends it there): its seat neither speaks to the\n\t// worker nor hears it from now on, though its page goes on showing it a while (an app's scene before the next is in)\n\tlines.get(worker)?.()\n\tlet cut = false\n\tconst post = (message: ToWorker | string) => {\n\t\tif (!cut) worker.postMessage(message)\n\t}\n\n\tlet refuse: (error: Error) => void = () => {}\n\tconst refused = new Promise<never>((_, reject) => (refuse = reject))\n\t// nobody may be waiting on it: a game that started is not refused\n\trefused.catch(() => {})\n\n\tconst heard = (message: unknown) => {\n\t\tif (typeof message === 'string') {\n\t\t\tconst began = performance.now()\n\t\t\ttoSession(message)\n\t\t\tif (session) session.received += (performance.now() - began - session.received) * 0.1\n\t\t\treturn\n\t\t}\n\t\tconst said = message as FromWorker\n\t\tif (typeof said !== 'object' || said === null) return\n\t\tif (said.vg === 'refused') {\n\t\t\tconst error = new Error(said.message)\n\t\t\tif (said.stack) error.stack = said.stack\n\t\t\trefuse(error)\n\t\t} else if (said.vg === 'log') {\n\t\t\tsaying = said.entry\n\t\t\tlog.log(said.entry.level, said.entry.category, said.entry.message, said.entry.fields)\n\t\t\tsaying = undefined\n\t\t} else if (said.vg === 'built') {\n\t\t\tconst waiting = builds.get(said.id)\n\t\t\tbuilds.delete(said.id)\n\t\t\tif (said.data) waiting?.done(said.data)\n\t\t\telse waiting?.failed(new Error(said.error ?? 'The navigation could not be built'))\n\t\t} else if (said.vg === 'ready') about = said.about\n\t\telse if (!session && said.vg === 'told') early.push(said)\n\t\telse session?.heard(said)\n\t}\n\tconst broke = (error: unknown) => {\n\t\tconst reason = new Error(\n\t\t\t`The game's worker stopped: ${error instanceof Error ? error.message : String((error as { message?: string })?.message ?? error)}`\n\t\t)\n\t\tlog.error('game', reason.message, { error: errorFields(error) })\n\t\trefuse(reason)\n\t\tclosed()\n\t}\n\tconst onMessage = (event: { data?: unknown }) => heard(event.data)\n\tif (worker.on) {\n\t\tworker.on('message', heard)\n\t\tworker.on('error', broke)\n\t} else {\n\t\tworker.addEventListener?.('message', onMessage)\n\t\tworker.addEventListener?.('error', broke)\n\t}\n\tconst stop = () => {\n\t\tif (worker.off) {\n\t\t\tworker.off('message', heard)\n\t\t\tworker.off('error', broke)\n\t\t} else {\n\t\t\tworker.removeEventListener?.('message', onMessage)\n\t\t\tworker.removeEventListener?.('error', broke)\n\t\t}\n\t}\n\n\tlines.set(worker, () => {\n\t\tcut = true\n\t\tstop()\n\t})\n\n\tconst transport: Transport = {\n\t\tsend: (text) => post(text),\n\t\tonMessage: (handler) => (toSession = handler),\n\t\tonClose: (handler) => (closed = handler),\n\t\tclose: () => {}\n\t}\n\tpost({ vg: 'start', ...asked })\n\ttry {\n\t\tsession = await Promise.race([\n\t\t\tconnectAs(\n\t\t\t\ttransport,\n\t\t\t\t{\n\t\t\t\t\trules: game,\n\t\t\t\t\tmaps,\n\t\t\t\t\t// the page's own navigation is built in the worker, where the world's was: the page is never held for it\n\t\t\t\t\tnavigation: {\n\t\t\t\t\t\t...navigation,\n\t\t\t\t\t\tbuilds: {\n\t\t\t\t\t\t\tbuilder: (build) =>\n\t\t\t\t\t\t\t\tnew Promise<Uint8Array>((done, failed) => {\n\t\t\t\t\t\t\t\t\tconst id = ++nextBuild\n\t\t\t\t\t\t\t\t\tbuilds.set(id, { done, failed })\n\t\t\t\t\t\t\t\t\tpost({\n\t\t\t\t\t\t\t\t\t\tvg: 'navigation',\n\t\t\t\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t\t\t\tbuild: {\n\t\t\t\t\t\t\t\t\t\t\tpositions: build.positions.slice(),\n\t\t\t\t\t\t\t\t\t\t\tindices: build.indices.slice(),\n\t\t\t\t\t\t\t\t\t\t\tconfig: build.config,\n\t\t\t\t\t\t\t\t\t\t\t...(build.speeds && { speeds: { ...build.speeds, values: build.speeds.values.slice() } })\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t(...made) => new WorkerSession(...made)\n\t\t\t),\n\t\t\trefused\n\t\t])\n\t} catch (error) {\n\t\tpost({ vg: 'stop' })\n\t\tstop()\n\t\tthrow error\n\t}\n\tsession.wire(post, log, stop)\n\tsession.about = about\n\tfor (const said of early.splice(0)) session.heard(said)\n\treturn session\n}\n"],"mappings":"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"}
|
package/dist/shared.d.ts
CHANGED
|
@@ -22,10 +22,21 @@ export type Relation = 'self' | 'ally' | 'enemy' | 'neutral';
|
|
|
22
22
|
* @beta
|
|
23
23
|
*/
|
|
24
24
|
export interface TargetFacts {
|
|
25
|
+
/** The target's entity kind, such as unit or structure */
|
|
25
26
|
kind: EntityKind;
|
|
27
|
+
/** The layer the target is on (ground, air, water), which an ability's `targets` may name */
|
|
26
28
|
layer: Layer;
|
|
29
|
+
/** Whether the target is a hero */
|
|
27
30
|
hero: boolean;
|
|
31
|
+
/** Whether the target cannot be hurt: its type (`UnitTypeDef.invulnerable`) or a buff on it (`BuffDef.invulnerable`) */
|
|
28
32
|
invulnerable: boolean;
|
|
33
|
+
/** The abilities that alone may target it (`UnitTypeDef.targetableBy`) */
|
|
34
|
+
targetableBy?: readonly string[];
|
|
35
|
+
/** A buff puts it out of everyone else's reach (`BuffDef.untargetable`): nothing but its own abilities is cast on it @beta */
|
|
36
|
+
untargetable?: boolean;
|
|
37
|
+
/** The tags of its type (`UnitTypeDef.tags`), for an ability that targets only some (`targets.tags`) @beta */
|
|
38
|
+
tags?: readonly string[];
|
|
39
|
+
/** What the target is to the caster: self, ally, enemy or neutral */
|
|
29
40
|
relation: Relation;
|
|
30
41
|
/** Immune to spells (see `UnitTypeDef.spellImmune`): no ability touches it but its own, and those that get through */
|
|
31
42
|
spellImmune?: boolean;
|
|
@@ -54,16 +65,27 @@ export interface ReadyFacts {
|
|
|
54
65
|
cooldown: number;
|
|
55
66
|
/** Uses left, of an ability with charges (`chargesLeft`): none, and it is not ready */
|
|
56
67
|
charges?: number;
|
|
68
|
+
/** The caster's mana now, to meet the ability's mana cost */
|
|
57
69
|
mana: number;
|
|
58
|
-
|
|
59
|
-
|
|
70
|
+
/** The caster's health now, for abilities that cost health */
|
|
71
|
+
health: number;
|
|
72
|
+
/** The caster's largest health, which a health cost may not take below */
|
|
73
|
+
maxHealth: number;
|
|
60
74
|
/** It comes from something carried: items ask for no mana, and silence does not stop them */
|
|
61
75
|
item?: boolean;
|
|
62
76
|
/** One of the spells the hero brought along rather than learned: silence does not stop those either */
|
|
63
77
|
spell?: boolean;
|
|
78
|
+
/** Whether the caster is silenced, which stops its spells but not items or brought-along spells */
|
|
64
79
|
silenced?: boolean;
|
|
80
|
+
/** A buff keeps it from rushing or jumping of its own (`BuffDef.grounded`), and the ability would (a `dash`, a `blink`) */
|
|
81
|
+
grounded?: boolean;
|
|
65
82
|
/** The debug switch that makes abilities cost nothing */
|
|
66
83
|
noManaCosts?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Health it pays for each point of mana an ability costs, in place of the mana (`BuffDef.paysWithHealth`): none, or
|
|
86
|
+
* left out, for one that pays with mana
|
|
87
|
+
*/
|
|
88
|
+
healthPerMana?: number;
|
|
67
89
|
/** What the simulation's `canCast` hook decided instead, when it told the screen: a reason, or null for none */
|
|
68
90
|
decided?: Message | null;
|
|
69
91
|
}
|
|
@@ -89,10 +111,13 @@ export declare function abilityRefusal(ability: AbilityDef, facts: ReadyFacts):
|
|
|
89
111
|
* @beta
|
|
90
112
|
*/
|
|
91
113
|
export interface PlayerFacts {
|
|
114
|
+
/** What the player has of each resource, to meet a cost */
|
|
92
115
|
resources: Readonly<Purse>;
|
|
116
|
+
/** Supply the player's units and queued units take up now */
|
|
93
117
|
supplyUsed: number;
|
|
118
|
+
/** The most supply the player may use */
|
|
94
119
|
supplyCap: number;
|
|
95
|
-
/** The game's other pools of supply, by name (`
|
|
120
|
+
/** The game's other pools of supply, by name (`RuleSettings.supply.pools`): left out in a game with none */
|
|
96
121
|
supplies?: Readonly<Record<string, {
|
|
97
122
|
used: number;
|
|
98
123
|
cap: number;
|
|
@@ -115,7 +140,7 @@ export interface PlayerFacts {
|
|
|
115
140
|
availability?: Record<string, boolean>;
|
|
116
141
|
}
|
|
117
142
|
/**
|
|
118
|
-
* Whether a worker gathers a kind of resource at all (`harvester.
|
|
143
|
+
* Whether a worker gathers a kind of resource at all (`harvester.ids`): the game's `canHarvest` hook may refuse it a
|
|
119
144
|
* resource all the same (`canHarvest`)
|
|
120
145
|
*
|
|
121
146
|
* @beta
|
|
@@ -164,7 +189,8 @@ export declare function trainRefusal(registry: Registry, def: UnitTypeDef, playe
|
|
|
164
189
|
tech?: boolean;
|
|
165
190
|
}): Message | undefined;
|
|
166
191
|
/**
|
|
167
|
-
* What a shop pays for an item: a part of its price
|
|
192
|
+
* What a shop pays for an item: a part of its price (the item's `sellRate`, or the game's `sellPrice`), and of what is
|
|
193
|
+
* left of it for what runs out (a stack counts each of it)
|
|
168
194
|
*
|
|
169
195
|
* @beta
|
|
170
196
|
*/
|