@jgengine/core 0.7.0 → 0.9.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 +63 -0
- package/README.md +2 -0
- package/dist/ai/flock.d.ts +36 -0
- package/dist/ai/flock.js +182 -0
- package/dist/ai/groupAssist.d.ts +19 -0
- package/dist/ai/groupAssist.js +59 -0
- package/dist/ai/laneSelect.d.ts +21 -0
- package/dist/ai/laneSelect.js +37 -0
- package/dist/ai/mobBrain.d.ts +68 -0
- package/dist/ai/mobBrain.js +115 -0
- package/dist/ai/spawnDirector.d.ts +5 -0
- package/dist/ai/spawnDirector.js +14 -2
- package/dist/ai/threat.d.ts +2 -0
- package/dist/ai/threat.js +34 -0
- package/dist/anim/easing.d.ts +14 -0
- package/dist/anim/easing.js +55 -0
- package/dist/behaviour/behaviour.d.ts +136 -0
- package/dist/behaviour/behaviour.js +388 -0
- package/dist/cards/cardPile.d.ts +1 -0
- package/dist/cards/cardPile.js +12 -3
- package/dist/cartridge/runtime.d.ts +15 -0
- package/dist/cartridge/runtime.js +556 -0
- package/dist/cartridge/spec.d.ts +188 -0
- package/dist/cartridge/spec.js +19 -0
- package/dist/cartridge/validate.d.ts +2 -0
- package/dist/cartridge/validate.js +78 -0
- package/dist/combat/abilityKit.d.ts +22 -2
- package/dist/combat/abilityKit.js +72 -13
- package/dist/combat/castRunner.d.ts +40 -0
- package/dist/combat/castRunner.js +56 -0
- package/dist/combat/comboPoints.d.ts +14 -0
- package/dist/combat/comboPoints.js +52 -0
- package/dist/combat/defensiveWindow.d.ts +1 -1
- package/dist/combat/defensiveWindow.js +5 -3
- package/dist/combat/effects.d.ts +1 -1
- package/dist/combat/effects.js +9 -6
- package/dist/combat/projectiles.d.ts +64 -6
- package/dist/combat/projectiles.js +232 -74
- package/dist/combat/resistance.d.ts +16 -4
- package/dist/combat/resistance.js +43 -7
- package/dist/combat/resourcePool.d.ts +20 -0
- package/dist/combat/resourcePool.js +55 -0
- package/dist/combat/shotOrigin.d.ts +40 -0
- package/dist/combat/shotOrigin.js +57 -0
- package/dist/combat/telegraph.d.ts +30 -1
- package/dist/combat/telegraph.js +61 -0
- package/dist/commands/commandRegistry.d.ts +1 -1
- package/dist/commands/commandRegistry.js +2 -1
- package/dist/crafting/recipe.js +4 -1
- 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 +205 -0
- package/dist/devtools/devtools.js +832 -0
- package/dist/devtools/transformTunables.d.ts +14 -0
- package/dist/devtools/transformTunables.js +38 -0
- package/dist/devtools/tunableSchema.d.ts +140 -0
- package/dist/devtools/tunableSchema.js +476 -0
- package/dist/faction/factions.d.ts +33 -0
- package/dist/faction/factions.js +76 -0
- package/dist/faction/reputation.d.ts +32 -0
- package/dist/faction/reputation.js +82 -0
- package/dist/game/chat.d.ts +68 -0
- package/dist/game/chat.js +173 -0
- package/dist/game/chatFilter.d.ts +15 -0
- package/dist/game/chatFilter.js +55 -0
- package/dist/game/controlGate.d.ts +4 -0
- package/dist/game/controlGate.js +7 -0
- package/dist/game/defineGame.d.ts +10 -2
- package/dist/game/defineGame.js +2 -1
- package/dist/game/events.d.ts +35 -0
- package/dist/game/gamePhase.d.ts +20 -0
- package/dist/game/gamePhase.js +21 -0
- package/dist/game/levelSequence.d.ts +44 -0
- package/dist/game/levelSequence.js +78 -0
- package/dist/game/lootTable.d.ts +10 -1
- package/dist/game/lootTable.js +27 -7
- package/dist/game/playableGame.d.ts +286 -6
- 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/quest.d.ts +7 -3
- package/dist/game/quest.js +17 -8
- package/dist/game/race.d.ts +44 -1
- package/dist/game/race.js +116 -11
- package/dist/game/recordBook.d.ts +29 -0
- package/dist/game/recordBook.js +86 -0
- package/dist/game/social.d.ts +42 -0
- package/dist/game/social.js +122 -0
- package/dist/game/spawnPoints.d.ts +19 -0
- package/dist/game/spawnPoints.js +23 -0
- package/dist/game/talents.d.ts +47 -0
- package/dist/game/talents.js +140 -0
- package/dist/game/worldItem.d.ts +3 -0
- package/dist/game/worldItem.js +12 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/input/actionBindings.d.ts +10 -0
- package/dist/input/actionBindings.js +14 -0
- package/dist/input/axisInput.d.ts +26 -3
- package/dist/input/axisInput.js +44 -4
- package/dist/input/bindingOverrides.d.ts +25 -0
- package/dist/input/bindingOverrides.js +95 -0
- package/dist/input/gestureSurface.d.ts +31 -0
- package/dist/input/gestureSurface.js +120 -0
- package/dist/input/pointer.d.ts +45 -0
- package/dist/input/pointer.js +48 -0
- package/dist/input/pointerAxis.d.ts +30 -0
- package/dist/input/pointerAxis.js +31 -0
- package/dist/input/touchScheme.d.ts +89 -0
- package/dist/input/touchScheme.js +153 -0
- package/dist/item/affix.d.ts +1 -1
- package/dist/item/affix.js +1 -19
- package/dist/meta/changelog.d.ts +1 -1
- package/dist/meta/changelog.js +59 -1
- package/dist/movement/dash.d.ts +3 -0
- package/dist/movement/dash.js +19 -5
- package/dist/movement/glideModel.d.ts +44 -0
- package/dist/movement/glideModel.js +54 -0
- package/dist/movement/grappleSwing.d.ts +34 -0
- package/dist/movement/grappleSwing.js +56 -0
- package/dist/movement/leaderTrail.d.ts +29 -0
- package/dist/movement/leaderTrail.js +67 -0
- package/dist/movement/movementModel.d.ts +36 -3
- package/dist/movement/movementModel.js +81 -5
- package/dist/movement/steering.d.ts +27 -0
- package/dist/movement/steering.js +40 -0
- 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/feedWriteGate.d.ts +10 -0
- package/dist/multiplayer/feedWriteGate.js +12 -0
- package/dist/multiplayer/identity.d.ts +13 -0
- package/dist/multiplayer/identity.js +20 -0
- package/dist/multiplayer/poseSyncGate.d.ts +1 -0
- package/dist/multiplayer/poseSyncGate.js +13 -1
- package/dist/multiplayer/presenceModel.d.ts +17 -2
- package/dist/multiplayer/presenceModel.js +30 -4
- package/dist/multiplayer/voiceContract.d.ts +44 -0
- package/dist/multiplayer/voiceContract.js +108 -0
- package/dist/nav/corridors.d.ts +30 -0
- package/dist/nav/corridors.js +69 -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 +10 -0
- package/dist/nav/navGrid.js +48 -5
- package/dist/nav/pathFollow.d.ts +4 -2
- package/dist/nav/pathFollow.js +5 -3
- package/dist/nav/railGraph.d.ts +66 -0
- package/dist/nav/railGraph.js +129 -0
- package/dist/nav/timetable.d.ts +41 -0
- package/dist/nav/timetable.js +94 -0
- package/dist/physics/ballisticSweep.d.ts +18 -0
- package/dist/physics/ballisticSweep.js +49 -0
- package/dist/physics/buoyancy.d.ts +6 -0
- package/dist/physics/buoyancy.js +14 -0
- package/dist/physics/flowTube.d.ts +32 -0
- package/dist/physics/flowTube.js +64 -0
- package/dist/physics/forceVolume.d.ts +27 -0
- package/dist/physics/forceVolume.js +43 -5
- package/dist/physics/kinematicVehicle.d.ts +52 -0
- package/dist/physics/kinematicVehicle.js +81 -0
- package/dist/physics/physicsWorld.d.ts +54 -8
- package/dist/physics/physicsWorld.js +400 -79
- package/dist/physics/ragdoll.js +1 -1
- package/dist/physics/spatialGrid.d.ts +1 -1
- package/dist/physics/spatialGrid.js +5 -0
- package/dist/physics/vehicleBody.d.ts +6 -0
- package/dist/physics/vehicleBody.js +18 -18
- 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/random/seedLink.d.ts +5 -0
- package/dist/random/seedLink.js +35 -0
- package/dist/runtime/adapter.d.ts +35 -0
- package/dist/runtime/adapter.js +37 -1
- package/dist/runtime/cameraDirector.d.ts +15 -0
- package/dist/runtime/cameraDirector.js +31 -0
- package/dist/runtime/commandRunner.d.ts +2 -2
- package/dist/runtime/commandRunner.js +2 -2
- package/dist/runtime/gameContext.d.ts +65 -2
- package/dist/runtime/gameContext.js +280 -9
- package/dist/runtime/gameRuntime.d.ts +5 -1
- package/dist/runtime/gameRuntime.js +13 -12
- package/dist/runtime/hostPersistence.d.ts +30 -1
- package/dist/runtime/hostPersistence.js +70 -5
- package/dist/runtime/inputSnapshot.d.ts +12 -0
- package/dist/runtime/inputSnapshot.js +17 -0
- package/dist/runtime/motionIntents.d.ts +33 -0
- package/dist/runtime/motionIntents.js +43 -0
- package/dist/runtime/snapshot.d.ts +1 -0
- package/dist/runtime/snapshot.js +1 -1
- package/dist/runtime/transport.d.ts +32 -0
- package/dist/runtime/visibility.d.ts +74 -0
- package/dist/runtime/visibility.js +127 -0
- package/dist/scene/colliders.d.ts +44 -0
- package/dist/scene/colliders.js +77 -0
- package/dist/scene/entityStore.d.ts +30 -5
- package/dist/scene/entityStore.js +83 -13
- package/dist/scene/movementSpeed.d.ts +35 -0
- package/dist/scene/movementSpeed.js +20 -0
- package/dist/scene/objectQuery.d.ts +29 -0
- package/dist/scene/objectQuery.js +140 -0
- package/dist/scene/objectStore.d.ts +13 -0
- package/dist/scene/objectStore.js +130 -6
- package/dist/scene/paintLayer.d.ts +15 -0
- package/dist/scene/paintLayer.js +53 -0
- package/dist/scene/sceneRaycast.d.ts +80 -0
- package/dist/scene/sceneRaycast.js +284 -0
- package/dist/scene/spatial.d.ts +17 -1
- package/dist/scene/spatial.js +140 -17
- 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/recordingBuffer.d.ts +6 -0
- package/dist/sensor/recordingBuffer.js +7 -0
- package/dist/sensor/replayLoop.d.ts +39 -0
- package/dist/sensor/replayLoop.js +64 -0
- package/dist/sensor/visionCone.d.ts +31 -0
- package/dist/sensor/visionCone.js +72 -0
- package/dist/session/extraction.d.ts +2 -2
- package/dist/session/extraction.js +13 -2
- package/dist/session/roles.d.ts +6 -0
- package/dist/session/roles.js +32 -0
- package/dist/session/roundState.d.ts +41 -17
- package/dist/session/roundState.js +67 -38
- package/dist/settings/settingsModel.d.ts +97 -0
- package/dist/settings/settingsModel.js +100 -0
- package/dist/stats/statModifiers.d.ts +5 -2
- package/dist/stats/statModifiers.js +32 -14
- package/dist/store/observableKeyedStore.js +8 -2
- package/dist/survival/decayMeter.d.ts +1 -1
- package/dist/survival/decayMeter.js +0 -1
- package/dist/tactics/fallingGrid.d.ts +62 -0
- package/dist/tactics/fallingGrid.js +158 -0
- package/dist/tactics/tacticalGrid.d.ts +11 -0
- package/dist/tactics/tacticalGrid.js +17 -0
- package/dist/time/beatClock.d.ts +18 -0
- package/dist/time/beatClock.js +24 -0
- package/dist/time/idleProgress.d.ts +29 -0
- package/dist/time/idleProgress.js +31 -0
- package/dist/time/serverTick.d.ts +7 -1
- package/dist/time/serverTick.js +27 -4
- package/dist/time/simClock.d.ts +25 -1
- package/dist/time/simClock.js +28 -3
- package/dist/time/stateSchedule.d.ts +57 -0
- package/dist/time/stateSchedule.js +121 -0
- package/dist/turn/commit.d.ts +2 -2
- package/dist/turn/commit.js +2 -2
- package/dist/turn/intent.d.ts +14 -0
- package/dist/turn/intent.js +29 -0
- package/dist/turn/turnLoop.d.ts +2 -0
- package/dist/turn/turnLoop.js +8 -1
- package/dist/ui/hudLayout.d.ts +58 -0
- package/dist/ui/hudLayout.js +207 -0
- package/dist/ui/hudScale.d.ts +44 -0
- package/dist/ui/hudScale.js +55 -0
- package/dist/visibility/assetStreaming.d.ts +66 -0
- package/dist/visibility/assetStreaming.js +201 -0
- package/dist/visibility/bounds.d.ts +66 -0
- package/dist/visibility/bounds.js +113 -0
- package/dist/visibility/camera.d.ts +21 -0
- package/dist/visibility/camera.js +3 -0
- package/dist/visibility/config.d.ts +21 -0
- package/dist/visibility/config.js +1 -0
- package/dist/visibility/diagnostics.d.ts +26 -0
- package/dist/visibility/diagnostics.js +36 -0
- package/dist/visibility/distance.d.ts +11 -0
- package/dist/visibility/distance.js +30 -0
- package/dist/visibility/frustum.d.ts +47 -0
- package/dist/visibility/frustum.js +186 -0
- package/dist/visibility/occlusion.d.ts +36 -0
- package/dist/visibility/occlusion.js +45 -0
- package/dist/visibility/settings.d.ts +75 -0
- package/dist/visibility/settings.js +49 -0
- package/dist/visibility/simulationCulling.d.ts +34 -0
- package/dist/visibility/simulationCulling.js +36 -0
- package/dist/visibility/spatialIndex.d.ts +45 -0
- package/dist/visibility/spatialIndex.js +198 -0
- package/dist/visibility/visibilitySystem.d.ts +90 -0
- package/dist/visibility/visibilitySystem.js +257 -0
- package/dist/world/buildings.d.ts +6 -0
- package/dist/world/buildings.js +152 -0
- package/dist/world/carve.d.ts +7 -2
- package/dist/world/carve.js +17 -7
- package/dist/world/cellStates.d.ts +45 -0
- package/dist/world/cellStates.js +103 -0
- package/dist/world/environmentSummary.d.ts +61 -0
- package/dist/world/environmentSummary.js +138 -0
- package/dist/world/features.d.ts +138 -9
- package/dist/world/features.js +73 -2
- package/dist/world/gridInstances.d.ts +12 -0
- package/dist/world/gridInstances.js +160 -0
- package/dist/world/lod.d.ts +17 -0
- package/dist/world/lod.js +66 -0
- package/dist/world/mapLayers.d.ts +60 -0
- package/dist/world/mapLayers.js +44 -0
- package/dist/world/massing.d.ts +45 -0
- package/dist/world/massing.js +581 -0
- package/dist/world/minimap.d.ts +13 -1
- package/dist/world/minimap.js +21 -2
- package/dist/world/placementController.d.ts +22 -1
- package/dist/world/placementController.js +56 -0
- package/dist/world/terrain.d.ts +62 -1
- package/dist/world/terrain.js +253 -9
- package/dist/world/voxelField.d.ts +54 -0
- package/dist/world/voxelField.js +241 -0
- package/dist/world/water.d.ts +7 -0
- package/dist/world/water.js +19 -4
- package/dist/world/weather.d.ts +3 -18
- package/dist/world/weather.js +4 -17
- package/dist/world/windZones.d.ts +47 -0
- package/dist/world/windZones.js +59 -0
- package/llms.txt +4983 -0
- package/package.json +14 -3
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface ResourcePoolConfig {
|
|
2
|
+
max: number;
|
|
3
|
+
initial?: number;
|
|
4
|
+
regenPerSecond?: number;
|
|
5
|
+
decayPerSecond?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ResourcePool {
|
|
8
|
+
current(): number;
|
|
9
|
+
max(): number;
|
|
10
|
+
setMax(value: number): void;
|
|
11
|
+
fraction(): number;
|
|
12
|
+
canSpend(amount: number): boolean;
|
|
13
|
+
spend(amount: number): boolean;
|
|
14
|
+
gain(amount: number): number;
|
|
15
|
+
set(value: number): void;
|
|
16
|
+
tick(dtSeconds: number): void;
|
|
17
|
+
isFull(): boolean;
|
|
18
|
+
isEmpty(): boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function createResourcePool(config: ResourcePoolConfig): ResourcePool;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export function createResourcePool(config) {
|
|
2
|
+
let max = Math.max(0, config.max);
|
|
3
|
+
const regenPerSecond = Math.max(0, config.regenPerSecond ?? 0);
|
|
4
|
+
const decayPerSecond = Math.max(0, config.decayPerSecond ?? 0);
|
|
5
|
+
let current = clamp(config.initial ?? max, max);
|
|
6
|
+
function clamp(value, ceiling) {
|
|
7
|
+
return Math.max(0, Math.min(ceiling, value));
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
current() {
|
|
11
|
+
return current;
|
|
12
|
+
},
|
|
13
|
+
max() {
|
|
14
|
+
return max;
|
|
15
|
+
},
|
|
16
|
+
setMax(value) {
|
|
17
|
+
max = Math.max(0, value);
|
|
18
|
+
current = clamp(current, max);
|
|
19
|
+
},
|
|
20
|
+
fraction() {
|
|
21
|
+
return max <= 0 ? 0 : current / max;
|
|
22
|
+
},
|
|
23
|
+
canSpend(amount) {
|
|
24
|
+
return amount <= 0 || amount <= current;
|
|
25
|
+
},
|
|
26
|
+
spend(amount) {
|
|
27
|
+
if (amount <= 0)
|
|
28
|
+
return true;
|
|
29
|
+
if (amount > current)
|
|
30
|
+
return false;
|
|
31
|
+
current = clamp(current - amount, max);
|
|
32
|
+
return true;
|
|
33
|
+
},
|
|
34
|
+
gain(amount) {
|
|
35
|
+
if (amount > 0)
|
|
36
|
+
current = clamp(current + amount, max);
|
|
37
|
+
return current;
|
|
38
|
+
},
|
|
39
|
+
set(value) {
|
|
40
|
+
current = clamp(value, max);
|
|
41
|
+
},
|
|
42
|
+
tick(dtSeconds) {
|
|
43
|
+
if (dtSeconds <= 0)
|
|
44
|
+
return;
|
|
45
|
+
const net = (regenPerSecond - decayPerSecond) * dtSeconds;
|
|
46
|
+
current = clamp(current + net, max);
|
|
47
|
+
},
|
|
48
|
+
isFull() {
|
|
49
|
+
return current >= max;
|
|
50
|
+
},
|
|
51
|
+
isEmpty() {
|
|
52
|
+
return current <= 0;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { EntityPosition } from "../scene/entityStore.js";
|
|
2
|
+
import type { Aim } from "../scene/spatial.js";
|
|
3
|
+
/**
|
|
4
|
+
* How a shot's world-space origin (and optional direction) is resolved before prediction/settlement.
|
|
5
|
+
* - `legacy` — `aim.origin` when present, else the shooter's entity position (pre-#431 default).
|
|
6
|
+
* - `entity` — always the shooter's entity position.
|
|
7
|
+
* - `entityOffset` / `muzzle` — entity-local offset rotated by the shooter's yaw (muzzle on a weapon model).
|
|
8
|
+
* - `camera` — explicit camera/reticle world origin (and optional direction override).
|
|
9
|
+
* - `world` — absolute world origin.
|
|
10
|
+
*/
|
|
11
|
+
export type ShotOriginPolicy = {
|
|
12
|
+
kind: "legacy";
|
|
13
|
+
} | {
|
|
14
|
+
kind: "entity";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "entityOffset";
|
|
17
|
+
offset: EntityPosition;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "muzzle";
|
|
20
|
+
offset?: EntityPosition;
|
|
21
|
+
} | {
|
|
22
|
+
kind: "camera";
|
|
23
|
+
origin: EntityPosition;
|
|
24
|
+
direction?: EntityPosition;
|
|
25
|
+
} | {
|
|
26
|
+
kind: "world";
|
|
27
|
+
origin: EntityPosition;
|
|
28
|
+
direction?: EntityPosition;
|
|
29
|
+
};
|
|
30
|
+
export interface ResolvedShot {
|
|
31
|
+
origin: EntityPosition;
|
|
32
|
+
direction: EntityPosition;
|
|
33
|
+
}
|
|
34
|
+
export interface ShotOriginDeps {
|
|
35
|
+
positionOf(instanceId: string): EntityPosition | undefined;
|
|
36
|
+
rotationYOf?(instanceId: string): number | undefined;
|
|
37
|
+
}
|
|
38
|
+
export declare function aimDirection(aim: Aim): EntityPosition | null;
|
|
39
|
+
export declare function aimSpreadDeg(aim: Aim): number;
|
|
40
|
+
export declare function resolveShot(deps: ShotOriginDeps, from: string, aim: Aim, policy?: ShotOriginPolicy): ResolvedShot | null;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { worldOffset } from "../scene/colliders.js";
|
|
2
|
+
const DEFAULT_MUZZLE_OFFSET = [0, 1.4, 0.35];
|
|
3
|
+
function normalize(vector) {
|
|
4
|
+
const length = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]);
|
|
5
|
+
if (length === 0)
|
|
6
|
+
return null;
|
|
7
|
+
return [vector[0] / length, vector[1] / length, vector[2] / length];
|
|
8
|
+
}
|
|
9
|
+
export function aimDirection(aim) {
|
|
10
|
+
if ("origin" in aim)
|
|
11
|
+
return normalize(aim.direction);
|
|
12
|
+
const cosPitch = Math.cos(aim.pitch);
|
|
13
|
+
return [Math.sin(aim.yaw) * cosPitch, Math.sin(aim.pitch), Math.cos(aim.yaw) * cosPitch];
|
|
14
|
+
}
|
|
15
|
+
export function aimSpreadDeg(aim) {
|
|
16
|
+
return "origin" in aim ? 0 : aim.spread ?? 0;
|
|
17
|
+
}
|
|
18
|
+
export function resolveShot(deps, from, aim, policy = { kind: "legacy" }) {
|
|
19
|
+
const aimDir = aimDirection(aim);
|
|
20
|
+
if (aimDir === null && policy.kind !== "camera" && policy.kind !== "world")
|
|
21
|
+
return null;
|
|
22
|
+
switch (policy.kind) {
|
|
23
|
+
case "legacy": {
|
|
24
|
+
const origin = "origin" in aim ? aim.origin : deps.positionOf(from);
|
|
25
|
+
if (origin === undefined || aimDir === null)
|
|
26
|
+
return null;
|
|
27
|
+
return { origin, direction: aimDir };
|
|
28
|
+
}
|
|
29
|
+
case "entity": {
|
|
30
|
+
const origin = deps.positionOf(from);
|
|
31
|
+
if (origin === undefined || aimDir === null)
|
|
32
|
+
return null;
|
|
33
|
+
return { origin, direction: aimDir };
|
|
34
|
+
}
|
|
35
|
+
case "entityOffset":
|
|
36
|
+
case "muzzle": {
|
|
37
|
+
const position = deps.positionOf(from);
|
|
38
|
+
if (position === undefined || aimDir === null)
|
|
39
|
+
return null;
|
|
40
|
+
const rotationY = deps.rotationYOf?.(from) ?? 0;
|
|
41
|
+
const offset = policy.kind === "muzzle" ? (policy.offset ?? DEFAULT_MUZZLE_OFFSET) : policy.offset;
|
|
42
|
+
return { origin: worldOffset(offset, position, rotationY), direction: aimDir };
|
|
43
|
+
}
|
|
44
|
+
case "camera": {
|
|
45
|
+
const direction = policy.direction !== undefined ? normalize(policy.direction) : aimDir;
|
|
46
|
+
if (direction === null)
|
|
47
|
+
return null;
|
|
48
|
+
return { origin: policy.origin, direction };
|
|
49
|
+
}
|
|
50
|
+
case "world": {
|
|
51
|
+
const direction = policy.direction !== undefined ? normalize(policy.direction) : aimDir;
|
|
52
|
+
if (direction === null)
|
|
53
|
+
return null;
|
|
54
|
+
return { origin: policy.origin, direction };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -19,9 +19,38 @@ export interface TelegraphConfig {
|
|
|
19
19
|
shape: TelegraphShape;
|
|
20
20
|
at: EntityPosition;
|
|
21
21
|
dir?: number;
|
|
22
|
-
windupMs
|
|
22
|
+
windupMs?: number;
|
|
23
|
+
turns?: number;
|
|
23
24
|
kind?: string;
|
|
24
25
|
}
|
|
25
26
|
export declare function telegraphProgress(windupMs: number, startedAtMs: number, nowMs: number): number;
|
|
27
|
+
export interface HazardCycleConfig {
|
|
28
|
+
windupMs: number;
|
|
29
|
+
activeMs: number;
|
|
30
|
+
/** Rest between one activation's end and the next windup; default `0` (back-to-back). */
|
|
31
|
+
cooldownMs?: number;
|
|
32
|
+
/** Shifts the whole cycle — staggers identical hazards. */
|
|
33
|
+
offsetMs?: number;
|
|
34
|
+
}
|
|
35
|
+
export type HazardPhase = "windup" | "active" | "cooldown";
|
|
36
|
+
export interface HazardCycleSample {
|
|
37
|
+
phase: HazardPhase;
|
|
38
|
+
/** Elapsed fraction of the current phase in `[0, 1]` — the windup fraction is the decal fill. */
|
|
39
|
+
fraction: number;
|
|
40
|
+
remainingMs: number;
|
|
41
|
+
/** How many full cycles have completed before this one. */
|
|
42
|
+
cycleIndex: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Deterministic repeating hazard timing — windup → active → cooldown as a pure function of absolute
|
|
46
|
+
* time, for recurring flame vents, crushers, lightning rings. Sample `hazardCycleAt` each tick: draw
|
|
47
|
+
* the telegraph during `windup`, apply the effect during `active`, rest through `cooldown`.
|
|
48
|
+
*/
|
|
49
|
+
export declare function hazardCycleAt(config: HazardCycleConfig, nowMs: number): HazardCycleSample;
|
|
50
|
+
/** Absolute time the hazard's next `active` phase begins at or after `nowMs` — the countdown seam. */
|
|
51
|
+
export declare function nextHazardActiveAt(config: HazardCycleConfig, nowMs: number): number;
|
|
26
52
|
export declare function telegraphFired(windupMs: number, startedAtMs: number, nowMs: number): boolean;
|
|
53
|
+
export declare function telegraphTurnProgress(config: TelegraphConfig, startedTurn: number, currentTurn: number): number;
|
|
54
|
+
export declare function telegraphFiredAtTurn(config: TelegraphConfig, startedTurn: number, currentTurn: number): boolean;
|
|
55
|
+
export declare function telegraphTurnsRemaining(config: TelegraphConfig, startedTurn: number, currentTurn: number): number;
|
|
27
56
|
export declare function pointInTelegraph(config: TelegraphConfig, point: EntityPosition): boolean;
|
package/dist/combat/telegraph.js
CHANGED
|
@@ -3,9 +3,70 @@ export function telegraphProgress(windupMs, startedAtMs, nowMs) {
|
|
|
3
3
|
return 1;
|
|
4
4
|
return Math.max(0, Math.min(1, (nowMs - startedAtMs) / windupMs));
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Deterministic repeating hazard timing — windup → active → cooldown as a pure function of absolute
|
|
8
|
+
* time, for recurring flame vents, crushers, lightning rings. Sample `hazardCycleAt` each tick: draw
|
|
9
|
+
* the telegraph during `windup`, apply the effect during `active`, rest through `cooldown`.
|
|
10
|
+
*/
|
|
11
|
+
export function hazardCycleAt(config, nowMs) {
|
|
12
|
+
const cooldownMs = Math.max(0, config.cooldownMs ?? 0);
|
|
13
|
+
const cycleMs = config.windupMs + config.activeMs + cooldownMs;
|
|
14
|
+
if (cycleMs <= 0)
|
|
15
|
+
return { phase: "active", fraction: 1, remainingMs: 0, cycleIndex: 0 };
|
|
16
|
+
const shifted = nowMs + (config.offsetMs ?? 0);
|
|
17
|
+
const local = ((shifted % cycleMs) + cycleMs) % cycleMs;
|
|
18
|
+
const cycleIndex = Math.floor((shifted - local) / cycleMs);
|
|
19
|
+
if (local < config.windupMs) {
|
|
20
|
+
return {
|
|
21
|
+
phase: "windup",
|
|
22
|
+
fraction: config.windupMs <= 0 ? 1 : local / config.windupMs,
|
|
23
|
+
remainingMs: config.windupMs - local,
|
|
24
|
+
cycleIndex,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const intoActive = local - config.windupMs;
|
|
28
|
+
if (intoActive < config.activeMs) {
|
|
29
|
+
return {
|
|
30
|
+
phase: "active",
|
|
31
|
+
fraction: config.activeMs <= 0 ? 1 : intoActive / config.activeMs,
|
|
32
|
+
remainingMs: config.activeMs - intoActive,
|
|
33
|
+
cycleIndex,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const intoCooldown = intoActive - config.activeMs;
|
|
37
|
+
return {
|
|
38
|
+
phase: "cooldown",
|
|
39
|
+
fraction: cooldownMs <= 0 ? 1 : intoCooldown / cooldownMs,
|
|
40
|
+
remainingMs: cooldownMs - intoCooldown,
|
|
41
|
+
cycleIndex,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Absolute time the hazard's next `active` phase begins at or after `nowMs` — the countdown seam. */
|
|
45
|
+
export function nextHazardActiveAt(config, nowMs) {
|
|
46
|
+
const sample = hazardCycleAt(config, nowMs);
|
|
47
|
+
if (sample.phase === "windup")
|
|
48
|
+
return nowMs + sample.remainingMs;
|
|
49
|
+
const cooldownMs = Math.max(0, config.cooldownMs ?? 0);
|
|
50
|
+
const restMs = sample.phase === "active" ? sample.remainingMs + cooldownMs : sample.remainingMs;
|
|
51
|
+
return nowMs + restMs + config.windupMs;
|
|
52
|
+
}
|
|
6
53
|
export function telegraphFired(windupMs, startedAtMs, nowMs) {
|
|
7
54
|
return nowMs - startedAtMs >= windupMs;
|
|
8
55
|
}
|
|
56
|
+
export function telegraphTurnProgress(config, startedTurn, currentTurn) {
|
|
57
|
+
const turns = config.turns ?? 0;
|
|
58
|
+
if (turns <= 0)
|
|
59
|
+
return 1;
|
|
60
|
+
return Math.max(0, Math.min(1, (currentTurn - startedTurn) / turns));
|
|
61
|
+
}
|
|
62
|
+
export function telegraphFiredAtTurn(config, startedTurn, currentTurn) {
|
|
63
|
+
const turns = config.turns ?? 0;
|
|
64
|
+
return currentTurn - startedTurn >= turns;
|
|
65
|
+
}
|
|
66
|
+
export function telegraphTurnsRemaining(config, startedTurn, currentTurn) {
|
|
67
|
+
const turns = config.turns ?? 0;
|
|
68
|
+
return Math.max(0, turns - (currentTurn - startedTurn));
|
|
69
|
+
}
|
|
9
70
|
function planarDelta(config, point) {
|
|
10
71
|
return { dx: point[0] - config.at[0], dz: point[2] - config.at[2] };
|
|
11
72
|
}
|
|
@@ -3,7 +3,7 @@ export interface CommandRejection {
|
|
|
3
3
|
}
|
|
4
4
|
export interface CommandDefinition<TState, TInput> {
|
|
5
5
|
validate?(state: TState, input: TInput): CommandRejection | null;
|
|
6
|
-
apply(state: TState, input: TInput): TState;
|
|
6
|
+
apply(state: TState, input: TInput): TState | void;
|
|
7
7
|
}
|
|
8
8
|
export type CommandResult<TState> = {
|
|
9
9
|
status: "applied";
|
|
@@ -20,7 +20,8 @@ export function createCommandRegistry() {
|
|
|
20
20
|
const rejection = definition.validate?.(state, input) ?? null;
|
|
21
21
|
if (rejection)
|
|
22
22
|
return { status: "rejected", reason: rejection.reason };
|
|
23
|
-
|
|
23
|
+
const next = definition.apply(state, input);
|
|
24
|
+
return { status: "applied", state: next === undefined ? state : next };
|
|
24
25
|
},
|
|
25
26
|
};
|
|
26
27
|
}
|
package/dist/crafting/recipe.js
CHANGED
|
@@ -19,6 +19,9 @@ export function stationSatisfied(recipe, context) {
|
|
|
19
19
|
return true;
|
|
20
20
|
const range = recipe.stationRange !== undefined && recipe.stationRange > 0 ? recipe.stationRange : Infinity;
|
|
21
21
|
const origin = context.origin;
|
|
22
|
+
if (range !== Infinity && origin === undefined) {
|
|
23
|
+
throw new Error(`recipe "${recipe.id}" sets stationRange=${recipe.stationRange} but CraftContext.origin is missing`);
|
|
24
|
+
}
|
|
22
25
|
const stations = context.stations ?? [];
|
|
23
26
|
for (const station of stations) {
|
|
24
27
|
if (station.catalogId !== recipe.station)
|
|
@@ -37,7 +40,7 @@ function lockedRequirements(recipe, context) {
|
|
|
37
40
|
return [];
|
|
38
41
|
const unlocked = context.unlocked;
|
|
39
42
|
if (unlocked === undefined)
|
|
40
|
-
return
|
|
43
|
+
return recipe.requires;
|
|
41
44
|
return recipe.requires.filter((id) => !unlocked(id));
|
|
42
45
|
}
|
|
43
46
|
function outputsFit(state, layout, traits, recipe) {
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type DataSourceStatus = "idle" | "loading" | "ready" | "error";
|
|
2
|
+
export interface DataSourceState<T> {
|
|
3
|
+
readonly status: DataSourceStatus;
|
|
4
|
+
readonly data: T | undefined;
|
|
5
|
+
readonly error: Error | undefined;
|
|
6
|
+
}
|
|
7
|
+
export interface DataSourceClock {
|
|
8
|
+
setInterval(handler: () => void, intervalMs: number): unknown;
|
|
9
|
+
clearInterval(handle: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
export interface DataSourceOptions {
|
|
12
|
+
intervalMs?: number;
|
|
13
|
+
clock?: DataSourceClock;
|
|
14
|
+
}
|
|
15
|
+
export interface RefreshOptions {
|
|
16
|
+
force?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface DataSource<T> {
|
|
19
|
+
getState(): DataSourceState<T>;
|
|
20
|
+
subscribe(listener: (state: DataSourceState<T>) => void): () => void;
|
|
21
|
+
refresh(options?: RefreshOptions): Promise<void>;
|
|
22
|
+
startPolling(intervalMs?: number): void;
|
|
23
|
+
stopPolling(): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
}
|
|
26
|
+
export declare function createDataSource<T>(load: (signal: AbortSignal) => Promise<T>, options?: DataSourceOptions): DataSource<T>;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
const defaultClock = {
|
|
2
|
+
setInterval: (handler, intervalMs) => globalThis.setInterval(handler, intervalMs),
|
|
3
|
+
clearInterval: (handle) => globalThis.clearInterval(handle),
|
|
4
|
+
};
|
|
5
|
+
export function createDataSource(load, options = {}) {
|
|
6
|
+
const clock = options.clock ?? defaultClock;
|
|
7
|
+
const listeners = new Set();
|
|
8
|
+
let state = { status: "idle", data: undefined, error: undefined };
|
|
9
|
+
let controller;
|
|
10
|
+
let inFlight;
|
|
11
|
+
let pollHandle;
|
|
12
|
+
let disposed = false;
|
|
13
|
+
function setState(next) {
|
|
14
|
+
state = next;
|
|
15
|
+
for (const listener of listeners)
|
|
16
|
+
listener(state);
|
|
17
|
+
}
|
|
18
|
+
async function run() {
|
|
19
|
+
const ownController = new AbortController();
|
|
20
|
+
controller = ownController;
|
|
21
|
+
setState({ status: "loading", data: state.data, error: undefined });
|
|
22
|
+
try {
|
|
23
|
+
const data = await load(ownController.signal);
|
|
24
|
+
if (ownController.signal.aborted)
|
|
25
|
+
return;
|
|
26
|
+
setState({ status: "ready", data, error: undefined });
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
if (ownController.signal.aborted)
|
|
30
|
+
return;
|
|
31
|
+
setState({
|
|
32
|
+
status: "error",
|
|
33
|
+
data: state.data,
|
|
34
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
if (controller === ownController)
|
|
39
|
+
controller = undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function refresh(refreshOptions = {}) {
|
|
43
|
+
if (disposed)
|
|
44
|
+
return Promise.resolve();
|
|
45
|
+
if (inFlight !== undefined) {
|
|
46
|
+
if (!refreshOptions.force)
|
|
47
|
+
return inFlight;
|
|
48
|
+
controller?.abort();
|
|
49
|
+
}
|
|
50
|
+
const promise = run().finally(() => {
|
|
51
|
+
if (inFlight === promise)
|
|
52
|
+
inFlight = undefined;
|
|
53
|
+
});
|
|
54
|
+
inFlight = promise;
|
|
55
|
+
return promise;
|
|
56
|
+
}
|
|
57
|
+
function stopPolling() {
|
|
58
|
+
if (pollHandle !== undefined) {
|
|
59
|
+
clock.clearInterval(pollHandle);
|
|
60
|
+
pollHandle = undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function startPolling(intervalMs) {
|
|
64
|
+
stopPolling();
|
|
65
|
+
const resolvedInterval = intervalMs ?? options.intervalMs;
|
|
66
|
+
if (resolvedInterval === undefined) {
|
|
67
|
+
throw new Error("startPolling requires an intervalMs (pass one, or set options.intervalMs at creation)");
|
|
68
|
+
}
|
|
69
|
+
void refresh();
|
|
70
|
+
pollHandle = clock.setInterval(() => {
|
|
71
|
+
void refresh();
|
|
72
|
+
}, resolvedInterval);
|
|
73
|
+
}
|
|
74
|
+
function dispose() {
|
|
75
|
+
disposed = true;
|
|
76
|
+
stopPolling();
|
|
77
|
+
controller?.abort();
|
|
78
|
+
listeners.clear();
|
|
79
|
+
}
|
|
80
|
+
if (options.intervalMs !== undefined)
|
|
81
|
+
startPolling(options.intervalMs);
|
|
82
|
+
return {
|
|
83
|
+
getState: () => state,
|
|
84
|
+
subscribe(listener) {
|
|
85
|
+
listeners.add(listener);
|
|
86
|
+
return () => listeners.delete(listener);
|
|
87
|
+
},
|
|
88
|
+
refresh,
|
|
89
|
+
startPolling,
|
|
90
|
+
stopPolling,
|
|
91
|
+
dispose,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface DevProxyTable {
|
|
2
|
+
readonly [routeName: string]: string;
|
|
3
|
+
}
|
|
4
|
+
export interface ProxiedUrlOptions {
|
|
5
|
+
dev?: boolean;
|
|
6
|
+
table?: DevProxyTable;
|
|
7
|
+
prefix?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function parseDevProxyTable(raw: string | undefined): DevProxyTable;
|
|
10
|
+
export declare const DEFAULT_DEV_PROXY_PREFIX = "/proxy";
|
|
11
|
+
export declare function proxiedUrl(target: string, options?: ProxiedUrlOptions): string;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
function readImportMetaEnv() {
|
|
2
|
+
try {
|
|
3
|
+
const meta = import.meta;
|
|
4
|
+
return meta.env ?? {};
|
|
5
|
+
}
|
|
6
|
+
catch {
|
|
7
|
+
return {};
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function parseDevProxyTable(raw) {
|
|
11
|
+
if (raw === undefined || raw.length === 0)
|
|
12
|
+
return {};
|
|
13
|
+
try {
|
|
14
|
+
const parsed = JSON.parse(raw);
|
|
15
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed))
|
|
16
|
+
return {};
|
|
17
|
+
const entries = Object.entries(parsed).filter((entry) => typeof entry[1] === "string");
|
|
18
|
+
return Object.fromEntries(entries);
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const DEFAULT_DEV_PROXY_PREFIX = "/proxy";
|
|
25
|
+
export function proxiedUrl(target, options = {}) {
|
|
26
|
+
const env = readImportMetaEnv();
|
|
27
|
+
const dev = options.dev ?? env.DEV === true;
|
|
28
|
+
if (!dev)
|
|
29
|
+
return target;
|
|
30
|
+
const table = options.table ?? parseDevProxyTable(env.VITE_JGENGINE_DEV_PROXY);
|
|
31
|
+
const prefix = options.prefix ?? DEFAULT_DEV_PROXY_PREFIX;
|
|
32
|
+
for (const [routeName, base] of Object.entries(table)) {
|
|
33
|
+
if (target.startsWith(base)) {
|
|
34
|
+
return `${prefix}/${routeName}${target.slice(base.length)}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return target;
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export type FetchImpl = typeof fetch;
|
|
2
|
+
export interface FetchJsonOptions {
|
|
3
|
+
method?: string;
|
|
4
|
+
headers?: Record<string, string>;
|
|
5
|
+
body?: string;
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
fetchImpl?: FetchImpl;
|
|
8
|
+
}
|
|
9
|
+
export declare class HttpStatusError extends Error {
|
|
10
|
+
readonly status: number;
|
|
11
|
+
readonly statusText: string;
|
|
12
|
+
readonly url: string;
|
|
13
|
+
constructor(status: number, statusText: string, url: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class JsonParseError extends Error {
|
|
16
|
+
readonly url: string;
|
|
17
|
+
readonly cause: unknown;
|
|
18
|
+
constructor(url: string, cause: unknown);
|
|
19
|
+
}
|
|
20
|
+
export declare function fetchJson<T>(url: string, options?: FetchJsonOptions): Promise<T>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export class HttpStatusError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
statusText;
|
|
4
|
+
url;
|
|
5
|
+
constructor(status, statusText, url) {
|
|
6
|
+
super(`HTTP ${status} ${statusText} for ${url}`);
|
|
7
|
+
this.name = "HttpStatusError";
|
|
8
|
+
this.status = status;
|
|
9
|
+
this.statusText = statusText;
|
|
10
|
+
this.url = url;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export class JsonParseError extends Error {
|
|
14
|
+
url;
|
|
15
|
+
cause;
|
|
16
|
+
constructor(url, cause) {
|
|
17
|
+
super(`failed to parse JSON response from ${url}`);
|
|
18
|
+
this.name = "JsonParseError";
|
|
19
|
+
this.url = url;
|
|
20
|
+
this.cause = cause;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export async function fetchJson(url, options = {}) {
|
|
24
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
25
|
+
const response = await fetchImpl(url, {
|
|
26
|
+
method: options.method,
|
|
27
|
+
headers: options.headers,
|
|
28
|
+
body: options.body,
|
|
29
|
+
signal: options.signal,
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
throw new HttpStatusError(response.status, response.statusText, url);
|
|
33
|
+
}
|
|
34
|
+
const text = await response.text();
|
|
35
|
+
if (text.length === 0)
|
|
36
|
+
return undefined;
|
|
37
|
+
try {
|
|
38
|
+
return JSON.parse(text);
|
|
39
|
+
}
|
|
40
|
+
catch (cause) {
|
|
41
|
+
throw new JsonParseError(url, cause);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type DataSource, type DataSourceOptions } from "./dataSource.js";
|
|
2
|
+
import { type FetchJsonOptions } from "./fetchJson.js";
|
|
3
|
+
export type JsonDataSourceOptions = DataSourceOptions & Omit<FetchJsonOptions, "signal">;
|
|
4
|
+
export declare function createJsonDataSource<T>(url: string, options?: JsonDataSourceOptions): DataSource<T>;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { createDataSource } from "./dataSource.js";
|
|
2
|
+
import { fetchJson } from "./fetchJson.js";
|
|
3
|
+
export function createJsonDataSource(url, options = {}) {
|
|
4
|
+
const { intervalMs, clock, ...fetchOptions } = options;
|
|
5
|
+
return createDataSource((signal) => fetchJson(url, { ...fetchOptions, signal }), { intervalMs, clock });
|
|
6
|
+
}
|