@jgengine/core 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +214 -2
- package/README.md +2 -0
- package/dist/ai/crowd.d.ts +36 -0
- package/dist/ai/crowd.js +213 -0
- package/dist/ai/jobBoard.d.ts +49 -0
- package/dist/ai/jobBoard.js +155 -0
- package/dist/ai/spawnDirector.d.ts +61 -0
- package/dist/ai/spawnDirector.js +162 -0
- package/dist/ai/threat.d.ts +25 -0
- package/dist/ai/threat.js +67 -0
- package/dist/anim/easing.d.ts +14 -0
- package/dist/anim/easing.js +55 -0
- package/dist/audio/audioFalloff.d.ts +38 -0
- package/dist/audio/audioFalloff.js +32 -0
- package/dist/behaviour/behaviour.d.ts +136 -0
- package/dist/behaviour/behaviour.js +388 -0
- package/dist/board/laneBoard.d.ts +63 -0
- package/dist/board/laneBoard.js +114 -0
- package/dist/board/timelineBoard.d.ts +36 -0
- package/dist/board/timelineBoard.js +70 -0
- package/dist/cards/cardPile.d.ts +64 -0
- package/dist/cards/cardPile.js +175 -0
- package/dist/cards/modifierPipeline.d.ts +33 -0
- package/dist/cards/modifierPipeline.js +48 -0
- package/dist/combat/abilityKit.d.ts +47 -0
- package/dist/combat/abilityKit.js +139 -0
- package/dist/combat/animationState.d.ts +47 -0
- package/dist/combat/animationState.js +101 -0
- package/dist/combat/attackTags.d.ts +14 -0
- package/dist/combat/attackTags.js +26 -0
- package/dist/combat/breakMeters.d.ts +32 -0
- package/dist/combat/breakMeters.js +51 -0
- package/dist/combat/comboString.d.ts +35 -0
- package/dist/combat/comboString.js +59 -0
- package/dist/combat/death.d.ts +8 -0
- package/dist/combat/death.js +5 -2
- package/dist/combat/defensiveWindow.d.ts +34 -0
- package/dist/combat/defensiveWindow.js +66 -0
- package/dist/combat/downed.d.ts +35 -0
- package/dist/combat/downed.js +104 -0
- package/dist/combat/effects.d.ts +12 -1
- package/dist/combat/effects.js +31 -19
- package/dist/combat/hitReaction.d.ts +23 -0
- package/dist/combat/hitReaction.js +20 -0
- package/dist/combat/projectiles.d.ts +42 -5
- package/dist/combat/projectiles.js +98 -12
- package/dist/combat/resistance.d.ts +13 -0
- package/dist/combat/resistance.js +46 -0
- package/dist/combat/telegraph.d.ts +31 -0
- package/dist/combat/telegraph.js +51 -0
- package/dist/commands/commandRegistry.d.ts +1 -1
- package/dist/commands/commandRegistry.js +2 -1
- package/dist/crafting/crop.d.ts +59 -0
- package/dist/crafting/crop.js +181 -0
- package/dist/crafting/production.d.ts +64 -0
- package/dist/crafting/production.js +130 -0
- package/dist/crafting/recipe.d.ts +62 -0
- package/dist/crafting/recipe.js +101 -0
- package/dist/data/dataSource.d.ts +26 -0
- package/dist/data/dataSource.js +93 -0
- package/dist/data/devProxy.d.ts +11 -0
- package/dist/data/devProxy.js +38 -0
- package/dist/data/fetchJson.d.ts +20 -0
- package/dist/data/fetchJson.js +43 -0
- package/dist/data/jsonDataSource.d.ts +4 -0
- package/dist/data/jsonDataSource.js +6 -0
- package/dist/devtools/devtools.d.ts +157 -0
- package/dist/devtools/devtools.js +484 -0
- package/dist/devtools/transformTunables.d.ts +14 -0
- package/dist/devtools/transformTunables.js +38 -0
- package/dist/economy/sharedWallet.d.ts +28 -0
- package/dist/economy/sharedWallet.js +62 -0
- package/dist/economy/techTree.d.ts +40 -0
- package/dist/economy/techTree.js +66 -0
- package/dist/game/chat.d.ts +66 -0
- package/dist/game/chat.js +165 -0
- package/dist/game/cosmetics.d.ts +25 -0
- package/dist/game/cosmetics.js +51 -0
- package/dist/game/defineGame.d.ts +10 -2
- package/dist/game/defineGame.js +2 -1
- package/dist/game/events.d.ts +87 -0
- package/dist/game/levelSequence.d.ts +44 -0
- package/dist/game/levelSequence.js +78 -0
- package/dist/game/lootFilter.d.ts +33 -0
- package/dist/game/lootFilter.js +48 -0
- package/dist/game/ping.d.ts +67 -0
- package/dist/game/ping.js +86 -0
- package/dist/game/playableGame.d.ts +516 -8
- package/dist/game/playableGame.js +6 -1
- package/dist/game/progression.d.ts +1 -0
- package/dist/game/progression.js +23 -2
- package/dist/game/race.d.ts +100 -0
- package/dist/game/race.js +236 -0
- package/dist/game/runDraft.d.ts +34 -0
- package/dist/game/runDraft.js +97 -0
- package/dist/game/social.d.ts +69 -0
- package/dist/game/social.js +138 -0
- package/dist/game/spawnPoints.d.ts +19 -0
- package/dist/game/spawnPoints.js +23 -0
- package/dist/game/worldItem.d.ts +95 -0
- package/dist/game/worldItem.js +138 -0
- package/dist/input/actionBindings.d.ts +10 -0
- package/dist/input/actionBindings.js +14 -0
- package/dist/input/axisInput.d.ts +43 -0
- package/dist/input/axisInput.js +70 -0
- package/dist/input/gestureSurface.d.ts +31 -0
- package/dist/input/gestureSurface.js +120 -0
- package/dist/input/pointer.d.ts +69 -0
- package/dist/input/pointer.js +65 -0
- package/dist/input/touchScheme.d.ts +83 -0
- package/dist/input/touchScheme.js +115 -0
- package/dist/interaction/contextMenu.d.ts +30 -0
- package/dist/interaction/contextMenu.js +22 -0
- package/dist/interaction/qte.d.ts +20 -0
- package/dist/interaction/qte.js +24 -0
- package/dist/interaction/skillCheck.d.ts +20 -0
- package/dist/interaction/skillCheck.js +26 -0
- package/dist/inventory/shapedGrid.d.ts +56 -0
- package/dist/inventory/shapedGrid.js +176 -0
- package/dist/inventory/storageTier.d.ts +52 -0
- package/dist/inventory/storageTier.js +77 -0
- package/dist/item/affix.d.ts +54 -0
- package/dist/item/affix.js +115 -0
- package/dist/item/durability.d.ts +51 -0
- package/dist/item/durability.js +78 -0
- package/dist/item/modularItem.d.ts +46 -0
- package/dist/item/modularItem.js +75 -0
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +71 -1
- package/dist/movement/dash.d.ts +37 -0
- package/dist/movement/dash.js +65 -0
- package/dist/movement/movementModel.d.ts +36 -3
- package/dist/movement/movementModel.js +81 -5
- package/dist/movement/voxelController.d.ts +61 -0
- package/dist/movement/voxelController.js +229 -0
- package/dist/multiplayer/chatContract.d.ts +42 -0
- package/dist/multiplayer/chatContract.js +57 -0
- package/dist/multiplayer/combatSnapshot.d.ts +45 -0
- package/dist/multiplayer/combatSnapshot.js +89 -0
- package/dist/multiplayer/identity.d.ts +13 -0
- package/dist/multiplayer/identity.js +20 -0
- package/dist/multiplayer/lagCompensation.d.ts +43 -0
- package/dist/multiplayer/lagCompensation.js +154 -0
- package/dist/multiplayer/matchmaking.d.ts +33 -0
- package/dist/multiplayer/matchmaking.js +60 -0
- package/dist/multiplayer/poseSyncGate.d.ts +1 -0
- package/dist/multiplayer/poseSyncGate.js +13 -1
- package/dist/multiplayer/presenceModel.d.ts +3 -0
- package/dist/multiplayer/presenceModel.js +15 -1
- package/dist/multiplayer/simultaneousCommit.d.ts +34 -0
- package/dist/multiplayer/simultaneousCommit.js +53 -0
- package/dist/multiplayer/voiceContract.d.ts +44 -0
- package/dist/multiplayer/voiceContract.js +108 -0
- package/dist/nav/navConstrain.d.ts +14 -0
- package/dist/nav/navConstrain.js +26 -0
- package/dist/nav/navFromEnvironment.d.ts +11 -0
- package/dist/nav/navFromEnvironment.js +16 -0
- package/dist/nav/navGrid.d.ts +56 -0
- package/dist/nav/navGrid.js +265 -0
- package/dist/nav/pathFollow.d.ts +31 -0
- package/dist/nav/pathFollow.js +69 -0
- package/dist/physics/ballisticSweep.d.ts +18 -0
- package/dist/physics/ballisticSweep.js +49 -0
- package/dist/physics/buoyancy.d.ts +49 -0
- package/dist/physics/buoyancy.js +112 -0
- package/dist/physics/carryable.d.ts +46 -0
- package/dist/physics/carryable.js +110 -0
- package/dist/physics/damageZones.d.ts +56 -0
- package/dist/physics/damageZones.js +107 -0
- package/dist/physics/forceVolume.d.ts +48 -0
- package/dist/physics/forceVolume.js +119 -0
- package/dist/physics/physicsWorld.d.ts +124 -2
- package/dist/physics/physicsWorld.js +493 -41
- package/dist/physics/ragdoll.d.ts +49 -0
- package/dist/physics/ragdoll.js +103 -0
- package/dist/physics/spatialGrid.d.ts +41 -0
- package/dist/physics/spatialGrid.js +143 -0
- package/dist/physics/structure.d.ts +83 -0
- package/dist/physics/structure.js +0 -0
- package/dist/physics/traversal.d.ts +75 -0
- package/dist/physics/traversal.js +138 -0
- package/dist/physics/vehicleBody.d.ts +99 -0
- package/dist/physics/vehicleBody.js +233 -0
- package/dist/puzzle/cellGrid.d.ts +26 -0
- package/dist/puzzle/cellGrid.js +110 -0
- package/dist/puzzle/fallingPiece.d.ts +24 -0
- package/dist/puzzle/fallingPiece.js +51 -0
- package/dist/random/nameGen.d.ts +18 -0
- package/dist/random/nameGen.js +35 -0
- package/dist/random/rng.d.ts +2 -0
- package/dist/random/rng.js +23 -0
- package/dist/runtime/adapter.d.ts +35 -0
- package/dist/runtime/adapter.js +37 -1
- package/dist/runtime/cameraDirector.d.ts +10 -0
- package/dist/runtime/cameraDirector.js +25 -0
- package/dist/runtime/gameContext.d.ts +107 -3
- package/dist/runtime/gameContext.js +253 -7
- package/dist/runtime/hostPersistence.d.ts +39 -0
- package/dist/runtime/hostPersistence.js +54 -0
- package/dist/runtime/inputSnapshot.d.ts +7 -0
- package/dist/runtime/inputSnapshot.js +12 -0
- package/dist/runtime/motionIntents.d.ts +25 -0
- package/dist/runtime/motionIntents.js +25 -0
- package/dist/runtime/persistenceScope.d.ts +32 -0
- package/dist/runtime/persistenceScope.js +64 -0
- package/dist/runtime/transport.d.ts +32 -0
- package/dist/scene/autoTarget.d.ts +15 -0
- package/dist/scene/autoTarget.js +54 -0
- package/dist/scene/behaviors.d.ts +13 -1
- package/dist/scene/behaviors.js +3 -0
- package/dist/scene/captureCheck.d.ts +7 -0
- package/dist/scene/captureCheck.js +11 -0
- package/dist/scene/entityStore.d.ts +9 -1
- package/dist/scene/entityStore.js +25 -2
- package/dist/scene/form.d.ts +40 -0
- package/dist/scene/form.js +56 -0
- package/dist/scene/mount.d.ts +62 -0
- package/dist/scene/mount.js +107 -0
- package/dist/scene/movementSpeed.d.ts +35 -0
- package/dist/scene/movementSpeed.js +20 -0
- package/dist/scene/objectQuery.d.ts +18 -0
- package/dist/scene/objectQuery.js +108 -0
- package/dist/scene/objectStore.d.ts +11 -0
- package/dist/scene/objectStore.js +109 -4
- package/dist/scene/paintLayer.d.ts +15 -0
- package/dist/scene/paintLayer.js +53 -0
- package/dist/scene/possession.d.ts +30 -0
- package/dist/scene/possession.js +51 -0
- package/dist/scene/roster.d.ts +25 -0
- package/dist/scene/roster.js +57 -0
- package/dist/scene/selection.d.ts +30 -0
- package/dist/scene/selection.js +38 -0
- package/dist/scene/spatial.d.ts +21 -0
- package/dist/scene/spatial.js +63 -1
- package/dist/scene/stationClaim.d.ts +43 -0
- package/dist/scene/stationClaim.js +109 -0
- package/dist/sensor/concealment.d.ts +21 -0
- package/dist/sensor/concealment.js +63 -0
- package/dist/sensor/freezeMonitor.d.ts +17 -0
- package/dist/sensor/freezeMonitor.js +35 -0
- package/dist/sensor/frustumSensor.d.ts +60 -0
- package/dist/sensor/frustumSensor.js +104 -0
- package/dist/sensor/hiddenStateProbe.d.ts +31 -0
- package/dist/sensor/hiddenStateProbe.js +40 -0
- package/dist/sensor/recordingBuffer.d.ts +29 -0
- package/dist/sensor/recordingBuffer.js +61 -0
- package/dist/sensor/revealQuery.d.ts +22 -0
- package/dist/sensor/revealQuery.js +36 -0
- package/dist/session/contestedChannel.d.ts +36 -0
- package/dist/session/contestedChannel.js +100 -0
- package/dist/session/extraction.d.ts +54 -0
- package/dist/session/extraction.js +108 -0
- package/dist/session/ring.d.ts +36 -0
- package/dist/session/ring.js +88 -0
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +32 -0
- package/dist/session/roundState.d.ts +79 -0
- package/dist/session/roundState.js +158 -0
- package/dist/stats/accumulatorMeter.d.ts +31 -0
- package/dist/stats/accumulatorMeter.js +81 -0
- package/dist/stats/eventMeter.d.ts +34 -0
- package/dist/stats/eventMeter.js +76 -0
- package/dist/stats/rollCheck.d.ts +15 -0
- package/dist/stats/rollCheck.js +15 -0
- package/dist/survival/decayMeter.d.ts +59 -0
- package/dist/survival/decayMeter.js +95 -0
- package/dist/survival/moodle.d.ts +48 -0
- package/dist/survival/moodle.js +91 -0
- package/dist/survival/regionHealth.d.ts +72 -0
- package/dist/survival/regionHealth.js +129 -0
- package/dist/tactics/fallingGrid.d.ts +62 -0
- package/dist/tactics/fallingGrid.js +158 -0
- package/dist/tactics/predictiveQuery.d.ts +34 -0
- package/dist/tactics/predictiveQuery.js +44 -0
- package/dist/tactics/snapshot.d.ts +18 -0
- package/dist/tactics/snapshot.js +65 -0
- package/dist/tactics/surface.d.ts +52 -0
- package/dist/tactics/surface.js +135 -0
- package/dist/tactics/tacticalGrid.d.ts +68 -0
- package/dist/tactics/tacticalGrid.js +261 -0
- package/dist/time/beatClock.d.ts +40 -0
- package/dist/time/beatClock.js +73 -0
- package/dist/time/simClock.d.ts +25 -1
- package/dist/time/simClock.js +28 -3
- package/dist/turn/commit.d.ts +27 -0
- package/dist/turn/commit.js +72 -0
- package/dist/turn/intent.d.ts +14 -0
- package/dist/turn/intent.js +29 -0
- package/dist/turn/turnLoop.d.ts +60 -0
- package/dist/turn/turnLoop.js +223 -0
- package/dist/world/buildPermissions.d.ts +47 -0
- package/dist/world/buildPermissions.js +134 -0
- package/dist/world/carve.d.ts +105 -0
- package/dist/world/carve.js +175 -0
- package/dist/world/connectors.d.ts +40 -0
- package/dist/world/connectors.js +67 -0
- package/dist/world/envField.d.ts +71 -0
- package/dist/world/envField.js +96 -0
- package/dist/world/environmentSummary.d.ts +53 -0
- package/dist/world/environmentSummary.js +129 -0
- package/dist/world/features.d.ts +87 -6
- package/dist/world/features.js +52 -2
- package/dist/world/fog.d.ts +40 -0
- package/dist/world/fog.js +137 -0
- package/dist/world/gridInstances.d.ts +13 -0
- package/dist/world/gridInstances.js +22 -0
- package/dist/world/markers.d.ts +52 -0
- package/dist/world/markers.js +96 -0
- package/dist/world/minimap.d.ts +42 -0
- package/dist/world/minimap.js +72 -0
- package/dist/world/placedStructureStore.d.ts +39 -0
- package/dist/world/placedStructureStore.js +95 -0
- package/dist/world/placementController.d.ts +69 -0
- package/dist/world/placementController.js +153 -0
- package/dist/world/realm.d.ts +61 -0
- package/dist/world/realm.js +66 -0
- package/dist/world/support.d.ts +27 -0
- package/dist/world/support.js +75 -0
- package/dist/world/terraform.d.ts +54 -0
- package/dist/world/terraform.js +186 -0
- package/dist/world/terrain.d.ts +23 -1
- package/dist/world/terrain.js +64 -1
- package/dist/world/voxelField.d.ts +54 -0
- package/dist/world/voxelField.js +241 -0
- package/dist/world/walls.d.ts +61 -0
- package/dist/world/walls.js +221 -0
- package/dist/world/weather.d.ts +92 -0
- package/dist/world/weather.js +169 -0
- package/llms.txt +4102 -0
- package/package.json +3 -2
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface LootFilterItem {
|
|
2
|
+
rarity: string;
|
|
3
|
+
baseType: string;
|
|
4
|
+
affixTier?: number;
|
|
5
|
+
}
|
|
6
|
+
export interface LootFilterCondition {
|
|
7
|
+
rarity?: string | readonly string[];
|
|
8
|
+
baseType?: string | readonly string[];
|
|
9
|
+
minAffixTier?: number;
|
|
10
|
+
maxAffixTier?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface LootFilterRule {
|
|
13
|
+
id: string;
|
|
14
|
+
when: LootFilterCondition;
|
|
15
|
+
hide?: boolean;
|
|
16
|
+
color?: string;
|
|
17
|
+
beam?: boolean;
|
|
18
|
+
label?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface LootFilterOverride {
|
|
21
|
+
hidden?: boolean;
|
|
22
|
+
color?: string;
|
|
23
|
+
beam?: boolean;
|
|
24
|
+
label?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* First matching rule wins (PoE/Last Epoch block semantics) — later rules
|
|
28
|
+
* never override an earlier match. Returns overrides only; fields the rule
|
|
29
|
+
* doesn't set are left for the caller's baseline (rarity style) to fill in.
|
|
30
|
+
*/
|
|
31
|
+
export declare function evaluateLootFilter(rules: readonly LootFilterRule[], item: LootFilterItem): LootFilterOverride;
|
|
32
|
+
/** Validating factory — rule ids must be unique so authoring mistakes fail loudly. */
|
|
33
|
+
export declare function lootFilter(rules: readonly LootFilterRule[]): readonly LootFilterRule[];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
function matchesOneOf(value, expected) {
|
|
2
|
+
if (expected === undefined)
|
|
3
|
+
return true;
|
|
4
|
+
return typeof expected === "string" ? expected === value : expected.includes(value);
|
|
5
|
+
}
|
|
6
|
+
function matchesCondition(when, item) {
|
|
7
|
+
if (!matchesOneOf(item.rarity, when.rarity))
|
|
8
|
+
return false;
|
|
9
|
+
if (!matchesOneOf(item.baseType, when.baseType))
|
|
10
|
+
return false;
|
|
11
|
+
if (when.minAffixTier !== undefined && (item.affixTier ?? 0) < when.minAffixTier)
|
|
12
|
+
return false;
|
|
13
|
+
if (when.maxAffixTier !== undefined && (item.affixTier ?? 0) > when.maxAffixTier)
|
|
14
|
+
return false;
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* First matching rule wins (PoE/Last Epoch block semantics) — later rules
|
|
19
|
+
* never override an earlier match. Returns overrides only; fields the rule
|
|
20
|
+
* doesn't set are left for the caller's baseline (rarity style) to fill in.
|
|
21
|
+
*/
|
|
22
|
+
export function evaluateLootFilter(rules, item) {
|
|
23
|
+
for (const rule of rules) {
|
|
24
|
+
if (!matchesCondition(rule.when, item))
|
|
25
|
+
continue;
|
|
26
|
+
const override = {};
|
|
27
|
+
if (rule.hide !== undefined)
|
|
28
|
+
override.hidden = rule.hide;
|
|
29
|
+
if (rule.color !== undefined)
|
|
30
|
+
override.color = rule.color;
|
|
31
|
+
if (rule.beam !== undefined)
|
|
32
|
+
override.beam = rule.beam;
|
|
33
|
+
if (rule.label !== undefined)
|
|
34
|
+
override.label = rule.label;
|
|
35
|
+
return override;
|
|
36
|
+
}
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
/** Validating factory — rule ids must be unique so authoring mistakes fail loudly. */
|
|
40
|
+
export function lootFilter(rules) {
|
|
41
|
+
const seen = new Set();
|
|
42
|
+
for (const rule of rules) {
|
|
43
|
+
if (seen.has(rule.id))
|
|
44
|
+
throw new Error(`loot filter rule id "${rule.id}" is duplicated`);
|
|
45
|
+
seen.add(rule.id);
|
|
46
|
+
}
|
|
47
|
+
return rules;
|
|
48
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { PointerHit } from "../input/pointer.js";
|
|
2
|
+
import type { MapMarker, MarkerPosition, MarkerSet } from "../world/markers.js";
|
|
3
|
+
export type PingCategory = string;
|
|
4
|
+
export interface PingCategoryDef {
|
|
5
|
+
id: PingCategory;
|
|
6
|
+
markerKind: string;
|
|
7
|
+
label: string;
|
|
8
|
+
callout: string;
|
|
9
|
+
}
|
|
10
|
+
/** Content-agnostic default ping wheel: enemy / loot / location / danger. */
|
|
11
|
+
export declare const DEFAULT_PING_CATEGORIES: Record<PingCategory, PingCategoryDef>;
|
|
12
|
+
export declare const PING_FEED_ACTION = "party.ping";
|
|
13
|
+
export interface PingClassifyDeps {
|
|
14
|
+
roleOf?(entityId: string): string | null | undefined;
|
|
15
|
+
categoryOf?(objectId: string): PingCategory | null | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface PingClassifyOptions {
|
|
18
|
+
hostileRoles?: readonly string[];
|
|
19
|
+
enemyCategory?: PingCategory;
|
|
20
|
+
lootCategory?: PingCategory;
|
|
21
|
+
locationCategory?: PingCategory;
|
|
22
|
+
dangerCategory?: PingCategory;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Classify what a pointer/aim ray hit into a ping category. Entity hits resolve
|
|
26
|
+
* by catalog role (hostile → enemy, else location); object hits by an
|
|
27
|
+
* optional catalog category tag; open ground is a location ping.
|
|
28
|
+
*/
|
|
29
|
+
export declare function classifyPing(hit: PointerHit, deps?: PingClassifyDeps, options?: PingClassifyOptions): PingCategory;
|
|
30
|
+
export interface PingPayload {
|
|
31
|
+
id: string;
|
|
32
|
+
from: string;
|
|
33
|
+
category: PingCategory;
|
|
34
|
+
position: MarkerPosition;
|
|
35
|
+
entityId: string | null;
|
|
36
|
+
objectId: string | null;
|
|
37
|
+
at: number;
|
|
38
|
+
callout: string;
|
|
39
|
+
/** Party members the broadcast targets; empty when solo or party unconfigured. */
|
|
40
|
+
recipients: readonly string[];
|
|
41
|
+
}
|
|
42
|
+
export interface PingFeedSink {
|
|
43
|
+
push(action: string, entry: unknown): void;
|
|
44
|
+
}
|
|
45
|
+
export interface PingParty {
|
|
46
|
+
membersOf(userId: string): string[];
|
|
47
|
+
}
|
|
48
|
+
export interface PingSystemDeps {
|
|
49
|
+
markers: MarkerSet;
|
|
50
|
+
feed: PingFeedSink;
|
|
51
|
+
party?: PingParty;
|
|
52
|
+
categories?: Record<PingCategory, PingCategoryDef>;
|
|
53
|
+
now?(): number;
|
|
54
|
+
/** Marker lifetime in ms; omit for permanent markers. */
|
|
55
|
+
ttlMs?: number;
|
|
56
|
+
feedAction?: string;
|
|
57
|
+
classify?: PingClassifyDeps;
|
|
58
|
+
classifyOptions?: PingClassifyOptions;
|
|
59
|
+
}
|
|
60
|
+
export interface PingSystem {
|
|
61
|
+
classify(hit: PointerHit): PingCategory;
|
|
62
|
+
buildPayload(from: string, hit: PointerHit, category?: PingCategory): PingPayload;
|
|
63
|
+
broadcast(payload: PingPayload): MapMarker;
|
|
64
|
+
/** Classify → build → broadcast in one call; the ping verb. */
|
|
65
|
+
ping(from: string, hit: PointerHit, category?: PingCategory): PingPayload;
|
|
66
|
+
}
|
|
67
|
+
export declare function createPingSystem(deps: PingSystemDeps): PingSystem;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/** Content-agnostic default ping wheel: enemy / loot / location / danger. */
|
|
2
|
+
export const DEFAULT_PING_CATEGORIES = {
|
|
3
|
+
enemy: { id: "enemy", markerKind: "enemy", label: "Enemy", callout: "Enemy spotted" },
|
|
4
|
+
loot: { id: "loot", markerKind: "loot", label: "Loot", callout: "Loot here" },
|
|
5
|
+
location: { id: "location", markerKind: "location", label: "Location", callout: "Going here" },
|
|
6
|
+
danger: { id: "danger", markerKind: "danger", label: "Danger", callout: "Watch out" },
|
|
7
|
+
};
|
|
8
|
+
export const PING_FEED_ACTION = "party.ping";
|
|
9
|
+
const DEFAULT_HOSTILE_ROLES = ["enemy", "hostile"];
|
|
10
|
+
/**
|
|
11
|
+
* Classify what a pointer/aim ray hit into a ping category. Entity hits resolve
|
|
12
|
+
* by catalog role (hostile → enemy, else location); object hits by an
|
|
13
|
+
* optional catalog category tag; open ground is a location ping.
|
|
14
|
+
*/
|
|
15
|
+
export function classifyPing(hit, deps = {}, options = {}) {
|
|
16
|
+
const hostileRoles = options.hostileRoles ?? DEFAULT_HOSTILE_ROLES;
|
|
17
|
+
const enemyCategory = options.enemyCategory ?? "enemy";
|
|
18
|
+
const locationCategory = options.locationCategory ?? "location";
|
|
19
|
+
if (hit.entity !== null) {
|
|
20
|
+
const role = deps.roleOf?.(hit.entity);
|
|
21
|
+
if (role !== null && role !== undefined && hostileRoles.includes(role))
|
|
22
|
+
return enemyCategory;
|
|
23
|
+
return locationCategory;
|
|
24
|
+
}
|
|
25
|
+
if (hit.object !== null) {
|
|
26
|
+
const category = deps.categoryOf?.(hit.object);
|
|
27
|
+
if (category !== null && category !== undefined)
|
|
28
|
+
return category;
|
|
29
|
+
return locationCategory;
|
|
30
|
+
}
|
|
31
|
+
return locationCategory;
|
|
32
|
+
}
|
|
33
|
+
function categoryDef(categories, category) {
|
|
34
|
+
return categories[category] ?? { id: category, markerKind: category, label: category, callout: category };
|
|
35
|
+
}
|
|
36
|
+
export function createPingSystem(deps) {
|
|
37
|
+
const now = deps.now ?? Date.now;
|
|
38
|
+
const categories = deps.categories ?? DEFAULT_PING_CATEGORIES;
|
|
39
|
+
const feedAction = deps.feedAction ?? PING_FEED_ACTION;
|
|
40
|
+
let counter = 0;
|
|
41
|
+
const system = {
|
|
42
|
+
classify(hit) {
|
|
43
|
+
return classifyPing(hit, deps.classify, deps.classifyOptions);
|
|
44
|
+
},
|
|
45
|
+
buildPayload(from, hit, category) {
|
|
46
|
+
const resolved = category ?? system.classify(hit);
|
|
47
|
+
const at = now();
|
|
48
|
+
counter += 1;
|
|
49
|
+
const def = categoryDef(categories, resolved);
|
|
50
|
+
const recipients = deps.party?.membersOf(from).filter((member) => member !== from) ?? [];
|
|
51
|
+
return {
|
|
52
|
+
id: `ping-${from}-${counter}`,
|
|
53
|
+
from,
|
|
54
|
+
category: resolved,
|
|
55
|
+
position: hit.point,
|
|
56
|
+
entityId: hit.entity,
|
|
57
|
+
objectId: hit.object,
|
|
58
|
+
at,
|
|
59
|
+
callout: def.callout,
|
|
60
|
+
recipients,
|
|
61
|
+
};
|
|
62
|
+
},
|
|
63
|
+
broadcast(payload) {
|
|
64
|
+
const def = categoryDef(categories, payload.category);
|
|
65
|
+
const markerInput = {
|
|
66
|
+
id: payload.id,
|
|
67
|
+
kind: def.markerKind,
|
|
68
|
+
position: payload.position,
|
|
69
|
+
label: def.label,
|
|
70
|
+
owner: payload.from,
|
|
71
|
+
createdAt: payload.at,
|
|
72
|
+
...(deps.ttlMs !== undefined ? { expiresAt: payload.at + deps.ttlMs } : {}),
|
|
73
|
+
meta: { ping: true, category: payload.category, callout: payload.callout },
|
|
74
|
+
};
|
|
75
|
+
deps.markers.add(markerInput);
|
|
76
|
+
deps.feed.push(feedAction, payload);
|
|
77
|
+
return deps.markers.get(payload.id);
|
|
78
|
+
},
|
|
79
|
+
ping(from, hit, category) {
|
|
80
|
+
const payload = system.buildPayload(from, hit, category);
|
|
81
|
+
system.broadcast(payload);
|
|
82
|
+
return payload;
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
return system;
|
|
86
|
+
}
|