@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,296 @@
1
+ import type {GathererStats} from '../types/capabilities'
2
+ import type {ServerContract} from '../contracts'
3
+ import {calc_gather_duration, calc_gather_energy} from '../capabilities/gathering'
4
+ import {calc_rechargetime} from '../travel/travel'
5
+ import {projectRemainingAt, type Projectable} from '../scheduling/projection'
6
+ import {selectGatherLane} from '../scheduling/lanes'
7
+
8
+ export type GatherLane = ServerContract.Types.gatherer_lane
9
+
10
+ export interface LanePlanEntry {
11
+ slot: number
12
+ quantity: number
13
+ }
14
+
15
+ export type PlanTarget = {quantity: number} | 'max'
16
+
17
+ export interface GatherPlanEntity extends Projectable {
18
+ gatherer_lanes: ServerContract.Types.gatherer_lane[]
19
+ loader_lanes: ServerContract.Types.loader_lane[]
20
+ }
21
+
22
+ export interface GatherLimpet {
23
+ slot: number
24
+ quantity: number
25
+ durationSeconds: number
26
+ }
27
+
28
+ export interface GatherCycle {
29
+ rechargeBefore: boolean
30
+ rechargeSeconds: number
31
+ limpets: GatherLimpet[]
32
+ gatherSeconds: number
33
+ batchOre: number
34
+ }
35
+
36
+ export type FillCap = 'reserve' | 'hold' | 'requested'
37
+
38
+ export interface GatherPlan {
39
+ cycles: GatherCycle[]
40
+ cycleCount: number
41
+ totalOre: number
42
+ totalSeconds: number
43
+ cap: FillCap
44
+ reachingCount: number
45
+ totalLimpets: number
46
+ warnings: string[]
47
+ }
48
+
49
+ export interface BuildGatherPlanOpts {
50
+ richness: number
51
+ itemMass: number
52
+ holdRoom: number
53
+ reserveRemaining: number
54
+ now: Date
55
+ }
56
+
57
+ const MAX_CYCLES = 10_000
58
+
59
+ const MAX_TRANSFER_QTY = 10000
60
+
61
+ export function allocateProportional(
62
+ lanes: {slot: number; weight: number}[],
63
+ total: number
64
+ ): LanePlanEntry[] {
65
+ if (lanes.length === 0) return []
66
+ const weightSum = lanes.reduce((s, l) => s + l.weight, 0)
67
+ if (weightSum === 0) return []
68
+
69
+ const entries: LanePlanEntry[] = lanes.map((l) => ({
70
+ slot: l.slot,
71
+ quantity: Math.floor((total * l.weight) / weightSum),
72
+ }))
73
+
74
+ let remainder = total - entries.reduce((s, e) => s + e.quantity, 0)
75
+ for (let i = 0; remainder > 0; i = (i + 1) % entries.length) {
76
+ entries[i].quantity++
77
+ remainder--
78
+ }
79
+
80
+ return entries
81
+ }
82
+
83
+ function laneStats(lane: ServerContract.Types.gatherer_lane): GathererStats {
84
+ return lane as unknown as GathererStats
85
+ }
86
+
87
+ export function gatherEnergyCost(
88
+ lane: ServerContract.Types.gatherer_lane,
89
+ quantity: number,
90
+ stratum: number,
91
+ itemMass: number,
92
+ richness: number
93
+ ): number {
94
+ if (quantity <= 0) return 0
95
+ const dur = Number(calc_gather_duration(laneStats(lane), itemMass, quantity, stratum, richness))
96
+ return Number(calc_gather_energy(laneStats(lane), dur))
97
+ }
98
+
99
+ export function splitCost(
100
+ reaching: ServerContract.Types.gatherer_lane[],
101
+ quantity: number,
102
+ stratum: number,
103
+ itemMass: number,
104
+ richness: number
105
+ ): number {
106
+ if (quantity <= 0) return 0
107
+ const weights = reaching.map((l) => ({
108
+ slot: l.slot_index.toNumber(),
109
+ weight: l.yield.toNumber(),
110
+ }))
111
+ const split = allocateProportional(weights, quantity)
112
+ return split.reduce((sum, e) => {
113
+ const lane = reaching.find((l) => l.slot_index.toNumber() === e.slot)!
114
+ return sum + gatherEnergyCost(lane, e.quantity, stratum, itemMass, richness)
115
+ }, 0)
116
+ }
117
+
118
+ // Binary search is exact because splitCost is monotonic non-decreasing in Q.
119
+ export function maxQtyForCharge(
120
+ reaching: ServerContract.Types.gatherer_lane[],
121
+ hi: number,
122
+ capacity: number,
123
+ stratum: number,
124
+ itemMass: number,
125
+ richness: number
126
+ ): number {
127
+ if (hi <= 0) return 0
128
+ if (splitCost(reaching, hi, stratum, itemMass, richness) <= capacity) return hi
129
+ let lo = 0
130
+ let high = hi
131
+ while (lo < high) {
132
+ const mid = Math.ceil((lo + high) / 2)
133
+ if (splitCost(reaching, mid, stratum, itemMass, richness) <= capacity) lo = mid
134
+ else high = mid - 1
135
+ }
136
+ return lo
137
+ }
138
+
139
+ export function buildGatherPlan(
140
+ entity: GatherPlanEntity,
141
+ stratum: number,
142
+ target: PlanTarget,
143
+ opts: BuildGatherPlanOpts
144
+ ): GatherPlan {
145
+ const {richness, itemMass, holdRoom, reserveRemaining, now} = opts
146
+ const warnings: string[] = []
147
+
148
+ const reaching = entity.gatherer_lanes.filter((l) => l.depth.toNumber() >= stratum)
149
+ if (reaching.length === 0) throw new Error('no gatherer reaches this stratum')
150
+ if (!entity.generator) throw new Error('entity has no generator')
151
+
152
+ const blocked = entity.gatherer_lanes.length - reaching.length
153
+ if (blocked > 0) {
154
+ warnings.push(
155
+ `${blocked} of ${entity.gatherer_lanes.length} limpets can't reach this depth`
156
+ )
157
+ }
158
+
159
+ const capacity = entity.generator.capacity.toNumber()
160
+ const rechargeRate = entity.generator.recharge.toNumber()
161
+ let energy = Number(projectRemainingAt(entity, now).energy)
162
+
163
+ const requested = target === 'max' ? Infinity : target.quantity
164
+ let fillTarget = requested
165
+ let cap: FillCap = 'requested'
166
+ if (holdRoom < fillTarget) {
167
+ fillTarget = holdRoom
168
+ cap = 'hold'
169
+ }
170
+ if (reserveRemaining < fillTarget) {
171
+ fillTarget = reserveRemaining
172
+ cap = 'reserve'
173
+ }
174
+ fillTarget = Math.max(0, Math.floor(fillTarget))
175
+
176
+ const cycles: GatherCycle[] = []
177
+ let remaining = fillTarget
178
+ let guard = 0
179
+ while (remaining > 0 && guard++ < MAX_CYCLES) {
180
+ const batch = maxQtyForCharge(reaching, remaining, capacity, stratum, itemMass, richness)
181
+ if (batch <= 0) {
182
+ warnings.push('a single gather cannot fit within one full charge')
183
+ break
184
+ }
185
+
186
+ const costFull = splitCost(reaching, batch, stratum, itemMass, richness)
187
+ const rechargeBefore = energy < costFull
188
+ const rechargeSeconds = rechargeBefore
189
+ ? Number(calc_rechargetime(capacity, energy, rechargeRate))
190
+ : 0
191
+ if (rechargeBefore) energy = capacity
192
+
193
+ const weights = reaching.map((l) => ({
194
+ slot: l.slot_index.toNumber(),
195
+ weight: l.yield.toNumber(),
196
+ }))
197
+ const split = allocateProportional(weights, batch).filter((e) => e.quantity > 0)
198
+ const limpets: GatherLimpet[] = split.map((e) => {
199
+ const lane = reaching.find((l) => l.slot_index.toNumber() === e.slot)!
200
+ const dur = Number(
201
+ calc_gather_duration(laneStats(lane), itemMass, e.quantity, stratum, richness)
202
+ )
203
+ return {slot: e.slot, quantity: e.quantity, durationSeconds: dur}
204
+ })
205
+ const actualCost = limpets.reduce((sum, l) => {
206
+ const lane = reaching.find((r) => r.slot_index.toNumber() === l.slot)!
207
+ return sum + Number(calc_gather_energy(laneStats(lane), l.durationSeconds))
208
+ }, 0)
209
+ energy = Math.max(0, energy - actualCost)
210
+
211
+ const gatherSeconds = limpets.reduce((m, l) => Math.max(m, l.durationSeconds), 0)
212
+ cycles.push({rechargeBefore, rechargeSeconds, limpets, gatherSeconds, batchOre: batch})
213
+ remaining -= batch
214
+ }
215
+
216
+ const totalOre = cycles.reduce((s, c) => s + c.batchOre, 0)
217
+ const totalSeconds = cycles.reduce((s, c) => s + c.rechargeSeconds + c.gatherSeconds, 0)
218
+ return {
219
+ cycles,
220
+ cycleCount: cycles.length,
221
+ totalOre,
222
+ totalSeconds,
223
+ cap,
224
+ reachingCount: reaching.length,
225
+ totalLimpets: entity.gatherer_lanes.length,
226
+ warnings,
227
+ }
228
+ }
229
+
230
+ export interface SingleGatherPlan {
231
+ laneKey: number
232
+ quantity: number
233
+ energyCost: number
234
+ needsRecharge: boolean
235
+ }
236
+
237
+ // None of these are PRECISION-scaled: stratum/itemMass/richness/energy fields are plain units, same as maxQtyForCharge/splitCost.
238
+ export interface SingleGatherInput {
239
+ modules: ServerContract.Types.module_entry[]
240
+ entityItemId: number
241
+ lanes: ServerContract.Types.lane[]
242
+ gathererLanes: GatherLane[]
243
+ stratum: number
244
+ desiredQuantity: number
245
+ itemMass: number
246
+ richness: number
247
+ generatorCapacity: number
248
+ currentEnergy: number
249
+ }
250
+
251
+ export function planSingleGather(opts: SingleGatherInput): SingleGatherPlan {
252
+ const {
253
+ modules,
254
+ entityItemId,
255
+ lanes,
256
+ gathererLanes,
257
+ stratum,
258
+ desiredQuantity,
259
+ itemMass,
260
+ richness,
261
+ generatorCapacity,
262
+ currentEnergy,
263
+ } = opts
264
+
265
+ const laneKey = selectGatherLane(modules, entityItemId, lanes, stratum)
266
+ const lane = gathererLanes.find((l) => l.slot_index.toNumber() === laneKey - 1)
267
+ if (!lane) throw new Error('gatherer lane not found for selected slot')
268
+
269
+ const quantity = maxQtyForCharge(
270
+ [lane],
271
+ desiredQuantity,
272
+ generatorCapacity,
273
+ stratum,
274
+ itemMass,
275
+ richness
276
+ )
277
+ const energyCost = splitCost([lane], quantity, stratum, itemMass, richness)
278
+ return {laneKey, quantity, energyCost, needsRecharge: currentEnergy < energyCost}
279
+ }
280
+
281
+ export function planParallelTransfer(
282
+ entity: GatherPlanEntity,
283
+ target: PlanTarget
284
+ ): LanePlanEntry[] {
285
+ const lanes = entity.loader_lanes.filter((l) => l.thrust.toNumber() > 0)
286
+ if (lanes.length === 0) return []
287
+
288
+ const requestedQty = target === 'max' ? MAX_TRANSFER_QTY : target.quantity
289
+
290
+ const laneWeights = lanes.map((l) => ({
291
+ slot: l.slot_index.toNumber(),
292
+ weight: l.thrust.toNumber(),
293
+ }))
294
+
295
+ return allocateProportional(laneWeights, requestedQty).filter((e) => e.quantity > 0)
296
+ }