@shipload/sdk 1.0.0-next.7 → 1.0.0-next.71

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 (203) hide show
  1. package/lib/scan.d.ts +52 -0
  2. package/lib/scan.js +162 -0
  3. package/lib/scan.js.map +1 -0
  4. package/lib/scan.m.js +152 -0
  5. package/lib/scan.m.js.map +1 -0
  6. package/lib/shipload.d.ts +5822 -1484
  7. package/lib/shipload.js +20838 -5419
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +20674 -5669
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +1691 -0
  12. package/lib/testing.js +7109 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +7103 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.test.ts +82 -0
  18. package/src/capabilities/craftable.ts +82 -0
  19. package/src/capabilities/crafting.test.ts +80 -0
  20. package/src/capabilities/crafting.ts +50 -8
  21. package/src/capabilities/gathering.test.ts +29 -0
  22. package/src/capabilities/gathering.ts +38 -20
  23. package/src/capabilities/hauling.ts +0 -5
  24. package/src/capabilities/index.ts +0 -1
  25. package/src/capabilities/modules.ts +27 -30
  26. package/src/capabilities/movement.ts +1 -1
  27. package/src/capabilities/storage.test.ts +26 -0
  28. package/src/capabilities/storage.ts +22 -7
  29. package/src/contracts/fund.ts +306 -0
  30. package/src/contracts/platform.ts +312 -3
  31. package/src/contracts/server.ts +2793 -478
  32. package/src/contracts/token.ts +170 -0
  33. package/src/contracts.ts +2 -0
  34. package/src/coordinates/address.ts +88 -0
  35. package/src/coordinates/constants.test.ts +15 -0
  36. package/src/coordinates/constants.ts +23 -0
  37. package/src/coordinates/index.ts +15 -0
  38. package/src/coordinates/memo.test.ts +47 -0
  39. package/src/coordinates/memo.ts +20 -0
  40. package/src/coordinates/permutation.ts +77 -0
  41. package/src/coordinates/regions.ts +48 -0
  42. package/src/coordinates/sectors.ts +115 -0
  43. package/src/data/capabilities.ts +49 -18
  44. package/src/data/capability-formulas.ts +26 -14
  45. package/src/data/catalog.test.ts +19 -0
  46. package/src/data/catalog.ts +13 -3
  47. package/src/data/charters.json +396 -0
  48. package/src/data/citizenry-adjectives.json +42 -0
  49. package/src/data/citizenry-nouns.json +50 -0
  50. package/src/data/colors.ts +14 -32
  51. package/src/data/entities.json +421 -15
  52. package/src/data/item-ids.ts +53 -13
  53. package/src/data/items.json +330 -77
  54. package/src/data/kind-registry.json +212 -0
  55. package/src/data/kind-registry.ts +192 -0
  56. package/src/data/metadata.ts +312 -51
  57. package/src/data/recipes-runtime.ts +6 -23
  58. package/src/data/recipes.json +2173 -173
  59. package/src/data/tiers.ts +9 -6
  60. package/src/derivation/build-methods.test.ts +71 -0
  61. package/src/derivation/build-methods.ts +50 -0
  62. package/src/derivation/capabilities.test.ts +348 -0
  63. package/src/derivation/capabilities.ts +707 -0
  64. package/src/derivation/capability-mappings.ts +60 -16
  65. package/src/derivation/crafting.test.ts +17 -0
  66. package/src/derivation/crafting.ts +57 -34
  67. package/src/derivation/index.ts +27 -2
  68. package/src/derivation/recipe-usage.test.ts +88 -0
  69. package/src/derivation/recipe-usage.ts +141 -0
  70. package/src/derivation/reserve-regen.ts +34 -0
  71. package/src/derivation/resources.ts +9 -1
  72. package/src/derivation/rollups.test.ts +55 -0
  73. package/src/derivation/rollups.ts +72 -0
  74. package/src/derivation/stars.test.ts +67 -0
  75. package/src/derivation/stars.ts +25 -0
  76. package/src/derivation/stat-scaling.ts +12 -0
  77. package/src/derivation/stats.ts +6 -6
  78. package/src/derivation/strata.ts +5 -3
  79. package/src/derivation/stratum.ts +26 -22
  80. package/src/derivation/tiers.ts +40 -7
  81. package/src/derivation/upgrades.ts +14 -0
  82. package/src/derivation/wormhole.ts +154 -0
  83. package/src/entities/entity.ts +102 -0
  84. package/src/entities/gamestate.ts +3 -28
  85. package/src/entities/makers.ts +144 -136
  86. package/src/entities/slot-multiplier.ts +43 -0
  87. package/src/entity/hydrate.test.ts +156 -0
  88. package/src/entity/hydrate.ts +86 -0
  89. package/src/errors.ts +21 -16
  90. package/src/format.ts +42 -9
  91. package/src/index-module.ts +425 -32
  92. package/src/influence/ballot.test.ts +103 -0
  93. package/src/influence/ballot.ts +98 -0
  94. package/src/influence/categories.ts +32 -0
  95. package/src/influence/charter-metadata.test.ts +136 -0
  96. package/src/influence/charter-metadata.ts +236 -0
  97. package/src/influence/charters.test.ts +112 -0
  98. package/src/influence/charters.ts +150 -0
  99. package/src/influence/citizenry.ts +38 -0
  100. package/src/influence/civic-shuttle.test.ts +202 -0
  101. package/src/influence/civic-shuttle.ts +142 -0
  102. package/src/influence/civic.test.ts +287 -0
  103. package/src/influence/civic.ts +269 -0
  104. package/src/influence/constants.ts +84 -0
  105. package/src/influence/decay.ts +20 -0
  106. package/src/influence/decomp.ts +95 -0
  107. package/src/influence/demand.ts +106 -0
  108. package/src/influence/duration.ts +101 -0
  109. package/src/influence/index.ts +118 -0
  110. package/src/influence/influence.test.ts +450 -0
  111. package/src/influence/quality.ts +25 -0
  112. package/src/influence/valuation.ts +154 -0
  113. package/src/managers/actions.ts +950 -93
  114. package/src/managers/balances.test.ts +161 -0
  115. package/src/managers/balances.ts +93 -0
  116. package/src/managers/base.ts +10 -2
  117. package/src/managers/cluster.test.ts +39 -0
  118. package/src/managers/cluster.ts +53 -0
  119. package/src/managers/construction-types.ts +80 -0
  120. package/src/managers/construction.ts +453 -0
  121. package/src/managers/context.ts +58 -1
  122. package/src/managers/coordinates.ts +14 -0
  123. package/src/managers/entities.ts +35 -63
  124. package/src/managers/epochs.ts +72 -1
  125. package/src/managers/index.ts +38 -1
  126. package/src/managers/influence.test.ts +56 -0
  127. package/src/managers/influence.ts +425 -0
  128. package/src/managers/jobs.test.ts +96 -0
  129. package/src/managers/jobs.ts +58 -0
  130. package/src/managers/locations.ts +25 -29
  131. package/src/managers/nft.test.ts +21 -0
  132. package/src/managers/nft.ts +110 -0
  133. package/src/managers/players.ts +25 -0
  134. package/src/managers/plot.ts +122 -0
  135. package/src/nft/atomicassets.abi.json +1342 -0
  136. package/src/nft/atomicassets.ts +237 -0
  137. package/src/nft/atomicdata.ts +130 -0
  138. package/src/nft/buildImmutableData.ts +388 -0
  139. package/src/nft/description.ts +222 -100
  140. package/src/nft/index.ts +3 -0
  141. package/src/planner/index.ts +296 -0
  142. package/src/planner/planner.test.ts +459 -0
  143. package/src/receipts.ts +22 -0
  144. package/src/resolution/describe-module.ts +43 -25
  145. package/src/resolution/display-name.ts +39 -11
  146. package/src/resolution/resolve-item.test.ts +48 -0
  147. package/src/resolution/resolve-item.ts +112 -58
  148. package/src/scan/index.ts +244 -0
  149. package/src/scan/scan-wasm.base64.ts +2 -0
  150. package/src/scheduling/accessor.ts +65 -23
  151. package/src/scheduling/availability.test.ts +320 -0
  152. package/src/scheduling/availability.ts +251 -0
  153. package/src/scheduling/cancel.test.ts +550 -0
  154. package/src/scheduling/cancel.ts +254 -0
  155. package/src/scheduling/cluster-stock.test.ts +31 -0
  156. package/src/scheduling/cluster-stock.ts +15 -0
  157. package/src/scheduling/energy.ts +47 -0
  158. package/src/scheduling/epoch.ts +1 -0
  159. package/src/scheduling/idle-resolve.ts +45 -0
  160. package/src/scheduling/jobs.test.ts +448 -0
  161. package/src/scheduling/jobs.ts +343 -0
  162. package/src/scheduling/lane-core.ts +128 -0
  163. package/src/scheduling/lanes.test.ts +250 -0
  164. package/src/scheduling/lanes.ts +279 -0
  165. package/src/scheduling/projection.ts +265 -149
  166. package/src/scheduling/schedule.test.ts +163 -0
  167. package/src/scheduling/schedule.ts +282 -116
  168. package/src/scheduling/task-cargo.test.ts +110 -0
  169. package/src/scheduling/task-cargo.ts +62 -0
  170. package/src/scheduling/task-effects.test.ts +35 -0
  171. package/src/scheduling/task-effects.ts +34 -0
  172. package/src/scheduling/unwrap.test.ts +86 -0
  173. package/src/scheduling/unwrap.ts +190 -0
  174. package/src/shipload.ts +63 -4
  175. package/src/subscriptions/manager.cluster.test.ts +51 -0
  176. package/src/subscriptions/manager.ts +245 -172
  177. package/src/subscriptions/mappers.ts +5 -8
  178. package/src/subscriptions/types.ts +28 -3
  179. package/src/testing/catalog-hash.ts +19 -0
  180. package/src/testing/index.ts +2 -0
  181. package/src/testing/projection-parity.ts +167 -0
  182. package/src/travel/reach.test.ts +86 -0
  183. package/src/travel/reach.ts +34 -0
  184. package/src/travel/route-build.test.ts +63 -0
  185. package/src/travel/route-build.ts +60 -0
  186. package/src/travel/route-planner.ts +288 -0
  187. package/src/travel/route-simulator.ts +170 -0
  188. package/src/travel/travel.ts +190 -123
  189. package/src/types/capabilities.ts +37 -8
  190. package/src/types/entity.ts +3 -3
  191. package/src/types/index.ts +0 -1
  192. package/src/types.ts +81 -23
  193. package/src/utils/cargo.test.ts +14 -0
  194. package/src/utils/cargo.ts +2 -0
  195. package/src/utils/display-name.ts +70 -0
  196. package/src/utils/hash.ts +22 -2
  197. package/src/utils/system.ts +24 -5
  198. package/src/capabilities/loading.ts +0 -8
  199. package/src/entities/container.ts +0 -123
  200. package/src/entities/ship-deploy.ts +0 -295
  201. package/src/entities/ship.ts +0 -221
  202. package/src/entities/warehouse.ts +0 -127
  203. package/src/types/entity-traits.ts +0 -69
@@ -0,0 +1,156 @@
1
+ import {UInt64} from '@wharfkit/antelope'
2
+ import {describe, expect, test} from 'bun:test'
3
+ import {entityToRouteMover, hydrateEntityLanes} from './hydrate'
4
+
5
+ describe('hydrateEntityLanes', () => {
6
+ test('maps camelCase gathererLanes to gatherer_lane with snake_case fields', () => {
7
+ const lanes = hydrateEntityLanes({
8
+ gathererLanes: [
9
+ {slotIndex: 2, yield: 700, drain: 1_250_000, depth: 5000, outputPct: 100},
10
+ ],
11
+ })
12
+ expect(lanes).toHaveLength(1)
13
+ expect(lanes[0].slot_index.toNumber()).toBe(2)
14
+ expect(lanes[0].yield.toNumber()).toBe(700)
15
+ expect(lanes[0].drain.toNumber()).toBe(1_250_000)
16
+ expect(lanes[0].depth.toNumber()).toBe(5000)
17
+ expect(lanes[0].output_pct.toNumber()).toBe(100)
18
+ })
19
+
20
+ test('falls back to a single synthetic lane from caps.gatherer when gathererLanes is absent', () => {
21
+ const lanes = hydrateEntityLanes({gatherer: {yield: 300, drain: 50, depth: 1000}})
22
+ expect(lanes).toHaveLength(1)
23
+ expect(lanes[0].slot_index.toNumber()).toBe(0)
24
+ expect(lanes[0].yield.toNumber()).toBe(300)
25
+ expect(lanes[0].drain.toNumber()).toBe(50)
26
+ expect(lanes[0].depth.toNumber()).toBe(1000)
27
+ expect(lanes[0].output_pct.toNumber()).toBe(100)
28
+ })
29
+
30
+ test('prefers gathererLanes over the caps.gatherer fallback when both are present', () => {
31
+ const lanes = hydrateEntityLanes({
32
+ gathererLanes: [{slotIndex: 1, yield: 10, drain: 20, depth: 30, outputPct: 40}],
33
+ gatherer: {yield: 999, drain: 999, depth: 999},
34
+ })
35
+ expect(lanes).toHaveLength(1)
36
+ expect(lanes[0].slot_index.toNumber()).toBe(1)
37
+ })
38
+
39
+ test('returns an empty array when there is no gatherer capability at all', () => {
40
+ expect(hydrateEntityLanes({})).toEqual([])
41
+ })
42
+
43
+ test('clamps out-of-range and non-integer fields to the contract field bounds', () => {
44
+ const lanes = hydrateEntityLanes({
45
+ gathererLanes: [
46
+ {
47
+ slotIndex: -5,
48
+ yield: 999_999,
49
+ drain: -1,
50
+ depth: 70_000.7,
51
+ outputPct: Number.NaN,
52
+ },
53
+ ],
54
+ })
55
+ expect(lanes[0].slot_index.toNumber()).toBe(0)
56
+ expect(lanes[0].yield.toNumber()).toBe(65_535)
57
+ expect(lanes[0].drain.toNumber()).toBe(0)
58
+ expect(lanes[0].depth.toNumber()).toBe(65_535)
59
+ expect(lanes[0].output_pct.toNumber()).toBe(0)
60
+ })
61
+
62
+ test('clamps a slot index above the uint8 ceiling', () => {
63
+ const lanes = hydrateEntityLanes({
64
+ gathererLanes: [{slotIndex: 300, yield: 0, drain: 0, depth: 0, outputPct: 0}],
65
+ })
66
+ expect(lanes[0].slot_index.toNumber()).toBe(255)
67
+ })
68
+
69
+ test('clamps drain above the uint32 ceiling', () => {
70
+ const lanes = hydrateEntityLanes({
71
+ gathererLanes: [{slotIndex: 0, yield: 0, drain: 5_000_000_000, depth: 0, outputPct: 0}],
72
+ })
73
+ expect(lanes[0].drain.toNumber()).toBe(4_294_967_295)
74
+ })
75
+ })
76
+
77
+ describe('entityToRouteMover', () => {
78
+ test('sums hullmass, cargomass, and loader lane mass into total mass', () => {
79
+ const mover = entityToRouteMover(
80
+ {id: UInt64.from(1), energy: 500, cargomass: 200},
81
+ {
82
+ hullmass: 1000,
83
+ loaderLanes: [
84
+ {slotIndex: 0, mass: 50, thrust: 10, outputPct: 100},
85
+ {slotIndex: 1, mass: 25, thrust: 10, outputPct: 100},
86
+ ],
87
+ }
88
+ )
89
+ expect(mover.mass).toBe(1000 + 200 + 50 + 25)
90
+ expect(mover.energy).toBe(500)
91
+ expect(mover.ref).toEqual({entityType: 'ship', entityId: UInt64.from(1)})
92
+ })
93
+
94
+ test('derives hasMovement from the presence of both engines and a generator', () => {
95
+ const withMovement = entityToRouteMover(
96
+ {id: UInt64.from(1)},
97
+ {
98
+ hullmass: 0,
99
+ engines: {thrust: 100, drain: 10},
100
+ generator: {capacity: 1000, recharge: 10},
101
+ }
102
+ )
103
+ expect(withMovement.hasMovement).toBe(true)
104
+
105
+ const withoutMovement = entityToRouteMover({id: UInt64.from(1)}, {hullmass: 0})
106
+ expect(withoutMovement.hasMovement).toBe(false)
107
+ })
108
+
109
+ test('an explicit hasMovement opt overrides the derived value', () => {
110
+ const mover = entityToRouteMover(
111
+ {id: UInt64.from(1)},
112
+ {
113
+ hullmass: 0,
114
+ engines: {thrust: 100, drain: 10},
115
+ generator: {capacity: 1000, recharge: 10},
116
+ },
117
+ {hasMovement: false}
118
+ )
119
+ expect(mover.hasMovement).toBe(false)
120
+ })
121
+
122
+ test('narrows hauler down to capacity and efficiency, dropping drain and capacityByTier', () => {
123
+ const mover = entityToRouteMover(
124
+ {id: UInt64.from(1)},
125
+ {
126
+ hullmass: 0,
127
+ hauler: {
128
+ capacity: 500,
129
+ efficiency: 80,
130
+ drain: 10,
131
+ capacityByTier: [{tier: 1, capacity: 500}],
132
+ },
133
+ }
134
+ )
135
+ expect(mover.hauler).toEqual({capacity: 500, efficiency: 80})
136
+ })
137
+
138
+ test('defaults energy, priorMobilityEnd, and narrowBarrierEnd to zero when unset', () => {
139
+ const mover = entityToRouteMover({id: UInt64.from(1)}, {hullmass: 0})
140
+ expect(mover.energy).toBe(0)
141
+ expect(mover.priorMobilityEnd).toBe(0)
142
+ expect(mover.narrowBarrierEnd).toBe(0)
143
+ })
144
+
145
+ test('opts override entityType and scheduling fields', () => {
146
+ const mover = entityToRouteMover(
147
+ {id: UInt64.from(7)},
148
+ {hullmass: 0},
149
+ {entityType: 'starbase', priorMobilityEnd: 30, narrowBarrierEnd: 15, allLanesEnd: 45}
150
+ )
151
+ expect(mover.ref).toEqual({entityType: 'starbase', entityId: UInt64.from(7)})
152
+ expect(mover.priorMobilityEnd).toBe(30)
153
+ expect(mover.narrowBarrierEnd).toBe(15)
154
+ expect(mover.allLanesEnd).toBe(45)
155
+ })
156
+ })
@@ -0,0 +1,86 @@
1
+ import type {UInt32Type, UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import type {ComputedCapabilities} from '../derivation/capabilities'
4
+ import type {RouteMoverInput} from '../travel/route-simulator'
5
+ import type {GatherLane} from '../planner'
6
+
7
+ const U8_MAX = 255
8
+ const U16_MAX = 65_535
9
+ const U32_MAX = 4_294_967_295
10
+
11
+ function clampField(value: number, max: number): number {
12
+ return Math.min(max, Math.max(0, Math.floor(Number(value) || 0)))
13
+ }
14
+
15
+ export interface GathererLaneSource {
16
+ gathererLanes?: ComputedCapabilities['gathererLanes']
17
+ gatherer?: ComputedCapabilities['gatherer']
18
+ }
19
+
20
+ export function hydrateEntityLanes(caps: GathererLaneSource): GatherLane[] {
21
+ const lanes = caps.gathererLanes?.length
22
+ ? caps.gathererLanes
23
+ : caps.gatherer
24
+ ? [
25
+ {
26
+ slotIndex: 0,
27
+ yield: caps.gatherer.yield,
28
+ drain: caps.gatherer.drain,
29
+ depth: caps.gatherer.depth,
30
+ outputPct: 100,
31
+ },
32
+ ]
33
+ : []
34
+ return lanes.map((lane) =>
35
+ ServerContract.Types.gatherer_lane.from({
36
+ slot_index: clampField(lane.slotIndex, U8_MAX),
37
+ yield: clampField(lane.yield, U16_MAX),
38
+ drain: clampField(lane.drain, U32_MAX),
39
+ depth: clampField(lane.depth, U16_MAX),
40
+ output_pct: clampField(lane.outputPct, U16_MAX),
41
+ })
42
+ )
43
+ }
44
+
45
+ export interface RouteMoverRow {
46
+ id: UInt64Type
47
+ energy?: UInt32Type | number
48
+ cargomass?: UInt32Type | number
49
+ }
50
+
51
+ export type RouteMoverCaps = Pick<
52
+ ComputedCapabilities,
53
+ 'hullmass' | 'engines' | 'generator' | 'hauler' | 'loaderLanes'
54
+ >
55
+
56
+ export interface RouteMoverOpts {
57
+ entityType?: string
58
+ hasMovement?: boolean
59
+ priorMobilityEnd?: number
60
+ narrowBarrierEnd?: number
61
+ allLanesEnd?: number
62
+ }
63
+
64
+ export function entityToRouteMover(
65
+ row: RouteMoverRow,
66
+ caps: RouteMoverCaps,
67
+ opts: RouteMoverOpts = {}
68
+ ): RouteMoverInput {
69
+ const loaderMass = (caps.loaderLanes ?? []).reduce((sum, lane) => sum + Number(lane.mass), 0)
70
+ const mass = Number(row.cargomass ?? 0) + Number(caps.hullmass ?? 0) + loaderMass
71
+ return {
72
+ ref: {entityType: opts.entityType ?? 'ship', entityId: row.id},
73
+ hasMovement:
74
+ opts.hasMovement ?? (caps.engines !== undefined && caps.generator !== undefined),
75
+ engines: caps.engines,
76
+ generator: caps.generator,
77
+ hauler: caps.hauler
78
+ ? {capacity: caps.hauler.capacity, efficiency: caps.hauler.efficiency}
79
+ : undefined,
80
+ mass,
81
+ energy: Number(row.energy ?? 0),
82
+ priorMobilityEnd: opts.priorMobilityEnd ?? 0,
83
+ narrowBarrierEnd: opts.narrowBarrierEnd ?? 0,
84
+ allLanesEnd: opts.allLanesEnd,
85
+ }
86
+ }
package/src/errors.ts CHANGED
@@ -16,20 +16,18 @@ export const REQUIRES_POSITIVE_VALUE = 'Value must be greater than zero.'
16
16
  export const PLAYER_ALREADY_JOINED = 'Player has already joined the game.'
17
17
  export const PLAYER_NOT_JOINED = 'Player has not joined the game.'
18
18
  export const PLAYER_NOT_FOUND = 'Cannot find player for given account name.'
19
- export const STARTER_ALREADY_CLAIMED =
20
- 'Starter ship already claimed; destroy existing ships to re-claim.'
21
- export const SHIP_ALREADY_THERE = 'Ship cannot travel to the location its already at.'
19
+ export const ENTITY_ALREADY_THERE = 'Entity cannot travel to the location it is already at.'
22
20
  export const SHIP_ALREADY_TRAVELING = 'Ship is already traveling.'
23
21
  export const SHIP_CANNOT_BUY_TRAVELING = 'Ship cannot buy goods while traveling.'
24
22
  export const SHIP_CANNOT_UPDATE_TRAVELING = 'Ship cannot be updated while traveling.'
25
- export const SHIP_INVALID_DESTINATION = 'Ship cannot travel, no system at specified destination.'
26
- export const SHIP_INVALID_TRAVEL_DURATION =
23
+ export const ENTITY_INVALID_DESTINATION = 'Cannot travel: no system at specified destination.'
24
+ export const ENTITY_INVALID_TRAVEL_DURATION =
27
25
  'This trip cannot be made as it would exceed the maximum travel duration.'
28
26
  export const SHIP_NOT_ARRIVED = 'Ship has not yet arrived at its destination.'
29
- export const SHIP_NOT_ENOUGH_ENERGY =
30
- 'Ship does not have enough energy to travel to the destination.'
31
- export const SHIP_NOT_ENOUGH_ENERGY_CAPACITY =
32
- 'Ship does not have enough energy capacity to travel.'
27
+ export const ENTITY_NOT_ENOUGH_ENERGY =
28
+ 'Entity does not have enough energy to travel to the destination.'
29
+ export const ENTITY_NOT_ENOUGH_ENERGY_CAPACITY =
30
+ 'Entity does not have enough energy capacity to travel.'
33
31
  export const SHIP_NOT_FOUND = 'Cannot find ship for given account.'
34
32
  export const SHIP_NOT_OWNED = 'Ship is not owned by this account.'
35
33
  export const NO_SCHEDULE = 'No scheduled tasks.'
@@ -38,19 +36,15 @@ export const SHIP_NO_COMPLETED_TASKS = 'No completed tasks to resolve.'
38
36
  export const RESOLVE_COUNT_EXCEEDS_COMPLETED = 'Requested resolve count exceeds completed tasks.'
39
37
  export const SHIP_CANNOT_CANCEL_TASK = 'Cannot cancel task that is immutable or in progress.'
40
38
  export const SHIP_NO_TASKS_TO_CANCEL = 'No tasks to cancel.'
41
- export const SHIP_INVALID_CARGO = 'Invalid cargo specified for load/unload.'
42
- export const SHIP_CARGO_NOT_OWNED = 'Cannot load cargo that is not owned.'
43
- export const SHIP_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.'
44
- export const SHIP_CAPACITY_EXCEEDED = 'Ship cargo capacity would be exceeded.'
39
+ export const ENTITY_INVALID_CARGO = 'Invalid cargo specified for load/unload.'
40
+ export const ENTITY_CARGO_NOT_OWNED = 'Cannot load cargo that is not owned.'
41
+ export const ENTITY_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.'
45
42
  export const ENTITY_CAPACITY_EXCEEDED = 'Entity cargo capacity would be exceeded.'
46
43
  export const WAREHOUSE_NOT_FOUND = 'Cannot find warehouse for given id.'
47
44
  export const WAREHOUSE_ALREADY_AT_LOCATION = 'Warehouse already exists at this location.'
48
- export const WAREHOUSE_CAPACITY_EXCEEDED = 'Warehouse capacity would be exceeded.'
49
45
  export const CONTAINER_NOT_FOUND = 'Cannot find container for given id.'
50
- export const CONTAINER_CAPACITY_EXCEEDED = 'Container capacity would be exceeded.'
51
46
  export const DESTINATION_CAPACITY_EXCEEDED =
52
47
  'Destination entity does not have enough capacity for the gather.'
53
- export const CANCEL_PAIRED_HAS_PENDING = 'Cannot cancel transfer, paired entity has pending tasks.'
54
48
  export const GROUP_EMPTY = 'Group travel requires at least one entity.'
55
49
  export const GROUP_NO_THRUST = 'Group travel requires at least one entity with engines.'
56
50
  export const GROUP_NOT_SAME_LOCATION = 'All entities must be at the same location for group travel.'
@@ -62,6 +56,8 @@ export const GROUP_HAUL_CAPACITY_EXCEEDED =
62
56
  'Group travel requires sufficient hauler capacity for all non-self-propelled entities.'
63
57
  export const CANCEL_CONTAINS_GROUPED_TASK =
64
58
  'Cannot cancel range containing grouped task - cancel non-grouped tasks first.'
59
+ export const WOULD_STRAND = 'Cancelling this would leave a later task without the cargo it needs.'
60
+ export const WOULD_OVERFILL = 'Cancelling this would overfill the other entity with returned cargo.'
65
61
  export const WARP_NO_CAPABILITY = 'Entity does not have warp capability.'
66
62
  export const WARP_HAS_SCHEDULE = 'Entity must be idle to warp.'
67
63
  export const WARP_HAS_CARGO = 'Entity must have no cargo to warp.'
@@ -98,3 +94,12 @@ export const ITEM_NOT_AVAILABLE_AT_LOCATION = 'Item is not tradeable at ship loc
98
94
  export const INSUFFICIENT_BALANCE = 'Insufficient balance.'
99
95
  export const INSUFFICIENT_ITEM_QUANTITY = 'Insufficient quantity in cargo.'
100
96
  export const INSUFFICIENT_ITEM_SUPPLY = 'Insufficient supply of item at location.'
97
+
98
+ export const VOTE_NOT_CITIZEN = 'player is not a citizen of this world'
99
+ export const BALLOT_SETTLING = 'world is settling the last epoch'
100
+ export const BALLOT_NOT_DUE = 'ballot is not due'
101
+ export const BALLOT_NONE_DUE = 'no ballots are due'
102
+
103
+ export function isSettling(error: unknown): boolean {
104
+ return error instanceof Error && error.message.includes(BALLOT_SETTLING)
105
+ }
package/src/format.ts CHANGED
@@ -1,12 +1,45 @@
1
- export function formatMass(kg: number): string {
2
- const t = kg / 1000
3
- const fixed = t.toFixed(2)
4
- const trimmed = fixed.replace(/\.?0+$/, '')
5
- return `${trimmed} t`
1
+ import {MASS_UNITS_PER_TONNE} from './types'
2
+
3
+ export function formatMass(mass: number): string {
4
+ if (mass === 0) return '0 t'
5
+ const sign = mass < 0 ? '-' : ''
6
+ const centitonnes = Math.abs(mass) * 10
7
+ const t = Math.floor(centitonnes / 100)
8
+ const frac = centitonnes % 100
9
+ if (frac === 0) return `${sign}${t} t`
10
+ const fracStr = String(frac).padStart(2, '0').replace(/0$/, '')
11
+ return `${sign}${t}.${fracStr} t`
12
+ }
13
+
14
+ export function formatMassDelta(mass: number): string {
15
+ if (mass === 0) return '0 t'
16
+ const sign = mass > 0 ? '+' : '-'
17
+ return `${sign}${formatMass(Math.abs(mass))}`
18
+ }
19
+
20
+ export function formatLocation(loc: {x: number; y: number}): string {
21
+ return `${loc.x}, ${loc.y}`
22
+ }
23
+
24
+ function trim(n: number, digits = 1): string {
25
+ return n.toFixed(digits).replace(/\.?0+$/, '')
26
+ }
27
+
28
+ export function formatMassScaled(mass: number): string {
29
+ if (mass === 0) return '0 t'
30
+ const sign = mass < 0 ? '-' : ''
31
+ const tonnes = Math.abs(mass) / MASS_UNITS_PER_TONNE
32
+ if (tonnes >= 1_000_000_000) return `${sign}${trim(tonnes / 1_000_000_000)}b t`
33
+ if (tonnes >= 1_000_000) return `${sign}${trim(tonnes / 1_000_000)}m t`
34
+ if (tonnes >= 1_000) return `${sign}${trim(tonnes / 1_000)}k t`
35
+ return formatMass(mass)
36
+ }
37
+
38
+ export function formatInfluence(atomic: bigint | number | string): string {
39
+ const points = BigInt(String(atomic)) / 10_000n
40
+ return `${points.toLocaleString('en-US')} pts`
6
41
  }
7
42
 
8
- export function formatMassDelta(kg: number): string {
9
- if (kg === 0) return '0 t'
10
- const sign = kg > 0 ? '+' : '-'
11
- return `${sign}${formatMass(Math.abs(kg))}`
43
+ export function formatNeedMultiplier(needFp: bigint | number | string): string {
44
+ return `×${(Number(BigInt(String(needFp))) / 10_000).toFixed(1)}`
12
45
  }