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

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 (44) hide show
  1. package/lib/shipload.d.ts +115 -27
  2. package/lib/shipload.js +806 -697
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +795 -694
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +21 -11
  7. package/lib/testing.js +272 -339
  8. package/lib/testing.js.map +1 -1
  9. package/lib/testing.m.js +272 -339
  10. package/lib/testing.m.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/contracts/server.ts +69 -26
  13. package/src/data/capability-formulas.ts +4 -4
  14. package/src/data/catalog.test.ts +81 -1
  15. package/src/data/catalog.ts +6 -4
  16. package/src/data/entities.json +84 -68
  17. package/src/data/item-ids.ts +5 -4
  18. package/src/data/items.json +30 -24
  19. package/src/data/kind-registry.json +75 -39
  20. package/src/data/kind-registry.ts +13 -0
  21. package/src/data/metadata.ts +203 -334
  22. package/src/data/recipes.json +194 -155
  23. package/src/data/task-types.json +184 -0
  24. package/src/derivation/build-methods.test.ts +4 -4
  25. package/src/derivation/capabilities.test.ts +14 -10
  26. package/src/derivation/capabilities.ts +8 -10
  27. package/src/derivation/capability-mappings.ts +4 -4
  28. package/src/derivation/capacity-fn-registry.test.ts +9 -0
  29. package/src/derivation/capacity-fn-registry.ts +18 -0
  30. package/src/derivation/recipe-usage.test.ts +7 -11
  31. package/src/entities/makers.ts +2 -2
  32. package/src/index-module.ts +15 -1
  33. package/src/influence/influence.test.ts +1 -1
  34. package/src/managers/actions.ts +17 -0
  35. package/src/managers/context.ts +9 -0
  36. package/src/managers/fund.ts +49 -0
  37. package/src/managers/index.ts +3 -0
  38. package/src/nft/description.ts +5 -10
  39. package/src/resolution/resolve-item.test.ts +15 -10
  40. package/src/resolution/resolve-item.ts +2 -2
  41. package/src/scheduling/unwrap.test.ts +60 -0
  42. package/src/scheduling/unwrap.ts +24 -8
  43. package/src/shipload.ts +5 -0
  44. package/src/types.ts +1 -0
@@ -1,5 +1,8 @@
1
1
  import {describe, expect, test} from 'bun:test'
2
- import {getItems, itemTypeIndex, typeLabel} from './catalog'
2
+ import {getComponents, getItem, getItems, itemTypeIndex, typeLabel} from './catalog'
3
+ import {getRecipe} from './recipes-runtime'
4
+ import items from './items.json'
5
+ import {itemFamilies, itemFamilyKey} from './metadata'
3
6
 
4
7
  describe('itemTypeIndex', () => {
5
8
  test('agrees with typeLabel for every item in the catalog', () => {
@@ -17,3 +20,80 @@ describe('itemTypeIndex', () => {
17
20
  expect(() => itemTypeIndex(65535)).toThrow()
18
21
  })
19
22
  })
23
+
24
+ const catalogItems = () => (items as Array<{id: number}>).map((raw) => getItem(raw.id))
25
+
26
+ describe('item families', () => {
27
+ test('every item resolves to a family that carries its name', () => {
28
+ for (const item of catalogItems()) {
29
+ expect(itemFamilies[item.family]?.name).toBe(item.name)
30
+ }
31
+ })
32
+
33
+ test('every tier of a family shares one name, description, and colour', () => {
34
+ const seen = new Map<string, {name: string; description: string; color: string}>()
35
+ for (const item of catalogItems()) {
36
+ const prior = seen.get(item.family)
37
+ if (prior) {
38
+ expect({
39
+ name: item.name,
40
+ description: item.description,
41
+ color: item.color,
42
+ }).toEqual(prior)
43
+ } else {
44
+ seen.set(item.family, {
45
+ name: item.name,
46
+ description: item.description,
47
+ color: item.color,
48
+ })
49
+ }
50
+ }
51
+ })
52
+
53
+ test('every family is reachable from at least one item id', () => {
54
+ const reachable = new Set(catalogItems().map((item) => item.family))
55
+ for (const id of [10202, 10203, 10204, 10207]) reachable.add(itemFamilyKey(id)!)
56
+ expect([...Object.keys(itemFamilies)].filter((key) => !reachable.has(key))).toEqual([])
57
+ })
58
+
59
+ test('descriptions never name a tier', () => {
60
+ for (const [key, family] of Object.entries(itemFamilies)) {
61
+ expect(`${key}: ${family.description}`).not.toMatch(/\btier\b|\bT\d\b/i)
62
+ }
63
+ })
64
+ })
65
+
66
+ describe('component descriptions', () => {
67
+ test('name only items that a recipe actually builds from the component', () => {
68
+ const consumers = new Map<string, Set<string>>()
69
+ for (const output of getItems()) {
70
+ const recipe = getRecipe(output.id)
71
+ if (!recipe) continue
72
+ for (const input of recipe.inputs) {
73
+ const inputItem = getItem(input.itemId)
74
+ if (inputItem.type !== 'component') continue
75
+ if (!consumers.has(inputItem.family)) consumers.set(inputItem.family, new Set())
76
+ consumers
77
+ .get(inputItem.family)!
78
+ .add(
79
+ output.type === 'entity' && output.family !== 'container'
80
+ ? 'hulls'
81
+ : output.name
82
+ )
83
+ }
84
+ }
85
+ for (const item of getComponents({tier: 1})) {
86
+ const named = item.description
87
+ .replace(/^Goes into /, '')
88
+ .replace(/\.$/, '')
89
+ .split(/, and |, | and /)
90
+ .map((name) => name.replace(/s$/, ''))
91
+ for (const name of named) {
92
+ const plain = name === 'hull' ? 'hulls' : name
93
+ expect(consumers.get(item.family)?.has(plain), `${item.name} -> ${plain}`).toBe(
94
+ true
95
+ )
96
+ }
97
+ }
98
+ })
99
+ })
@@ -1,6 +1,6 @@
1
1
  import {UInt16, type UInt16Type} from '@wharfkit/antelope'
2
2
  import items from './items.json'
3
- import {itemMetadata} from './metadata'
3
+ import {getItemFamily, itemFamilyKey} from './metadata'
4
4
  import {
5
5
  CATEGORY_LABELS,
6
6
  type Item,
@@ -12,12 +12,14 @@ import {
12
12
  const itemsById = new Map<number, Item>()
13
13
 
14
14
  for (const raw of items as any[]) {
15
- const meta = itemMetadata[raw.id]
16
- if (!meta) {
17
- throw new Error(`Missing metadata for item ${raw.id}. Add an entry to metadata.ts.`)
15
+ const family = itemFamilyKey(raw.id)
16
+ const meta = getItemFamily(raw.id)
17
+ if (!family || !meta) {
18
+ throw new Error(`Missing family for item ${raw.id}. Add an entry to metadata.ts.`)
18
19
  }
19
20
  itemsById.set(raw.id, {
20
21
  id: raw.id,
22
+ family,
21
23
  name: meta.name,
22
24
  description: meta.description,
23
25
  color: meta.color,
@@ -35,69 +35,6 @@
35
35
  ],
36
36
  "baseHullmass": 40000
37
37
  },
38
- {
39
- "entityItemId": 10202,
40
- "slots": [
41
- {
42
- "type": "loader",
43
- "outputPct": 100,
44
- "maxTier": 1
45
- },
46
- {
47
- "type": "storage",
48
- "outputPct": 100,
49
- "maxTier": 1
50
- },
51
- {
52
- "type": "storage",
53
- "outputPct": 100,
54
- "maxTier": 1
55
- },
56
- {
57
- "type": "storage",
58
- "outputPct": 100,
59
- "maxTier": 1
60
- },
61
- {
62
- "type": "storage",
63
- "outputPct": 100,
64
- "maxTier": 1
65
- }
66
- ],
67
- "baseHullmass": 1000
68
- },
69
- {
70
- "entityItemId": 10203,
71
- "slots": [
72
- {
73
- "type": "generator",
74
- "outputPct": 200,
75
- "maxTier": 1
76
- },
77
- {
78
- "type": "gatherer",
79
- "outputPct": 200,
80
- "maxTier": 1
81
- }
82
- ],
83
- "baseHullmass": 1000
84
- },
85
- {
86
- "entityItemId": 10204,
87
- "slots": [
88
- {
89
- "type": "generator",
90
- "outputPct": 200,
91
- "maxTier": 1
92
- },
93
- {
94
- "type": "crafter",
95
- "outputPct": 200,
96
- "maxTier": 1
97
- }
98
- ],
99
- "baseHullmass": 1000
100
- },
101
38
  {
102
39
  "entityItemId": 10205,
103
40
  "slots": [
@@ -135,11 +72,6 @@
135
72
  ],
136
73
  "baseHullmass": 1000
137
74
  },
138
- {
139
- "entityItemId": 10207,
140
- "slots": [],
141
- "baseHullmass": 1000
142
- },
143
75
  {
144
76
  "entityItemId": 10208,
145
77
  "slots": [
@@ -380,6 +312,90 @@
380
312
  "slots": [],
381
313
  "baseHullmass": 1000
382
314
  },
315
+ {
316
+ "entityItemId": 11202,
317
+ "slots": [
318
+ {
319
+ "type": "loader",
320
+ "outputPct": 100,
321
+ "maxTier": 2
322
+ },
323
+ {
324
+ "type": "storage",
325
+ "outputPct": 100,
326
+ "maxTier": 2
327
+ },
328
+ {
329
+ "type": "storage",
330
+ "outputPct": 100,
331
+ "maxTier": 2
332
+ },
333
+ {
334
+ "type": "storage",
335
+ "outputPct": 100,
336
+ "maxTier": 2
337
+ },
338
+ {
339
+ "type": "storage",
340
+ "outputPct": 100,
341
+ "maxTier": 2
342
+ }
343
+ ],
344
+ "baseHullmass": 1000
345
+ },
346
+ {
347
+ "entityItemId": 11203,
348
+ "slots": [
349
+ {
350
+ "type": "generator",
351
+ "outputPct": 200,
352
+ "maxTier": 2
353
+ },
354
+ {
355
+ "type": "gatherer",
356
+ "outputPct": 200,
357
+ "maxTier": 2
358
+ }
359
+ ],
360
+ "baseHullmass": 1000
361
+ },
362
+ {
363
+ "entityItemId": 11204,
364
+ "slots": [
365
+ {
366
+ "type": "generator",
367
+ "outputPct": 200,
368
+ "maxTier": 2
369
+ },
370
+ {
371
+ "type": "crafter",
372
+ "outputPct": 200,
373
+ "maxTier": 2
374
+ }
375
+ ],
376
+ "baseHullmass": 1000
377
+ },
378
+ {
379
+ "entityItemId": 11207,
380
+ "slots": [],
381
+ "baseHullmass": 1000
382
+ },
383
+ {
384
+ "entityItemId": 11209,
385
+ "slots": [
386
+ {
387
+ "type": "generator",
388
+ "outputPct": 200,
389
+ "maxTier": 2
390
+ },
391
+ {
392
+ "type": "builder",
393
+ "outputPct": 200,
394
+ "maxTier": 2
395
+ }
396
+ ],
397
+ "baseHullmass": 1000
398
+ },
383
399
  {
384
400
  "entityItemId": 11212,
385
401
  "slots": [
@@ -73,12 +73,8 @@ export const ITEM_LAUNCHER_T1 = 10109
73
73
  export const ITEM_BUILDER_T1 = 10110
74
74
  export const ITEM_CONTAINER_T1_PACKED = 10200
75
75
  export const ITEM_SHIP_T1_PACKED = 10201
76
- export const ITEM_WAREHOUSE_T1_PACKED = 10202
77
- export const ITEM_EXTRACTOR_T1_PACKED = 10203
78
- export const ITEM_FACTORY_T1_PACKED = 10204
79
76
  export const ITEM_MASS_DRIVER_T1_PACKED = 10205
80
77
  export const ITEM_MASS_CATCHER_T1_PACKED = 10206
81
- export const ITEM_HUB_T1_PACKED = 10207
82
78
  export const ITEM_WORKSHOP_T1_PACKED = 10208
83
79
  export const ITEM_CONSTRUCTION_DOCK_T1_PACKED = 10209
84
80
  export const ITEM_ROUSTABOUT_T1A_PACKED = 10210
@@ -111,6 +107,11 @@ export const ITEM_WARP_T2 = 11107
111
107
  export const ITEM_BATTERY_T2 = 11108
112
108
  export const ITEM_BUILDER_T2 = 11110
113
109
  export const ITEM_CONTAINER_T2_PACKED = 11200
110
+ export const ITEM_WAREHOUSE_T2_PACKED = 11202
111
+ export const ITEM_EXTRACTOR_T2_PACKED = 11203
112
+ export const ITEM_FACTORY_T2_PACKED = 11204
113
+ export const ITEM_HUB_T2_PACKED = 11207
114
+ export const ITEM_ASSEMBLY_YARD_T2_PACKED = 11209
114
115
  export const ITEM_PROSPECTOR_T2A_PACKED = 11212
115
116
  export const ITEM_PROSPECTOR_T2B_PACKED = 11213
116
117
  export const ITEM_DREDGER_T2A_PACKED = 11214
@@ -498,24 +498,6 @@
498
498
  "type": "entity",
499
499
  "tier": 1
500
500
  },
501
- {
502
- "id": 10202,
503
- "mass": 32000,
504
- "type": "entity",
505
- "tier": 1
506
- },
507
- {
508
- "id": 10203,
509
- "mass": 19000,
510
- "type": "entity",
511
- "tier": 1
512
- },
513
- {
514
- "id": 10204,
515
- "mass": 19000,
516
- "type": "entity",
517
- "tier": 1
518
- },
519
501
  {
520
502
  "id": 10205,
521
503
  "mass": 80000,
@@ -528,12 +510,6 @@
528
510
  "type": "entity",
529
511
  "tier": 1
530
512
  },
531
- {
532
- "id": 10207,
533
- "mass": 24000,
534
- "type": "entity",
535
- "tier": 1
536
- },
537
513
  {
538
514
  "id": 10208,
539
515
  "mass": 48000,
@@ -736,6 +712,36 @@
736
712
  "type": "entity",
737
713
  "tier": 2
738
714
  },
715
+ {
716
+ "id": 11202,
717
+ "mass": 51200,
718
+ "type": "entity",
719
+ "tier": 2
720
+ },
721
+ {
722
+ "id": 11203,
723
+ "mass": 30400,
724
+ "type": "entity",
725
+ "tier": 2
726
+ },
727
+ {
728
+ "id": 11204,
729
+ "mass": 30400,
730
+ "type": "entity",
731
+ "tier": 2
732
+ },
733
+ {
734
+ "id": 11207,
735
+ "mass": 38400,
736
+ "type": "entity",
737
+ "tier": 2
738
+ },
739
+ {
740
+ "id": 11209,
741
+ "mass": 30400,
742
+ "type": "entity",
743
+ "tier": 2
744
+ },
739
745
  {
740
746
  "id": 11212,
741
747
  "mass": 43200,
@@ -84,6 +84,13 @@
84
84
  "zCoord": 0,
85
85
  "defaultLabel": "Construction Dock"
86
86
  },
87
+ {
88
+ "kind": "asmblyard",
89
+ "classification": "OrbitalStructure",
90
+ "capabilityFlags": 20,
91
+ "zCoord": 0,
92
+ "defaultLabel": "Assembly Yard"
93
+ },
87
94
  {
88
95
  "kind": "depot",
89
96
  "classification": "PlanetaryStructure",
@@ -96,117 +103,146 @@
96
103
  {
97
104
  "itemId": 10201,
98
105
  "kind": "ship",
99
- "displayLabel": "Ship"
106
+ "displayLabel": "Ship",
107
+ "baseCapacityFn": "ship"
100
108
  },
101
109
  {
102
110
  "itemId": 10210,
103
111
  "kind": "ship",
104
- "displayLabel": "Roustabout"
112
+ "displayLabel": "Roustabout",
113
+ "baseCapacityFn": "ship"
105
114
  },
106
115
  {
107
116
  "itemId": 10211,
108
117
  "kind": "ship",
109
- "displayLabel": "Prospector"
118
+ "displayLabel": "Prospector",
119
+ "baseCapacityFn": "ship"
110
120
  },
111
121
  {
112
122
  "itemId": 10212,
113
123
  "kind": "ship",
114
- "displayLabel": "Tender"
124
+ "displayLabel": "Tender",
125
+ "baseCapacityFn": "ship"
115
126
  },
116
127
  {
117
128
  "itemId": 10213,
118
129
  "kind": "ship",
119
- "displayLabel": "Wright"
130
+ "displayLabel": "Wright",
131
+ "baseCapacityFn": "ship"
120
132
  },
121
133
  {
122
134
  "itemId": 10214,
123
135
  "kind": "ship",
124
- "displayLabel": "Tug"
136
+ "displayLabel": "Tug",
137
+ "baseCapacityFn": "ship"
125
138
  },
126
139
  {
127
140
  "itemId": 10215,
128
141
  "kind": "ship",
129
- "displayLabel": "Porter"
142
+ "displayLabel": "Porter",
143
+ "baseCapacityFn": "ship"
130
144
  },
131
145
  {
132
146
  "itemId": 10218,
133
147
  "kind": "ship",
134
- "displayLabel": "Smith"
135
- },
136
- {
137
- "itemId": 10202,
138
- "kind": "warehouse",
139
- "displayLabel": ""
140
- },
141
- {
142
- "itemId": 10203,
143
- "kind": "extractor",
144
- "displayLabel": ""
145
- },
146
- {
147
- "itemId": 10204,
148
- "kind": "factory",
149
- "displayLabel": ""
148
+ "displayLabel": "Smith",
149
+ "baseCapacityFn": "ship"
150
150
  },
151
151
  {
152
152
  "itemId": 10205,
153
153
  "kind": "mdriver",
154
- "displayLabel": ""
154
+ "displayLabel": "",
155
+ "baseCapacityFn": "container"
155
156
  },
156
157
  {
157
158
  "itemId": 10206,
158
159
  "kind": "mcatcher",
159
- "displayLabel": ""
160
+ "displayLabel": "",
161
+ "baseCapacityFn": "container"
160
162
  },
161
163
  {
162
164
  "itemId": 10200,
163
165
  "kind": "container",
164
- "displayLabel": ""
166
+ "displayLabel": "",
167
+ "baseCapacityFn": "container"
165
168
  },
166
169
  {
167
170
  "itemId": 11200,
168
171
  "kind": "container",
169
- "displayLabel": ""
170
- },
171
- {
172
- "itemId": 10207,
173
- "kind": "hub",
174
- "displayLabel": ""
172
+ "displayLabel": "",
173
+ "baseCapacityFn": "container"
175
174
  },
176
175
  {
177
176
  "itemId": 10208,
178
177
  "kind": "workshop",
179
- "displayLabel": ""
178
+ "displayLabel": "",
179
+ "baseCapacityFn": "workshop"
180
180
  },
181
181
  {
182
182
  "itemId": 10209,
183
183
  "kind": "builddock",
184
- "displayLabel": ""
184
+ "displayLabel": "",
185
+ "baseCapacityFn": "container"
185
186
  },
186
187
  {
187
188
  "itemId": 10216,
188
189
  "kind": "nexus",
189
- "displayLabel": ""
190
+ "displayLabel": "",
191
+ "baseCapacityFn": "container"
190
192
  },
191
193
  {
192
194
  "itemId": 11212,
193
195
  "kind": "ship",
194
- "displayLabel": "Prospector"
196
+ "displayLabel": "Prospector",
197
+ "baseCapacityFn": "ship"
195
198
  },
196
199
  {
197
200
  "itemId": 11213,
198
201
  "kind": "ship",
199
- "displayLabel": "Prospector"
202
+ "displayLabel": "Prospector",
203
+ "baseCapacityFn": "ship"
200
204
  },
201
205
  {
202
206
  "itemId": 11214,
203
207
  "kind": "ship",
204
- "displayLabel": "Dredger"
208
+ "displayLabel": "Dredger",
209
+ "baseCapacityFn": "ship"
205
210
  },
206
211
  {
207
212
  "itemId": 10219,
208
213
  "kind": "depot",
209
- "displayLabel": ""
214
+ "displayLabel": "",
215
+ "baseCapacityFn": "depot"
216
+ },
217
+ {
218
+ "itemId": 11202,
219
+ "kind": "warehouse",
220
+ "displayLabel": "",
221
+ "baseCapacityFn": "warehouse"
222
+ },
223
+ {
224
+ "itemId": 11203,
225
+ "kind": "extractor",
226
+ "displayLabel": "",
227
+ "baseCapacityFn": "container"
228
+ },
229
+ {
230
+ "itemId": 11204,
231
+ "kind": "factory",
232
+ "displayLabel": "",
233
+ "baseCapacityFn": "container"
234
+ },
235
+ {
236
+ "itemId": 11207,
237
+ "kind": "hub",
238
+ "displayLabel": "",
239
+ "baseCapacityFn": ""
240
+ },
241
+ {
242
+ "itemId": 11209,
243
+ "kind": "asmblyard",
244
+ "displayLabel": "Assembly Yard",
245
+ "baseCapacityFn": "container"
210
246
  }
211
247
  ]
212
248
  }
@@ -36,6 +36,7 @@ export type EntityTypeName =
36
36
  | 'mcatcher'
37
37
  | 'hub'
38
38
  | 'depot'
39
+ | 'asmblyard'
39
40
 
40
41
  export interface KindMeta {
41
42
  kind: Name
@@ -49,6 +50,7 @@ export interface TemplateMeta {
49
50
  itemId: number
50
51
  kind: Name
51
52
  displayLabel: string
53
+ baseCapacityFn: string
52
54
  }
53
55
 
54
56
  interface RawKindEntry {
@@ -63,6 +65,7 @@ interface RawTemplateEntry {
63
65
  itemId: number
64
66
  kind: string
65
67
  displayLabel: string
68
+ baseCapacityFn: string
66
69
  }
67
70
 
68
71
  const KIND_META: Map<string, KindMeta> = (() => {
@@ -96,6 +99,7 @@ const TEMPLATE_BY_ITEM_ID: Map<number, TemplateMeta> = (() => {
96
99
  itemId: r.itemId,
97
100
  kind: Name.from(r.kind),
98
101
  displayLabel: r.displayLabel,
102
+ baseCapacityFn: r.baseCapacityFn,
99
103
  })
100
104
  }
101
105
  return m
@@ -114,6 +118,11 @@ export function getTemplateMeta(itemId: number): TemplateMeta | undefined {
114
118
  return TEMPLATE_BY_ITEM_ID.get(itemId)
115
119
  }
116
120
 
121
+ export function getBaseCapacityFnName(itemId: number): string | undefined {
122
+ const fn = TEMPLATE_BY_ITEM_ID.get(itemId)?.baseCapacityFn
123
+ return fn ? fn : undefined
124
+ }
125
+
117
126
  export function getPackedEntityType(itemId: number): Name | null {
118
127
  return TEMPLATE_BY_ITEM_ID.get(itemId)?.kind ?? null
119
128
  }
@@ -150,6 +159,7 @@ export const ENTITY_MASS_DRIVER = Name.from('mdriver')
150
159
  export const ENTITY_MASS_CATCHER = Name.from('mcatcher')
151
160
  export const ENTITY_HUB = Name.from('hub')
152
161
  export const ENTITY_DEPOT = Name.from('depot')
162
+ export const ENTITY_ASSEMBLY_YARD = Name.from('asmblyard')
153
163
 
154
164
  export function isShip(entity: {type?: Name}): boolean {
155
165
  return entity.type?.equals(ENTITY_SHIP) ?? false
@@ -190,3 +200,6 @@ export function isHub(entity: {type?: Name}): boolean {
190
200
  export function isDepot(entity: {type?: Name}): boolean {
191
201
  return entity.type?.equals(ENTITY_DEPOT) ?? false
192
202
  }
203
+ export function isAssemblyYard(entity: {type?: Name}): boolean {
204
+ return entity.type?.equals(ENTITY_ASSEMBLY_YARD) ?? false
205
+ }