@v12-engine/engine 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/dist/abilities/buffs.d.ts +83 -0
- package/dist/abilities/castTold.d.ts +12 -0
- package/dist/abilities/charges.d.ts +28 -0
- package/dist/abilities/dispel.d.ts +9 -0
- package/dist/abilities/effectFields.d.ts +10 -0
- package/dist/abilities/effects/buff.d.ts +8 -0
- package/dist/abilities/effects/core.d.ts +1 -0
- package/dist/abilities/effects/damage.d.ts +1 -0
- package/dist/abilities/effects/heal.d.ts +2 -0
- package/dist/abilities/effects/missile.d.ts +1 -0
- package/dist/abilities/effects/moves.d.ts +11 -0
- package/dist/abilities/effects/passives.d.ts +15 -0
- package/dist/abilities/effects/sight.d.ts +4 -0
- package/dist/abilities/effects/spawn.d.ts +2 -0
- package/dist/abilities/effects/timed.d.ts +4 -0
- package/dist/abilities/effects/trade.d.ts +1 -0
- package/dist/abilities/effects.d.ts +122 -0
- package/dist/abilities/land.d.ts +21 -0
- package/dist/abilities/scaled.d.ts +21 -0
- package/dist/abilities/text.d.ts +113 -0
- package/dist/ai/area.d.ts +53 -0
- package/dist/ai/brain.d.ts +528 -0
- package/dist/ai/budget.d.ts +67 -0
- package/dist/ai/checks.d.ts +115 -0
- package/dist/ai/computer.d.ts +166 -0
- package/dist/ai/defence.d.ts +108 -0
- package/dist/ai/define.d.ts +21 -0
- package/dist/ai/economy.d.ts +129 -0
- package/dist/ai/geometry.d.ts +35 -0
- package/dist/ai/goals.d.ts +360 -0
- package/dist/ai/index.d.ts +38 -0
- package/dist/ai/knowledge.d.ts +418 -0
- package/dist/ai/lanes.d.ts +232 -0
- package/dist/ai/melee/build.d.ts +61 -0
- package/dist/ai/melee/goals.d.ts +299 -0
- package/dist/ai/melee/heroes.d.ts +27 -0
- package/dist/ai/melee/index.d.ts +14 -0
- package/dist/ai/melee/production.d.ts +8 -0
- package/dist/ai/melee/surrender.d.ts +24 -0
- package/dist/ai/micro.d.ts +278 -0
- package/dist/ai/mission.d.ts +195 -0
- package/dist/ai/missionRules.d.ts +18 -0
- package/dist/ai/module.d.ts +116 -0
- package/dist/ai/options.d.ts +61 -0
- package/dist/ai/plans/build.d.ts +280 -0
- package/dist/ai/plans/placement.d.ts +82 -0
- package/dist/ai/plans/plans.d.ts +105 -0
- package/dist/ai/plans/production.d.ts +210 -0
- package/dist/ai/plans/purse.d.ts +73 -0
- package/dist/ai/plans/tech.d.ts +37 -0
- package/dist/ai/profiles.d.ts +204 -0
- package/dist/ai/reach.d.ts +4 -0
- package/dist/ai/report.d.ts +203 -0
- package/dist/ai/roles.d.ts +133 -0
- package/dist/ai/rules.d.ts +288 -0
- package/dist/ai/scouting.d.ts +98 -0
- package/dist/ai/settings.d.ts +73 -0
- package/dist/ai/squads.d.ts +429 -0
- package/dist/ai/strength.d.ts +167 -0
- package/dist/ai/task.d.ts +118 -0
- package/dist/ai/tasks/attack.d.ts +7 -0
- package/dist/ai/tasks/capture.d.ts +21 -0
- package/dist/ai/tasks/creep.d.ts +16 -0
- package/dist/ai/tasks/defend.d.ts +29 -0
- package/dist/ai/tasks/drop.d.ts +34 -0
- package/dist/ai/tasks/escort.d.ts +16 -0
- package/dist/ai/tasks/gather.d.ts +23 -0
- package/dist/ai/tasks/harass.d.ts +7 -0
- package/dist/ai/tasks/hold.d.ts +20 -0
- package/dist/ai/tasks/index.d.ts +32 -0
- package/dist/ai/tasks/move.d.ts +19 -0
- package/dist/ai/tasks/patrol.d.ts +8 -0
- package/dist/ai/tasks/retreat.d.ts +20 -0
- package/dist/ai/tasks/scout.d.ts +29 -0
- package/dist/ai/tasks/shared.d.ts +74 -0
- package/dist/ai/team.d.ts +155 -0
- package/dist/ai/threat.d.ts +91 -0
- package/dist/ai/view.d.ts +366 -0
- package/dist/ai/waves.d.ts +126 -0
- package/dist/ai.js +6239 -0
- package/dist/ai.js.map +1 -0
- package/dist/aiTesting.d.ts +179 -0
- package/dist/areas.d.ts +149 -0
- package/dist/attacks.d.ts +66 -0
- package/dist/attributes.d.ts +66 -0
- package/dist/brain-BvVdUhX8.js +7659 -0
- package/dist/brain-BvVdUhX8.js.map +1 -0
- package/dist/builds-C6LfgvEU.js +460 -0
- package/dist/builds-C6LfgvEU.js.map +1 -0
- package/dist/bytes.d.ts +6 -0
- package/dist/camps.d.ts +95 -0
- package/dist/capture.d.ts +131 -0
- package/dist/cellLayers.d.ts +75 -0
- package/dist/cinematics.d.ts +194 -0
- package/dist/clock.d.ts +32 -0
- package/dist/commands.d.ts +235 -0
- package/dist/components.d.ts +184 -0
- package/dist/computers.d.ts +108 -0
- package/dist/concealment.d.ts +61 -0
- package/dist/coreComponents-syuh2fPG.js +5149 -0
- package/dist/coreComponents-syuh2fPG.js.map +1 -0
- package/dist/coreComponents.d.ts +1 -0
- package/dist/dashing.d.ts +8 -0
- package/dist/debug.d.ts +36 -0
- package/dist/debug.js +3 -0
- package/dist/debugCommands-CzjrSm66.js +14739 -0
- package/dist/debugCommands-CzjrSm66.js.map +1 -0
- package/dist/debugCommands.d.ts +213 -0
- package/dist/debugging.d.ts +10 -0
- package/dist/definitions.d.ts +43 -0
- package/dist/defs.d.ts +1162 -0
- package/dist/denying.d.ts +81 -0
- package/dist/destructibles.d.ts +27 -0
- package/dist/determinism-BCymQwiE.js +518 -0
- package/dist/determinism-BCymQwiE.js.map +1 -0
- package/dist/determinism.d.ts +121 -0
- package/dist/dialog.d.ts +94 -0
- package/dist/effectRefs.d.ts +16 -0
- package/dist/effects.d.ts +80 -0
- package/dist/endings.d.ts +22 -0
- package/dist/engagement.d.ts +108 -0
- package/dist/engineEvents.d.ts +710 -0
- package/dist/entity.d.ts +409 -0
- package/dist/entityIndex.d.ts +50 -0
- package/dist/errors.d.ts +85 -0
- package/dist/events.d.ts +97 -0
- package/dist/exactMath.d.ts +63 -0
- package/dist/features.d.ts +10 -0
- package/dist/fields.d.ts +114 -0
- package/dist/fixture.d.ts +17 -0
- package/dist/fog.d.ts +110 -0
- package/dist/formation.d.ts +111 -0
- package/dist/friendlyFire.d.ts +26 -0
- package/dist/game-DiJEN-Ks.js +5800 -0
- package/dist/game-DiJEN-Ks.js.map +1 -0
- package/dist/game.d.ts +501 -0
- package/dist/gameData.d.ts +325 -0
- package/dist/gameFiles.d.ts +26 -0
- package/dist/gates.d.ts +28 -0
- package/dist/generate.d.ts +403 -0
- package/dist/generateWorker.d.ts +39 -0
- package/dist/grid.d.ts +53 -0
- package/dist/ground.d.ts +127 -0
- package/dist/groundSpeed.d.ts +22 -0
- package/dist/hero.d.ts +177 -0
- package/dist/home.d.ts +14 -0
- package/dist/hooks.d.ts +780 -0
- package/dist/hotReload.d.ts +76 -0
- package/dist/ids.d.ts +26 -0
- package/dist/index.d.ts +227 -0
- package/dist/index.js +4701 -0
- package/dist/index.js.map +1 -0
- package/dist/inspect-D9dWHmZ0.js +491 -0
- package/dist/inspect-D9dWHmZ0.js.map +1 -0
- package/dist/inspect.d.ts +176 -0
- package/dist/inventory.d.ts +18 -0
- package/dist/items.d.ts +91 -0
- package/dist/lanes.d.ts +213 -0
- package/dist/life.d.ts +53 -0
- package/dist/local-Dkovq42k.js +1379 -0
- package/dist/local-Dkovq42k.js.map +1 -0
- package/dist/log.d.ts +140 -0
- package/dist/manaBurn.d.ts +39 -0
- package/dist/map/file.d.ts +114 -0
- package/dist/map/images.d.ts +18 -0
- package/dist/map/look.d.ts +47 -0
- package/dist/map/pathProfile.d.ts +13 -0
- package/dist/map/resize.d.ts +54 -0
- package/dist/map/schema.d.ts +10 -0
- package/dist/map/terrain.d.ts +32 -0
- package/dist/map/types.d.ts +613 -0
- package/dist/map.d.ts +7 -0
- package/dist/mapCheck/cells.d.ts +19 -0
- package/dist/mapCheck/rule.d.ts +30 -0
- package/dist/mapCheck/rules/names.d.ts +3 -0
- package/dist/mapCheck/rules/objects.d.ts +3 -0
- package/dist/mapCheck/rules/paths.d.ts +3 -0
- package/dist/mapCheck/rules/players.d.ts +3 -0
- package/dist/mapCheck/rules/races.d.ts +3 -0
- package/dist/mapCheck/rules/random.d.ts +3 -0
- package/dist/mapCheck/rules/regions.d.ts +3 -0
- package/dist/mapCheck/rules/targets.d.ts +3 -0
- package/dist/mapCheck/rules/walking.d.ts +3 -0
- package/dist/mapCheck.d.ts +23 -0
- package/dist/mapFields.d.ts +364 -0
- package/dist/mapFile.d.ts +23 -0
- package/dist/mapMeasure.d.ts +95 -0
- package/dist/mapMerge.d.ts +19 -0
- package/dist/mapObjectives.d.ts +82 -0
- package/dist/mapObjects.d.ts +1 -0
- package/dist/math.d.ts +44 -0
- package/dist/messages.d.ts +150 -0
- package/dist/missionRules-C-bGxm0Q.js +523 -0
- package/dist/missionRules-C-bGxm0Q.js.map +1 -0
- package/dist/missionRules.d.ts +179 -0
- package/dist/mods.d.ts +146 -0
- package/dist/names.d.ts +93 -0
- package/dist/navigation/agentParams.d.ts +4 -0
- package/dist/navigation/air.d.ts +89 -0
- package/dist/navigation/builds.d.ts +140 -0
- package/dist/navigation/groundAreas.d.ts +23 -0
- package/dist/navigation/navigation.d.ts +127 -0
- package/dist/navigation/recast.d.ts +214 -0
- package/dist/navigation/sidePaths.d.ts +69 -0
- package/dist/navigation/sized.d.ts +1 -0
- package/dist/navigation-worker.js +11 -0
- package/dist/navigation-worker.js.map +1 -0
- package/dist/nearest.d.ts +8 -0
- package/dist/noise.d.ts +12 -0
- package/dist/objectives.d.ts +93 -0
- package/dist/orders/basic.d.ts +96 -0
- package/dist/orders/build.d.ts +91 -0
- package/dist/orders/cast.d.ts +105 -0
- package/dist/orders/facts.d.ts +14 -0
- package/dist/orders/harvest.d.ts +94 -0
- package/dist/orders/idle.d.ts +7 -0
- package/dist/orders/items.d.ts +14 -0
- package/dist/orders/queue.d.ts +24 -0
- package/dist/pack.schema.json +6621 -0
- package/dist/packs/director/index.d.ts +81 -0
- package/dist/packs/heroes/campaign.d.ts +137 -0
- package/dist/packs/heroes/carry.d.ts +59 -0
- package/dist/packs/heroes/commands.d.ts +6 -0
- package/dist/packs/heroes/hire.d.ts +9 -0
- package/dist/packs/heroes/index.d.ts +12 -0
- package/dist/packs/heroes/making.d.ts +16 -0
- package/dist/packs/heroes/respawn.d.ts +42 -0
- package/dist/packs/moba/index.d.ts +34 -0
- package/dist/packs/pack.d.ts +84 -0
- package/dist/packs-g5thvmGn.js +3199 -0
- package/dist/packs-g5thvmGn.js.map +1 -0
- package/dist/packs.d.ts +84 -0
- package/dist/paths.d.ts +51 -0
- package/dist/plain.d.ts +17 -0
- package/dist/player.d.ts +117 -0
- package/dist/portals.d.ts +66 -0
- package/dist/prefabs.d.ts +139 -0
- package/dist/presetBuildings.d.ts +52 -0
- package/dist/presetGround.d.ts +22 -0
- package/dist/profiles-B3NS9jwk.js +335 -0
- package/dist/profiles-B3NS9jwk.js.map +1 -0
- package/dist/races.d.ts +136 -0
- package/dist/randomGroups.d.ts +2 -0
- package/dist/registry.d.ts +464 -0
- package/dist/remains.d.ts +119 -0
- package/dist/replication.d.ts +103 -0
- package/dist/rng.d.ts +17 -0
- package/dist/rules.d.ts +395 -0
- package/dist/rulesCheck.d.ts +37 -0
- package/dist/runes.d.ts +41 -0
- package/dist/save.d.ts +277 -0
- package/dist/scenario.d.ts +56 -0
- package/dist/scheduler.d.ts +67 -0
- package/dist/score.d.ts +306 -0
- package/dist/sequences.d.ts +132 -0
- package/dist/server/doorman.d.ts +21 -0
- package/dist/server/gameServer.d.ts +346 -0
- package/dist/server/index.d.ts +24 -0
- package/dist/server/lobby.d.ts +1 -0
- package/dist/server/log.d.ts +13 -0
- package/dist/server/match.d.ts +24 -0
- package/dist/server/mode.d.ts +168 -0
- package/dist/server/navigation-worker.d.ts +1 -0
- package/dist/server/navigation.d.ts +11 -0
- package/dist/server/ops.d.ts +78 -0
- package/dist/server/packs.d.ts +15 -0
- package/dist/server/ratings.d.ts +62 -0
- package/dist/server/relay.d.ts +34 -0
- package/dist/server/rooms.d.ts +162 -0
- package/dist/server/seat.d.ts +2 -0
- package/dist/server/seatSettings.d.ts +15 -0
- package/dist/server/secret.d.ts +5 -0
- package/dist/server/start.d.ts +54 -0
- package/dist/server/websocket.d.ts +74 -0
- package/dist/server.js +2861 -0
- package/dist/server.js.map +1 -0
- package/dist/session/can.d.ts +20 -0
- package/dist/session/commandReplay.d.ts +92 -0
- package/dist/session/debug.d.ts +65 -0
- package/dist/session/delay.d.ts +15 -0
- package/dist/session/delta.d.ts +98 -0
- package/dist/session/entityState.d.ts +1 -0
- package/dist/session/local.d.ts +214 -0
- package/dist/session/memory.d.ts +27 -0
- package/dist/session/protocol.d.ts +1155 -0
- package/dist/session/remote.d.ts +530 -0
- package/dist/session/replay.d.ts +114 -0
- package/dist/session/seed.d.ts +7 -0
- package/dist/session/share.d.ts +78 -0
- package/dist/session/socket.d.ts +8 -0
- package/dist/session/wire.d.ts +153 -0
- package/dist/session/worker.d.ts +227 -0
- package/dist/shared.d.ts +171 -0
- package/dist/sides.d.ts +75 -0
- package/dist/sight.d.ts +27 -0
- package/dist/simulate-oXBiw1Ff.js +167 -0
- package/dist/simulate-oXBiw1Ff.js.map +1 -0
- package/dist/simulate-worker.d.ts +1 -0
- package/dist/simulate-worker.js +28 -0
- package/dist/simulate-worker.js.map +1 -0
- package/dist/simulate.d.ts +154 -0
- package/dist/smart.d.ts +9 -0
- package/dist/spatial.d.ts +62 -0
- package/dist/spawning.d.ts +33 -0
- package/dist/stances.d.ts +76 -0
- package/dist/start.d.ts +71 -0
- package/dist/stats.d.ts +122 -0
- package/dist/summons.d.ts +63 -0
- package/dist/systems/abilities.d.ts +3 -0
- package/dist/systems/combat.d.ts +71 -0
- package/dist/systems/combatTold.d.ts +14 -0
- package/dist/systems/construction.d.ts +34 -0
- package/dist/systems/economy.d.ts +21 -0
- package/dist/systems/fog.d.ts +19 -0
- package/dist/systems/life.d.ts +3 -0
- package/dist/systems/movement.d.ts +105 -0
- package/dist/systems/orders.d.ts +7 -0
- package/dist/systems/production.d.ts +49 -0
- package/dist/systems/productionQueue.d.ts +40 -0
- package/dist/systems/victory.d.ts +14 -0
- package/dist/talk.d.ts +65 -0
- package/dist/tech.d.ts +62 -0
- package/dist/techTree.d.ts +38 -0
- package/dist/terrain.d.ts +173 -0
- package/dist/terrainSave.d.ts +29 -0
- package/dist/testing.d.ts +58 -0
- package/dist/testing.js +822 -0
- package/dist/testing.js.map +1 -0
- package/dist/tiles.d.ts +34 -0
- package/dist/timers.d.ts +146 -0
- package/dist/tomes.d.ts +48 -0
- package/dist/trade.d.ts +28 -0
- package/dist/transport.d.ts +76 -0
- package/dist/tunables.d.ts +45 -0
- package/dist/upkeep.d.ts +16 -0
- package/dist/veterancy.d.ts +80 -0
- package/dist/walls.d.ts +86 -0
- package/dist/world.d.ts +1118 -0
- package/package.json +80 -5
- package/README.md +0 -3
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
import { type GameHostMessage, type HostToPlayer, type ServerToPlayer } from './wire';
|
|
2
|
+
import type { GameMap, MapCamera, MapDoodad, MapEnvironment, MapPath, MapRegion } from '#engine/map';
|
|
3
|
+
import type { PlayerId } from '#engine/entity';
|
|
4
|
+
import type { GameModule } from '#engine/game';
|
|
5
|
+
import { BuildGrid } from '#engine/grid';
|
|
6
|
+
import type { Vec2 } from '#engine/math';
|
|
7
|
+
import type { Navigation } from '#engine/navigation/navigation';
|
|
8
|
+
import { type RecastNavigationOptions } from '#engine/navigation/recast';
|
|
9
|
+
import type { Registry } from '#engine/registry';
|
|
10
|
+
import type { Terrain } from '#engine/terrain';
|
|
11
|
+
import type { World } from '#engine/world';
|
|
12
|
+
import { type MessageRef } from '#engine/messages';
|
|
13
|
+
import { type CampInfo, type FogState, type GameSession, type PlayerCommand, type Snapshot, type SessionCan, type SessionDebug } from './protocol';
|
|
14
|
+
/**
|
|
15
|
+
* One end of a connection: text in, text out, in order
|
|
16
|
+
*
|
|
17
|
+
* @beta
|
|
18
|
+
*/
|
|
19
|
+
export interface Transport {
|
|
20
|
+
send(message: string): void;
|
|
21
|
+
/** What comes in from the other end. One handler: a later one takes the place of the one before */
|
|
22
|
+
onMessage(handler: (message: string) => void): void;
|
|
23
|
+
/** Told when the other end closes */
|
|
24
|
+
onClose(handler: () => void): void;
|
|
25
|
+
close(): void;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* An end of a `loopback`, which counts what it sends: for a budget of bandwidth
|
|
29
|
+
*
|
|
30
|
+
* @beta
|
|
31
|
+
*/
|
|
32
|
+
export interface LoopbackEnd extends Transport {
|
|
33
|
+
/** Characters sent, a byte each as the JSON goes over a WebSocket of mostly ASCII */
|
|
34
|
+
readonly bytesSent: number;
|
|
35
|
+
readonly messagesSent: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A connection inside the page, standing in for a network (`loopback`)
|
|
39
|
+
*
|
|
40
|
+
* @beta
|
|
41
|
+
*/
|
|
42
|
+
export interface LoopbackOptions {
|
|
43
|
+
/** Milliseconds each message takes, one way */
|
|
44
|
+
latency?: number;
|
|
45
|
+
/** Milliseconds a message may take on top of that, at random: never out of order, the way a WebSocket keeps it */
|
|
46
|
+
jitter?: number;
|
|
47
|
+
/**
|
|
48
|
+
* The share of the snapshots that never arrive, 0..1, for what a lossy connection does to the screen. Only from the
|
|
49
|
+
* host: the welcome and the player's commands always do. The events of a snapshot lost are lost with it
|
|
50
|
+
*/
|
|
51
|
+
loss?: number;
|
|
52
|
+
/** Random numbers for jitter and loss: `Math.random` when left out (the simulation does not use it) */
|
|
53
|
+
random?: () => number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Two ends of a connection in the page, `[client, host]`: everything sent is text, delivered after the latency the
|
|
57
|
+
* options give. The whole networked way, in one page and in tests
|
|
58
|
+
*
|
|
59
|
+
* @beta
|
|
60
|
+
*/
|
|
61
|
+
export declare function loopback(options?: LoopbackOptions): [LoopbackEnd, LoopbackEnd];
|
|
62
|
+
/** Seconds of jitter the interpolation buffer makes room for, at most */
|
|
63
|
+
export declare const MAX_JITTER = 0.2;
|
|
64
|
+
/**
|
|
65
|
+
* What a player's side keeps and how often it asks, set by `ConnectOptions`: each the number it has always been when
|
|
66
|
+
* left out
|
|
67
|
+
*
|
|
68
|
+
* @beta
|
|
69
|
+
*/
|
|
70
|
+
export interface PlayerLimits {
|
|
71
|
+
/** Milliseconds between two pings, to measure the time to the host and back. 2000 when left out */
|
|
72
|
+
pingEvery?: number;
|
|
73
|
+
/** Seconds of jitter the interpolation buffer makes room for, at most: a spike of lateness is not waited out for good. 0.2 when left out */
|
|
74
|
+
maxJitter?: number;
|
|
75
|
+
/** Snapshots waiting for the screen, at most: past that the oldest is folded into the next. 64 when left out */
|
|
76
|
+
keptSnapshots?: number;
|
|
77
|
+
/** Events the folded snapshots carry together, at most: the newest kept. 2000 when left out */
|
|
78
|
+
keptScreenEvents?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Where a host's time went over a while: see `SessionHost.takeTiming`
|
|
82
|
+
*
|
|
83
|
+
* @beta
|
|
84
|
+
*/
|
|
85
|
+
export interface HostTiming {
|
|
86
|
+
/** When the counting started, `performance.now()` */
|
|
87
|
+
since: number;
|
|
88
|
+
ticks: number;
|
|
89
|
+
/** Milliseconds the ticks took, added up, and the longest */
|
|
90
|
+
tickTime: number;
|
|
91
|
+
tickMax: number;
|
|
92
|
+
/** Rounds of sending everyone what changed */
|
|
93
|
+
sends: number;
|
|
94
|
+
sendTime: number;
|
|
95
|
+
sendMax: number;
|
|
96
|
+
/**
|
|
97
|
+
* Where the sending's milliseconds went, added up over the seats: what each player may know taken from the world
|
|
98
|
+
* (`capture`), its positions rounded (`quantize`), the fog made runs (`fog`), what changed since the frame they
|
|
99
|
+
* have (`diff`), made text (`stringify`)
|
|
100
|
+
*
|
|
101
|
+
* @beta
|
|
102
|
+
*/
|
|
103
|
+
parts: {
|
|
104
|
+
capture: number;
|
|
105
|
+
quantize: number;
|
|
106
|
+
fog: number;
|
|
107
|
+
diff: number;
|
|
108
|
+
stringify: number;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Characters of the rounds' text, to every seat, before any compression of the wire
|
|
112
|
+
*
|
|
113
|
+
* @beta
|
|
114
|
+
*/
|
|
115
|
+
bytes: number;
|
|
116
|
+
/**
|
|
117
|
+
* Those characters by what they carry, when the host counts them (`SessionHostOptions.bytesByKey`): each field of
|
|
118
|
+
* the entities added and changed (`entity.hp`, `entity.own.abilities`), the other parts (`rest.players`, `rest.fog`),
|
|
119
|
+
* `events`, `removed`, and the rest (ids, brackets) as `other`. They add up to `bytes`
|
|
120
|
+
*
|
|
121
|
+
* @beta
|
|
122
|
+
*/
|
|
123
|
+
keys?: Record<string, number>;
|
|
124
|
+
}
|
|
125
|
+
/** @beta */
|
|
126
|
+
export interface SessionHostOptions {
|
|
127
|
+
/** Snapshots a second sent to each player, at most: the simulation runs at its tick rate all the same. 20 when left out */
|
|
128
|
+
sendRate?: number;
|
|
129
|
+
/**
|
|
130
|
+
* Ticks one update catches up at most. A host that fell further behind (a stall, a machine too slow for the game)
|
|
131
|
+
* lets the rest go, and the game runs slower for a moment, rather than spiralling. 8 when left out
|
|
132
|
+
*/
|
|
133
|
+
maxTicksPerUpdate?: number;
|
|
134
|
+
/** Told of a tick that took longer than a tick lasts, with how many milliseconds: the watchdog */
|
|
135
|
+
onSlowTick?: (milliseconds: number, tick: number) => void;
|
|
136
|
+
/**
|
|
137
|
+
* Told when stepping the world threw, running by the clock (`start`): the host has stopped by then, and what
|
|
138
|
+
* becomes of the game is whoever runs it's to say. Said in the world's log, and nothing more, when left out. An
|
|
139
|
+
* error is never a reason for the process to go
|
|
140
|
+
*/
|
|
141
|
+
onError?: (error: unknown) => void;
|
|
142
|
+
/**
|
|
143
|
+
* The world is the host's, and goes with it (`dispose`): for a server's game, or a game run in the page behind a
|
|
144
|
+
* wire. Not for a world the page plays itself and only lets others watch (`recordGame`, `shareGame`). No when left out
|
|
145
|
+
*/
|
|
146
|
+
ownsWorld?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* Seconds of the game a player may go without saying it got what it was sent, before its seat is closed: what is
|
|
149
|
+
* kept for it to send again (the events it has not said it got) would grow for as long as it says nothing. 15 when
|
|
150
|
+
* left out; `Infinity` never closes one
|
|
151
|
+
*/
|
|
152
|
+
dropSilentAfter?: number;
|
|
153
|
+
/**
|
|
154
|
+
* Ticks of events kept for a player who has not said they got them, at most: past that the oldest that already went
|
|
155
|
+
* are let go, not sent again. They are there already over a transport that loses nothing (a worker, a WebSocket),
|
|
156
|
+
* so this bounds only a player who goes on hearing but has stopped answering (a page frozen in the background). 600
|
|
157
|
+
* when left out
|
|
158
|
+
*
|
|
159
|
+
* @beta
|
|
160
|
+
*/
|
|
161
|
+
keptEvents?: number;
|
|
162
|
+
/**
|
|
163
|
+
* Frames kept for each player to make a delta against, at most: a player who says nothing for longer is sent
|
|
164
|
+
* everything again, once, and nothing more until it answers (or its answer is overdue); an answer to a frame let go
|
|
165
|
+
* still says the player is there. 64 when left out (more than a second and a half of ticks)
|
|
166
|
+
*
|
|
167
|
+
* @beta
|
|
168
|
+
*/
|
|
169
|
+
keptFrames?: number;
|
|
170
|
+
/**
|
|
171
|
+
* Bytes of the frames kept for each player, at most, summed (what each takes as the wire writes it): a player who
|
|
172
|
+
* says nothing while a thousand units fight is sent everything again sooner than `keptFrames` would. 8 MB when left
|
|
173
|
+
* out
|
|
174
|
+
*
|
|
175
|
+
* @beta
|
|
176
|
+
*/
|
|
177
|
+
keptBytes?: number;
|
|
178
|
+
/**
|
|
179
|
+
* Characters of the ground in one message, for a player who does not have the map and asks for it a part at a
|
|
180
|
+
* time: well under what a connection holds. 262144 when left out
|
|
181
|
+
*
|
|
182
|
+
* @beta
|
|
183
|
+
*/
|
|
184
|
+
groundPart?: number;
|
|
185
|
+
/**
|
|
186
|
+
* Whether `takeTiming` says what the characters sent were spent on, field by field (`HostTiming.keys`): what a
|
|
187
|
+
* measure of the wire asks for (`net.bench.ts`), at the cost of writing each field again. No when left out
|
|
188
|
+
*
|
|
189
|
+
* @beta
|
|
190
|
+
*/
|
|
191
|
+
bytesByKey?: boolean;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Runs a world for players connected to it over transports: the server's job, done anywhere. It steps the world by
|
|
195
|
+
* the clock (`start`) or by hand (`update`), and at most `sendRate` times a second sends every player what changed in
|
|
196
|
+
* what they may know (`Delta`), as their `LocalSession` seat sees it: against the last tick they said they got, with
|
|
197
|
+
* the events they have not. Their commands come in as they arrive, and go in at the next tick
|
|
198
|
+
*
|
|
199
|
+
* @beta
|
|
200
|
+
*/
|
|
201
|
+
export declare class SessionHost {
|
|
202
|
+
readonly world: World;
|
|
203
|
+
private readonly seats;
|
|
204
|
+
private accumulator;
|
|
205
|
+
private sinceSent;
|
|
206
|
+
private timer?;
|
|
207
|
+
private last;
|
|
208
|
+
private readonly sendEvery;
|
|
209
|
+
/** Simulation speed multiplier, 0 pauses */
|
|
210
|
+
speed: number;
|
|
211
|
+
constructor(world: World, options?: SessionHostOptions);
|
|
212
|
+
private readonly onError?;
|
|
213
|
+
private readonly stopFailed;
|
|
214
|
+
private readonly dropSilentAfter;
|
|
215
|
+
private readonly keptFrames;
|
|
216
|
+
private readonly keptBytes;
|
|
217
|
+
private readonly groundPart;
|
|
218
|
+
private readonly keptEvents;
|
|
219
|
+
/** Whether the characters sent are counted by what they carry (`bytesByKey`) */
|
|
220
|
+
private readonly byKey;
|
|
221
|
+
private readonly ownsWorld;
|
|
222
|
+
private readonly maxTicks;
|
|
223
|
+
private readonly onSlowTick?;
|
|
224
|
+
/**
|
|
225
|
+
* Seats a player at the world, on the host's end of a transport. The welcome goes out at once: everything the player
|
|
226
|
+
* may know, also to one who comes back. `readOnly` for who only watches: their commands go nowhere but their lines
|
|
227
|
+
* of chat and their pings, which go to who watches alone (`observers`, said by `name`); and with `observer` they see
|
|
228
|
+
* everything, from `player`'s side. `allow` decides on each command before it goes in: a limit of how many, a game
|
|
229
|
+
* paused. One it lets go is answered, refused (the `command` event of its `seq`): with what it gives for why, or
|
|
230
|
+
* `cannotDoThat` for `false`
|
|
231
|
+
*/
|
|
232
|
+
connect(player: PlayerId, transport: Transport, options?: {
|
|
233
|
+
readOnly?: boolean;
|
|
234
|
+
observer?: boolean;
|
|
235
|
+
allow?: () => boolean | MessageRef;
|
|
236
|
+
name?: string;
|
|
237
|
+
}): void;
|
|
238
|
+
/** The ground the world started as, whole, in parts small enough to go one at a time: made the first time one is asked for */
|
|
239
|
+
private groundParts;
|
|
240
|
+
private ground?;
|
|
241
|
+
/** The player has the frame of `tick`: what comes next is made against it, and what it has is not sent again */
|
|
242
|
+
private acknowledge;
|
|
243
|
+
/**
|
|
244
|
+
* Whether a player is sent nothing this round: it has no frame kept to make a delta against, and the whole one it
|
|
245
|
+
* was sent last is on its way still. Another would be as big, and come no sooner than the answer to the first
|
|
246
|
+
*/
|
|
247
|
+
private holding;
|
|
248
|
+
private leave;
|
|
249
|
+
/** How many players are connected */
|
|
250
|
+
get players(): number;
|
|
251
|
+
private post;
|
|
252
|
+
/** Lets `dt` seconds pass: the ticks that fit into it, then what changed to everyone, when it is time to send */
|
|
253
|
+
update(dt: number): void;
|
|
254
|
+
/** What the debug tools of a seat follow, as the world stands: when they follow, list or log anything */
|
|
255
|
+
private sendDebug;
|
|
256
|
+
/** Moves the game on by `ticks` at the next update, however fast it goes: a step of a held game (`speed` 0) */
|
|
257
|
+
advance(ticks?: number): void;
|
|
258
|
+
/**
|
|
259
|
+
* Sends everyone what changed, when it is time to, for a world something else steps: the page's own game, shared with
|
|
260
|
+
* those who watch it (`shareGame`). `dt` is the seconds since the last call. Nothing goes while the world stands still
|
|
261
|
+
*/
|
|
262
|
+
publish(dt: number): void;
|
|
263
|
+
/** The tick what changed went out at last */
|
|
264
|
+
private sentTick;
|
|
265
|
+
/** Talk was carried out since what changed went out last: it goes out with no tick to wait for (RV14) */
|
|
266
|
+
private heardOutside;
|
|
267
|
+
/** What changed to everyone, when the rate allows */
|
|
268
|
+
private sendDue;
|
|
269
|
+
/**
|
|
270
|
+
* Where the host's time went since it was last asked (`takeTiming`): ticks of the simulation, and rounds of sending
|
|
271
|
+
* everyone what changed (the snapshots, the diffs, the JSON), each in milliseconds, added up and at most
|
|
272
|
+
*/
|
|
273
|
+
private timing;
|
|
274
|
+
/**
|
|
275
|
+
* Where the host's time went since it started, never counted anew: ticks and rounds of sending, with the
|
|
276
|
+
* milliseconds they took, and how long the last tick took. What a server's numbers are made of (`/metrics`)
|
|
277
|
+
*/
|
|
278
|
+
readonly totals: {
|
|
279
|
+
ticks: number;
|
|
280
|
+
tickTime: number;
|
|
281
|
+
lastTick: number;
|
|
282
|
+
sends: number;
|
|
283
|
+
sendTime: number;
|
|
284
|
+
};
|
|
285
|
+
/** Where the time went since the last call, and starts counting anew: for a server to print */
|
|
286
|
+
takeTiming(): HostTiming & {
|
|
287
|
+
seconds: number;
|
|
288
|
+
};
|
|
289
|
+
/** The lists of entities told this round so far, and what each was sent as, for the seats told the same to share one (`quantizedList`) */
|
|
290
|
+
private roundEntities;
|
|
291
|
+
/** What the player knows now, as what changed since the tick they last said they got */
|
|
292
|
+
private deltaFor;
|
|
293
|
+
/**
|
|
294
|
+
* Keeps the frame a player was sent, to make the next delta against: the oldest let go past `keptFrames` of them or
|
|
295
|
+
* `keptBytes` together, the newest kept whatever it takes. A player who says nothing for long is sent everything
|
|
296
|
+
* again, once its base is no longer kept
|
|
297
|
+
*/
|
|
298
|
+
private keep;
|
|
299
|
+
/** Lets go of a frame kept for a player */
|
|
300
|
+
private forget;
|
|
301
|
+
/** Runs the world by the clock, `rate` updates a second, until `stop` or `dispose` */
|
|
302
|
+
start(rate?: number): void;
|
|
303
|
+
stop(): void;
|
|
304
|
+
/** Whether it runs by the clock */
|
|
305
|
+
get running(): boolean;
|
|
306
|
+
/** Stops, and closes every connection. The world goes too, when it is the host's (`ownsWorld`) */
|
|
307
|
+
/**
|
|
308
|
+
* Stops, and lets every player go: their connections closed, unless `closeTransports` is false (a server that keeps
|
|
309
|
+
* them for its lobby, after the game)
|
|
310
|
+
*/
|
|
311
|
+
dispose(options?: {
|
|
312
|
+
closeTransports?: boolean;
|
|
313
|
+
}): void;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* What the player's side keeps of the map, to answer the screen without asking the host: a placement grid and the
|
|
317
|
+
* ways to walk of the map as it was made, with the structures the player has seen on them. What they have not seen
|
|
318
|
+
* is not there: a path preview never goes around a building in the dark, and gives it away
|
|
319
|
+
*/
|
|
320
|
+
export declare class ClientWorld {
|
|
321
|
+
readonly terrain: Terrain;
|
|
322
|
+
private readonly registry;
|
|
323
|
+
readonly nav: Navigation;
|
|
324
|
+
readonly air: Navigation;
|
|
325
|
+
readonly grid: BuildGrid;
|
|
326
|
+
private readonly known;
|
|
327
|
+
private readonly seen;
|
|
328
|
+
constructor(terrain: Terrain, registry: Registry, nav: Navigation, air: Navigation);
|
|
329
|
+
/** Whether a resource of a kind that it knows of covers just this ground, with nothing it knows of standing on it */
|
|
330
|
+
resourceAt(kind: string, cellX: number, cellZ: number, w: number, d: number): boolean;
|
|
331
|
+
/** Brings the structures up to date with a snapshot: those in it stand, those no longer in it are gone */
|
|
332
|
+
sync(snapshot: Snapshot): void;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* The host said no, with why: to come back to a game that is over, or a player let go. Trying again does not help
|
|
336
|
+
*
|
|
337
|
+
* @beta
|
|
338
|
+
*/
|
|
339
|
+
export declare class SessionRefused extends Error {
|
|
340
|
+
readonly reason: string;
|
|
341
|
+
constructor(reason: string);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* A player's seat at a world that runs elsewhere, over a transport (see `connect`). It rebuilds what the host sends
|
|
345
|
+
* as changes (`Delta`) into whole snapshots, keeping the objects of what did not change, says which ticks it got, and
|
|
346
|
+
* answers the screen's questions from those and its own copy of the map (`ClientWorld`). No debug access, and no
|
|
347
|
+
* checkpoints: those belong to a simulation in the page
|
|
348
|
+
*
|
|
349
|
+
* @beta
|
|
350
|
+
*/
|
|
351
|
+
export declare class RemoteSession implements GameSession {
|
|
352
|
+
private transport;
|
|
353
|
+
private readonly map;
|
|
354
|
+
/** How much it keeps and how often it asks (`ConnectOptions`) */
|
|
355
|
+
protected readonly limits: PlayerLimits;
|
|
356
|
+
/**
|
|
357
|
+
* A seat over a wire can none of what a game in this page can (`SessionCan`), but the debug tools' view of the world
|
|
358
|
+
* for a player the host lets use them (`inspect`, said over the wire)
|
|
359
|
+
*/
|
|
360
|
+
readonly can: SessionCan;
|
|
361
|
+
/** The debug tools' view of the world, for a player the host lets use them (the welcome's `debug`) */
|
|
362
|
+
protected get debugView(): SessionDebug | undefined;
|
|
363
|
+
private readonly remoteDebug?;
|
|
364
|
+
readonly playerId: PlayerId;
|
|
365
|
+
team: number;
|
|
366
|
+
readonly terrain: Terrain;
|
|
367
|
+
readonly environment?: MapEnvironment;
|
|
368
|
+
readonly doodads: readonly MapDoodad[];
|
|
369
|
+
readonly regions: readonly MapRegion[];
|
|
370
|
+
readonly cameras: readonly MapCamera[];
|
|
371
|
+
readonly paths: readonly MapPath[];
|
|
372
|
+
readonly registry: Registry;
|
|
373
|
+
readonly tickRate: number;
|
|
374
|
+
alpha: number;
|
|
375
|
+
/** What the player knows by tick, for the deltas to come: from the base of the last one on */
|
|
376
|
+
private readonly frames;
|
|
377
|
+
private latest;
|
|
378
|
+
private readonly incoming;
|
|
379
|
+
/** What the host's definitions were changed to while it ran (`world.redefine`), as this screen heard it */
|
|
380
|
+
private readonly redefined;
|
|
381
|
+
/** The number of the last batch of events that went to the screen (`Delta.events`): those sent again are not applied twice */
|
|
382
|
+
private eventsUpTo;
|
|
383
|
+
private readonly fogState;
|
|
384
|
+
private closed;
|
|
385
|
+
/** The tick the screen shows, between the last two snapshots given out */
|
|
386
|
+
private renderTick?;
|
|
387
|
+
/** The tick of the snapshot given out last, and of the one before it */
|
|
388
|
+
private shownTick;
|
|
389
|
+
private shownBefore;
|
|
390
|
+
/** Ticks between two snapshots, evened out */
|
|
391
|
+
protected interval: number;
|
|
392
|
+
/** How far off the time snapshots arrive at is from the ticks between them, in seconds, evened out */
|
|
393
|
+
protected jitter: number;
|
|
394
|
+
/** When the last snapshot arrived, and its tick */
|
|
395
|
+
private arrival?;
|
|
396
|
+
constructor(transport: Transport, welcome: Extract<GameHostMessage, {
|
|
397
|
+
type: 'welcome';
|
|
398
|
+
}>, registry: Registry, map: ClientWorld,
|
|
399
|
+
/** How much it keeps and how often it asks (`ConnectOptions`) */
|
|
400
|
+
limits?: PlayerLimits);
|
|
401
|
+
/** Talks through a transport from now on: what comes in is taken, and its closing is a drop */
|
|
402
|
+
private attach;
|
|
403
|
+
/** Whether the host has gone */
|
|
404
|
+
get disconnected(): boolean;
|
|
405
|
+
/**
|
|
406
|
+
* Told when the connection drops, not by this side's leaving (`dispose`): to try again (`resume`), or to say the
|
|
407
|
+
* game is lost
|
|
408
|
+
*/
|
|
409
|
+
onDisconnect?: () => void;
|
|
410
|
+
/** This side closed it: not a drop */
|
|
411
|
+
private leaving;
|
|
412
|
+
/**
|
|
413
|
+
* Goes on with the same game over a new connection, once the host has welcomed it there again (a server does, to who
|
|
414
|
+
* comes back with their seat's token): everything known sent again, and the screen catches up. What the host says
|
|
415
|
+
* besides the game before the welcome goes to `onServer`; a `refused` fails it with the reason, as does a connection
|
|
416
|
+
* that closes first, or a host that runs another game
|
|
417
|
+
*/
|
|
418
|
+
resume(transport: Transport): Promise<void>;
|
|
419
|
+
/** Keeps what the host's definitions were changed to, over what was kept before */
|
|
420
|
+
private heardRedefined;
|
|
421
|
+
/**
|
|
422
|
+
* Takes a new version of the game into this screen's registry (hot reload, a game in a worker): its definitions as
|
|
423
|
+
* the new version has them, what the host changed of them while it ran over them again
|
|
424
|
+
*/
|
|
425
|
+
takeGame(game: GameModule): void;
|
|
426
|
+
/** Takes in a message of the host's: what the transport hands it, and what came in while the session was made */
|
|
427
|
+
receive(message: HostToPlayer): void;
|
|
428
|
+
/**
|
|
429
|
+
* The game paused by the server, for everyone: by a player (`player`, until a time at most, in `Date.now()`'s
|
|
430
|
+
* milliseconds) or an admin (neither). Null while it goes on
|
|
431
|
+
*/
|
|
432
|
+
pause: {
|
|
433
|
+
player?: PlayerId;
|
|
434
|
+
until?: number;
|
|
435
|
+
} | null;
|
|
436
|
+
/** Told each time the server pauses the game or lets it go on */
|
|
437
|
+
onPause?: (pause: {
|
|
438
|
+
player?: PlayerId;
|
|
439
|
+
until?: number;
|
|
440
|
+
} | null) => void;
|
|
441
|
+
/** Says something to the server beside the game: a lobby's message (`{ type: 'resume' }`) */
|
|
442
|
+
tell(message: {
|
|
443
|
+
type: string;
|
|
444
|
+
} & Record<string, unknown>): void;
|
|
445
|
+
/** Why the game ended on an error in its rules, once the host said so */
|
|
446
|
+
failure: {
|
|
447
|
+
message: string;
|
|
448
|
+
} | null;
|
|
449
|
+
/** Milliseconds a message takes to the host and back, evened out: measured every couple of seconds */
|
|
450
|
+
ping?: number;
|
|
451
|
+
/** Whether the player only watches, and sees everything */
|
|
452
|
+
readonly observer: boolean;
|
|
453
|
+
private pinger?;
|
|
454
|
+
/** Asks the host to answer at once, to measure the time there and back */
|
|
455
|
+
private sendPing;
|
|
456
|
+
/** Told of what the host says besides the game: a server's messages (see `ConnectOptions.onServer`) */
|
|
457
|
+
onServer?: ConnectOptions['onServer'];
|
|
458
|
+
/** Rebuilds the frame a delta makes, says it got it, and has its snapshot wait for the screen */
|
|
459
|
+
private take;
|
|
460
|
+
/**
|
|
461
|
+
* The oldest snapshot waiting let go, its events put before the next one's: the screen, when it asks again, jumps
|
|
462
|
+
* to the newest anyway. The state is in every snapshot; the events (deaths, sounds, lines said) are what would be lost
|
|
463
|
+
*/
|
|
464
|
+
private fold;
|
|
465
|
+
/**
|
|
466
|
+
* Snapshots come in and not yet given to the screen (`update`): a few normally, never more than a few seconds of
|
|
467
|
+
* them, however long the screen does not ask
|
|
468
|
+
*
|
|
469
|
+
* @beta
|
|
470
|
+
*/
|
|
471
|
+
get waiting(): number;
|
|
472
|
+
private takeFog;
|
|
473
|
+
snapshot(): Snapshot;
|
|
474
|
+
/** The tick the screen is shown at, between two snapshots: behind the newest by `delay` */
|
|
475
|
+
get shownAt(): number;
|
|
476
|
+
/** How far behind the newest snapshot the screen is shown, in ticks: about two snapshots, and room for the jitter */
|
|
477
|
+
get delay(): number;
|
|
478
|
+
/** Takes note of when a snapshot arrived, for how far apart they come and how unevenly */
|
|
479
|
+
private arrived;
|
|
480
|
+
/**
|
|
481
|
+
* Lets the screen's clock go on by `dt`, and gives out the snapshots it has come to, oldest first: the screen draws
|
|
482
|
+
* between the last two (`alpha`). The time is the host's: the clock follows the snapshots, not the other way around
|
|
483
|
+
*/
|
|
484
|
+
update(dt: number): Snapshot[];
|
|
485
|
+
send(command: PlayerCommand): number;
|
|
486
|
+
/** The number of the last command sent */
|
|
487
|
+
private lastSeq;
|
|
488
|
+
fog(): FogState;
|
|
489
|
+
camps(): readonly CampInfo[];
|
|
490
|
+
/**
|
|
491
|
+
* Whether the player could build this here, as far as they can tell: on their copy of the map, with the structures
|
|
492
|
+
* they know, on ground they have explored. The game's own say (the `canPlace` hook) is the host's: it may still refuse
|
|
493
|
+
*/
|
|
494
|
+
canPlace(unitType: string, point: Vec2): boolean;
|
|
495
|
+
/** Which cells of a building's ground are in the way, as `canPlace` sees them: on the player's copy of the map, explored */
|
|
496
|
+
placeCells(unitType: string, point: Vec2): readonly boolean[] | undefined;
|
|
497
|
+
/** The way a unit would walk, on the player's copy of the map: around the structures they know, and no others */
|
|
498
|
+
findPath(from: Vec2, to: Vec2, flying?: boolean): Vec2[] | null;
|
|
499
|
+
dispose(): void;
|
|
500
|
+
}
|
|
501
|
+
/** @beta */
|
|
502
|
+
export interface ConnectOptions {
|
|
503
|
+
/**
|
|
504
|
+
* The game module the host runs: the player's side needs its data, and checks it is the very same version. Or the
|
|
505
|
+
* games the player has, by id, for a host that says which it runs
|
|
506
|
+
*/
|
|
507
|
+
game: GameModule | Record<string, GameModule>;
|
|
508
|
+
navigation?: RecastNavigationOptions;
|
|
509
|
+
/** The maps the welcome's ground may be one of (S36): the game's own (`GameModule.maps`) when left out */
|
|
510
|
+
maps?: readonly GameMap[];
|
|
511
|
+
/**
|
|
512
|
+
* What the player's side keeps and how often it asks: `pingEvery`, `maxJitter`, `keptSnapshots`,
|
|
513
|
+
* `keptScreenEvents` (`PlayerLimits`)
|
|
514
|
+
*
|
|
515
|
+
* @beta
|
|
516
|
+
*/
|
|
517
|
+
limits?: PlayerLimits;
|
|
518
|
+
/** What else the host says, before the game and during it: a server's lobby, a pause, the result */
|
|
519
|
+
onServer?: (message: ServerToPlayer) => void;
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Connects to a host over a transport (the player's end of it), and waits for the welcome: what the session is
|
|
523
|
+
* made of. Fails when the host runs another version of the game, or of the engine's wire (`PROTOCOL_VERSION`), and
|
|
524
|
+
* when the connection closes before the session is made: while the map is made from the welcome too
|
|
525
|
+
*
|
|
526
|
+
* @beta
|
|
527
|
+
*/
|
|
528
|
+
export declare function connect(transport: Transport, options: ConnectOptions): Promise<RemoteSession>;
|
|
529
|
+
/** `connect`, for a session of a kind of its own: `make` is given what a `RemoteSession` is made of */
|
|
530
|
+
export declare function connectAs<S extends RemoteSession>(transport: Transport, options: ConnectOptions, make: (...made: ConstructorParameters<typeof RemoteSession>) => S): Promise<S>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { type CommandReplay } from './commandReplay';
|
|
2
|
+
import type { PlayerId } from '#engine/entity';
|
|
3
|
+
import type { GameModule } from '#engine/game';
|
|
4
|
+
import type { Component } from '#engine/components';
|
|
5
|
+
import type { World } from '#engine/world';
|
|
6
|
+
import { type RemoteSession } from './remote';
|
|
7
|
+
/**
|
|
8
|
+
* A game recorded (`recordGame`), to play back (`playReplay`): its commands, run again (`CommandReplay`), or the frames
|
|
9
|
+
* a watcher of it was sent (`FramesReplay`)
|
|
10
|
+
*
|
|
11
|
+
* @beta
|
|
12
|
+
*/
|
|
13
|
+
export type Replay = FramesReplay | CommandReplay;
|
|
14
|
+
/**
|
|
15
|
+
* A game recorded as the frames a watcher of it was sent: only what `player` saw, and what it was sent of it
|
|
16
|
+
*
|
|
17
|
+
* @beta
|
|
18
|
+
*/
|
|
19
|
+
export interface FramesReplay {
|
|
20
|
+
format: 1;
|
|
21
|
+
/** The game it is of, by id: a page plays back what it has */
|
|
22
|
+
game: string;
|
|
23
|
+
/** Whose side it was seen from: their lines and cinematics, everything in sight besides */
|
|
24
|
+
player: PlayerId;
|
|
25
|
+
tickRate: number;
|
|
26
|
+
/** The tick it started and ended at */
|
|
27
|
+
from: number;
|
|
28
|
+
to: number;
|
|
29
|
+
/** What the host sent, as it sent it, with the tick of the world then */
|
|
30
|
+
frames: [tick: number, message: string][];
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* A game being recorded
|
|
34
|
+
*
|
|
35
|
+
* @beta
|
|
36
|
+
*/
|
|
37
|
+
export interface ReplayRecorder {
|
|
38
|
+
/** Ticks recorded so far */
|
|
39
|
+
readonly ticks: number;
|
|
40
|
+
/** Stops, and gives what was recorded */
|
|
41
|
+
stop(): Replay;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* How a game is recorded (`recordGame`): whose side it is seen from when played back, and which kind of replay.
|
|
45
|
+
* `commands` (the default) keeps the start and what the players told it, and plays it back by running it again: a few
|
|
46
|
+
* kilobytes, every side of it, and the same to the last bit while the rules are (determinism D4). `frames` keeps what a
|
|
47
|
+
* watcher from `player`'s side was sent, `sendRate` times a second: for a game whose rules cannot be run again
|
|
48
|
+
*
|
|
49
|
+
* @beta
|
|
50
|
+
*/
|
|
51
|
+
export interface RecordOptions {
|
|
52
|
+
player: PlayerId;
|
|
53
|
+
kind?: 'commands' | 'frames';
|
|
54
|
+
/** Frames a second, of a `frames` replay: 10 when left out */
|
|
55
|
+
sendRate?: number;
|
|
56
|
+
/** Ticks between the hashes a `commands` replay keeps: 300 when left out */
|
|
57
|
+
every?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Ticks between the checkpoints a `commands` replay keeps (the world as a save, to be played from a moment without
|
|
60
|
+
* running all before it: going back, opening it halfway). None when left out: each is as big as a save @beta
|
|
61
|
+
*/
|
|
62
|
+
checkpoints?: number;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Records a game played in the page (`RecordOptions`): as its start and its players' commands (`kind: 'commands'`,
|
|
66
|
+
* the default: `recordCommands`), or as an observer from `player`'s side sees it, what changed `sendRate` times a
|
|
67
|
+
* second (`kind: 'frames'`). Frames are answered at once, as by a watcher who missed nothing, so what is kept is what
|
|
68
|
+
* changed and not the whole world again
|
|
69
|
+
*
|
|
70
|
+
* @beta
|
|
71
|
+
*/
|
|
72
|
+
export declare function recordGame(world: World, options: RecordOptions): ReplayRecorder;
|
|
73
|
+
/**
|
|
74
|
+
* A replay playing (`playReplay`): its session, and its clock
|
|
75
|
+
*
|
|
76
|
+
* @beta
|
|
77
|
+
*/
|
|
78
|
+
export interface ReplayPlayer {
|
|
79
|
+
/** The game as it was, once the welcome is in */
|
|
80
|
+
session: Promise<RemoteSession>;
|
|
81
|
+
/** The tick of the game it is at */
|
|
82
|
+
readonly tick: number;
|
|
83
|
+
/** How fast it plays: 1 as it was played, 0 holds it */
|
|
84
|
+
speed: number;
|
|
85
|
+
/**
|
|
86
|
+
* Goes to a tick, ahead or back, run (or handed over) a slice a look (`REPLAY_SLICE`) so that the page goes on
|
|
87
|
+
* meanwhile: `behind` says how much is left. Back starts again in the same session (`RemoteSession.resume`): a
|
|
88
|
+
* replay of commands from the last checkpoint before the tick, one of frames from its start
|
|
89
|
+
*/
|
|
90
|
+
skipTo(tick: number): void;
|
|
91
|
+
/** Ticks still to run (or hand over) to come to the moment asked, by a seek or a fast speed: 0 while it keeps up */
|
|
92
|
+
readonly behind: number;
|
|
93
|
+
/** Whether all of it has played */
|
|
94
|
+
readonly ended: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Of a replay of commands, the tick it came apart from the game recorded at (its hash differed: the rules changed
|
|
97
|
+
* since), or null while it has not. Never for a replay of frames
|
|
98
|
+
*/
|
|
99
|
+
readonly apart?: number | null;
|
|
100
|
+
stop(): void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Plays a replay back, as a watcher's session (`connect`): a replay of commands run again (`playCommands`), or what the
|
|
104
|
+
* host sent coming in as it came, by the replay's ticks; `speed` times as fast. `game` is the game module it is of, or
|
|
105
|
+
* the modules the page has, by id
|
|
106
|
+
*
|
|
107
|
+
* @beta
|
|
108
|
+
*/
|
|
109
|
+
export declare function playReplay(replay: Replay, options: {
|
|
110
|
+
game: GameModule | Record<string, GameModule>;
|
|
111
|
+
at?: number;
|
|
112
|
+
/** What the app kept in the world beside the game's (`CreateWorldOptions.components`): a replay of commands loads its saves with them */
|
|
113
|
+
components?: readonly Component<unknown, unknown>[];
|
|
114
|
+
}): ReplayPlayer;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A seed of the moment, for a game no other was (the clock: a session's, never the rules'): where every new world made without a seed of its own gets its seed
|
|
3
|
+
* (a map played in a page, on a server, in a worker). The same seed, the same game
|
|
4
|
+
*
|
|
5
|
+
* @beta
|
|
6
|
+
*/
|
|
7
|
+
export declare const randomSeed: () => number;
|