@shipload/sdk 1.0.0-next.5 → 1.0.0-next.51
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 +3167 -1353
- package/lib/shipload.js +13319 -5640
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +13091 -5589
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1037 -0
- package/lib/testing.js +4363 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +4357 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.ts +51 -0
- package/src/capabilities/crafting.test.ts +7 -0
- package/src/capabilities/crafting.ts +6 -7
- package/src/capabilities/gathering.test.ts +29 -0
- package/src/capabilities/gathering.ts +37 -19
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +22 -0
- package/src/capabilities/storage.ts +16 -1
- package/src/contracts/platform.ts +231 -3
- package/src/contracts/server.ts +1178 -511
- 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 +31 -16
- package/src/data/capability-formulas.ts +21 -14
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +13 -47
- package/src/data/entities.json +154 -10
- package/src/data/item-ids.ts +31 -12
- package/src/data/items.json +192 -74
- package/src/data/kind-registry.json +131 -0
- package/src/data/kind-registry.ts +172 -0
- package/src/data/metadata.ts +166 -48
- package/src/data/recipes-runtime.ts +5 -23
- package/src/data/recipes.json +1003 -163
- package/src/derivation/build-methods.test.ts +13 -0
- package/src/derivation/build-methods.ts +48 -0
- package/src/derivation/capabilities.test.ts +151 -0
- package/src/derivation/capabilities.ts +527 -0
- package/src/derivation/capability-mappings.ts +58 -16
- package/src/derivation/crafting.ts +36 -33
- package/src/derivation/index.ts +28 -2
- package/src/derivation/recipe-usage.test.ts +81 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +98 -19
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +56 -0
- package/src/derivation/stars.test.ts +67 -0
- package/src/derivation/stars.ts +25 -0
- package/src/derivation/stats.ts +6 -6
- 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 +141 -0
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +131 -134
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/errors.ts +12 -16
- package/src/format.ts +26 -4
- package/src/index-module.ts +294 -34
- package/src/managers/actions.ts +616 -105
- package/src/managers/base.ts +6 -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 +412 -0
- package/src/managers/context.ts +29 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +27 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/flatten-gather-plan.test.ts +80 -0
- package/src/managers/index.ts +20 -1
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +14 -0
- package/src/managers/nft.ts +70 -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 +336 -0
- package/src/nft/description.ts +104 -36
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +242 -0
- package/src/planner/planner.test.ts +325 -0
- package/src/resolution/describe-module.ts +43 -25
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.test.ts +48 -0
- package/src/resolution/resolve-item.ts +74 -47
- 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.ts +108 -0
- package/src/scheduling/cancel.test.ts +348 -0
- package/src/scheduling/cancel.ts +209 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +249 -0
- package/src/scheduling/lanes.ts +198 -0
- package/src/scheduling/projection.ts +210 -107
- package/src/scheduling/schedule.ts +240 -117
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/scheduling/unwrap.test.ts +86 -0
- package/src/scheduling/unwrap.ts +190 -0
- package/src/shipload.ts +26 -1
- 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.ts +23 -0
- package/src/travel/route-planner.ts +277 -0
- package/src/travel/route-simulator.ts +174 -0
- package/src/travel/travel.ts +175 -118
- package/src/types/capabilities.ts +29 -6
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +39 -14
- package/src/utils/cargo.test.ts +14 -0
- package/src/utils/cargo.ts +29 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/system.ts +36 -24
- 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
package/src/travel/travel.ts
CHANGED
|
@@ -23,17 +23,29 @@ import {
|
|
|
23
23
|
|
|
24
24
|
import type {ServerContract} from '../contracts'
|
|
25
25
|
import {
|
|
26
|
+
BASE_HAUL_PENALTY_MILLI,
|
|
26
27
|
BASE_ORBITAL_MASS,
|
|
27
28
|
type CargoMassInfo,
|
|
28
29
|
type Distance,
|
|
30
|
+
HAULER_EFFICIENCY_DENOM,
|
|
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,7 +189,8 @@ 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 {
|
|
@@ -192,15 +206,31 @@ 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_transit_duration(ax: number, ay: number, bx: number, by: number): UInt32 {
|
|
210
|
+
const distance = distanceBetweenPoints(ax, ay, bx, by)
|
|
211
|
+
return UInt32.from(Math.floor(distance.toNumber() / (PRECISION * WH.TRANSIT_SPEED)))
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// The active entity's chosen loader lane (lowest slot), mirroring cargo.cpp lane selection.
|
|
215
|
+
export function shipLoaderLane(ship: ShipLike): {thrust: number; mass: number} | undefined {
|
|
216
|
+
const lanes = ship.loader_lanes ?? []
|
|
217
|
+
if (lanes.length === 0) return undefined
|
|
218
|
+
let lowest = lanes[0]
|
|
219
|
+
for (const lane of lanes) {
|
|
220
|
+
if (Number(lane.slot_index) < Number(lowest.slot_index)) lowest = lane
|
|
221
|
+
}
|
|
222
|
+
return {thrust: Number(lowest.thrust), mass: Number(lowest.mass)}
|
|
223
|
+
}
|
|
224
|
+
|
|
195
225
|
export function calc_loader_flighttime(ship: ShipLike, mass: UInt64, altitude?: number): UInt32 {
|
|
196
226
|
const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass))
|
|
197
227
|
return calc_flighttime(z, calc_loader_acceleration(ship, mass))
|
|
198
228
|
}
|
|
199
229
|
|
|
200
230
|
export function calc_loader_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
return calc_acceleration(thrust, Number(mass)
|
|
231
|
+
const lane = shipLoaderLane(ship)
|
|
232
|
+
const thrust = lane ? lane.thrust : 0
|
|
233
|
+
return calc_acceleration(thrust, Number(mass))
|
|
204
234
|
}
|
|
205
235
|
|
|
206
236
|
export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UInt64): UInt32 {
|
|
@@ -222,8 +252,10 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
|
|
|
222
252
|
|
|
223
253
|
mass.add(ship.hullmass)
|
|
224
254
|
|
|
225
|
-
if (ship.
|
|
226
|
-
|
|
255
|
+
if (ship.loader_lanes && ship.loader_lanes.length > 0) {
|
|
256
|
+
for (const l of ship.loader_lanes) {
|
|
257
|
+
mass.add(UInt64.from(l.mass))
|
|
258
|
+
}
|
|
227
259
|
}
|
|
228
260
|
|
|
229
261
|
for (const cargo of cargos) {
|
|
@@ -234,6 +266,29 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
|
|
|
234
266
|
return mass
|
|
235
267
|
}
|
|
236
268
|
|
|
269
|
+
export function calc_group_flighttime(
|
|
270
|
+
totalThrust: number,
|
|
271
|
+
haulCount: number,
|
|
272
|
+
pooledHaulCap: number,
|
|
273
|
+
weightedHaulEffNum: number,
|
|
274
|
+
totalMass: number,
|
|
275
|
+
distance: UInt64Type
|
|
276
|
+
): UInt32 {
|
|
277
|
+
const avgHaulEff = pooledHaulCap > 0 ? Math.trunc(weightedHaulEffNum / pooledHaulCap) : 0
|
|
278
|
+
let effectiveThrust = totalThrust
|
|
279
|
+
if (haulCount > 0) {
|
|
280
|
+
const penaltyMilli =
|
|
281
|
+
1000 +
|
|
282
|
+
Math.trunc(
|
|
283
|
+
(haulCount * BASE_HAUL_PENALTY_MILLI * (HAULER_EFFICIENCY_DENOM - avgHaulEff)) /
|
|
284
|
+
HAULER_EFFICIENCY_DENOM
|
|
285
|
+
)
|
|
286
|
+
effectiveThrust = Math.trunc((totalThrust * 1000) / penaltyMilli)
|
|
287
|
+
}
|
|
288
|
+
const acceleration = calc_acceleration(effectiveThrust, totalMass)
|
|
289
|
+
return calc_flighttime(distance, acceleration)
|
|
290
|
+
}
|
|
291
|
+
|
|
237
292
|
export function calc_energyusage(distance: UInt64Type, drain: UInt32Type): UInt32 {
|
|
238
293
|
return UInt64.from(distance).dividing(PRECISION).multiplying(drain)
|
|
239
294
|
}
|
|
@@ -258,10 +313,10 @@ export function calculateTransferTime(
|
|
|
258
313
|
return UInt32.from(0)
|
|
259
314
|
}
|
|
260
315
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return
|
|
316
|
+
const lane = shipLoaderLane(ship)
|
|
317
|
+
if (!lane) return UInt32.from(0)
|
|
318
|
+
mass = UInt64.from(mass).adding(UInt64.from(lane.mass))
|
|
319
|
+
return calc_loader_flighttime(ship, mass)
|
|
265
320
|
}
|
|
266
321
|
|
|
267
322
|
export function calculateRefuelingTime(ship: ShipLike): UInt32 {
|
|
@@ -316,25 +371,22 @@ export function calculateLoadTimeBreakdown(
|
|
|
316
371
|
let unloadTime = 0
|
|
317
372
|
let loadTime = 0
|
|
318
373
|
|
|
319
|
-
|
|
320
|
-
|
|
374
|
+
const lane = shipLoaderLane(ship)
|
|
375
|
+
|
|
376
|
+
if (mass_unload.gt(UInt64.zero) && lane) {
|
|
377
|
+
const totalMass = UInt64.from(mass_unload).adding(UInt64.from(lane.mass))
|
|
321
378
|
unloadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
322
379
|
}
|
|
323
380
|
|
|
324
|
-
if (mass_load.gt(UInt64.zero) &&
|
|
325
|
-
const totalMass = UInt64.from(mass_load).adding(
|
|
381
|
+
if (mass_load.gt(UInt64.zero) && lane) {
|
|
382
|
+
const totalMass = UInt64.from(mass_load).adding(UInt64.from(lane.mass))
|
|
326
383
|
loadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
327
384
|
}
|
|
328
385
|
|
|
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
386
|
return {
|
|
335
|
-
unloadTime
|
|
336
|
-
loadTime
|
|
337
|
-
totalTime,
|
|
387
|
+
unloadTime,
|
|
388
|
+
loadTime,
|
|
389
|
+
totalTime: unloadTime + loadTime,
|
|
338
390
|
unloadMass: Number(mass_unload),
|
|
339
391
|
loadMass: Number(mass_load),
|
|
340
392
|
}
|
|
@@ -368,24 +420,16 @@ export function estimateTravelTime(
|
|
|
368
420
|
let loadTime = UInt32.zero
|
|
369
421
|
let unloadTime = UInt32.zero
|
|
370
422
|
|
|
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)
|
|
423
|
+
const lane = shipLoaderLane(ship)
|
|
424
|
+
|
|
425
|
+
if (loadMass && UInt32.from(loadMass).gt(UInt32.zero) && lane) {
|
|
426
|
+
const totalMass = UInt64.from(loadMass).adding(UInt64.from(lane.mass))
|
|
427
|
+
loadTime = calc_loader_flighttime(ship, totalMass)
|
|
379
428
|
}
|
|
380
429
|
|
|
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)
|
|
430
|
+
if (unloadMass && UInt32.from(unloadMass).gt(UInt32.zero) && lane) {
|
|
431
|
+
const totalMass = UInt64.from(unloadMass).adding(UInt64.from(lane.mass))
|
|
432
|
+
unloadTime = calc_loader_flighttime(ship, totalMass)
|
|
389
433
|
}
|
|
390
434
|
|
|
391
435
|
return {
|
|
@@ -417,30 +461,51 @@ export function hasEnergyForDistance(ship: ShipLike, distance: UInt64Type): bool
|
|
|
417
461
|
return UInt64.from(ship.energy ?? 0).gte(energyNeeded)
|
|
418
462
|
}
|
|
419
463
|
|
|
464
|
+
export interface TransferLoaderLane {
|
|
465
|
+
slot_index?: {toNumber(): number} | number
|
|
466
|
+
thrust: {toNumber(): number} | number
|
|
467
|
+
mass: {toNumber(): number} | number
|
|
468
|
+
}
|
|
469
|
+
|
|
420
470
|
export interface TransferEntity {
|
|
421
471
|
location: {z?: {toNumber(): number} | number}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
472
|
+
entityClass: EntityClass
|
|
473
|
+
loaderLanes?: TransferLoaderLane[]
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function toNum(v: {toNumber(): number} | number | undefined): number {
|
|
477
|
+
if (v === undefined) return 0
|
|
478
|
+
return typeof v === 'number' ? v : v.toNumber()
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Mirrors cargo.cpp worker_lane_key_or_mobility: lowest-slot loader lane (display has no busy context).
|
|
482
|
+
function chosenLoaderLane(entity: TransferEntity): TransferLoaderLane | undefined {
|
|
483
|
+
const lanes = entity.loaderLanes ?? []
|
|
484
|
+
if (lanes.length === 0) return undefined
|
|
485
|
+
let lowest = lanes[0]
|
|
486
|
+
for (const lane of lanes) {
|
|
487
|
+
if (toNum(lane.slot_index) < toNum(lowest.slot_index)) lowest = lane
|
|
426
488
|
}
|
|
489
|
+
return lowest
|
|
427
490
|
}
|
|
428
491
|
|
|
429
|
-
export interface HasScheduleAndLocation {
|
|
492
|
+
export interface HasScheduleAndLocation extends ScheduleData {
|
|
430
493
|
coordinates: ServerContract.ActionParams.Type.coordinates
|
|
431
|
-
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function mobilityTasks(entity: HasScheduleAndLocation): ServerContract.Types.task[] {
|
|
497
|
+
return scheduleModel.mobilityLane(entity)?.schedule.tasks ?? []
|
|
432
498
|
}
|
|
433
499
|
|
|
434
500
|
export function getFlightOrigin(
|
|
435
501
|
entity: HasScheduleAndLocation,
|
|
436
502
|
flightTaskIndex: number
|
|
437
503
|
): ServerContract.ActionParams.Type.coordinates {
|
|
438
|
-
|
|
439
|
-
|
|
504
|
+
const tasks = mobilityTasks(entity)
|
|
440
505
|
let origin = entity.coordinates
|
|
441
|
-
for (let i = 0; i < flightTaskIndex && i <
|
|
442
|
-
const task =
|
|
443
|
-
if (task
|
|
506
|
+
for (let i = 0; i < flightTaskIndex && i < tasks.length; i++) {
|
|
507
|
+
const task = tasks[i]
|
|
508
|
+
if (isPositionalTask(task) && task.coordinates) {
|
|
444
509
|
origin = task.coordinates
|
|
445
510
|
}
|
|
446
511
|
}
|
|
@@ -450,11 +515,10 @@ export function getFlightOrigin(
|
|
|
450
515
|
export function getDestinationLocation(
|
|
451
516
|
entity: HasScheduleAndLocation
|
|
452
517
|
): ServerContract.ActionParams.Type.coordinates | undefined {
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
|
|
518
|
+
const tasks = mobilityTasks(entity)
|
|
519
|
+
for (let i = tasks.length - 1; i >= 0; i--) {
|
|
520
|
+
const task = tasks[i]
|
|
521
|
+
if (isPositionalTask(task) && task.coordinates) {
|
|
458
522
|
return task.coordinates
|
|
459
523
|
}
|
|
460
524
|
}
|
|
@@ -467,16 +531,17 @@ export function getPositionAt(
|
|
|
467
531
|
taskIndex: number,
|
|
468
532
|
taskProgress: number
|
|
469
533
|
): ServerContract.ActionParams.Type.coordinates {
|
|
470
|
-
|
|
534
|
+
const tasks = mobilityTasks(entity)
|
|
535
|
+
if (tasks.length === 0) {
|
|
471
536
|
return entity.coordinates
|
|
472
537
|
}
|
|
473
538
|
if (taskIndex < 0) {
|
|
474
|
-
return getFlightOrigin(entity,
|
|
539
|
+
return getFlightOrigin(entity, tasks.length)
|
|
475
540
|
}
|
|
476
541
|
|
|
477
|
-
const task =
|
|
542
|
+
const task = tasks[taskIndex]
|
|
478
543
|
|
|
479
|
-
if (!task
|
|
544
|
+
if (!isPositionalTask(task) || !task.coordinates) {
|
|
480
545
|
return getFlightOrigin(entity, taskIndex)
|
|
481
546
|
}
|
|
482
547
|
|
|
@@ -490,68 +555,60 @@ export function getPositionAt(
|
|
|
490
555
|
}
|
|
491
556
|
}
|
|
492
557
|
|
|
493
|
-
export function
|
|
494
|
-
|
|
495
|
-
|
|
558
|
+
export function minTransferDistance(entityClass: EntityClass): number {
|
|
559
|
+
return entityClass === EntityClass.OrbitalVessel
|
|
560
|
+
? MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL
|
|
561
|
+
: MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// Mirrors cargo.cpp calc_onesided_duration: single active loader's thrust + mass, no ÷quantity.
|
|
565
|
+
export function calc_onesided_duration(
|
|
566
|
+
loaderThrust: number,
|
|
567
|
+
loaderMass: number,
|
|
568
|
+
activeZ: number,
|
|
569
|
+
counterpartZ: number,
|
|
570
|
+
activeEntityClass: EntityClass,
|
|
571
|
+
counterpartEntityClass: EntityClass,
|
|
496
572
|
cargoMass: number
|
|
497
573
|
): number {
|
|
498
|
-
if (cargoMass === 0) {
|
|
574
|
+
if (cargoMass === 0 || loaderThrust === 0) {
|
|
499
575
|
return 0
|
|
500
576
|
}
|
|
577
|
+
const rawDistance = Math.abs(activeZ - counterpartZ)
|
|
578
|
+
const minDistance = Math.max(
|
|
579
|
+
minTransferDistance(activeEntityClass),
|
|
580
|
+
minTransferDistance(counterpartEntityClass)
|
|
581
|
+
)
|
|
582
|
+
const distance = rawDistance < minDistance ? minDistance : rawDistance
|
|
583
|
+
const totalMass = cargoMass + loaderMass
|
|
584
|
+
const acceleration = calc_acceleration(loaderThrust, totalMass)
|
|
585
|
+
const flightTime = Math.floor(2 * Math.sqrt(distance / acceleration))
|
|
586
|
+
return flightTime === 0 ? 1 : flightTime
|
|
587
|
+
}
|
|
501
588
|
|
|
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) {
|
|
589
|
+
// Mirrors cargo.cpp: the active (loader-bearing) entity's chosen loader lane drives the duration.
|
|
590
|
+
export function calc_transfer_duration(
|
|
591
|
+
source: TransferEntity,
|
|
592
|
+
dest: TransferEntity,
|
|
593
|
+
cargoMass: number
|
|
594
|
+
): number {
|
|
595
|
+
const active = chosenLoaderLane(source) ? source : dest
|
|
596
|
+
const counterpart = active === source ? dest : source
|
|
597
|
+
const lane = chosenLoaderLane(active)
|
|
598
|
+
if (!lane) {
|
|
541
599
|
return 0
|
|
542
600
|
}
|
|
543
601
|
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
return Math.floor(flightTime / totalQuantity)
|
|
602
|
+
const activeZ = toNum(active.location.z)
|
|
603
|
+
const counterpartZ = toNum(counterpart.location.z)
|
|
604
|
+
|
|
605
|
+
return calc_onesided_duration(
|
|
606
|
+
toNum(lane.thrust),
|
|
607
|
+
toNum(lane.mass),
|
|
608
|
+
activeZ,
|
|
609
|
+
counterpartZ,
|
|
610
|
+
active.entityClass,
|
|
611
|
+
counterpart.entityClass,
|
|
612
|
+
cargoMass
|
|
613
|
+
)
|
|
557
614
|
}
|
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
import type {Name, UInt16, UInt32} from '@wharfkit/antelope'
|
|
1
|
+
import type {Name, UInt16, UInt32, UInt8} from '@wharfkit/antelope'
|
|
2
2
|
import type {ServerContract} from '../contracts'
|
|
3
3
|
|
|
4
|
+
export interface LoaderStats {
|
|
5
|
+
mass: {toNumber(): number; multiplying(v: unknown): {toNumber(): number}}
|
|
6
|
+
thrust: {toNumber(): number}
|
|
7
|
+
quantity: {toNumber(): number; gt(v: unknown): boolean}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface GathererStats {
|
|
11
|
+
yield: {toNumber(): number}
|
|
12
|
+
drain: {toNumber(): number}
|
|
13
|
+
depth: {toNumber(): number; toString(): string}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface CrafterStats {
|
|
17
|
+
speed: {toNumber(): number}
|
|
18
|
+
drain: {toNumber(): number}
|
|
19
|
+
}
|
|
20
|
+
|
|
4
21
|
export interface MovementCapability {
|
|
5
22
|
engines: ServerContract.Types.movement_stats
|
|
6
23
|
generator: ServerContract.Types.energy_stats
|
|
@@ -17,11 +34,11 @@ export interface StorageCapability {
|
|
|
17
34
|
}
|
|
18
35
|
|
|
19
36
|
export interface LoaderCapability {
|
|
20
|
-
loaders:
|
|
37
|
+
loaders: LoaderStats
|
|
21
38
|
}
|
|
22
39
|
|
|
23
40
|
export interface GathererCapability {
|
|
24
|
-
gatherer:
|
|
41
|
+
gatherer: GathererStats
|
|
25
42
|
}
|
|
26
43
|
|
|
27
44
|
export interface MassCapability {
|
|
@@ -29,6 +46,7 @@ export interface MassCapability {
|
|
|
29
46
|
}
|
|
30
47
|
|
|
31
48
|
export interface ScheduleCapability {
|
|
49
|
+
lanes?: ServerContract.Types.lane[]
|
|
32
50
|
schedule?: ServerContract.Types.schedule
|
|
33
51
|
}
|
|
34
52
|
|
|
@@ -37,10 +55,11 @@ export interface EntityCapabilities {
|
|
|
37
55
|
capacity?: UInt32
|
|
38
56
|
engines?: ServerContract.Types.movement_stats
|
|
39
57
|
generator?: ServerContract.Types.energy_stats
|
|
40
|
-
loaders?:
|
|
41
|
-
gatherer?:
|
|
42
|
-
crafter?:
|
|
58
|
+
loaders?: LoaderStats
|
|
59
|
+
gatherer?: GathererStats
|
|
60
|
+
crafter?: CrafterStats
|
|
43
61
|
hauler?: ServerContract.Types.hauler_stats
|
|
62
|
+
launcher?: ServerContract.Types.launcher_stats
|
|
44
63
|
}
|
|
45
64
|
|
|
46
65
|
export interface EntityState {
|
|
@@ -74,3 +93,7 @@ export function capsHasMass(caps: EntityCapabilities): boolean {
|
|
|
74
93
|
export function capsHasHauler(caps: EntityCapabilities): boolean {
|
|
75
94
|
return caps.hauler !== undefined
|
|
76
95
|
}
|
|
96
|
+
|
|
97
|
+
export function capsHasLauncher(caps: EntityCapabilities): boolean {
|
|
98
|
+
return caps.launcher !== undefined
|
|
99
|
+
}
|
package/src/types/entity.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {ServerContract} from '../contracts'
|
|
|
3
3
|
import type {Coordinates} from '../types'
|
|
4
4
|
import type {
|
|
5
5
|
EnergyCapability,
|
|
6
|
+
GathererCapability,
|
|
6
7
|
LoaderCapability,
|
|
7
8
|
MassCapability,
|
|
8
9
|
MovementCapability,
|
|
@@ -24,9 +25,8 @@ export type ShipEntity = Entity &
|
|
|
24
25
|
StorageCapability &
|
|
25
26
|
Partial<LoaderCapability> &
|
|
26
27
|
MassCapability &
|
|
27
|
-
ScheduleCapability &
|
|
28
|
-
|
|
29
|
-
}
|
|
28
|
+
ScheduleCapability &
|
|
29
|
+
Partial<GathererCapability>
|
|
30
30
|
|
|
31
31
|
export type WarehouseEntity = Entity &
|
|
32
32
|
StorageCapability &
|
package/src/types/index.ts
CHANGED
package/src/types.ts
CHANGED
|
@@ -1,35 +1,47 @@
|
|
|
1
1
|
import {
|
|
2
2
|
type Int64Type,
|
|
3
|
-
Name,
|
|
4
3
|
type UInt16,
|
|
5
4
|
type UInt16Type,
|
|
6
5
|
type UInt32,
|
|
7
6
|
type UInt32Type,
|
|
8
7
|
UInt64,
|
|
8
|
+
type UInt64Type,
|
|
9
9
|
} from '@wharfkit/antelope'
|
|
10
10
|
import {ServerContract} from './contracts'
|
|
11
11
|
|
|
12
12
|
export const PRECISION = 10000
|
|
13
13
|
export const CRAFT_ENERGY_DIVISOR = 150000
|
|
14
14
|
|
|
15
|
-
export const
|
|
15
|
+
export const PLANETARY_STRUCTURE_Z = 0
|
|
16
16
|
|
|
17
17
|
export const CONTAINER_Z = 300
|
|
18
18
|
|
|
19
19
|
export const TRAVEL_MAX_DURATION = 86400
|
|
20
20
|
|
|
21
|
+
export const BASE_HAUL_PENALTY_MILLI = 300
|
|
22
|
+
export const HAULER_EFFICIENCY_DENOM = 10000
|
|
23
|
+
|
|
21
24
|
export const MIN_ORBITAL_ALTITUDE = 800
|
|
22
25
|
export const MAX_ORBITAL_ALTITUDE = 3000
|
|
23
26
|
|
|
24
27
|
export const BASE_ORBITAL_MASS = 100000
|
|
25
28
|
|
|
29
|
+
export const MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE = 100
|
|
30
|
+
export const MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL = 200
|
|
31
|
+
|
|
32
|
+
export interface ClusterSlotType {
|
|
33
|
+
hub: UInt64Type
|
|
34
|
+
gx: number
|
|
35
|
+
gy: number
|
|
36
|
+
}
|
|
37
|
+
|
|
26
38
|
export interface ShipLike {
|
|
27
39
|
coordinates: ServerContract.Types.coordinates
|
|
28
40
|
hullmass?: UInt32
|
|
29
41
|
energy?: UInt16
|
|
30
42
|
engines?: ServerContract.Types.movement_stats
|
|
31
43
|
generator?: ServerContract.Types.energy_stats
|
|
32
|
-
|
|
44
|
+
loader_lanes?: ServerContract.Types.loader_lane[]
|
|
33
45
|
hauler?: ServerContract.Types.hauler_stats
|
|
34
46
|
capacity?: UInt32
|
|
35
47
|
}
|
|
@@ -49,11 +61,22 @@ export enum TaskType {
|
|
|
49
61
|
WARP = 6,
|
|
50
62
|
CRAFT = 7,
|
|
51
63
|
DEPLOY = 8,
|
|
52
|
-
|
|
64
|
+
TRANSIT = 9,
|
|
53
65
|
UNWRAP = 10,
|
|
54
66
|
UNDEPLOY = 11,
|
|
55
|
-
WRAP_ENTITY = 12,
|
|
56
67
|
DEMOLISH = 13,
|
|
68
|
+
CLAIMPLOT = 14,
|
|
69
|
+
BUILDPLOT = 15,
|
|
70
|
+
CHARGE = 16,
|
|
71
|
+
UPGRADE = 17,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export enum HoldKind {
|
|
75
|
+
PULL = 1,
|
|
76
|
+
PUSH = 2,
|
|
77
|
+
GATHER = 3,
|
|
78
|
+
BUILD = 4,
|
|
79
|
+
UPGRADE = 6,
|
|
57
80
|
}
|
|
58
81
|
|
|
59
82
|
export enum LocationType {
|
|
@@ -61,6 +84,7 @@ export enum LocationType {
|
|
|
61
84
|
PLANET = 1,
|
|
62
85
|
ASTEROID = 2,
|
|
63
86
|
NEBULA = 3,
|
|
87
|
+
ICE_FIELD = 4,
|
|
64
88
|
}
|
|
65
89
|
|
|
66
90
|
export enum TaskCancelable {
|
|
@@ -69,14 +93,6 @@ export enum TaskCancelable {
|
|
|
69
93
|
ALWAYS = 2,
|
|
70
94
|
}
|
|
71
95
|
|
|
72
|
-
export const EntityType = {
|
|
73
|
-
SHIP: Name.from('ship'),
|
|
74
|
-
WAREHOUSE: Name.from('warehouse'),
|
|
75
|
-
CONTAINER: Name.from('container'),
|
|
76
|
-
} as const
|
|
77
|
-
|
|
78
|
-
export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
|
|
79
|
-
|
|
80
96
|
export type CoordinatesType =
|
|
81
97
|
| Coordinates
|
|
82
98
|
| ServerContract.Types.coordinates
|
|
@@ -125,8 +141,10 @@ export type ModuleType =
|
|
|
125
141
|
| 'launcher'
|
|
126
142
|
| 'storage'
|
|
127
143
|
| 'hauler'
|
|
144
|
+
| 'battery'
|
|
145
|
+
| 'catcher'
|
|
128
146
|
|
|
129
|
-
export const
|
|
147
|
+
export const RESOURCE_TIER_ADJECTIVES: Record<number, string> = {
|
|
130
148
|
1: 'Crude',
|
|
131
149
|
2: 'Dense',
|
|
132
150
|
3: 'Pure',
|
|
@@ -139,6 +157,9 @@ export const TIER_ADJECTIVES: Record<number, string> = {
|
|
|
139
157
|
10: 'Ascendant',
|
|
140
158
|
}
|
|
141
159
|
|
|
160
|
+
export const COMPONENT_TIER_PREFIXES: Record<number, string> = {}
|
|
161
|
+
export const MODULE_TIER_PREFIXES: Record<number, string> = {}
|
|
162
|
+
|
|
142
163
|
export const CATEGORY_LABELS: Record<ResourceCategory, string> = {
|
|
143
164
|
ore: 'Ore',
|
|
144
165
|
crystal: 'Crystal',
|
|
@@ -162,3 +183,7 @@ export interface Item {
|
|
|
162
183
|
export function formatTier(tier: number): string {
|
|
163
184
|
return 'T' + tier
|
|
164
185
|
}
|
|
186
|
+
|
|
187
|
+
export function tierAdjective(tier: number): string {
|
|
188
|
+
return RESOURCE_TIER_ADJECTIVES[tier] ?? `T${tier}`
|
|
189
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {describe, expect, test} from 'bun:test'
|
|
2
|
+
import {cargoRef} from './cargo'
|
|
3
|
+
|
|
4
|
+
describe('cargoRef', () => {
|
|
5
|
+
test('forwards entity_id when provided', () => {
|
|
6
|
+
const ref = cargoRef({item_id: 10201, stats: 196849n, modules: [], entity_id: 42n})
|
|
7
|
+
expect(ref.entity_id).toBe(42n)
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
test('omits entity_id when absent', () => {
|
|
11
|
+
const ref = cargoRef({item_id: 10201, stats: 196849n})
|
|
12
|
+
expect(ref.entity_id).toBeUndefined()
|
|
13
|
+
})
|
|
14
|
+
})
|