@shipload/sdk 1.0.0-next.35 → 1.0.0-next.36

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.
Files changed (50) hide show
  1. package/lib/shipload.d.ts +237 -80
  2. package/lib/shipload.js +2979 -2598
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +2960 -2599
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +66 -20
  7. package/lib/testing.js +95 -57
  8. package/lib/testing.js.map +1 -1
  9. package/lib/testing.m.js +95 -57
  10. package/lib/testing.m.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/capabilities/crafting.ts +2 -3
  13. package/src/capabilities/gathering.test.ts +16 -0
  14. package/src/capabilities/gathering.ts +8 -11
  15. package/src/contracts/server.ts +45 -29
  16. package/src/coordinates/address.ts +9 -5
  17. package/src/coordinates/constants.test.ts +15 -0
  18. package/src/coordinates/constants.ts +5 -3
  19. package/src/coordinates/index.ts +11 -0
  20. package/src/coordinates/memo.test.ts +47 -0
  21. package/src/coordinates/memo.ts +20 -0
  22. package/src/data/capability-formulas.ts +0 -1
  23. package/src/data/entities.json +4 -4
  24. package/src/data/items.json +5 -5
  25. package/src/data/recipes.json +39 -65
  26. package/src/derivation/capabilities.test.ts +133 -0
  27. package/src/derivation/capabilities.ts +66 -14
  28. package/src/derivation/rollups.test.ts +55 -0
  29. package/src/derivation/rollups.ts +56 -0
  30. package/src/entities/makers.ts +30 -3
  31. package/src/index-module.ts +15 -2
  32. package/src/managers/actions.ts +34 -3
  33. package/src/managers/construction.ts +6 -4
  34. package/src/managers/context.ts +9 -0
  35. package/src/managers/coordinates.ts +14 -0
  36. package/src/managers/plot.ts +2 -4
  37. package/src/nft/description.ts +25 -6
  38. package/src/planner/index.ts +127 -0
  39. package/src/planner/planner.test.ts +319 -0
  40. package/src/resolution/resolve-item.ts +4 -1
  41. package/src/scheduling/cancel.test.ts +21 -0
  42. package/src/scheduling/lanes.test.ts +249 -0
  43. package/src/scheduling/lanes.ts +140 -2
  44. package/src/scheduling/projection.ts +73 -16
  45. package/src/shipload.ts +5 -0
  46. package/src/testing/projection-parity.ts +26 -2
  47. package/src/travel/travel.ts +102 -101
  48. package/src/types/capabilities.ts +23 -6
  49. package/src/types/entity.ts +3 -3
  50. package/src/types.ts +1 -1
@@ -208,15 +208,26 @@ export function calc_transit_duration(ax: number, ay: number, bx: number, by: nu
208
208
  return UInt32.from(Math.floor(distance.toNumber() / (PRECISION * WH.TRANSIT_SPEED)))
209
209
  }
210
210
 
211
+ // The active entity's chosen loader lane (lowest slot), mirroring cargo.cpp lane selection.
212
+ export function shipLoaderLane(ship: ShipLike): {thrust: number; mass: number} | undefined {
213
+ const lanes = ship.loader_lanes ?? []
214
+ if (lanes.length === 0) return undefined
215
+ let lowest = lanes[0]
216
+ for (const lane of lanes) {
217
+ if (Number(lane.slot_index) < Number(lowest.slot_index)) lowest = lane
218
+ }
219
+ return {thrust: Number(lowest.thrust), mass: Number(lowest.mass)}
220
+ }
221
+
211
222
  export function calc_loader_flighttime(ship: ShipLike, mass: UInt64, altitude?: number): UInt32 {
212
223
  const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass))
213
224
  return calc_flighttime(z, calc_loader_acceleration(ship, mass))
214
225
  }
215
226
 
216
227
  export function calc_loader_acceleration(ship: ShipLike, mass: UInt64): number {
217
- const thrust = ship.loaders ? Number(ship.loaders.thrust) : 0
218
- const loaderMass = ship.loaders ? Number(ship.loaders.mass) : 0
219
- return calc_acceleration(thrust, Number(mass) + loaderMass)
228
+ const lane = shipLoaderLane(ship)
229
+ const thrust = lane ? lane.thrust : 0
230
+ return calc_acceleration(thrust, Number(mass))
220
231
  }
221
232
 
222
233
  export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UInt64): UInt32 {
@@ -238,8 +249,10 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
238
249
 
239
250
  mass.add(ship.hullmass)
240
251
 
241
- if (ship.loaders && ship.loaders.quantity.gt(UInt32.zero)) {
242
- mass.add(ship.loaders.mass.multiplying(ship.loaders.quantity))
252
+ if (ship.loader_lanes && ship.loader_lanes.length > 0) {
253
+ for (const l of ship.loader_lanes) {
254
+ mass.add(UInt64.from(l.mass))
255
+ }
243
256
  }
244
257
 
245
258
  for (const cargo of cargos) {
@@ -274,10 +287,10 @@ export function calculateTransferTime(
274
287
  return UInt32.from(0)
275
288
  }
276
289
 
277
- if (!ship.loaders) return UInt32.from(0)
278
- mass = UInt64.from(mass).adding(ship.loaders.mass)
279
- const transfer_time = calc_loader_flighttime(ship, mass)
280
- return transfer_time.dividing(ship.loaders.quantity)
290
+ const lane = shipLoaderLane(ship)
291
+ if (!lane) return UInt32.from(0)
292
+ mass = UInt64.from(mass).adding(UInt64.from(lane.mass))
293
+ return calc_loader_flighttime(ship, mass)
281
294
  }
282
295
 
283
296
  export function calculateRefuelingTime(ship: ShipLike): UInt32 {
@@ -332,25 +345,22 @@ export function calculateLoadTimeBreakdown(
332
345
  let unloadTime = 0
333
346
  let loadTime = 0
334
347
 
335
- if (mass_unload.gt(UInt64.zero) && ship.loaders) {
336
- const totalMass = UInt64.from(mass_unload).adding(ship.loaders.mass)
348
+ const lane = shipLoaderLane(ship)
349
+
350
+ if (mass_unload.gt(UInt64.zero) && lane) {
351
+ const totalMass = UInt64.from(mass_unload).adding(UInt64.from(lane.mass))
337
352
  unloadTime = Number(calc_loader_flighttime(ship, totalMass))
338
353
  }
339
354
 
340
- if (mass_load.gt(UInt64.zero) && ship.loaders) {
341
- const totalMass = UInt64.from(mass_load).adding(ship.loaders.mass)
355
+ if (mass_load.gt(UInt64.zero) && lane) {
356
+ const totalMass = UInt64.from(mass_load).adding(UInt64.from(lane.mass))
342
357
  loadTime = Number(calc_loader_flighttime(ship, totalMass))
343
358
  }
344
359
 
345
- const numLoaders = ship.loaders ? Number(ship.loaders.quantity) : 0
346
- const totalTime = numLoaders > 0 ? (unloadTime + loadTime) / numLoaders : 0
347
- const unloadTimePerLoader = numLoaders > 0 ? unloadTime / numLoaders : 0
348
- const loadTimePerLoader = numLoaders > 0 ? loadTime / numLoaders : 0
349
-
350
360
  return {
351
- unloadTime: unloadTimePerLoader,
352
- loadTime: loadTimePerLoader,
353
- totalTime,
361
+ unloadTime,
362
+ loadTime,
363
+ totalTime: unloadTime + loadTime,
354
364
  unloadMass: Number(mass_unload),
355
365
  loadMass: Number(mass_load),
356
366
  }
@@ -384,24 +394,16 @@ export function estimateTravelTime(
384
394
  let loadTime = UInt32.zero
385
395
  let unloadTime = UInt32.zero
386
396
 
387
- if (
388
- loadMass &&
389
- UInt32.from(loadMass).gt(UInt32.zero) &&
390
- ship.loaders &&
391
- ship.loaders.quantity.gt(UInt32.zero)
392
- ) {
393
- const totalMass = UInt64.from(loadMass).adding(ship.loaders.mass)
394
- loadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity)
397
+ const lane = shipLoaderLane(ship)
398
+
399
+ if (loadMass && UInt32.from(loadMass).gt(UInt32.zero) && lane) {
400
+ const totalMass = UInt64.from(loadMass).adding(UInt64.from(lane.mass))
401
+ loadTime = calc_loader_flighttime(ship, totalMass)
395
402
  }
396
403
 
397
- if (
398
- unloadMass &&
399
- UInt32.from(unloadMass).gt(UInt32.zero) &&
400
- ship.loaders &&
401
- ship.loaders.quantity.gt(UInt32.zero)
402
- ) {
403
- const totalMass = UInt64.from(unloadMass).adding(ship.loaders.mass)
404
- unloadTime = calc_loader_flighttime(ship, totalMass).dividing(ship.loaders.quantity)
404
+ if (unloadMass && UInt32.from(unloadMass).gt(UInt32.zero) && lane) {
405
+ const totalMass = UInt64.from(unloadMass).adding(UInt64.from(lane.mass))
406
+ unloadTime = calc_loader_flighttime(ship, totalMass)
405
407
  }
406
408
 
407
409
  return {
@@ -433,14 +435,32 @@ export function hasEnergyForDistance(ship: ShipLike, distance: UInt64Type): bool
433
435
  return UInt64.from(ship.energy ?? 0).gte(energyNeeded)
434
436
  }
435
437
 
438
+ export interface TransferLoaderLane {
439
+ slot_index?: {toNumber(): number} | number
440
+ thrust: {toNumber(): number} | number
441
+ mass: {toNumber(): number} | number
442
+ }
443
+
436
444
  export interface TransferEntity {
437
445
  location: {z?: {toNumber(): number} | number}
438
446
  entityClass: EntityClass
439
- loaders?: {
440
- thrust: {toNumber(): number} | number
441
- mass: {toNumber(): number} | number
442
- quantity: {toNumber(): number} | number
447
+ loaderLanes?: TransferLoaderLane[]
448
+ }
449
+
450
+ function toNum(v: {toNumber(): number} | number | undefined): number {
451
+ if (v === undefined) return 0
452
+ return typeof v === 'number' ? v : v.toNumber()
453
+ }
454
+
455
+ // Mirrors cargo.cpp worker_lane_key_or_mobility: lowest-slot loader lane (display has no busy context).
456
+ function chosenLoaderLane(entity: TransferEntity): TransferLoaderLane | undefined {
457
+ const lanes = entity.loaderLanes ?? []
458
+ if (lanes.length === 0) return undefined
459
+ let lowest = lanes[0]
460
+ for (const lane of lanes) {
461
+ if (toNum(lane.slot_index) < toNum(lowest.slot_index)) lowest = lane
443
462
  }
463
+ return lowest
444
464
  }
445
465
 
446
466
  export interface HasScheduleAndLocation extends ScheduleData {
@@ -515,73 +535,54 @@ export function minTransferDistance(entityClass: EntityClass): number {
515
535
  : MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE
516
536
  }
517
537
 
518
- export function calc_transfer_duration(
519
- source: TransferEntity,
520
- dest: TransferEntity,
538
+ // Mirrors cargo.cpp calc_onesided_duration: single active loader's thrust + mass, no ÷quantity.
539
+ export function calc_onesided_duration(
540
+ loaderThrust: number,
541
+ loaderMass: number,
542
+ activeZ: number,
543
+ counterpartZ: number,
544
+ activeEntityClass: EntityClass,
545
+ counterpartEntityClass: EntityClass,
521
546
  cargoMass: number
522
547
  ): number {
523
- if (cargoMass === 0) {
548
+ if (cargoMass === 0 || loaderThrust === 0) {
524
549
  return 0
525
550
  }
526
-
527
- let totalThrust = 0
528
- let totalLoaderMass = 0
529
- let totalQuantity = 0
530
-
531
- if (source.loaders) {
532
- const thrust =
533
- typeof source.loaders.thrust === 'number'
534
- ? source.loaders.thrust
535
- : source.loaders.thrust.toNumber()
536
- const mass =
537
- typeof source.loaders.mass === 'number'
538
- ? source.loaders.mass
539
- : source.loaders.mass.toNumber()
540
- const qty =
541
- typeof source.loaders.quantity === 'number'
542
- ? source.loaders.quantity
543
- : source.loaders.quantity.toNumber()
544
- totalThrust += thrust * qty
545
- totalLoaderMass += mass * qty
546
- totalQuantity += qty
547
- }
548
-
549
- if (dest.loaders) {
550
- const thrust =
551
- typeof dest.loaders.thrust === 'number'
552
- ? dest.loaders.thrust
553
- : dest.loaders.thrust.toNumber()
554
- const mass =
555
- typeof dest.loaders.mass === 'number' ? dest.loaders.mass : dest.loaders.mass.toNumber()
556
- const qty =
557
- typeof dest.loaders.quantity === 'number'
558
- ? dest.loaders.quantity
559
- : dest.loaders.quantity.toNumber()
560
- totalThrust += thrust * qty
561
- totalLoaderMass += mass * qty
562
- totalQuantity += qty
563
- }
564
-
565
- if (totalThrust === 0 || totalQuantity === 0) {
566
- return 0
567
- }
568
-
569
- const sourceZ =
570
- typeof source.location.z === 'number'
571
- ? source.location.z
572
- : (source.location.z?.toNumber() ?? 0)
573
- const destZ =
574
- typeof dest.location.z === 'number' ? dest.location.z : (dest.location.z?.toNumber() ?? 0)
575
- const rawDistance = Math.abs(sourceZ - destZ)
551
+ const rawDistance = Math.abs(activeZ - counterpartZ)
576
552
  const minDistance = Math.max(
577
- minTransferDistance(source.entityClass),
578
- minTransferDistance(dest.entityClass)
553
+ minTransferDistance(activeEntityClass),
554
+ minTransferDistance(counterpartEntityClass)
579
555
  )
580
556
  const distance = rawDistance < minDistance ? minDistance : rawDistance
557
+ const totalMass = cargoMass + loaderMass
558
+ const acceleration = calc_acceleration(loaderThrust, totalMass)
559
+ const flightTime = Math.floor(2 * Math.sqrt(distance / acceleration))
560
+ return flightTime === 0 ? 1 : flightTime
561
+ }
581
562
 
582
- const totalMass = cargoMass + totalLoaderMass
583
- const acceleration = calc_acceleration(totalThrust, totalMass)
584
- const flightTime = 2 * Math.sqrt(distance / acceleration)
563
+ // Mirrors cargo.cpp: the active (loader-bearing) entity's chosen loader lane drives the duration.
564
+ export function calc_transfer_duration(
565
+ source: TransferEntity,
566
+ dest: TransferEntity,
567
+ cargoMass: number
568
+ ): number {
569
+ const active = chosenLoaderLane(source) ? source : dest
570
+ const counterpart = active === source ? dest : source
571
+ const lane = chosenLoaderLane(active)
572
+ if (!lane) {
573
+ return 0
574
+ }
585
575
 
586
- return Math.floor(flightTime / totalQuantity)
576
+ const activeZ = toNum(active.location.z)
577
+ const counterpartZ = toNum(counterpart.location.z)
578
+
579
+ return calc_onesided_duration(
580
+ toNum(lane.thrust),
581
+ toNum(lane.mass),
582
+ activeZ,
583
+ counterpartZ,
584
+ active.entityClass,
585
+ counterpart.entityClass,
586
+ cargoMass
587
+ )
587
588
  }
@@ -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: ServerContract.Types.loader_stats
37
+ loaders: LoaderStats
21
38
  }
22
39
 
23
40
  export interface GathererCapability {
24
- gatherer: ServerContract.Types.gatherer_stats
41
+ gatherer: GathererStats
25
42
  }
26
43
 
27
44
  export interface MassCapability {
@@ -38,9 +55,9 @@ export interface EntityCapabilities {
38
55
  capacity?: UInt32
39
56
  engines?: ServerContract.Types.movement_stats
40
57
  generator?: ServerContract.Types.energy_stats
41
- loaders?: ServerContract.Types.loader_stats
42
- gatherer?: ServerContract.Types.gatherer_stats
43
- crafter?: ServerContract.Types.crafter_stats
58
+ loaders?: LoaderStats
59
+ gatherer?: GathererStats
60
+ crafter?: CrafterStats
44
61
  hauler?: ServerContract.Types.hauler_stats
45
62
  }
46
63
 
@@ -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
- gatherer?: ServerContract.Types.gatherer_stats
29
- }
28
+ ScheduleCapability &
29
+ Partial<GathererCapability>
30
30
 
31
31
  export type WarehouseEntity = Entity &
32
32
  StorageCapability &
package/src/types.ts CHANGED
@@ -31,7 +31,7 @@ export interface ShipLike {
31
31
  energy?: UInt16
32
32
  engines?: ServerContract.Types.movement_stats
33
33
  generator?: ServerContract.Types.energy_stats
34
- loaders?: ServerContract.Types.loader_stats
34
+ loader_lanes?: ServerContract.Types.loader_lane[]
35
35
  hauler?: ServerContract.Types.hauler_stats
36
36
  capacity?: UInt32
37
37
  }