@shipload/sdk 1.0.0-next.7 → 1.0.0-next.70
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/lib/scan.d.ts +52 -0
- package/lib/scan.js +162 -0
- package/lib/scan.js.map +1 -0
- package/lib/scan.m.js +152 -0
- package/lib/scan.m.js.map +1 -0
- package/lib/shipload.d.ts +5696 -1503
- package/lib/shipload.js +20294 -5200
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +20371 -5683
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1648 -0
- package/lib/testing.js +6980 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +6974 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.test.ts +82 -0
- package/src/capabilities/craftable.ts +82 -0
- package/src/capabilities/crafting.test.ts +80 -0
- package/src/capabilities/crafting.ts +50 -8
- package/src/capabilities/gathering.test.ts +29 -0
- package/src/capabilities/gathering.ts +38 -20
- package/src/capabilities/hauling.ts +0 -5
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +27 -30
- package/src/capabilities/movement.ts +1 -1
- package/src/capabilities/storage.test.ts +26 -0
- package/src/capabilities/storage.ts +22 -7
- package/src/contracts/fund.ts +306 -0
- package/src/contracts/platform.ts +312 -3
- package/src/contracts/server.ts +2661 -466
- package/src/contracts/token.ts +170 -0
- package/src/contracts.ts +2 -0
- package/src/coordinates/address.ts +88 -0
- package/src/coordinates/constants.test.ts +15 -0
- package/src/coordinates/constants.ts +23 -0
- package/src/coordinates/index.ts +15 -0
- package/src/coordinates/memo.test.ts +47 -0
- package/src/coordinates/memo.ts +20 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/data/capabilities.ts +49 -18
- package/src/data/capability-formulas.ts +26 -14
- package/src/data/catalog.test.ts +19 -0
- package/src/data/catalog.ts +13 -3
- package/src/data/charters.json +396 -0
- package/src/data/citizenry-adjectives.json +42 -0
- package/src/data/citizenry-nouns.json +50 -0
- package/src/data/colors.ts +14 -32
- package/src/data/entities.json +421 -15
- package/src/data/item-ids.ts +53 -13
- package/src/data/items.json +330 -77
- package/src/data/kind-registry.json +212 -0
- package/src/data/kind-registry.ts +192 -0
- package/src/data/metadata.ts +312 -51
- package/src/data/recipes-runtime.ts +6 -23
- package/src/data/recipes.json +2173 -173
- package/src/data/tiers.ts +9 -6
- package/src/derivation/build-methods.test.ts +71 -0
- package/src/derivation/build-methods.ts +50 -0
- package/src/derivation/capabilities.test.ts +348 -0
- package/src/derivation/capabilities.ts +707 -0
- package/src/derivation/capability-mappings.ts +60 -16
- package/src/derivation/crafting.test.ts +17 -0
- package/src/derivation/crafting.ts +57 -34
- package/src/derivation/index.ts +27 -2
- package/src/derivation/recipe-usage.test.ts +88 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +9 -1
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +72 -0
- package/src/derivation/stars.test.ts +67 -0
- package/src/derivation/stars.ts +25 -0
- package/src/derivation/stat-scaling.ts +12 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/strata.ts +5 -3
- package/src/derivation/stratum.ts +26 -22
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/upgrades.ts +14 -0
- package/src/derivation/wormhole.ts +154 -0
- package/src/entities/entity.ts +102 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +144 -136
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/entity/hydrate.test.ts +156 -0
- package/src/entity/hydrate.ts +86 -0
- package/src/errors.ts +21 -16
- package/src/format.ts +42 -9
- package/src/index-module.ts +411 -32
- package/src/influence/ballot.test.ts +103 -0
- package/src/influence/ballot.ts +98 -0
- package/src/influence/categories.ts +32 -0
- package/src/influence/charter-metadata.test.ts +136 -0
- package/src/influence/charter-metadata.ts +236 -0
- package/src/influence/charters.test.ts +112 -0
- package/src/influence/charters.ts +150 -0
- package/src/influence/citizenry.ts +38 -0
- package/src/influence/civic-shuttle.test.ts +202 -0
- package/src/influence/civic-shuttle.ts +142 -0
- package/src/influence/civic.test.ts +287 -0
- package/src/influence/civic.ts +269 -0
- package/src/influence/constants.ts +84 -0
- package/src/influence/decay.ts +20 -0
- package/src/influence/decomp.ts +95 -0
- package/src/influence/demand.ts +106 -0
- package/src/influence/duration.ts +101 -0
- package/src/influence/index.ts +118 -0
- package/src/influence/influence.test.ts +450 -0
- package/src/influence/quality.ts +25 -0
- package/src/influence/valuation.ts +154 -0
- package/src/managers/actions.ts +940 -93
- package/src/managers/balances.test.ts +161 -0
- package/src/managers/balances.ts +93 -0
- package/src/managers/base.ts +10 -2
- package/src/managers/cluster.test.ts +39 -0
- package/src/managers/cluster.ts +53 -0
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +453 -0
- package/src/managers/context.ts +58 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +35 -63
- package/src/managers/epochs.ts +72 -1
- package/src/managers/index.ts +38 -1
- package/src/managers/influence.test.ts +56 -0
- package/src/managers/influence.ts +425 -0
- package/src/managers/jobs.test.ts +80 -0
- package/src/managers/jobs.ts +54 -0
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +21 -0
- package/src/managers/nft.ts +110 -0
- package/src/managers/players.ts +25 -0
- package/src/managers/plot.ts +122 -0
- package/src/nft/atomicassets.abi.json +1342 -0
- package/src/nft/atomicassets.ts +237 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +388 -0
- package/src/nft/description.ts +222 -100
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +296 -0
- package/src/planner/planner.test.ts +459 -0
- package/src/receipts.ts +22 -0
- package/src/resolution/describe-module.ts +43 -25
- package/src/resolution/display-name.ts +39 -11
- package/src/resolution/resolve-item.test.ts +48 -0
- package/src/resolution/resolve-item.ts +112 -58
- package/src/scan/index.ts +244 -0
- package/src/scan/scan-wasm.base64.ts +2 -0
- package/src/scheduling/accessor.ts +65 -23
- package/src/scheduling/availability.test.ts +320 -0
- package/src/scheduling/availability.ts +251 -0
- package/src/scheduling/cancel.test.ts +550 -0
- package/src/scheduling/cancel.ts +254 -0
- package/src/scheduling/cluster-stock.test.ts +31 -0
- package/src/scheduling/cluster-stock.ts +15 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/epoch.ts +1 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/jobs.test.ts +49 -0
- package/src/scheduling/jobs.ts +137 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +250 -0
- package/src/scheduling/lanes.ts +227 -0
- package/src/scheduling/projection.ts +265 -149
- package/src/scheduling/schedule.test.ts +163 -0
- package/src/scheduling/schedule.ts +282 -116
- package/src/scheduling/task-cargo.test.ts +110 -0
- package/src/scheduling/task-cargo.ts +62 -0
- package/src/scheduling/task-effects.test.ts +35 -0
- package/src/scheduling/task-effects.ts +34 -0
- package/src/scheduling/unwrap.test.ts +86 -0
- package/src/scheduling/unwrap.ts +190 -0
- package/src/shipload.ts +63 -4
- package/src/subscriptions/manager.cluster.test.ts +51 -0
- package/src/subscriptions/manager.ts +245 -172
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +28 -3
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +167 -0
- package/src/travel/reach.test.ts +86 -0
- package/src/travel/reach.ts +34 -0
- package/src/travel/route-build.test.ts +63 -0
- package/src/travel/route-build.ts +60 -0
- package/src/travel/route-planner.ts +288 -0
- package/src/travel/route-simulator.ts +170 -0
- package/src/travel/travel.ts +190 -123
- package/src/types/capabilities.ts +37 -8
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +81 -23
- package/src/utils/cargo.test.ts +14 -0
- package/src/utils/cargo.ts +2 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/hash.ts +22 -2
- package/src/utils/system.ts +24 -5
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -123
- package/src/entities/ship-deploy.ts +0 -295
- package/src/entities/ship.ts +0 -221
- package/src/entities/warehouse.ts +0 -127
- package/src/types/entity-traits.ts +0 -69
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import type {UInt64Type} from '@wharfkit/antelope'
|
|
2
|
+
import {PRECISION, TRAVEL_MAX_DURATION} from '../types'
|
|
3
|
+
import {
|
|
4
|
+
calc_energyusage,
|
|
5
|
+
calc_group_flighttime,
|
|
6
|
+
calc_rechargetime,
|
|
7
|
+
distanceBetweenPoints,
|
|
8
|
+
} from './travel'
|
|
9
|
+
|
|
10
|
+
export interface RouteMoverInput {
|
|
11
|
+
ref: {entityType: string; entityId: UInt64Type}
|
|
12
|
+
hasMovement: boolean
|
|
13
|
+
engines?: {thrust: number; drain: number}
|
|
14
|
+
generator?: {capacity: number; recharge: number}
|
|
15
|
+
hauler?: {capacity: number; efficiency: number}
|
|
16
|
+
mass: number
|
|
17
|
+
energy: number
|
|
18
|
+
priorMobilityEnd: number
|
|
19
|
+
narrowBarrierEnd: number
|
|
20
|
+
/** Max end (seconds-from-now) over all this entity's lanes incl. worker/craft; gates recharges like the contract's all_lanes_end. Default 0. */
|
|
21
|
+
allLanesEnd?: number
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RouteLegSim {
|
|
25
|
+
from: {x: number; y: number}
|
|
26
|
+
to: {x: number; y: number}
|
|
27
|
+
distanceCells: number
|
|
28
|
+
energyCostByMover: Record<string, number>
|
|
29
|
+
rechargeBefore: boolean
|
|
30
|
+
rechargeSeconds: number
|
|
31
|
+
flightSeconds: number
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface RouteSim {
|
|
35
|
+
legs: RouteLegSim[]
|
|
36
|
+
totalSeconds: number
|
|
37
|
+
reachable: boolean
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function simulateRoute(
|
|
41
|
+
movers: RouteMoverInput[],
|
|
42
|
+
waypoints: {x: number; y: number}[],
|
|
43
|
+
origin: {x: number; y: number},
|
|
44
|
+
recharge: boolean
|
|
45
|
+
): RouteSim {
|
|
46
|
+
const totalThrust = movers
|
|
47
|
+
.filter((m) => m.hasMovement && m.engines)
|
|
48
|
+
.reduce((sum, m) => sum + m.engines!.thrust, 0)
|
|
49
|
+
|
|
50
|
+
const totalMass = movers.reduce((sum, m) => sum + m.mass, 0)
|
|
51
|
+
|
|
52
|
+
const haulCount = movers.filter((m) => !m.hasMovement).length
|
|
53
|
+
|
|
54
|
+
const pooledHaulCap = movers
|
|
55
|
+
.filter((m) => m.hasMovement && m.hauler)
|
|
56
|
+
.reduce((sum, m) => sum + m.hauler!.capacity, 0)
|
|
57
|
+
|
|
58
|
+
const weightedHaulEffNum = movers
|
|
59
|
+
.filter((m) => m.hasMovement && m.hauler)
|
|
60
|
+
.reduce((sum, m) => sum + m.hauler!.efficiency * m.hauler!.capacity, 0)
|
|
61
|
+
|
|
62
|
+
const energyByMover: Map<string, number> = new Map(
|
|
63
|
+
movers.map((m) => [String(m.ref.entityId), m.energy])
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
let reachable = true
|
|
67
|
+
const legs: RouteLegSim[] = []
|
|
68
|
+
|
|
69
|
+
const mobilityBarrier = movers
|
|
70
|
+
.filter((m) => m.hasMovement)
|
|
71
|
+
.reduce((mx, m) => Math.max(mx, m.priorMobilityEnd, m.narrowBarrierEnd), 0)
|
|
72
|
+
|
|
73
|
+
const rechargeFloor = movers
|
|
74
|
+
.filter((m) => m.hasMovement && m.generator)
|
|
75
|
+
.reduce((mx, m) => Math.max(mx, m.allLanesEnd ?? 0), 0)
|
|
76
|
+
|
|
77
|
+
let clock = 0
|
|
78
|
+
|
|
79
|
+
let from = origin
|
|
80
|
+
for (const to of waypoints) {
|
|
81
|
+
const distance = distanceBetweenPoints(from.x, from.y, to.x, to.y)
|
|
82
|
+
const distanceNum = Number(distance)
|
|
83
|
+
const distanceCells = distanceNum / PRECISION
|
|
84
|
+
|
|
85
|
+
const energyCostByMover: Record<string, number> = {}
|
|
86
|
+
|
|
87
|
+
for (const m of movers) {
|
|
88
|
+
if (!m.hasMovement || !m.engines) continue
|
|
89
|
+
const key = String(m.ref.entityId)
|
|
90
|
+
energyCostByMover[key] = Number(calc_energyusage(distance, m.engines.drain))
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let rechargeBefore = false
|
|
94
|
+
let rechargeSeconds = 0
|
|
95
|
+
|
|
96
|
+
if (recharge) {
|
|
97
|
+
let maxDur = 0
|
|
98
|
+
for (const m of movers) {
|
|
99
|
+
if (!m.hasMovement || !m.generator) continue
|
|
100
|
+
const key = String(m.ref.entityId)
|
|
101
|
+
const curEnergy = energyByMover.get(key) ?? 0
|
|
102
|
+
const dur = Number(
|
|
103
|
+
calc_rechargetime(m.generator.capacity, curEnergy, m.generator.recharge)
|
|
104
|
+
)
|
|
105
|
+
if (dur > maxDur) maxDur = dur
|
|
106
|
+
}
|
|
107
|
+
rechargeSeconds = maxDur
|
|
108
|
+
rechargeBefore = rechargeSeconds > 0
|
|
109
|
+
|
|
110
|
+
if (rechargeBefore) {
|
|
111
|
+
for (const m of movers) {
|
|
112
|
+
if (!m.hasMovement || !m.generator) continue
|
|
113
|
+
const key = String(m.ref.entityId)
|
|
114
|
+
energyByMover.set(key, m.generator.capacity)
|
|
115
|
+
}
|
|
116
|
+
clock = Math.max(clock, rechargeFloor) + rechargeSeconds
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
for (const m of movers) {
|
|
121
|
+
if (!m.hasMovement || !m.engines) continue
|
|
122
|
+
const key = String(m.ref.entityId)
|
|
123
|
+
const cost = energyCostByMover[key] ?? 0
|
|
124
|
+
const curEnergy = energyByMover.get(key) ?? 0
|
|
125
|
+
|
|
126
|
+
if (recharge && m.generator) {
|
|
127
|
+
if (cost > m.generator.capacity) reachable = false
|
|
128
|
+
} else {
|
|
129
|
+
if (cost > curEnergy) reachable = false
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const flightSeconds = Number(
|
|
134
|
+
calc_group_flighttime(
|
|
135
|
+
totalThrust,
|
|
136
|
+
haulCount,
|
|
137
|
+
pooledHaulCap,
|
|
138
|
+
weightedHaulEffNum,
|
|
139
|
+
totalMass,
|
|
140
|
+
distance
|
|
141
|
+
)
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
if (flightSeconds > TRAVEL_MAX_DURATION) reachable = false
|
|
145
|
+
|
|
146
|
+
for (const m of movers) {
|
|
147
|
+
if (!m.hasMovement || !m.engines) continue
|
|
148
|
+
const key = String(m.ref.entityId)
|
|
149
|
+
const cost = energyCostByMover[key] ?? 0
|
|
150
|
+
const curEnergy = energyByMover.get(key) ?? 0
|
|
151
|
+
energyByMover.set(key, Math.max(0, curEnergy - cost))
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
clock = Math.max(clock, mobilityBarrier) + flightSeconds
|
|
155
|
+
|
|
156
|
+
legs.push({
|
|
157
|
+
from,
|
|
158
|
+
to,
|
|
159
|
+
distanceCells,
|
|
160
|
+
energyCostByMover,
|
|
161
|
+
rechargeBefore,
|
|
162
|
+
rechargeSeconds,
|
|
163
|
+
flightSeconds,
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
from = to
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return {legs, totalSeconds: clock, reachable}
|
|
170
|
+
}
|
package/src/travel/travel.ts
CHANGED
|
@@ -14,7 +14,6 @@ import {
|
|
|
14
14
|
type Checksum256,
|
|
15
15
|
Int64,
|
|
16
16
|
type Int64Type,
|
|
17
|
-
UInt16,
|
|
18
17
|
UInt32,
|
|
19
18
|
type UInt32Type,
|
|
20
19
|
UInt64,
|
|
@@ -23,17 +22,30 @@ import {
|
|
|
23
22
|
|
|
24
23
|
import type {ServerContract} from '../contracts'
|
|
25
24
|
import {
|
|
25
|
+
BASE_HAUL_PENALTY_MILLI,
|
|
26
26
|
BASE_ORBITAL_MASS,
|
|
27
27
|
type CargoMassInfo,
|
|
28
28
|
type Distance,
|
|
29
|
+
HAULER_EFFICIENCY_DENOM,
|
|
30
|
+
MASS_STAT_SCALE,
|
|
29
31
|
MAX_ORBITAL_ALTITUDE,
|
|
30
32
|
MIN_ORBITAL_ALTITUDE,
|
|
33
|
+
MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL,
|
|
34
|
+
MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE,
|
|
31
35
|
PRECISION,
|
|
32
36
|
type ShipLike,
|
|
33
37
|
TaskType,
|
|
34
38
|
} from '../types'
|
|
39
|
+
import {EntityClass} from '../data/kind-registry'
|
|
35
40
|
import {getItem} from '../data/catalog'
|
|
36
41
|
import {hasSystem} from '../utils/system'
|
|
42
|
+
import {WH} from '../derivation/wormhole'
|
|
43
|
+
import * as scheduleModel from '../scheduling/schedule'
|
|
44
|
+
import type {ScheduleData} from '../scheduling/schedule'
|
|
45
|
+
|
|
46
|
+
function isPositionalTask(task: ServerContract.Types.task): boolean {
|
|
47
|
+
return task.type.equals(TaskType.TRAVEL) || task.type.equals(TaskType.TRANSIT)
|
|
48
|
+
}
|
|
37
49
|
|
|
38
50
|
export function calc_orbital_altitude(mass: number): number {
|
|
39
51
|
if (mass <= BASE_ORBITAL_MASS) {
|
|
@@ -111,15 +123,16 @@ export function getInterpolatedPosition(
|
|
|
111
123
|
taskIndex: number,
|
|
112
124
|
taskProgress: number
|
|
113
125
|
): FloatPosition {
|
|
114
|
-
|
|
126
|
+
const tasks = mobilityTasks(entity)
|
|
127
|
+
if (tasks.length === 0) {
|
|
115
128
|
return {x: Number(entity.coordinates.x), y: Number(entity.coordinates.y)}
|
|
116
129
|
}
|
|
117
130
|
if (taskIndex < 0) {
|
|
118
|
-
const settled = getFlightOrigin(entity,
|
|
131
|
+
const settled = getFlightOrigin(entity, tasks.length)
|
|
119
132
|
return {x: Number(settled.x), y: Number(settled.y)}
|
|
120
133
|
}
|
|
121
|
-
const task =
|
|
122
|
-
if (!task
|
|
134
|
+
const task = tasks[taskIndex]
|
|
135
|
+
if (!isPositionalTask(task) || !task.coordinates) {
|
|
123
136
|
const origin = getFlightOrigin(entity, taskIndex)
|
|
124
137
|
return {x: Number(origin.x), y: Number(origin.y)}
|
|
125
138
|
}
|
|
@@ -176,14 +189,15 @@ export function calc_rechargetime(
|
|
|
176
189
|
const cap = UInt32.from(capacity)
|
|
177
190
|
const eng = UInt32.from(energy)
|
|
178
191
|
if (eng.gte(cap)) return UInt32.zero
|
|
179
|
-
|
|
192
|
+
const ticks = cap.subtracting(eng).dividing(recharge)
|
|
193
|
+
return ticks.equals(UInt32.zero) ? UInt32.from(1) : ticks
|
|
180
194
|
}
|
|
181
195
|
|
|
182
196
|
export function calc_ship_rechargetime(ship: ShipLike): UInt32 {
|
|
183
197
|
if (!ship.generator) return UInt32.from(0)
|
|
184
198
|
return calc_rechargetime(
|
|
185
199
|
ship.generator.capacity,
|
|
186
|
-
ship.energy ??
|
|
200
|
+
ship.energy ?? UInt32.from(0),
|
|
187
201
|
ship.generator.recharge
|
|
188
202
|
)
|
|
189
203
|
}
|
|
@@ -192,20 +206,46 @@ export function calc_flighttime(distance: UInt64Type, acceleration: number): UIn
|
|
|
192
206
|
return UInt32.from(2 * Math.sqrt(Number(distance) / acceleration))
|
|
193
207
|
}
|
|
194
208
|
|
|
209
|
+
export function calc_travel_flighttime(distance: UInt64Type, acceleration: number): UInt32 {
|
|
210
|
+
const cruiseTransitionDistance = 2 * PRECISION
|
|
211
|
+
if (Number(distance) <= cruiseTransitionDistance) {
|
|
212
|
+
return calc_flighttime(distance, acceleration)
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const cruiseVelocity = Math.sqrt(acceleration * cruiseTransitionDistance)
|
|
216
|
+
return UInt32.from(Number(distance) / cruiseVelocity + cruiseVelocity / acceleration)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function calc_transit_duration(ax: number, ay: number, bx: number, by: number): UInt32 {
|
|
220
|
+
const distance = distanceBetweenPoints(ax, ay, bx, by)
|
|
221
|
+
return UInt32.from(Math.floor(distance.toNumber() / (PRECISION * WH.TRANSIT_SPEED)))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// The active entity's chosen loader lane (lowest slot), mirroring cargo.cpp lane selection.
|
|
225
|
+
export function shipLoaderLane(ship: ShipLike): {thrust: number; mass: number} | undefined {
|
|
226
|
+
const lanes = ship.loader_lanes ?? []
|
|
227
|
+
if (lanes.length === 0) return undefined
|
|
228
|
+
let lowest = lanes[0]
|
|
229
|
+
for (const lane of lanes) {
|
|
230
|
+
if (Number(lane.slot_index) < Number(lowest.slot_index)) lowest = lane
|
|
231
|
+
}
|
|
232
|
+
return {thrust: Number(lowest.thrust), mass: Number(lowest.mass)}
|
|
233
|
+
}
|
|
234
|
+
|
|
195
235
|
export function calc_loader_flighttime(ship: ShipLike, mass: UInt64, altitude?: number): UInt32 {
|
|
196
236
|
const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass))
|
|
197
237
|
return calc_flighttime(z, calc_loader_acceleration(ship, mass))
|
|
198
238
|
}
|
|
199
239
|
|
|
200
240
|
export function calc_loader_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
return calc_acceleration(thrust, Number(mass)
|
|
241
|
+
const lane = shipLoaderLane(ship)
|
|
242
|
+
const thrust = lane ? lane.thrust : 0
|
|
243
|
+
return calc_acceleration(thrust, Number(mass))
|
|
204
244
|
}
|
|
205
245
|
|
|
206
246
|
export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UInt64): UInt32 {
|
|
207
247
|
const acceleration = calc_ship_acceleration(ship, mass)
|
|
208
|
-
return
|
|
248
|
+
return calc_travel_flighttime(distance, acceleration)
|
|
209
249
|
}
|
|
210
250
|
|
|
211
251
|
export function calc_ship_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
@@ -214,7 +254,7 @@ export function calc_ship_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
|
214
254
|
}
|
|
215
255
|
|
|
216
256
|
export function calc_acceleration(thrust: number, mass: number): number {
|
|
217
|
-
return (thrust / mass) * PRECISION
|
|
257
|
+
return (thrust / (mass * MASS_STAT_SCALE)) * PRECISION
|
|
218
258
|
}
|
|
219
259
|
|
|
220
260
|
export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64 {
|
|
@@ -222,8 +262,10 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
|
|
|
222
262
|
|
|
223
263
|
mass.add(ship.hullmass)
|
|
224
264
|
|
|
225
|
-
if (ship.
|
|
226
|
-
|
|
265
|
+
if (ship.loader_lanes && ship.loader_lanes.length > 0) {
|
|
266
|
+
for (const l of ship.loader_lanes) {
|
|
267
|
+
mass.add(UInt64.from(l.mass))
|
|
268
|
+
}
|
|
227
269
|
}
|
|
228
270
|
|
|
229
271
|
for (const cargo of cargos) {
|
|
@@ -234,8 +276,31 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
|
|
|
234
276
|
return mass
|
|
235
277
|
}
|
|
236
278
|
|
|
279
|
+
export function calc_group_flighttime(
|
|
280
|
+
totalThrust: number,
|
|
281
|
+
haulCount: number,
|
|
282
|
+
pooledHaulCap: number,
|
|
283
|
+
weightedHaulEffNum: number,
|
|
284
|
+
totalMass: number,
|
|
285
|
+
distance: UInt64Type
|
|
286
|
+
): UInt32 {
|
|
287
|
+
const avgHaulEff = pooledHaulCap > 0 ? Math.trunc(weightedHaulEffNum / pooledHaulCap) : 0
|
|
288
|
+
let effectiveThrust = totalThrust
|
|
289
|
+
if (haulCount > 0) {
|
|
290
|
+
const penaltyMilli =
|
|
291
|
+
1000 +
|
|
292
|
+
Math.trunc(
|
|
293
|
+
(haulCount * BASE_HAUL_PENALTY_MILLI * (HAULER_EFFICIENCY_DENOM - avgHaulEff)) /
|
|
294
|
+
HAULER_EFFICIENCY_DENOM
|
|
295
|
+
)
|
|
296
|
+
effectiveThrust = Math.trunc((totalThrust * 1000) / penaltyMilli)
|
|
297
|
+
}
|
|
298
|
+
const acceleration = calc_acceleration(effectiveThrust, totalMass)
|
|
299
|
+
return calc_travel_flighttime(distance, acceleration)
|
|
300
|
+
}
|
|
301
|
+
|
|
237
302
|
export function calc_energyusage(distance: UInt64Type, drain: UInt32Type): UInt32 {
|
|
238
|
-
return UInt64.from(distance).
|
|
303
|
+
return UInt64.from(distance).multiplying(drain).dividing(PRECISION)
|
|
239
304
|
}
|
|
240
305
|
|
|
241
306
|
export function calculateTransferTime(
|
|
@@ -258,10 +323,10 @@ export function calculateTransferTime(
|
|
|
258
323
|
return UInt32.from(0)
|
|
259
324
|
}
|
|
260
325
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
326
|
+
const lane = shipLoaderLane(ship)
|
|
327
|
+
if (!lane) return UInt32.from(0)
|
|
328
|
+
mass = UInt64.from(mass).adding(UInt64.from(lane.mass))
|
|
329
|
+
return calc_loader_flighttime(ship, mass)
|
|
265
330
|
}
|
|
266
331
|
|
|
267
332
|
export function calculateRefuelingTime(ship: ShipLike): UInt32 {
|
|
@@ -316,25 +381,22 @@ export function calculateLoadTimeBreakdown(
|
|
|
316
381
|
let unloadTime = 0
|
|
317
382
|
let loadTime = 0
|
|
318
383
|
|
|
319
|
-
|
|
320
|
-
|
|
384
|
+
const lane = shipLoaderLane(ship)
|
|
385
|
+
|
|
386
|
+
if (mass_unload.gt(UInt64.zero) && lane) {
|
|
387
|
+
const totalMass = UInt64.from(mass_unload).adding(UInt64.from(lane.mass))
|
|
321
388
|
unloadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
322
389
|
}
|
|
323
390
|
|
|
324
|
-
if (mass_load.gt(UInt64.zero) &&
|
|
325
|
-
const totalMass = UInt64.from(mass_load).adding(
|
|
391
|
+
if (mass_load.gt(UInt64.zero) && lane) {
|
|
392
|
+
const totalMass = UInt64.from(mass_load).adding(UInt64.from(lane.mass))
|
|
326
393
|
loadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
327
394
|
}
|
|
328
395
|
|
|
329
|
-
const numLoaders = ship.loaders ? Number(ship.loaders.quantity) : 0
|
|
330
|
-
const totalTime = numLoaders > 0 ? (unloadTime + loadTime) / numLoaders : 0
|
|
331
|
-
const unloadTimePerLoader = numLoaders > 0 ? unloadTime / numLoaders : 0
|
|
332
|
-
const loadTimePerLoader = numLoaders > 0 ? loadTime / numLoaders : 0
|
|
333
|
-
|
|
334
396
|
return {
|
|
335
|
-
unloadTime
|
|
336
|
-
loadTime
|
|
337
|
-
totalTime,
|
|
397
|
+
unloadTime,
|
|
398
|
+
loadTime,
|
|
399
|
+
totalTime: unloadTime + loadTime,
|
|
338
400
|
unloadMass: Number(mass_unload),
|
|
339
401
|
loadMass: Number(mass_load),
|
|
340
402
|
}
|
|
@@ -368,24 +430,16 @@ export function estimateTravelTime(
|
|
|
368
430
|
let loadTime = UInt32.zero
|
|
369
431
|
let unloadTime = UInt32.zero
|
|
370
432
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
ship
|
|
376
|
-
) {
|
|
377
|
-
const totalMass = UInt64.from(loadMass).adding(ship.loaders.mass)
|
|
378
|
-
loadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity)
|
|
433
|
+
const lane = shipLoaderLane(ship)
|
|
434
|
+
|
|
435
|
+
if (loadMass && UInt32.from(loadMass).gt(UInt32.zero) && lane) {
|
|
436
|
+
const totalMass = UInt64.from(loadMass).adding(UInt64.from(lane.mass))
|
|
437
|
+
loadTime = calc_loader_flighttime(ship, totalMass)
|
|
379
438
|
}
|
|
380
439
|
|
|
381
|
-
if (
|
|
382
|
-
unloadMass
|
|
383
|
-
|
|
384
|
-
ship.loaders &&
|
|
385
|
-
ship.loaders.quantity.gt(UInt32.zero)
|
|
386
|
-
) {
|
|
387
|
-
const totalMass = UInt64.from(unloadMass).adding(ship.loaders.mass)
|
|
388
|
-
unloadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity)
|
|
440
|
+
if (unloadMass && UInt32.from(unloadMass).gt(UInt32.zero) && lane) {
|
|
441
|
+
const totalMass = UInt64.from(unloadMass).adding(UInt64.from(lane.mass))
|
|
442
|
+
unloadTime = calc_loader_flighttime(ship, totalMass)
|
|
389
443
|
}
|
|
390
444
|
|
|
391
445
|
return {
|
|
@@ -417,30 +471,51 @@ export function hasEnergyForDistance(ship: ShipLike, distance: UInt64Type): bool
|
|
|
417
471
|
return UInt64.from(ship.energy ?? 0).gte(energyNeeded)
|
|
418
472
|
}
|
|
419
473
|
|
|
474
|
+
export interface TransferLoaderLane {
|
|
475
|
+
slot_index?: {toNumber(): number} | number
|
|
476
|
+
thrust: {toNumber(): number} | number
|
|
477
|
+
mass: {toNumber(): number} | number
|
|
478
|
+
}
|
|
479
|
+
|
|
420
480
|
export interface TransferEntity {
|
|
421
481
|
location: {z?: {toNumber(): number} | number}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
482
|
+
entityClass: EntityClass
|
|
483
|
+
loaderLanes?: TransferLoaderLane[]
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
function toNum(v: {toNumber(): number} | number | undefined): number {
|
|
487
|
+
if (v === undefined) return 0
|
|
488
|
+
return typeof v === 'number' ? v : v.toNumber()
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
// Mirrors cargo.cpp worker_lane_key_or_mobility: lowest-slot loader lane (display has no busy context).
|
|
492
|
+
function chosenLoaderLane(entity: TransferEntity): TransferLoaderLane | undefined {
|
|
493
|
+
const lanes = entity.loaderLanes ?? []
|
|
494
|
+
if (lanes.length === 0) return undefined
|
|
495
|
+
let lowest = lanes[0]
|
|
496
|
+
for (const lane of lanes) {
|
|
497
|
+
if (toNum(lane.slot_index) < toNum(lowest.slot_index)) lowest = lane
|
|
426
498
|
}
|
|
499
|
+
return lowest
|
|
427
500
|
}
|
|
428
501
|
|
|
429
|
-
export interface HasScheduleAndLocation {
|
|
502
|
+
export interface HasScheduleAndLocation extends ScheduleData {
|
|
430
503
|
coordinates: ServerContract.ActionParams.Type.coordinates
|
|
431
|
-
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function mobilityTasks(entity: HasScheduleAndLocation): ServerContract.Types.task[] {
|
|
507
|
+
return scheduleModel.mobilityLane(entity)?.schedule.tasks ?? []
|
|
432
508
|
}
|
|
433
509
|
|
|
434
510
|
export function getFlightOrigin(
|
|
435
511
|
entity: HasScheduleAndLocation,
|
|
436
512
|
flightTaskIndex: number
|
|
437
513
|
): ServerContract.ActionParams.Type.coordinates {
|
|
438
|
-
|
|
439
|
-
|
|
514
|
+
const tasks = mobilityTasks(entity)
|
|
440
515
|
let origin = entity.coordinates
|
|
441
|
-
for (let i = 0; i < flightTaskIndex && i <
|
|
442
|
-
const task =
|
|
443
|
-
if (task
|
|
516
|
+
for (let i = 0; i < flightTaskIndex && i < tasks.length; i++) {
|
|
517
|
+
const task = tasks[i]
|
|
518
|
+
if (isPositionalTask(task) && task.coordinates) {
|
|
444
519
|
origin = task.coordinates
|
|
445
520
|
}
|
|
446
521
|
}
|
|
@@ -450,11 +525,10 @@ export function getFlightOrigin(
|
|
|
450
525
|
export function getDestinationLocation(
|
|
451
526
|
entity: HasScheduleAndLocation
|
|
452
527
|
): ServerContract.ActionParams.Type.coordinates | undefined {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
|
|
528
|
+
const tasks = mobilityTasks(entity)
|
|
529
|
+
for (let i = tasks.length - 1; i >= 0; i--) {
|
|
530
|
+
const task = tasks[i]
|
|
531
|
+
if (isPositionalTask(task) && task.coordinates) {
|
|
458
532
|
return task.coordinates
|
|
459
533
|
}
|
|
460
534
|
}
|
|
@@ -467,16 +541,17 @@ export function getPositionAt(
|
|
|
467
541
|
taskIndex: number,
|
|
468
542
|
taskProgress: number
|
|
469
543
|
): ServerContract.ActionParams.Type.coordinates {
|
|
470
|
-
|
|
544
|
+
const tasks = mobilityTasks(entity)
|
|
545
|
+
if (tasks.length === 0) {
|
|
471
546
|
return entity.coordinates
|
|
472
547
|
}
|
|
473
548
|
if (taskIndex < 0) {
|
|
474
|
-
return getFlightOrigin(entity,
|
|
549
|
+
return getFlightOrigin(entity, tasks.length)
|
|
475
550
|
}
|
|
476
551
|
|
|
477
|
-
const task =
|
|
552
|
+
const task = tasks[taskIndex]
|
|
478
553
|
|
|
479
|
-
if (!task
|
|
554
|
+
if (!isPositionalTask(task) || !task.coordinates) {
|
|
480
555
|
return getFlightOrigin(entity, taskIndex)
|
|
481
556
|
}
|
|
482
557
|
|
|
@@ -490,68 +565,60 @@ export function getPositionAt(
|
|
|
490
565
|
}
|
|
491
566
|
}
|
|
492
567
|
|
|
493
|
-
export function
|
|
494
|
-
|
|
495
|
-
|
|
568
|
+
export function minTransferDistance(entityClass: EntityClass): number {
|
|
569
|
+
return entityClass === EntityClass.OrbitalVessel
|
|
570
|
+
? MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL
|
|
571
|
+
: MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// Mirrors cargo.cpp calc_onesided_duration: single active loader's thrust + mass, no ÷quantity.
|
|
575
|
+
export function calc_onesided_duration(
|
|
576
|
+
loaderThrust: number,
|
|
577
|
+
loaderMass: number,
|
|
578
|
+
activeZ: number,
|
|
579
|
+
counterpartZ: number,
|
|
580
|
+
activeEntityClass: EntityClass,
|
|
581
|
+
counterpartEntityClass: EntityClass,
|
|
496
582
|
cargoMass: number
|
|
497
583
|
): number {
|
|
498
|
-
if (cargoMass === 0) {
|
|
584
|
+
if (cargoMass === 0 || loaderThrust === 0) {
|
|
499
585
|
return 0
|
|
500
586
|
}
|
|
587
|
+
const rawDistance = Math.abs(activeZ - counterpartZ)
|
|
588
|
+
const minDistance = Math.max(
|
|
589
|
+
minTransferDistance(activeEntityClass),
|
|
590
|
+
minTransferDistance(counterpartEntityClass)
|
|
591
|
+
)
|
|
592
|
+
const distance = rawDistance < minDistance ? minDistance : rawDistance
|
|
593
|
+
const totalMass = cargoMass + loaderMass
|
|
594
|
+
const acceleration = calc_acceleration(loaderThrust, totalMass)
|
|
595
|
+
const flightTime = Math.floor(2 * Math.sqrt(distance / acceleration))
|
|
596
|
+
return flightTime === 0 ? 1 : flightTime
|
|
597
|
+
}
|
|
501
598
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
typeof source.loaders.mass === 'number'
|
|
513
|
-
? source.loaders.mass
|
|
514
|
-
: source.loaders.mass.toNumber()
|
|
515
|
-
const qty =
|
|
516
|
-
typeof source.loaders.quantity === 'number'
|
|
517
|
-
? source.loaders.quantity
|
|
518
|
-
: source.loaders.quantity.toNumber()
|
|
519
|
-
totalThrust += thrust * qty
|
|
520
|
-
totalLoaderMass += mass * qty
|
|
521
|
-
totalQuantity += qty
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
if (dest.loaders) {
|
|
525
|
-
const thrust =
|
|
526
|
-
typeof dest.loaders.thrust === 'number'
|
|
527
|
-
? dest.loaders.thrust
|
|
528
|
-
: dest.loaders.thrust.toNumber()
|
|
529
|
-
const mass =
|
|
530
|
-
typeof dest.loaders.mass === 'number' ? dest.loaders.mass : dest.loaders.mass.toNumber()
|
|
531
|
-
const qty =
|
|
532
|
-
typeof dest.loaders.quantity === 'number'
|
|
533
|
-
? dest.loaders.quantity
|
|
534
|
-
: dest.loaders.quantity.toNumber()
|
|
535
|
-
totalThrust += thrust * qty
|
|
536
|
-
totalLoaderMass += mass * qty
|
|
537
|
-
totalQuantity += qty
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
if (totalThrust === 0 || totalQuantity === 0) {
|
|
599
|
+
// Mirrors cargo.cpp: the active (loader-bearing) entity's chosen loader lane drives the duration.
|
|
600
|
+
export function calc_transfer_duration(
|
|
601
|
+
source: TransferEntity,
|
|
602
|
+
dest: TransferEntity,
|
|
603
|
+
cargoMass: number
|
|
604
|
+
): number {
|
|
605
|
+
const active = chosenLoaderLane(source) ? source : dest
|
|
606
|
+
const counterpart = active === source ? dest : source
|
|
607
|
+
const lane = chosenLoaderLane(active)
|
|
608
|
+
if (!lane) {
|
|
541
609
|
return 0
|
|
542
610
|
}
|
|
543
611
|
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
return Math.floor(flightTime / totalQuantity)
|
|
612
|
+
const activeZ = toNum(active.location.z)
|
|
613
|
+
const counterpartZ = toNum(counterpart.location.z)
|
|
614
|
+
|
|
615
|
+
return calc_onesided_duration(
|
|
616
|
+
toNum(lane.thrust),
|
|
617
|
+
toNum(lane.mass),
|
|
618
|
+
activeZ,
|
|
619
|
+
counterpartZ,
|
|
620
|
+
active.entityClass,
|
|
621
|
+
counterpart.entityClass,
|
|
622
|
+
cargoMass
|
|
623
|
+
)
|
|
557
624
|
}
|