@shipload/sdk 1.0.0-next.5 → 1.0.0-next.50

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 (144) 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 +2881 -1149
  7. package/lib/shipload.js +13031 -5511
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +12807 -5460
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +1028 -0
  12. package/lib/testing.js +4336 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +4330 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.ts +51 -0
  18. package/src/capabilities/crafting.test.ts +7 -0
  19. package/src/capabilities/crafting.ts +6 -7
  20. package/src/capabilities/gathering.test.ts +29 -0
  21. package/src/capabilities/gathering.ts +37 -19
  22. package/src/capabilities/index.ts +0 -1
  23. package/src/capabilities/modules.ts +22 -0
  24. package/src/capabilities/storage.ts +16 -1
  25. package/src/contracts/platform.ts +231 -3
  26. package/src/contracts/server.ts +1160 -520
  27. package/src/coordinates/address.ts +88 -0
  28. package/src/coordinates/constants.test.ts +15 -0
  29. package/src/coordinates/constants.ts +23 -0
  30. package/src/coordinates/index.ts +15 -0
  31. package/src/coordinates/memo.test.ts +47 -0
  32. package/src/coordinates/memo.ts +20 -0
  33. package/src/coordinates/permutation.ts +77 -0
  34. package/src/coordinates/regions.ts +48 -0
  35. package/src/coordinates/sectors.ts +115 -0
  36. package/src/data/capabilities.ts +31 -16
  37. package/src/data/capability-formulas.ts +21 -14
  38. package/src/data/catalog.ts +0 -5
  39. package/src/data/colors.ts +13 -47
  40. package/src/data/entities.json +154 -10
  41. package/src/data/item-ids.ts +31 -12
  42. package/src/data/items.json +192 -74
  43. package/src/data/kind-registry.json +131 -0
  44. package/src/data/kind-registry.ts +172 -0
  45. package/src/data/metadata.ts +166 -48
  46. package/src/data/recipes-runtime.ts +5 -23
  47. package/src/data/recipes.json +1003 -163
  48. package/src/derivation/build-methods.test.ts +13 -0
  49. package/src/derivation/build-methods.ts +48 -0
  50. package/src/derivation/capabilities.test.ts +151 -0
  51. package/src/derivation/capabilities.ts +527 -0
  52. package/src/derivation/capability-mappings.ts +58 -16
  53. package/src/derivation/crafting.ts +36 -33
  54. package/src/derivation/index.ts +28 -2
  55. package/src/derivation/recipe-usage.test.ts +81 -0
  56. package/src/derivation/recipe-usage.ts +141 -0
  57. package/src/derivation/reserve-regen.ts +34 -0
  58. package/src/derivation/resources.ts +98 -19
  59. package/src/derivation/rollups.test.ts +55 -0
  60. package/src/derivation/rollups.ts +56 -0
  61. package/src/derivation/stars.test.ts +67 -0
  62. package/src/derivation/stars.ts +25 -0
  63. package/src/derivation/stats.ts +6 -6
  64. package/src/derivation/stratum.ts +26 -22
  65. package/src/derivation/tiers.ts +40 -7
  66. package/src/derivation/upgrades.ts +14 -0
  67. package/src/derivation/wormhole.ts +141 -0
  68. package/src/entities/entity.ts +98 -0
  69. package/src/entities/gamestate.ts +3 -28
  70. package/src/entities/makers.ts +131 -134
  71. package/src/entities/slot-multiplier.ts +43 -0
  72. package/src/errors.ts +12 -16
  73. package/src/format.ts +26 -4
  74. package/src/index-module.ts +290 -34
  75. package/src/managers/actions.ts +602 -105
  76. package/src/managers/base.ts +6 -2
  77. package/src/managers/cluster.test.ts +39 -0
  78. package/src/managers/cluster.ts +53 -0
  79. package/src/managers/construction-types.ts +80 -0
  80. package/src/managers/construction.ts +412 -0
  81. package/src/managers/context.ts +29 -1
  82. package/src/managers/coordinates.ts +14 -0
  83. package/src/managers/entities.ts +27 -66
  84. package/src/managers/epochs.ts +40 -0
  85. package/src/managers/flatten-gather-plan.test.ts +80 -0
  86. package/src/managers/index.ts +20 -1
  87. package/src/managers/locations.ts +25 -29
  88. package/src/managers/nft.test.ts +14 -0
  89. package/src/managers/nft.ts +70 -0
  90. package/src/managers/players.ts +25 -0
  91. package/src/managers/plot.ts +122 -0
  92. package/src/nft/atomicassets.abi.json +1342 -0
  93. package/src/nft/atomicassets.ts +237 -0
  94. package/src/nft/atomicdata.ts +130 -0
  95. package/src/nft/buildImmutableData.ts +336 -0
  96. package/src/nft/description.ts +104 -36
  97. package/src/nft/index.ts +3 -0
  98. package/src/planner/index.ts +242 -0
  99. package/src/planner/planner.test.ts +325 -0
  100. package/src/resolution/describe-module.ts +43 -25
  101. package/src/resolution/display-name.ts +38 -10
  102. package/src/resolution/resolve-item.test.ts +48 -0
  103. package/src/resolution/resolve-item.ts +74 -47
  104. package/src/scan/index.ts +244 -0
  105. package/src/scan/scan-wasm.base64.ts +2 -0
  106. package/src/scheduling/accessor.ts +65 -23
  107. package/src/scheduling/availability.ts +108 -0
  108. package/src/scheduling/cancel.test.ts +348 -0
  109. package/src/scheduling/cancel.ts +209 -0
  110. package/src/scheduling/energy.ts +47 -0
  111. package/src/scheduling/idle-resolve.ts +45 -0
  112. package/src/scheduling/lane-core.ts +128 -0
  113. package/src/scheduling/lanes.test.ts +249 -0
  114. package/src/scheduling/lanes.ts +198 -0
  115. package/src/scheduling/projection.ts +210 -107
  116. package/src/scheduling/schedule.ts +240 -117
  117. package/src/scheduling/task-cargo.ts +46 -0
  118. package/src/scheduling/unwrap.test.ts +86 -0
  119. package/src/scheduling/unwrap.ts +190 -0
  120. package/src/shipload.ts +26 -1
  121. package/src/subscriptions/manager.cluster.test.ts +51 -0
  122. package/src/subscriptions/manager.ts +245 -172
  123. package/src/subscriptions/mappers.ts +5 -8
  124. package/src/subscriptions/types.ts +28 -3
  125. package/src/testing/catalog-hash.ts +19 -0
  126. package/src/testing/index.ts +2 -0
  127. package/src/testing/projection-parity.ts +167 -0
  128. package/src/travel/reach.ts +23 -0
  129. package/src/travel/route-planner.ts +277 -0
  130. package/src/travel/travel.ts +148 -117
  131. package/src/types/capabilities.ts +29 -6
  132. package/src/types/entity.ts +3 -3
  133. package/src/types/index.ts +0 -1
  134. package/src/types.ts +36 -14
  135. package/src/utils/cargo.test.ts +14 -0
  136. package/src/utils/cargo.ts +29 -0
  137. package/src/utils/display-name.ts +70 -0
  138. package/src/utils/system.ts +36 -24
  139. package/src/capabilities/loading.ts +0 -8
  140. package/src/entities/container.ts +0 -123
  141. package/src/entities/ship-deploy.ts +0 -295
  142. package/src/entities/ship.ts +0 -221
  143. package/src/entities/warehouse.ts +0 -127
  144. package/src/types/entity-traits.ts +0 -69
@@ -0,0 +1,13 @@
1
+ import {describe, expect, test} from 'bun:test'
2
+ import {availableBuildMethods} from './build-methods'
3
+ import {ITEM_HUB_T1_PACKED, ITEM_WAREHOUSE_T1_PACKED} from '../data/item-ids'
4
+
5
+ describe('availableBuildMethods', () => {
6
+ test('orbital structures build via craft+deploy or plot', () => {
7
+ expect(availableBuildMethods(ITEM_WAREHOUSE_T1_PACKED)).toEqual(['craft+deploy', 'plot'])
8
+ })
9
+
10
+ test('hub is craft+deploy only — excluded from the plot path', () => {
11
+ expect(availableBuildMethods(ITEM_HUB_T1_PACKED)).toEqual(['craft+deploy'])
12
+ })
13
+ })
@@ -0,0 +1,48 @@
1
+ import {ENTITY_HUB, EntityClass, getKindMeta, getTemplateMeta} from '../data/kind-registry'
2
+ import {getRecipe} from '../data/recipes-runtime'
3
+ import {getItems} from '../data/catalog'
4
+ import type {Item} from '../types'
5
+
6
+ export type BuildMethod = 'craft+deploy' | 'plot'
7
+
8
+ export function availableBuildMethods(itemId: number): BuildMethod[] {
9
+ const recipe = getRecipe(itemId)
10
+ if (!recipe) return []
11
+
12
+ const template = getTemplateMeta(itemId)
13
+ if (!template) return ['craft+deploy']
14
+
15
+ const kindMeta = getKindMeta(template.kind)
16
+ if (!kindMeta) return ['craft+deploy']
17
+
18
+ if (
19
+ kindMeta.classification === EntityClass.OrbitalStructure &&
20
+ !kindMeta.kind.equals(ENTITY_HUB)
21
+ ) {
22
+ return ['craft+deploy', 'plot']
23
+ }
24
+ return ['craft+deploy']
25
+ }
26
+
27
+ export function isBuildable(itemId: number): boolean {
28
+ return availableBuildMethods(itemId).length > 0
29
+ }
30
+
31
+ export function isPlotBuildable(itemId: number): boolean {
32
+ return availableBuildMethods(itemId).includes('plot')
33
+ }
34
+
35
+ export function filterByBuildMethod<T extends {itemId: number}>(
36
+ items: T[],
37
+ method: BuildMethod
38
+ ): T[] {
39
+ return items.filter((i) => availableBuildMethods(i.itemId).includes(method))
40
+ }
41
+
42
+ export function allBuildableItems(): Item[] {
43
+ return getItems().filter((item) => isBuildable(item.id))
44
+ }
45
+
46
+ export function allPlotBuildableItems(): Item[] {
47
+ return getItems().filter((item) => isPlotBuildable(item.id))
48
+ }
@@ -0,0 +1,151 @@
1
+ import {expect, test} from 'bun:test'
2
+ import {
3
+ computeEntityCapabilities,
4
+ computeGathererCapabilities,
5
+ computeCrafterCapabilities,
6
+ computeLoaderCapabilities,
7
+ computeBaseCapacity,
8
+ computeContainerCapabilities,
9
+ } from './capabilities'
10
+ import {applySlotMultiplier, U16_MAX} from '../entities/slot-multiplier'
11
+ import {encodeStats} from './crafting'
12
+ import {
13
+ ITEM_EXTRACTOR_T1_PACKED,
14
+ ITEM_FACTORY_T1_PACKED,
15
+ ITEM_MASS_DRIVER_T1_PACKED,
16
+ ITEM_MASS_CATCHER_T1_PACKED,
17
+ ITEM_GATHERER_T1,
18
+ ITEM_CRAFTER_T1,
19
+ ITEM_LOADER_T1,
20
+ } from '../data/item-ids'
21
+ import type {InstalledModule} from '../entities/slot-multiplier'
22
+ import type {EntitySlot} from '../data/recipes-runtime'
23
+
24
+ function makeGathererStats(strength: number, hardness: number, saturation: number): bigint {
25
+ return encodeStats([strength, hardness, saturation, 0])
26
+ }
27
+
28
+ function makeCrafterStats(fineness: number, conductivity: number): bigint {
29
+ return encodeStats([fineness, conductivity])
30
+ }
31
+
32
+ function makeLoaderStats(insulation: number, plasticity: number): bigint {
33
+ return encodeStats([insulation, plasticity])
34
+ }
35
+
36
+ test('computeBaseCapacity uses container formula for all container-class entities', () => {
37
+ const stats = {strength: 300, hardness: 400, density: 100}
38
+ const expected = computeContainerCapabilities(stats).capacity
39
+ for (const itemId of [
40
+ ITEM_EXTRACTOR_T1_PACKED,
41
+ ITEM_FACTORY_T1_PACKED,
42
+ ITEM_MASS_DRIVER_T1_PACKED,
43
+ ITEM_MASS_CATCHER_T1_PACKED,
44
+ ]) {
45
+ expect(computeBaseCapacity(itemId, stats)).toBe(expected)
46
+ }
47
+ })
48
+
49
+ test('computeEntityCapabilities emits gathererLanes alongside legacy gatherer sum', () => {
50
+ // Two gatherers with distinct stats in separate slots, amp=100 for both
51
+ const gathStats1 = makeGathererStats(300, 200, 400)
52
+ const gathStats2 = makeGathererStats(500, 100, 300)
53
+
54
+ const modules: InstalledModule[] = [
55
+ {slotIndex: 0, itemId: ITEM_GATHERER_T1, stats: gathStats1},
56
+ {slotIndex: 1, itemId: ITEM_GATHERER_T1, stats: gathStats2},
57
+ ]
58
+
59
+ const layout: EntitySlot[] = [
60
+ {type: 'gatherer', outputPct: 100, maxTier: 1},
61
+ {type: 'gatherer', outputPct: 100, maxTier: 1},
62
+ ]
63
+
64
+ const result = computeEntityCapabilities({}, ITEM_EXTRACTOR_T1_PACKED, modules, layout)
65
+
66
+ // Lane lists must exist
67
+ expect(result.gathererLanes).toBeDefined()
68
+ expect(result.gathererLanes!.length).toBe(2)
69
+
70
+ // Each lane has the right slotIndex
71
+ expect(result.gathererLanes![0].slotIndex).toBe(0)
72
+ expect(result.gathererLanes![1].slotIndex).toBe(1)
73
+
74
+ // Yields are amp-scaled and distinct
75
+ const caps1 = computeGathererCapabilities({strength: 300, hardness: 200, saturation: 400}, 1)
76
+ const caps2 = computeGathererCapabilities({strength: 500, hardness: 100, saturation: 300}, 1)
77
+ const expectedYield1 = applySlotMultiplier(caps1.yield, 100)
78
+ const expectedYield2 = applySlotMultiplier(caps2.yield, 100)
79
+ expect(result.gathererLanes![0].yield).toBe(expectedYield1)
80
+ expect(result.gathererLanes![1].yield).toBe(expectedYield2)
81
+ expect(result.gathererLanes![0].yield).not.toBe(result.gathererLanes![1].yield)
82
+
83
+ // Unscaled per-module drain and depth carried verbatim from the compute helper
84
+ expect(result.gathererLanes![0].drain).toBe(caps1.drain)
85
+ expect(result.gathererLanes![1].drain).toBe(caps2.drain)
86
+ expect(result.gathererLanes![0].depth).toBe(caps1.depth)
87
+ expect(result.gathererLanes![1].depth).toBe(caps2.depth)
88
+
89
+ // outputPct reflects the slot amp
90
+ expect(result.gathererLanes![0].outputPct).toBe(100)
91
+ expect(result.gathererLanes![1].outputPct).toBe(100)
92
+
93
+ // Legacy sum still equals sum of both lane yields
94
+ expect(result.gatherer).toBeDefined()
95
+ expect(result.gatherer!.yield).toBe(expectedYield1 + expectedYield2)
96
+ })
97
+
98
+ test('computeEntityCapabilities emits crafterLanes alongside legacy crafter sum', () => {
99
+ const crafterStats = makeCrafterStats(400, 300)
100
+
101
+ const modules: InstalledModule[] = [
102
+ {slotIndex: 0, itemId: ITEM_CRAFTER_T1, stats: crafterStats},
103
+ ]
104
+
105
+ const layout: EntitySlot[] = [{type: 'crafter', outputPct: 120, maxTier: 1}]
106
+
107
+ const result = computeEntityCapabilities({}, ITEM_EXTRACTOR_T1_PACKED, modules, layout)
108
+
109
+ expect(result.crafterLanes).toBeDefined()
110
+ expect(result.crafterLanes!.length).toBe(1)
111
+ expect(result.crafterLanes![0].slotIndex).toBe(0)
112
+
113
+ const caps = computeCrafterCapabilities({fineness: 400, conductivity: 300})
114
+ const expectedSpeed = applySlotMultiplier(caps.speed, 120)
115
+ expect(result.crafterLanes![0].speed).toBe(expectedSpeed)
116
+ expect(result.crafterLanes![0].drain).toBe(caps.drain)
117
+ expect(result.crafterLanes![0].outputPct).toBe(120)
118
+
119
+ // Legacy crafter speed equals single-lane speed
120
+ expect(result.crafter).toBeDefined()
121
+ expect(result.crafter!.speed).toBe(expectedSpeed)
122
+ })
123
+
124
+ test('computeEntityCapabilities emits loaderLanes alongside legacy loaders sum', () => {
125
+ const loaderStats = makeLoaderStats(600, 500)
126
+
127
+ const modules: InstalledModule[] = [{slotIndex: 0, itemId: ITEM_LOADER_T1, stats: loaderStats}]
128
+
129
+ const layout: EntitySlot[] = [{type: 'loader', outputPct: 80, maxTier: 1}]
130
+
131
+ const result = computeEntityCapabilities({}, ITEM_EXTRACTOR_T1_PACKED, modules, layout)
132
+
133
+ expect(result.loaderLanes).toBeDefined()
134
+ expect(result.loaderLanes!.length).toBe(1)
135
+ expect(result.loaderLanes![0].slotIndex).toBe(0)
136
+
137
+ const caps = computeLoaderCapabilities({insulation: 600, plasticity: 500})
138
+ // mass is unscaled (raw); thrust is amp-scaled
139
+ expect(result.loaderLanes![0].mass).toBe(caps.mass)
140
+ expect(result.loaderLanes![0].thrust).toBe(applySlotMultiplier(caps.thrust, 80))
141
+ expect(result.loaderLanes![0].outputPct).toBe(80)
142
+
143
+ // Legacy loaders.mass is total (same as single-lane raw mass here)
144
+ expect(result.loaders).toBeDefined()
145
+ expect(result.loaders!.mass).toBe(caps.mass)
146
+ })
147
+
148
+ test('per-lane amp-scaled stats clamp to UInt16, matching the contract clamp_to_uint16', () => {
149
+ expect(applySlotMultiplier(60000, 200)).toBe(U16_MAX)
150
+ expect(applySlotMultiplier(1000, 150)).toBe(1500)
151
+ })