@v12-engine/engine 0.0.0-stage → 0.1.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/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,491 @@
|
|
|
1
|
+
import { cl as fighting, id as isGameEvent, ll as moving, nl as Entity, pd as statsOf, rl as deposit, ro as dashing, wc as productionOf, zi as harvesterOf } from "./debugCommands-CzjrSm66.js";
|
|
2
|
+
//#region src/inspect.ts
|
|
3
|
+
/**
|
|
4
|
+
* What the debug tools see of the rules: everything in the world (`listWorld`), an entity, a player or the world as the
|
|
5
|
+
* rules have it (`inspect`), a number of it changed (`setInspected`), and the events and hooks of the last seconds
|
|
6
|
+
* (`EventLog`). Everything they give is plain data,
|
|
7
|
+
* so that it can come from a simulation that runs somewhere else, the way the snapshots do
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A value as plain data, to be shown: entities become `footman#12`, definitions their id, numbers are rounded, and
|
|
11
|
+
* what is deep or long is cut short
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
function summarize(value, depth = 0) {
|
|
16
|
+
if (value === null || value === void 0 || typeof value === "string" || typeof value === "boolean") return value;
|
|
17
|
+
if (typeof value === "number") return Number.isInteger(value) || !Number.isFinite(value) ? value : Math.round(value * 1e3) / 1e3;
|
|
18
|
+
if (typeof value === "function") return void 0;
|
|
19
|
+
if (typeof value !== "object") return String(value);
|
|
20
|
+
if (value instanceof Entity) return `${value.def.id}#${value.id}`;
|
|
21
|
+
if (value instanceof Map || value instanceof Set) return `${value.constructor.name}(${value.size})`;
|
|
22
|
+
if (ArrayBuffer.isView(value)) return `${value.constructor.name}(${value.length})`;
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
if (depth > 3) return `[${value.length}]`;
|
|
25
|
+
const items = value.slice(0, 12).map((item) => summarize(item, depth + 1));
|
|
26
|
+
if (value.length > 12) items.push(`… ${value.length - 12} more`);
|
|
27
|
+
return items;
|
|
28
|
+
}
|
|
29
|
+
const record = value;
|
|
30
|
+
const plain = Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null;
|
|
31
|
+
if (depth > 0 && typeof record.id === "string" && (!plain || "name" in record)) return record.id;
|
|
32
|
+
if (depth > 0 && typeof record.id === "number" && !plain) return `${value.constructor.name.toLowerCase()} ${record.id}`;
|
|
33
|
+
if (depth > 3) return "{…}";
|
|
34
|
+
const out = {};
|
|
35
|
+
for (const key in record) {
|
|
36
|
+
const item = summarize(record[key], depth + 1);
|
|
37
|
+
if (item !== void 0) out[key] = item;
|
|
38
|
+
}
|
|
39
|
+
return out;
|
|
40
|
+
}
|
|
41
|
+
/** The parts of an entity the engine keeps, by field, with what the inspector calls them */
|
|
42
|
+
var PARTS = [
|
|
43
|
+
["orders", "Orders"],
|
|
44
|
+
["abilities", "Abilities"],
|
|
45
|
+
["buffs", "Buffs"]
|
|
46
|
+
];
|
|
47
|
+
/** The engine's parts that are components, by id, with what the inspector calls them */
|
|
48
|
+
var PART_COMPONENTS = {
|
|
49
|
+
[moving.id]: "Movement",
|
|
50
|
+
[fighting.id]: "Combat",
|
|
51
|
+
[deposit.id]: "Resource"
|
|
52
|
+
};
|
|
53
|
+
/** The numbers of an entity of its own, not in a part */
|
|
54
|
+
var OWN_NUMBERS = [
|
|
55
|
+
"hp",
|
|
56
|
+
"maxHp",
|
|
57
|
+
"mana",
|
|
58
|
+
"maxMana",
|
|
59
|
+
"facing",
|
|
60
|
+
"expires",
|
|
61
|
+
"unseenIn"
|
|
62
|
+
];
|
|
63
|
+
/** What `setInspected` may change of an entity: the numbers of its own, the parts and the components. Never where it is, nor its type */
|
|
64
|
+
var EDITABLE = /* @__PURE__ */ new Set([
|
|
65
|
+
...OWN_NUMBERS,
|
|
66
|
+
...PARTS.map(([key]) => key),
|
|
67
|
+
"components"
|
|
68
|
+
]);
|
|
69
|
+
/** The world's own state the inspector shows apart, rather than as a component */
|
|
70
|
+
var TIMERS_STATE = "core.timers";
|
|
71
|
+
/** Whether a timer's data says something about the entity: a field that names it by id */
|
|
72
|
+
function mentions(data, id, depth = 0) {
|
|
73
|
+
if (!data || typeof data !== "object" || depth > 3) return false;
|
|
74
|
+
for (const [key, value] of Object.entries(data)) {
|
|
75
|
+
if (typeof value === "number" && value === id && /id|entity|unit|target|source|caster|owner/i.test(key)) return true;
|
|
76
|
+
if (typeof value === "object" && mentions(value, id, depth + 1)) return true;
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
/** An entity by id as the inspector links to it, or nothing when there is none */
|
|
81
|
+
var named = (world, id) => {
|
|
82
|
+
const entity = id ? world.get(id) : void 0;
|
|
83
|
+
return entity && `${entity.def.id}#${entity.id}`;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* The other entities an entity has to do with, by what they are to it: what it is told to go for, fight, gather
|
|
87
|
+
* from, who put a buff on it; and the other way, who is after it. The world has no tree of entities: these are its
|
|
88
|
+
* relations
|
|
89
|
+
*/
|
|
90
|
+
function relationsOf(world, entity) {
|
|
91
|
+
const out = {};
|
|
92
|
+
const add = (what, id) => {
|
|
93
|
+
const name = named(world, id);
|
|
94
|
+
if (name && id !== entity.id) out[what] = name;
|
|
95
|
+
};
|
|
96
|
+
entity.orders.forEach((order, index) => add(`orders[${index}] ${order.type}`, order.init.target));
|
|
97
|
+
add("goes to", entity.get(moving)?.goalEntity);
|
|
98
|
+
add("fights", entity.get(fighting)?.autoTarget);
|
|
99
|
+
add("swings at", entity.get(fighting)?.swingTarget);
|
|
100
|
+
add("was hit by", entity.get(fighting)?.lastAttacker);
|
|
101
|
+
add("gathers from", harvesterOf(entity)?.resource);
|
|
102
|
+
add("rallies to", productionOf(entity)?.rally?.target);
|
|
103
|
+
for (const buff of entity.buffs) add(`buff ${buff.id} from`, buff.source);
|
|
104
|
+
let after = 0;
|
|
105
|
+
for (const other of world.actors.values()) {
|
|
106
|
+
if (other === entity || !other.alive) continue;
|
|
107
|
+
if (other.orders[0]?.init.target === entity.id || other.get(fighting)?.autoTarget === entity.id) {
|
|
108
|
+
if (++after > 8) break;
|
|
109
|
+
add(`after it ${after}`, other.id);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return out;
|
|
113
|
+
}
|
|
114
|
+
function inspectEntity(world, id) {
|
|
115
|
+
const entity = world.get(id);
|
|
116
|
+
if (!entity) return null;
|
|
117
|
+
const state = {};
|
|
118
|
+
for (const key of OWN_NUMBERS) if (entity[key] !== null) state[key] = summarize(entity[key]);
|
|
119
|
+
const flags = [];
|
|
120
|
+
if (entity.hidden) flags.push("hidden");
|
|
121
|
+
if (entity.asleep) flags.push("asleep");
|
|
122
|
+
if (entity.unseen) flags.push("unseen");
|
|
123
|
+
if (entity.scenery) flags.push("scenery");
|
|
124
|
+
if (entity.get(dashing)) flags.push("dashing");
|
|
125
|
+
if (entity.scale !== 1) flags.push(`scale ${entity.scale}`);
|
|
126
|
+
if (entity.look) flags.push(`look ${entity.look}`);
|
|
127
|
+
const sections = [{
|
|
128
|
+
title: "State",
|
|
129
|
+
value: state,
|
|
130
|
+
path: []
|
|
131
|
+
}, {
|
|
132
|
+
title: "Stats",
|
|
133
|
+
value: summarize({ ...statsOf(world, entity) })
|
|
134
|
+
}];
|
|
135
|
+
const related = relationsOf(world, entity);
|
|
136
|
+
if (Object.keys(related).length) sections.push({
|
|
137
|
+
title: "Related",
|
|
138
|
+
value: related
|
|
139
|
+
});
|
|
140
|
+
for (const [key, title] of PARTS) {
|
|
141
|
+
const value = entity[key];
|
|
142
|
+
if (value === void 0 || value === null || Array.isArray(value) && !value.length) continue;
|
|
143
|
+
sections.push({
|
|
144
|
+
title,
|
|
145
|
+
value: summarize(value),
|
|
146
|
+
path: [key]
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
for (const [component, value] of Object.entries(entity.components)) {
|
|
150
|
+
const part = PART_COMPONENTS[component];
|
|
151
|
+
sections.push({
|
|
152
|
+
title: part ?? component,
|
|
153
|
+
value: summarize(value),
|
|
154
|
+
path: ["components", component],
|
|
155
|
+
own: !part
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
const timers = world.timers.list().filter((timer) => mentions(timer.data, id));
|
|
159
|
+
if (timers.length) sections.push({
|
|
160
|
+
title: "Timers",
|
|
161
|
+
value: summarize(timers)
|
|
162
|
+
});
|
|
163
|
+
const owner = world.players.get(entity.owner)?.name ?? String(entity.owner);
|
|
164
|
+
return {
|
|
165
|
+
target: { entity: id },
|
|
166
|
+
title: `${entity.def.name} #${id}`,
|
|
167
|
+
about: `${entity.def.id}, ${owner}`,
|
|
168
|
+
tick: world.tick,
|
|
169
|
+
alive: entity.alive,
|
|
170
|
+
at: {
|
|
171
|
+
x: entity.pos.x,
|
|
172
|
+
z: entity.pos.z
|
|
173
|
+
},
|
|
174
|
+
flags,
|
|
175
|
+
sections
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/** The components kept in a state store, each a section of its own */
|
|
179
|
+
var componentSections = (values) => Object.entries(values).filter(([id]) => id !== TIMERS_STATE).map(([id, value]) => ({
|
|
180
|
+
title: id,
|
|
181
|
+
value: summarize(value),
|
|
182
|
+
path: ["state", id],
|
|
183
|
+
own: true
|
|
184
|
+
}));
|
|
185
|
+
function inspectPlayer(world, id) {
|
|
186
|
+
const player = world.players.get(id);
|
|
187
|
+
if (!player) return null;
|
|
188
|
+
const objectives = world.objectives.of(id);
|
|
189
|
+
const sections = [
|
|
190
|
+
{
|
|
191
|
+
title: "Resources",
|
|
192
|
+
value: summarize(player.resources),
|
|
193
|
+
path: ["resources"]
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
title: "Player",
|
|
197
|
+
value: {
|
|
198
|
+
team: player.team,
|
|
199
|
+
supplyUsed: player.supplyUsed,
|
|
200
|
+
supplyCap: player.supplyCap,
|
|
201
|
+
entities: world.index.ownedBy(id).size
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
title: "Upgrades",
|
|
206
|
+
value: Object.fromEntries(player.upgrades),
|
|
207
|
+
path: ["upgrades"]
|
|
208
|
+
}
|
|
209
|
+
];
|
|
210
|
+
if (player.researching.size) sections.push({
|
|
211
|
+
title: "Researching",
|
|
212
|
+
value: [...player.researching]
|
|
213
|
+
});
|
|
214
|
+
if (objectives.length) sections.push({
|
|
215
|
+
title: "Objectives",
|
|
216
|
+
value: summarize(objectives)
|
|
217
|
+
});
|
|
218
|
+
sections.push(...componentSections(player.states.values));
|
|
219
|
+
const seat = world.computers.get(id);
|
|
220
|
+
const thinking = seat?.computer.inspect?.();
|
|
221
|
+
const ai = isReport(thinking) ? {
|
|
222
|
+
...thinking,
|
|
223
|
+
timing: seat.timing()
|
|
224
|
+
} : void 0;
|
|
225
|
+
if (thinking !== void 0 && !ai) sections.push({
|
|
226
|
+
title: "Computer player",
|
|
227
|
+
value: summarize(thinking)
|
|
228
|
+
});
|
|
229
|
+
const flags = [
|
|
230
|
+
player.neutral && "neutral",
|
|
231
|
+
player.creeps && "creeps",
|
|
232
|
+
player.defeated && "defeated"
|
|
233
|
+
].filter((flag) => !!flag);
|
|
234
|
+
return {
|
|
235
|
+
target: { player: id },
|
|
236
|
+
title: player.name,
|
|
237
|
+
about: `player ${id}, team ${player.team}`,
|
|
238
|
+
tick: world.tick,
|
|
239
|
+
alive: !player.defeated,
|
|
240
|
+
flags,
|
|
241
|
+
sections,
|
|
242
|
+
...ai && { ai }
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/** Whether what a computer player says of itself is a brain's report */
|
|
246
|
+
var isReport = (value) => !!value && typeof value === "object" && value.v === 1 && typeof value.brain === "string" && Array.isArray(value.goals);
|
|
247
|
+
function inspectWorld(world) {
|
|
248
|
+
const sections = [
|
|
249
|
+
{
|
|
250
|
+
title: "World",
|
|
251
|
+
value: summarize({
|
|
252
|
+
tick: world.tick,
|
|
253
|
+
time: world.time,
|
|
254
|
+
hour: world.registry.day ? world.hour : void 0,
|
|
255
|
+
winner: world.winner,
|
|
256
|
+
entities: world.entities.size,
|
|
257
|
+
actors: world.actors.size,
|
|
258
|
+
projectiles: world.projectiles.length,
|
|
259
|
+
missiles: world.missiles.length,
|
|
260
|
+
items: world.items.length
|
|
261
|
+
})
|
|
262
|
+
},
|
|
263
|
+
...componentSections(world.states.values),
|
|
264
|
+
{
|
|
265
|
+
title: "Timers",
|
|
266
|
+
value: summarize(world.timers.list())
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
title: "Systems",
|
|
270
|
+
value: world.systems.map((system) => `${system.name} (${system.phase})`)
|
|
271
|
+
}
|
|
272
|
+
];
|
|
273
|
+
return {
|
|
274
|
+
target: { world: true },
|
|
275
|
+
title: "World",
|
|
276
|
+
about: `${world.players.size} players`,
|
|
277
|
+
tick: world.tick,
|
|
278
|
+
alive: true,
|
|
279
|
+
flags: [],
|
|
280
|
+
sections
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Something as the simulation has it right now, or null when there is no such entity or player
|
|
285
|
+
*
|
|
286
|
+
* @beta
|
|
287
|
+
*/
|
|
288
|
+
function inspect(world, target) {
|
|
289
|
+
if ("entity" in target) return inspectEntity(world, target.entity);
|
|
290
|
+
if ("player" in target) return inspectPlayer(world, target.player);
|
|
291
|
+
return inspectWorld(world);
|
|
292
|
+
}
|
|
293
|
+
/** Walks a path to what holds the last key. Null when it does not lead anywhere */
|
|
294
|
+
function holderOf(root, path) {
|
|
295
|
+
let holder = root;
|
|
296
|
+
for (const key of path.slice(0, -1)) {
|
|
297
|
+
const next = holder[key];
|
|
298
|
+
if (!next || typeof next !== "object") return null;
|
|
299
|
+
holder = next;
|
|
300
|
+
}
|
|
301
|
+
return holder;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Changes a number where `inspect` showed it: of an entity `['hp']`, `['abilities', 0, 'cooldown']`,
|
|
305
|
+
* `['components', 'td.bounty', 'gold']`; of a player `['resources', 'gold']`, `['upgrades', 'armor']`,
|
|
306
|
+
* `['state', 'td.score', 'kills']`; of the world `['state', 'td.waves', 'wave']`. An entity's health is kept within what
|
|
307
|
+
* it can have, and none left kills it. Whether it was changed: false for what is not a number or a switch (a boolean), or not to be changed
|
|
308
|
+
*
|
|
309
|
+
* @internal
|
|
310
|
+
*/
|
|
311
|
+
function setInspected(world, target, path, value) {
|
|
312
|
+
if (!path.length || typeof value === "number" && !Number.isFinite(value)) return false;
|
|
313
|
+
const last = path[path.length - 1];
|
|
314
|
+
if ("player" in target) {
|
|
315
|
+
const player = world.players.get(target.player);
|
|
316
|
+
if (!player) return false;
|
|
317
|
+
if (path[0] === "upgrades" && path.length === 2) {
|
|
318
|
+
if (typeof value !== "number") return false;
|
|
319
|
+
player.setUpgrade(String(last), Math.max(0, Math.round(value)));
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
const root = path[0] === "resources" ? player : path[0] === "state" ? { state: player.states.values } : null;
|
|
323
|
+
const holder = root && holderOf(root, path);
|
|
324
|
+
if (!holder || typeof holder[last] !== typeof value) return false;
|
|
325
|
+
holder[last] = value;
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
if ("world" in target) {
|
|
329
|
+
if (path[0] !== "state" || path[1] === TIMERS_STATE) return false;
|
|
330
|
+
const holder = holderOf({ state: world.states.values }, path);
|
|
331
|
+
if (!holder || typeof holder[last] !== typeof value) return false;
|
|
332
|
+
holder[last] = value;
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
const entity = world.get(target.entity);
|
|
336
|
+
if (!entity?.alive || !EDITABLE.has(String(path[0]))) return false;
|
|
337
|
+
const holder = holderOf(entity, path);
|
|
338
|
+
if (!holder || typeof holder[last] !== typeof value) return false;
|
|
339
|
+
if (typeof value === "number" && path.length === 1 && last === "hp") {
|
|
340
|
+
if (value <= 0) {
|
|
341
|
+
world.kill(entity);
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
value = Math.min(value, entity.maxHp);
|
|
345
|
+
}
|
|
346
|
+
if (typeof value === "number" && path.length === 1 && last === "mana") value = Math.max(0, Math.min(value, entity.maxMana));
|
|
347
|
+
holder[last] = value;
|
|
348
|
+
entity.statsCache = null;
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Every player and entity of the world, in a few numbers each
|
|
353
|
+
*
|
|
354
|
+
* @internal
|
|
355
|
+
*/
|
|
356
|
+
function listWorld(world) {
|
|
357
|
+
const entities = [];
|
|
358
|
+
for (const entity of world.entities.values()) {
|
|
359
|
+
if (!entity.alive) continue;
|
|
360
|
+
entities.push({
|
|
361
|
+
id: entity.id,
|
|
362
|
+
type: entity.def.id,
|
|
363
|
+
name: entity.def.name,
|
|
364
|
+
owner: entity.owner,
|
|
365
|
+
kind: entity.def.kind,
|
|
366
|
+
hp: Math.ceil(entity.hp),
|
|
367
|
+
maxHp: Math.ceil(entity.maxHp),
|
|
368
|
+
order: entity.orders[0]?.type ?? null,
|
|
369
|
+
scenery: entity.scenery,
|
|
370
|
+
hidden: entity.hidden
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
const players = [...world.players.values()].map(({ id, name, team, neutral, defeated }) => ({
|
|
374
|
+
id,
|
|
375
|
+
name,
|
|
376
|
+
team,
|
|
377
|
+
neutral,
|
|
378
|
+
defeated
|
|
379
|
+
}));
|
|
380
|
+
return {
|
|
381
|
+
tick: world.tick,
|
|
382
|
+
players,
|
|
383
|
+
entities
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* The events and hooks of the last seconds of a world, the game's own among them, with the listeners and handlers
|
|
388
|
+
* that ran on them. Hooks run often (every target search asks one), so a hook is one line a tick, with how many times.
|
|
389
|
+
* Following costs a little: it is only on while `attach`ed
|
|
390
|
+
*
|
|
391
|
+
* @beta
|
|
392
|
+
*/
|
|
393
|
+
var EventLog = class {
|
|
394
|
+
seconds;
|
|
395
|
+
max;
|
|
396
|
+
list = [];
|
|
397
|
+
seq = 0;
|
|
398
|
+
/** The hooks of the tick going on, by name */
|
|
399
|
+
hooks = /* @__PURE__ */ new Map();
|
|
400
|
+
hooksAt = -1;
|
|
401
|
+
/** The event going out, which listeners that run belong to */
|
|
402
|
+
current = null;
|
|
403
|
+
world = null;
|
|
404
|
+
untap = null;
|
|
405
|
+
constructor(seconds = 10, max = 2e3) {
|
|
406
|
+
this.seconds = seconds;
|
|
407
|
+
this.max = max;
|
|
408
|
+
}
|
|
409
|
+
/** Starts following a world */
|
|
410
|
+
attach(world) {
|
|
411
|
+
this.detach();
|
|
412
|
+
this.world = world;
|
|
413
|
+
world.trace = this;
|
|
414
|
+
this.untap = world.events.tap((type, payload) => this.event(type, payload));
|
|
415
|
+
}
|
|
416
|
+
/** Stops following it. What was logged stays */
|
|
417
|
+
detach() {
|
|
418
|
+
const { world } = this;
|
|
419
|
+
if (!world) return;
|
|
420
|
+
if (world.trace === this) world.trace = null;
|
|
421
|
+
this.untap?.();
|
|
422
|
+
this.untap = null;
|
|
423
|
+
this.world = null;
|
|
424
|
+
this.current = null;
|
|
425
|
+
}
|
|
426
|
+
get attached() {
|
|
427
|
+
return this.world !== null;
|
|
428
|
+
}
|
|
429
|
+
/** What was logged, oldest first. The same list, kept up to date: to read, not to keep */
|
|
430
|
+
get entries() {
|
|
431
|
+
return this.list;
|
|
432
|
+
}
|
|
433
|
+
clear() {
|
|
434
|
+
this.list.length = 0;
|
|
435
|
+
this.hooks.clear();
|
|
436
|
+
}
|
|
437
|
+
event(type, payload) {
|
|
438
|
+
const world = this.world;
|
|
439
|
+
const tick = world.events.releasing ? world.tick - 1 : world.tick;
|
|
440
|
+
const name = String(type);
|
|
441
|
+
this.current = this.add({
|
|
442
|
+
tick,
|
|
443
|
+
kind: "event",
|
|
444
|
+
name,
|
|
445
|
+
own: isGameEvent(name),
|
|
446
|
+
detail: summarize(payload, 1),
|
|
447
|
+
ran: []
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
listener(id) {
|
|
451
|
+
this.current?.ran.push(id);
|
|
452
|
+
}
|
|
453
|
+
hook(name, handlers, own, event) {
|
|
454
|
+
const { tick } = this.world;
|
|
455
|
+
if (tick !== this.hooksAt) {
|
|
456
|
+
this.hooks.clear();
|
|
457
|
+
this.hooksAt = tick;
|
|
458
|
+
}
|
|
459
|
+
const known = this.hooks.get(name);
|
|
460
|
+
if (known) {
|
|
461
|
+
known.count++;
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
const entry = this.add({
|
|
465
|
+
tick,
|
|
466
|
+
kind: "hook",
|
|
467
|
+
name,
|
|
468
|
+
own,
|
|
469
|
+
detail: summarize(event, 1),
|
|
470
|
+
ran: handlers.map((handler) => handler.id),
|
|
471
|
+
count: 1
|
|
472
|
+
});
|
|
473
|
+
this.hooks.set(name, entry);
|
|
474
|
+
}
|
|
475
|
+
add(entry) {
|
|
476
|
+
const logged = {
|
|
477
|
+
seq: ++this.seq,
|
|
478
|
+
...entry
|
|
479
|
+
};
|
|
480
|
+
this.list.push(logged);
|
|
481
|
+
const oldest = logged.tick - this.seconds * this.world.tickRate;
|
|
482
|
+
let drop = 0;
|
|
483
|
+
while (drop < this.list.length && (this.list.length - drop > this.max || this.list[drop].tick < oldest)) drop++;
|
|
484
|
+
if (drop) this.list.splice(0, drop);
|
|
485
|
+
return logged;
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
//#endregion
|
|
489
|
+
export { summarize as a, setInspected as i, inspect as n, listWorld as r, EventLog as t };
|
|
490
|
+
|
|
491
|
+
//# sourceMappingURL=inspect-D9dWHmZ0.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-D9dWHmZ0.js","names":[],"sources":["../src/inspect.ts"],"sourcesContent":["import { harvesterOf } from './orders/harvest'\nimport { dashing } from './dashing'\nimport { productionOf } from './systems/productionQueue'\nimport { deposit, Entity, type EntityId, fighting, moving, type PlayerId } from './entity'\nimport { isGameEvent } from './events'\nimport type { AiReport } from './ai/report'\nimport type { Vec2 } from './math'\nimport { statsOf } from './stats'\nimport type { World } from './world'\n\n/**\n * What the debug tools see of the rules: everything in the world (`listWorld`), an entity, a player or the world as the\n * rules have it (`inspect`), a number of it changed (`setInspected`), and the events and hooks of the last seconds\n * (`EventLog`). Everything they give is plain data,\n * so that it can come from a simulation that runs somewhere else, the way the snapshots do\n */\n\n/**\n * A value as plain data, to be shown: entities become `footman#12`, definitions their id, numbers are rounded, and\n * what is deep or long is cut short\n *\n * @internal\n */\nexport function summarize(value: unknown, depth = 0): unknown {\n\tif (value === null || value === undefined || typeof value === 'string' || typeof value === 'boolean') return value\n\tif (typeof value === 'number') return Number.isInteger(value) || !Number.isFinite(value) ? value : Math.round(value * 1000) / 1000\n\tif (typeof value === 'function') return undefined\n\tif (typeof value !== 'object') return String(value)\n\tif (value instanceof Entity) return `${value.def.id}#${value.id}`\n\tif (value instanceof Map || value instanceof Set) return `${value.constructor.name}(${value.size})`\n\tif (ArrayBuffer.isView(value)) return `${value.constructor.name}(${(value as unknown as ArrayLike<number>).length})`\n\tif (Array.isArray(value)) {\n\t\tif (depth > 3) return `[${value.length}]`\n\t\tconst items = value.slice(0, 12).map((item) => summarize(item, depth + 1))\n\t\tif (value.length > 12) items.push(`… ${value.length - 12} more`)\n\t\treturn items\n\t}\n\tconst record = value as Record<string, unknown>\n\tconst plain = Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null\n\t// what is inside something else and has an id of its own is said by that id: a definition, a projectile\n\tif (depth > 0 && typeof record.id === 'string' && (!plain || 'name' in record)) return record.id\n\tif (depth > 0 && typeof record.id === 'number' && !plain) return `${value.constructor.name.toLowerCase()} ${record.id}`\n\tif (depth > 3) return '{…}'\n\tconst out: Record<string, unknown> = {}\n\tfor (const key in record) {\n\t\tconst item = summarize(record[key], depth + 1)\n\t\tif (item !== undefined) out[key] = item\n\t}\n\treturn out\n}\n\n/**\n * A part of what is inspected, as the inspector shows it\n *\n * @beta\n */\nexport interface InspectedSection {\n\ttitle: string\n\t/** What it holds, plain data. Entities in it are written `footman#12`, for the inspector to link to */\n\tvalue: unknown\n\t/** Where it is kept, for `setInspected`. Left out for what is worked out, or not to be changed by hand, like stats */\n\tpath?: (string | number)[]\n\t/** State of the game's own (a component), rather than the engine's */\n\town?: boolean\n}\n\n/**\n * What the inspector can look at: an entity, a player, or the world itself\n *\n * @beta\n */\nexport type InspectTarget = { entity: EntityId } | { player: PlayerId } | { world: true }\n\n/**\n * Something as the simulation has it, for the inspector\n *\n * @beta\n */\nexport interface Inspection {\n\ttarget: InspectTarget\n\t/** What it is called: `Footman #14`, a player's name, `World` */\n\ttitle: string\n\t/** What else says what it is: type and owner, team */\n\tabout: string\n\ttick: number\n\talive: boolean\n\t/** Where it is, for an entity */\n\tat?: Vec2\n\t/** What is so of it that is not a number: hidden, asleep, scenery */\n\tflags: string[]\n\tsections: InspectedSection[]\n\t/**\n\t * What the computer that plays a player is thinking, where a brain does (`Brain.report`, with the seat's timing):\n\t * what the debug panel's AI tab draws. A computer player of another kind is a section (`Computer player`)\n\t */\n\tai?: AiReport\n}\n\n/** The parts of an entity the engine keeps, by field, with what the inspector calls them */\nconst PARTS: [keyof Entity, string][] = [\n\t['orders', 'Orders'],\n\t['abilities', 'Abilities'],\n\t['buffs', 'Buffs']\n]\n\n/** The engine's parts that are components, by id, with what the inspector calls them */\nconst PART_COMPONENTS: Record<string, string> = { [moving.id]: 'Movement', [fighting.id]: 'Combat', [deposit.id]: 'Resource' }\n\n/** The numbers of an entity of its own, not in a part */\nconst OWN_NUMBERS = ['hp', 'maxHp', 'mana', 'maxMana', 'facing', 'expires', 'unseenIn'] as const\n\n/** What `setInspected` may change of an entity: the numbers of its own, the parts and the components. Never where it is, nor its type */\nconst EDITABLE = new Set<string>([...OWN_NUMBERS, ...PARTS.map(([key]) => key), 'components'])\n\n/** The world's own state the inspector shows apart, rather than as a component */\nconst TIMERS_STATE = 'core.timers'\n\n/** Whether a timer's data says something about the entity: a field that names it by id */\nfunction mentions(data: unknown, id: EntityId, depth = 0): boolean {\n\tif (!data || typeof data !== 'object' || depth > 3) return false\n\tfor (const [key, value] of Object.entries(data)) {\n\t\tif (typeof value === 'number' && value === id && /id|entity|unit|target|source|caster|owner/i.test(key)) return true\n\t\tif (typeof value === 'object' && mentions(value, id, depth + 1)) return true\n\t}\n\treturn false\n}\n\n/** An entity by id as the inspector links to it, or nothing when there is none */\nconst named = (world: World, id: EntityId | undefined | null): string | undefined => {\n\tconst entity = id ? world.get(id) : undefined\n\treturn entity && `${entity.def.id}#${entity.id}`\n}\n\n/**\n * The other entities an entity has to do with, by what they are to it: what it is told to go for, fight, gather\n * from, who put a buff on it; and the other way, who is after it. The world has no tree of entities: these are its\n * relations\n */\nfunction relationsOf(world: World, entity: Entity): Record<string, string> {\n\tconst out: Record<string, string> = {}\n\tconst add = (what: string, id: EntityId | undefined | null) => {\n\t\tconst name = named(world, id)\n\t\tif (name && id !== entity.id) out[what] = name\n\t}\n\tentity.orders.forEach((order, index) => add(`orders[${index}] ${order.type}`, order.init.target))\n\tadd('goes to', entity.get(moving)?.goalEntity)\n\tadd('fights', entity.get(fighting)?.autoTarget)\n\tadd('swings at', entity.get(fighting)?.swingTarget)\n\tadd('was hit by', entity.get(fighting)?.lastAttacker)\n\tadd('gathers from', harvesterOf(entity)?.resource)\n\tadd('rallies to', productionOf(entity)?.rally?.target)\n\tfor (const buff of entity.buffs) add(`buff ${buff.id} from`, buff.source)\n\tlet after = 0\n\tfor (const other of world.actors.values()) {\n\t\tif (other === entity || !other.alive) continue\n\t\tif (other.orders[0]?.init.target === entity.id || other.get(fighting)?.autoTarget === entity.id) {\n\t\t\tif (++after > 8) break\n\t\t\tadd(`after it ${after}`, other.id)\n\t\t}\n\t}\n\treturn out\n}\n\nfunction inspectEntity(world: World, id: EntityId): Inspection | null {\n\tconst entity = world.get(id)\n\tif (!entity) return null\n\tconst state: Record<string, unknown> = {}\n\tfor (const key of OWN_NUMBERS) if (entity[key] !== null) state[key] = summarize(entity[key])\n\tconst flags: string[] = []\n\tif (entity.hidden) flags.push('hidden')\n\tif (entity.asleep) flags.push('asleep')\n\tif (entity.unseen) flags.push('unseen')\n\tif (entity.scenery) flags.push('scenery')\n\tif (entity.get(dashing)) flags.push('dashing')\n\tif (entity.scale !== 1) flags.push(`scale ${entity.scale}`)\n\tif (entity.look) flags.push(`look ${entity.look}`)\n\tconst sections: InspectedSection[] = [\n\t\t{ title: 'State', value: state, path: [] },\n\t\t{ title: 'Stats', value: summarize({ ...statsOf(world, entity) }) }\n\t]\n\tconst related = relationsOf(world, entity)\n\tif (Object.keys(related).length) sections.push({ title: 'Related', value: related })\n\tfor (const [key, title] of PARTS) {\n\t\tconst value = entity[key]\n\t\tif (value === undefined || value === null || (Array.isArray(value) && !value.length)) continue\n\t\tsections.push({ title, value: summarize(value), path: [key] })\n\t}\n\tfor (const [component, value] of Object.entries(entity.components)) {\n\t\tconst part = PART_COMPONENTS[component]\n\t\tsections.push({ title: part ?? component, value: summarize(value), path: ['components', component], own: !part })\n\t}\n\tconst timers = world.timers.list().filter((timer) => mentions(timer.data, id))\n\tif (timers.length) sections.push({ title: 'Timers', value: summarize(timers) })\n\tconst owner = world.players.get(entity.owner)?.name ?? String(entity.owner)\n\treturn {\n\t\ttarget: { entity: id },\n\t\ttitle: `${entity.def.name} #${id}`,\n\t\tabout: `${entity.def.id}, ${owner}`,\n\t\ttick: world.tick,\n\t\talive: entity.alive,\n\t\tat: { x: entity.pos.x, z: entity.pos.z },\n\t\tflags,\n\t\tsections\n\t}\n}\n\n/** The components kept in a state store, each a section of its own */\nconst componentSections = (values: Record<string, unknown>): InspectedSection[] =>\n\tObject.entries(values)\n\t\t.filter(([id]) => id !== TIMERS_STATE)\n\t\t.map(([id, value]) => ({ title: id, value: summarize(value), path: ['state', id], own: true }))\n\nfunction inspectPlayer(world: World, id: PlayerId): Inspection | null {\n\tconst player = world.players.get(id)\n\tif (!player) return null\n\tconst objectives = world.objectives.of(id)\n\tconst sections: InspectedSection[] = [\n\t\t{ title: 'Resources', value: summarize(player.resources), path: ['resources'] },\n\t\t{\n\t\t\ttitle: 'Player',\n\t\t\tvalue: { team: player.team, supplyUsed: player.supplyUsed, supplyCap: player.supplyCap, entities: world.index.ownedBy(id).size }\n\t\t},\n\t\t{ title: 'Upgrades', value: Object.fromEntries(player.upgrades), path: ['upgrades'] }\n\t]\n\tif (player.researching.size) sections.push({ title: 'Researching', value: [...player.researching] })\n\tif (objectives.length) sections.push({ title: 'Objectives', value: summarize(objectives) })\n\tsections.push(...componentSections(player.states.values))\n\t// the computer that plays it, where one does: what it is thinking, as it says (`ComputerPlayer.inspect`). A brain's\n\t// is its report, with the seat's milliseconds: the AI tab's\n\tconst seat = world.computers.get(id)\n\tconst thinking = seat?.computer.inspect?.()\n\tconst ai = isReport(thinking) ? { ...thinking, timing: seat!.timing() } : undefined\n\tif (thinking !== undefined && !ai) sections.push({ title: 'Computer player', value: summarize(thinking) })\n\tconst flags = [player.neutral && 'neutral', player.creeps && 'creeps', player.defeated && 'defeated'].filter((flag): flag is string => !!flag)\n\treturn {\n\t\ttarget: { player: id },\n\t\ttitle: player.name,\n\t\tabout: `player ${id}, team ${player.team}`,\n\t\ttick: world.tick,\n\t\talive: !player.defeated,\n\t\tflags,\n\t\tsections,\n\t\t...(ai && { ai })\n\t}\n}\n\n/** Whether what a computer player says of itself is a brain's report */\nconst isReport = (value: unknown): value is AiReport =>\n\t!!value &&\n\ttypeof value === 'object' &&\n\t(value as AiReport).v === 1 &&\n\ttypeof (value as AiReport).brain === 'string' &&\n\tArray.isArray((value as AiReport).goals)\n\nfunction inspectWorld(world: World): Inspection {\n\tconst sections: InspectedSection[] = [\n\t\t{\n\t\t\ttitle: 'World',\n\t\t\tvalue: summarize({\n\t\t\t\ttick: world.tick,\n\t\t\t\ttime: world.time,\n\t\t\t\thour: world.registry.day ? world.hour : undefined,\n\t\t\t\twinner: world.winner,\n\t\t\t\tentities: world.entities.size,\n\t\t\t\tactors: world.actors.size,\n\t\t\t\tprojectiles: world.projectiles.length,\n\t\t\t\tmissiles: world.missiles.length,\n\t\t\t\titems: world.items.length\n\t\t\t})\n\t\t},\n\t\t...componentSections(world.states.values),\n\t\t{ title: 'Timers', value: summarize(world.timers.list()) },\n\t\t{ title: 'Systems', value: world.systems.map((system) => `${system.name} (${system.phase})`) }\n\t]\n\treturn { target: { world: true }, title: 'World', about: `${world.players.size} players`, tick: world.tick, alive: true, flags: [], sections }\n}\n\n/**\n * Something as the simulation has it right now, or null when there is no such entity or player\n *\n * @beta\n */\nexport function inspect(world: World, target: InspectTarget): Inspection | null {\n\tif ('entity' in target) return inspectEntity(world, target.entity)\n\tif ('player' in target) return inspectPlayer(world, target.player)\n\treturn inspectWorld(world)\n}\n\n/** Walks a path to what holds the last key. Null when it does not lead anywhere */\nfunction holderOf(root: unknown, path: readonly (string | number)[]): Record<string | number, unknown> | null {\n\tlet holder = root as Record<string | number, unknown>\n\tfor (const key of path.slice(0, -1)) {\n\t\tconst next = holder[key]\n\t\tif (!next || typeof next !== 'object') return null\n\t\tholder = next as Record<string | number, unknown>\n\t}\n\treturn holder\n}\n\n/**\n * Changes a number where `inspect` showed it: of an entity `['hp']`, `['abilities', 0, 'cooldown']`,\n * `['components', 'td.bounty', 'gold']`; of a player `['resources', 'gold']`, `['upgrades', 'armor']`,\n * `['state', 'td.score', 'kills']`; of the world `['state', 'td.waves', 'wave']`. An entity's health is kept within what\n * it can have, and none left kills it. Whether it was changed: false for what is not a number or a switch (a boolean), or not to be changed\n *\n * @internal\n */\nexport function setInspected(world: World, target: InspectTarget, path: readonly (string | number)[], value: number | boolean): boolean {\n\tif (!path.length || (typeof value === 'number' && !Number.isFinite(value))) return false\n\tconst last = path[path.length - 1]\n\tif ('player' in target) {\n\t\tconst player = world.players.get(target.player)\n\t\tif (!player) return false\n\t\t// upgrades go through the player, which tells whatever is worked out from them\n\t\tif (path[0] === 'upgrades' && path.length === 2) {\n\t\t\tif (typeof value !== 'number') return false\n\t\t\tplayer.setUpgrade(String(last), Math.max(0, Math.round(value)))\n\t\t\treturn true\n\t\t}\n\t\tconst root = path[0] === 'resources' ? player : path[0] === 'state' ? { state: player.states.values } : null\n\t\tconst holder = root && holderOf(root, path)\n\t\tif (!holder || typeof holder[last] !== typeof value) return false\n\t\tholder[last] = value\n\t\treturn true\n\t}\n\tif ('world' in target) {\n\t\tif (path[0] !== 'state' || path[1] === TIMERS_STATE) return false\n\t\tconst holder = holderOf({ state: world.states.values }, path)\n\t\tif (!holder || typeof holder[last] !== typeof value) return false\n\t\tholder[last] = value\n\t\treturn true\n\t}\n\tconst entity = world.get(target.entity)\n\tif (!entity?.alive || !EDITABLE.has(String(path[0]))) return false\n\tconst holder = holderOf(entity, path)\n\tif (!holder || typeof holder[last] !== typeof value) return false\n\tif (typeof value === 'number' && path.length === 1 && last === 'hp') {\n\t\tif (value <= 0) {\n\t\t\tworld.kill(entity)\n\t\t\treturn true\n\t\t}\n\t\tvalue = Math.min(value, entity.maxHp)\n\t}\n\tif (typeof value === 'number' && path.length === 1 && last === 'mana') value = Math.max(0, Math.min(value, entity.maxMana))\n\tholder[last] = value\n\t// levels, buffs and the like go into its stats: they are worked out again\n\tentity.statsCache = null\n\treturn true\n}\n\n/**\n * An entity as the list of all of them shows it\n *\n * @beta\n */\nexport interface EntityRow {\n\tid: EntityId\n\ttype: string\n\tname: string\n\towner: PlayerId\n\tkind: string\n\thp: number\n\tmaxHp: number\n\t/** Type of what it is doing, null for nothing */\n\torder: string | null\n\tscenery: boolean\n\thidden: boolean\n}\n\n/**\n * A player as the list shows it\n *\n * @beta\n */\nexport interface PlayerRow {\n\tid: PlayerId\n\tname: string\n\tteam: number\n\tneutral: boolean\n\tdefeated: boolean\n}\n\n/**\n * Everything in the world, for the list of the debug tools: what is out of sight, hidden or scenery too\n *\n * @beta\n */\nexport interface WorldListing {\n\ttick: number\n\tplayers: PlayerRow[]\n\tentities: EntityRow[]\n}\n\n/**\n * Every player and entity of the world, in a few numbers each\n *\n * @internal\n */\nexport function listWorld(world: World): WorldListing {\n\tconst entities: EntityRow[] = []\n\tfor (const entity of world.entities.values()) {\n\t\tif (!entity.alive) continue\n\t\tentities.push({\n\t\t\tid: entity.id,\n\t\t\ttype: entity.def.id,\n\t\t\tname: entity.def.name,\n\t\t\towner: entity.owner,\n\t\t\tkind: entity.def.kind,\n\t\t\thp: Math.ceil(entity.hp),\n\t\t\tmaxHp: Math.ceil(entity.maxHp),\n\t\t\torder: entity.orders[0]?.type ?? null,\n\t\t\tscenery: entity.scenery,\n\t\t\thidden: entity.hidden\n\t\t})\n\t}\n\tconst players = [...world.players.values()].map(({ id, name, team, neutral, defeated }) => ({ id, name, team, neutral, defeated }))\n\treturn { tick: world.tick, players, entities }\n}\n\n/**\n * Something that happened in the rules, as the event log keeps it\n *\n * @beta\n */\nexport interface LoggedEvent {\n\t/** In the order they were logged, for asking for what came after */\n\tseq: number\n\t/** The tick it happened in */\n\ttick: number\n\tkind: 'event' | 'hook'\n\t/** The engine's name for it, or a game's id */\n\tname: string\n\t/** One of the game's own, rather than the engine's */\n\town: boolean\n\t/** What it said, plain data. For a hook, what the first run of it in the tick was given */\n\tdetail?: unknown\n\t/** The listeners that ran on an event, or the handlers of a hook */\n\tran: string[]\n\t/** How many times a hook ran in the tick */\n\tcount?: number\n}\n\n/**\n * What a world tells whoever follows it of the rules as they run, see `World.trace`\n *\n * @beta\n */\nexport interface Trace {\n\t/** A hook with handlers ran. `own`: a hook of the game's */\n\thook(name: string, handlers: readonly { id: string }[], own: boolean, event: unknown): void\n\t/** A listener of the game is about to run, on the event going out */\n\tlistener(id: string): void\n}\n\n/**\n * The events and hooks of the last seconds of a world, the game's own among them, with the listeners and handlers\n * that ran on them. Hooks run often (every target search asks one), so a hook is one line a tick, with how many times.\n * Following costs a little: it is only on while `attach`ed\n *\n * @beta\n */\nexport class EventLog implements Trace {\n\tprivate readonly list: LoggedEvent[] = []\n\tprivate seq = 0\n\t/** The hooks of the tick going on, by name */\n\tprivate hooks = new Map<string, LoggedEvent>()\n\tprivate hooksAt = -1\n\t/** The event going out, which listeners that run belong to */\n\tprivate current: LoggedEvent | null = null\n\tprivate world: World | null = null\n\tprivate untap: (() => void) | null = null\n\n\tconstructor(\n\t\t/** Seconds of it that are kept */\n\t\treadonly seconds = 10,\n\t\t/** Lines kept at most, however short a time they took */\n\t\treadonly max = 2000\n\t) {}\n\n\t/** Starts following a world */\n\tattach(world: World): void {\n\t\tthis.detach()\n\t\tthis.world = world\n\t\tworld.trace = this\n\t\tthis.untap = world.events.tap((type, payload) => this.event(type, payload))\n\t}\n\n\t/** Stops following it. What was logged stays */\n\tdetach(): void {\n\t\tconst { world } = this\n\t\tif (!world) return\n\t\tif (world.trace === this) world.trace = null\n\t\tthis.untap?.()\n\t\tthis.untap = null\n\t\tthis.world = null\n\t\tthis.current = null\n\t}\n\n\tget attached(): boolean {\n\t\treturn this.world !== null\n\t}\n\n\t/** What was logged, oldest first. The same list, kept up to date: to read, not to keep */\n\tget entries(): readonly LoggedEvent[] {\n\t\treturn this.list\n\t}\n\n\tclear(): void {\n\t\tthis.list.length = 0\n\t\tthis.hooks.clear()\n\t}\n\n\tprivate event(type: PropertyKey, payload: unknown): void {\n\t\tconst world = this.world!\n\t\t// what is held for the end of a tick goes out once the tick is counted\n\t\tconst tick = world.events.releasing ? world.tick - 1 : world.tick\n\t\tconst name = String(type)\n\t\tthis.current = this.add({ tick, kind: 'event', name, own: isGameEvent(name), detail: summarize(payload, 1), ran: [] })\n\t}\n\n\tlistener(id: string): void {\n\t\tthis.current?.ran.push(id)\n\t}\n\n\thook(name: string, handlers: readonly { id: string }[], own: boolean, event: unknown): void {\n\t\tconst { tick } = this.world!\n\t\tif (tick !== this.hooksAt) {\n\t\t\tthis.hooks.clear()\n\t\t\tthis.hooksAt = tick\n\t\t}\n\t\tconst known = this.hooks.get(name)\n\t\tif (known) {\n\t\t\tknown.count!++\n\t\t\treturn\n\t\t}\n\t\tconst entry = this.add({ tick, kind: 'hook', name, own, detail: summarize(event, 1), ran: handlers.map((handler) => handler.id), count: 1 })\n\t\tthis.hooks.set(name, entry)\n\t}\n\n\tprivate add(entry: Omit<LoggedEvent, 'seq'>): LoggedEvent {\n\t\tconst logged = { seq: ++this.seq, ...entry }\n\t\tthis.list.push(logged)\n\t\tconst oldest = logged.tick - this.seconds * this.world!.tickRate\n\t\tlet drop = 0\n\t\twhile (drop < this.list.length && (this.list.length - drop > this.max || this.list[drop].tick < oldest)) drop++\n\t\tif (drop) this.list.splice(0, drop)\n\t\treturn logged\n\t}\n}\n"],"mappings":"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"}
|