@shipload/sdk 2.0.0-rc5 → 2.0.0-rc7

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 (52) hide show
  1. package/README.md +1 -349
  2. package/lib/shipload.d.ts +607 -1113
  3. package/lib/shipload.js +1482 -2077
  4. package/lib/shipload.js.map +1 -1
  5. package/lib/shipload.m.js +1421 -2038
  6. package/lib/shipload.m.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/capabilities/crafting.ts +28 -0
  9. package/src/capabilities/extraction.ts +14 -8
  10. package/src/capabilities/guards.ts +0 -5
  11. package/src/capabilities/index.ts +2 -0
  12. package/src/capabilities/modules.ts +49 -0
  13. package/src/capabilities/storage.ts +0 -8
  14. package/src/contracts/server.ts +231 -313
  15. package/src/data/colors.ts +28 -0
  16. package/src/data/items.json +15 -15
  17. package/src/data/recipes.ts +351 -0
  18. package/src/derivation/crafting.ts +142 -0
  19. package/src/derivation/index.ts +1 -0
  20. package/src/derivation/stats.ts +91 -15
  21. package/src/derivation/stratum.ts +2 -2
  22. package/src/entities/cargo-utils.ts +6 -64
  23. package/src/entities/container.ts +18 -0
  24. package/src/entities/entity-inventory.ts +0 -4
  25. package/src/entities/inventory-accessor.ts +0 -4
  26. package/src/entities/location.ts +2 -197
  27. package/src/entities/makers.ts +10 -9
  28. package/src/entities/player.ts +1 -274
  29. package/src/entities/ship-deploy.ts +89 -0
  30. package/src/entities/ship.ts +14 -27
  31. package/src/entities/warehouse.ts +0 -4
  32. package/src/index-module.ts +66 -41
  33. package/src/managers/actions.ts +77 -88
  34. package/src/managers/context.ts +0 -9
  35. package/src/managers/index.ts +0 -1
  36. package/src/managers/locations.ts +2 -85
  37. package/src/market/items.ts +0 -1
  38. package/src/resolution/resolve-item.ts +242 -0
  39. package/src/scheduling/projection.ts +0 -10
  40. package/src/shipload.ts +0 -5
  41. package/src/travel/travel.ts +3 -3
  42. package/src/types/capabilities.ts +1 -9
  43. package/src/types/entity-traits.ts +3 -4
  44. package/src/types/entity.ts +3 -4
  45. package/src/types.ts +6 -43
  46. package/src/utils/system.ts +5 -4
  47. package/src/managers/trades.ts +0 -119
  48. package/src/market/market.ts +0 -195
  49. package/src/market/rolls.ts +0 -8
  50. package/src/trading/collect.ts +0 -938
  51. package/src/trading/deal.ts +0 -207
  52. package/src/trading/trade.ts +0 -203
@@ -0,0 +1,28 @@
1
+ import type {ResourceCategory, ResourceTier} from '../types'
2
+
3
+ export const categoryColors: Record<ResourceCategory, string> = {
4
+ metal: '#7B8D9E',
5
+ precious: '#D4A843',
6
+ gas: '#7EC8E3',
7
+ mineral: '#B8A9C9',
8
+ organic: '#6B8E5A',
9
+ }
10
+
11
+ export const tierColors: Record<ResourceTier, string> = {
12
+ t1: '#8b8b8b',
13
+ t2: '#4ade80',
14
+ t3: '#818cf8',
15
+ t4: '#c084fc',
16
+ t5: '#fbbf24',
17
+ }
18
+
19
+ export const categoryIcons: Record<ResourceCategory, string> = {
20
+ metal: '⬡',
21
+ precious: '◈',
22
+ gas: '◎',
23
+ mineral: '◇',
24
+ organic: '❋',
25
+ }
26
+
27
+ export const componentIcon = '▣'
28
+ export const moduleIcon = '⬢'
@@ -1,17 +1,17 @@
1
1
  [
2
- {"id": 26, "name": "Iron", "description": "A versatile metal used in hulls and structures.", "base_price": 125, "mass": 40000, "category": "metal", "tier": "t1", "color": "#B7410E"},
3
- {"id": 13, "name": "Aluminum", "description": "A lightweight metal for structural components.", "base_price": 175, "mass": 27000, "category": "metal", "tier": "t2", "color": "#A8B5C2"},
4
- {"id": 24, "name": "Chromium", "description": "A hard, corrosion-resistant alloy metal.", "base_price": 350, "mass": 52000, "category": "metal", "tier": "t3", "color": "#D4E6F1"},
5
- {"id": 29, "name": "Copper", "description": "A conductive metal for electronics and wiring.", "base_price": 100, "mass": 60000, "category": "precious", "tier": "t1", "color": "#B87333"},
6
- {"id": 47, "name": "Silver", "description": "A high-conductivity metal for precision components.", "base_price": 300, "mass": 55000, "category": "precious", "tier": "t2", "color": "#C0C0C0"},
7
- {"id": 79, "name": "Gold", "description": "A corrosion-proof metal for advanced electronics.", "base_price": 500, "mass": 70000, "category": "precious", "tier": "t3", "color": "#FFD700"},
8
- {"id": 1, "name": "Hydrogen", "description": "A lightweight gas used for fuel cells and propulsion.", "base_price": 50, "mass": 15000, "category": "gas", "tier": "t1", "color": "#7EC8E3"},
9
- {"id": 2, "name": "Helium", "description": "An inert noble gas used in energy systems.", "base_price": 75, "mass": 2000, "category": "gas", "tier": "t2", "color": "#F5E6CC"},
10
- {"id": 18, "name": "Argon", "description": "A noble gas used in industrial and energy applications.", "base_price": 250, "mass": 8000, "category": "gas", "tier": "t3", "color": "#9B59B6"},
11
- {"id": 14, "name": "Silicon", "description": "A semiconductor used in sensors and computing.", "base_price": 150, "mass": 28000, "category": "mineral", "tier": "t1", "color": "#B8A9C9"},
12
- {"id": 1000, "name": "Quartz", "description": "A crystalline mineral for sensors and optics.", "base_price": 200, "mass": 35000, "category": "mineral", "tier": "t2", "color": "#E8D5B7"},
13
- {"id": 1001, "name": "Sapphire", "description": "A precious crystal for precision instruments.", "base_price": 400, "mass": 45000, "category": "mineral", "tier": "t3", "color": "#0F52BA"},
14
- {"id": 6, "name": "Carbon", "description": "A versatile element for life support and coatings.", "base_price": 100, "mass": 12000, "category": "organic", "tier": "t1", "color": "#4A4A4A"},
15
- {"id": 1003, "name": "Biomass", "description": "Organic matter for life support systems.", "base_price": 100, "mass": 30000, "category": "organic", "tier": "t2", "color": "#8B4513"},
16
- {"id": 1002, "name": "Resin", "description": "A fossilized organic compound for coatings and sealants.", "base_price": 300, "mass": 25000, "category": "organic", "tier": "t3", "color": "#DAA520"}
2
+ {"id": 26, "name": "Iron", "description": "A versatile metal used in hulls and structures.", "mass": 30000, "category": "metal", "tier": "t1", "color": "#B7410E"},
3
+ {"id": 13, "name": "Aluminum", "description": "A lightweight metal for structural components.", "mass": 27000, "category": "metal", "tier": "t2", "color": "#A8B5C2"},
4
+ {"id": 24, "name": "Chromium", "description": "A hard, corrosion-resistant alloy metal.", "mass": 52000, "category": "metal", "tier": "t3", "color": "#D4E6F1"},
5
+ {"id": 29, "name": "Copper", "description": "A conductive metal for electronics and wiring.", "mass": 40000, "category": "precious", "tier": "t1", "color": "#B87333"},
6
+ {"id": 47, "name": "Silver", "description": "A high-conductivity metal for precision components.", "mass": 55000, "category": "precious", "tier": "t2", "color": "#C0C0C0"},
7
+ {"id": 79, "name": "Gold", "description": "A corrosion-proof metal for advanced electronics.", "mass": 70000, "category": "precious", "tier": "t3", "color": "#FFD700"},
8
+ {"id": 1, "name": "Hydrogen", "description": "A lightweight gas used for fuel cells and propulsion.", "mass": 15000, "category": "gas", "tier": "t1", "color": "#7EC8E3"},
9
+ {"id": 2, "name": "Helium", "description": "An inert noble gas used in energy systems.", "mass": 2000, "category": "gas", "tier": "t2", "color": "#F5E6CC"},
10
+ {"id": 18, "name": "Argon", "description": "A noble gas used in industrial and energy applications.", "mass": 8000, "category": "gas", "tier": "t3", "color": "#9B59B6"},
11
+ {"id": 14, "name": "Silicon", "description": "A semiconductor used in sensors and computing.", "mass": 22000, "category": "mineral", "tier": "t1", "color": "#B8A9C9"},
12
+ {"id": 1000, "name": "Quartz", "description": "A crystalline mineral for sensors and optics.", "mass": 35000, "category": "mineral", "tier": "t2", "color": "#E8D5B7"},
13
+ {"id": 1001, "name": "Sapphire", "description": "A precious crystal for precision instruments.", "mass": 45000, "category": "mineral", "tier": "t3", "color": "#0F52BA"},
14
+ {"id": 6, "name": "Carbon", "description": "A versatile element for life support and coatings.", "mass": 15000, "category": "organic", "tier": "t1", "color": "#4A4A4A"},
15
+ {"id": 1003, "name": "Biomass", "description": "Organic matter for life support systems.", "mass": 30000, "category": "organic", "tier": "t2", "color": "#8B4513"},
16
+ {"id": 1002, "name": "Resin", "description": "A fossilized organic compound for coatings and sealants.", "mass": 25000, "category": "organic", "tier": "t3", "color": "#DAA520"}
17
17
  ]
@@ -0,0 +1,351 @@
1
+ import {MODULE_ENGINE, MODULE_GENERATOR, MODULE_EXTRACTOR, MODULE_LOADER, MODULE_CRAFTER, ITEM_ENGINE_T1, ITEM_GENERATOR_T1, ITEM_EXTRACTOR_T1, ITEM_LOADER_T1, ITEM_MANUFACTURING_T1} from '../capabilities/modules'
2
+ import type {ResourceCategory} from '../types'
3
+
4
+ export {ITEM_ENGINE_T1, ITEM_GENERATOR_T1, ITEM_EXTRACTOR_T1, ITEM_LOADER_T1, ITEM_MANUFACTURING_T1}
5
+
6
+ export const ITEM_DRILL_SHAFT = 10009
7
+ export const ITEM_EXTRACTION_PROBE = 10010
8
+ export const ITEM_CARGO_ARM = 10011
9
+ export const ITEM_TOOL_BIT = 10012
10
+ export const ITEM_REACTION_CHAMBER = 10013
11
+
12
+ export const ITEM_HULL_PLATES = 10001
13
+ export const ITEM_CARGO_LINING = 10002
14
+ export const ITEM_CONTAINER_PACKED = 10003
15
+ export const ITEM_THRUSTER_CORE = 10004
16
+ export const ITEM_POWER_CELL = 10005
17
+ export const ITEM_SHIP_T1_PACKED = 10008
18
+
19
+ export interface RecipeInput {
20
+ category?: ResourceCategory
21
+ itemId?: number
22
+ quantity: number
23
+ }
24
+
25
+ export interface ComponentStat {
26
+ key: string
27
+ source: ResourceCategory
28
+ }
29
+
30
+ export interface ComponentDefinition {
31
+ id: number
32
+ name: string
33
+ description: string
34
+ color: string
35
+ mass: number
36
+ stats: ComponentStat[]
37
+ recipe: RecipeInput[]
38
+ usedIn: {type: 'entity' | 'module'; name: string}[]
39
+ }
40
+
41
+ export interface EntityRecipe {
42
+ id: string
43
+ name: string
44
+ description: string
45
+ color: string
46
+ packedItemId: number
47
+ recipe: RecipeInput[]
48
+ stats: {key: string; sourceComponentId: number; sourceStatKey: string}[]
49
+ }
50
+
51
+ export interface CraftableItem {
52
+ type: 'component' | 'entity' | 'module'
53
+ id: number | string
54
+ name: string
55
+ description: string
56
+ color: string
57
+ }
58
+
59
+ export const components: ComponentDefinition[] = [
60
+ {
61
+ id: ITEM_HULL_PLATES,
62
+ name: 'Hull Plates',
63
+ description: 'Structural plating formed from metal. Used in hulls, containers, and frames.',
64
+ color: '#7B8D9E',
65
+ mass: 50000,
66
+ stats: [
67
+ {key: 'strength', source: 'metal'},
68
+ {key: 'density', source: 'metal'},
69
+ ],
70
+ recipe: [{category: 'metal', quantity: 15}],
71
+ usedIn: [{type: 'entity', name: 'Container'}, {type: 'entity', name: 'Ship T1'}],
72
+ },
73
+ {
74
+ id: ITEM_CARGO_LINING,
75
+ name: 'Cargo Lining',
76
+ description:
77
+ 'Precision-formed composite lining for cargo storage. Combines precious metal shaping with organic sealing.',
78
+ color: '#D4A843',
79
+ mass: 30000,
80
+ stats: [
81
+ {key: 'ductility', source: 'precious'},
82
+ {key: 'purity', source: 'organic'},
83
+ ],
84
+ recipe: [
85
+ {category: 'precious', quantity: 6},
86
+ {category: 'organic', quantity: 14},
87
+ ],
88
+ usedIn: [{type: 'entity', name: 'Container'}, {type: 'entity', name: 'Ship T1'}],
89
+ },
90
+ {
91
+ id: ITEM_THRUSTER_CORE,
92
+ name: 'Thruster Core',
93
+ description: 'High-energy propulsion component formed from volatile gases.',
94
+ color: '#E86344',
95
+ mass: 50000,
96
+ stats: [
97
+ {key: 'volatility', source: 'gas'},
98
+ {key: 'thermal', source: 'gas'},
99
+ ],
100
+ recipe: [{category: 'gas' as ResourceCategory, quantity: 32}],
101
+ usedIn: [{type: 'module', name: 'Engine Module T1'}],
102
+ },
103
+ {
104
+ id: ITEM_POWER_CELL,
105
+ name: 'Power Cell',
106
+ description: 'Crystalline energy storage matrix formed from resonant minerals.',
107
+ color: '#7B5AE8',
108
+ mass: 30000,
109
+ stats: [
110
+ {key: 'resonance', source: 'mineral'},
111
+ {key: 'clarity', source: 'mineral'},
112
+ ],
113
+ recipe: [{category: 'mineral' as ResourceCategory, quantity: 20}],
114
+ usedIn: [{type: 'module', name: 'Generator Module T1'}],
115
+ },
116
+ {
117
+ id: ITEM_DRILL_SHAFT,
118
+ name: 'Drill Shaft',
119
+ description: 'Heavy-duty metal shaft used in extraction equipment.',
120
+ color: '#7B8D9E',
121
+ mass: 50000,
122
+ stats: [
123
+ {key: 'strength', source: 'metal'},
124
+ {key: 'tolerance', source: 'metal'},
125
+ ],
126
+ recipe: [{category: 'metal' as ResourceCategory, quantity: 15}],
127
+ usedIn: [{type: 'module', name: 'Extractor Module T1'}],
128
+ },
129
+ {
130
+ id: ITEM_EXTRACTION_PROBE,
131
+ name: 'Extraction Probe',
132
+ description: 'Precious metal sensor array for deep resource detection.',
133
+ color: '#D4A843',
134
+ mass: 30000,
135
+ stats: [
136
+ {key: 'conductivity', source: 'precious'},
137
+ {key: 'reflectivity', source: 'precious'},
138
+ ],
139
+ recipe: [{category: 'precious' as ResourceCategory, quantity: 10}],
140
+ usedIn: [{type: 'module', name: 'Extractor Module T1'}],
141
+ },
142
+ {
143
+ id: ITEM_CARGO_ARM,
144
+ name: 'Cargo Arm',
145
+ description: 'Flexible organic composite arm for cargo handling.',
146
+ color: '#6B8E5A',
147
+ mass: 30000,
148
+ stats: [
149
+ {key: 'plasticity', source: 'organic'},
150
+ {key: 'insulation', source: 'organic'},
151
+ ],
152
+ recipe: [{category: 'organic' as ResourceCategory, quantity: 32}],
153
+ usedIn: [{type: 'module', name: 'Loader Module T1'}],
154
+ },
155
+ {
156
+ id: ITEM_TOOL_BIT,
157
+ name: 'Tool Bit',
158
+ description: 'Dense mineral cutting head for manufacturing operations.',
159
+ color: '#B8A9C9',
160
+ mass: 30000,
161
+ stats: [
162
+ {key: 'hardness', source: 'mineral'},
163
+ {key: 'clarity', source: 'mineral'},
164
+ ],
165
+ recipe: [{category: 'mineral' as ResourceCategory, quantity: 20}],
166
+ usedIn: [{type: 'module', name: 'Manufacturing Module T1'}],
167
+ },
168
+ {
169
+ id: ITEM_REACTION_CHAMBER,
170
+ name: 'Reaction Chamber',
171
+ description: 'Gas-pressurized vessel for controlled manufacturing reactions.',
172
+ color: '#7EC8E3',
173
+ mass: 50000,
174
+ stats: [
175
+ {key: 'reactivity', source: 'gas'},
176
+ {key: 'thermal', source: 'gas'},
177
+ ],
178
+ recipe: [{category: 'gas' as ResourceCategory, quantity: 32}],
179
+ usedIn: [{type: 'module', name: 'Manufacturing Module T1'}],
180
+ },
181
+ ]
182
+
183
+ export const entityRecipes: EntityRecipe[] = [
184
+ {
185
+ id: 'container',
186
+ name: 'Container',
187
+ description: 'Passive floating cargo storage in space. Towed by ships.',
188
+ color: '#7B8D9E',
189
+ packedItemId: ITEM_CONTAINER_PACKED,
190
+ recipe: [
191
+ {itemId: ITEM_HULL_PLATES, quantity: 6},
192
+ {itemId: ITEM_CARGO_LINING, quantity: 2},
193
+ ],
194
+ stats: [
195
+ {key: 'strength', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'strength'},
196
+ {key: 'density', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'density'},
197
+ {key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
198
+ {key: 'purity', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'purity'},
199
+ ],
200
+ },
201
+ {
202
+ id: 'ship-t1',
203
+ name: 'Ship T1',
204
+ description: 'General-purpose vessel with 5 module slots.',
205
+ color: '#4AE898',
206
+ packedItemId: ITEM_SHIP_T1_PACKED,
207
+ recipe: [
208
+ {itemId: ITEM_HULL_PLATES, quantity: 8},
209
+ {itemId: ITEM_CARGO_LINING, quantity: 4},
210
+ ],
211
+ stats: [
212
+ {key: 'strength', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'strength'},
213
+ {key: 'density', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'density'},
214
+ {key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
215
+ {key: 'purity', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'purity'},
216
+ ],
217
+ },
218
+ ]
219
+
220
+ export interface ModuleRecipe {
221
+ id: string
222
+ name: string
223
+ description: string
224
+ color: string
225
+ itemId: number
226
+ moduleType: number
227
+ recipe: RecipeInput[]
228
+ stats: {key: string; sourceComponentId: number; sourceStatKey: string}[]
229
+ }
230
+
231
+ export const moduleRecipes: ModuleRecipe[] = [
232
+ {
233
+ id: 'engine-t1',
234
+ name: 'Engine Module T1',
235
+ description: 'Basic propulsion system. Converts volatile gases into thrust.',
236
+ color: '#E86344',
237
+ itemId: ITEM_ENGINE_T1,
238
+ moduleType: MODULE_ENGINE,
239
+ recipe: [{itemId: ITEM_THRUSTER_CORE, quantity: 6}],
240
+ stats: [
241
+ {key: 'volatility', sourceComponentId: ITEM_THRUSTER_CORE, sourceStatKey: 'volatility'},
242
+ {key: 'thermal', sourceComponentId: ITEM_THRUSTER_CORE, sourceStatKey: 'thermal'},
243
+ ],
244
+ },
245
+ {
246
+ id: 'generator-t1',
247
+ name: 'Generator Module T1',
248
+ description: 'Basic energy system. Stores and recharges energy from resonant minerals.',
249
+ color: '#7B5AE8',
250
+ itemId: ITEM_GENERATOR_T1,
251
+ moduleType: MODULE_GENERATOR,
252
+ recipe: [{itemId: ITEM_POWER_CELL, quantity: 5}],
253
+ stats: [
254
+ {key: 'resonance', sourceComponentId: ITEM_POWER_CELL, sourceStatKey: 'resonance'},
255
+ {key: 'clarity', sourceComponentId: ITEM_POWER_CELL, sourceStatKey: 'clarity'},
256
+ ],
257
+ },
258
+ {
259
+ id: 'extractor-t1',
260
+ name: 'Extractor Module T1',
261
+ description: 'Basic extraction system. Drills and probes for raw resources.',
262
+ color: '#7B8D9E',
263
+ itemId: ITEM_EXTRACTOR_T1,
264
+ moduleType: MODULE_EXTRACTOR,
265
+ recipe: [
266
+ {itemId: ITEM_DRILL_SHAFT, quantity: 4},
267
+ {itemId: ITEM_EXTRACTION_PROBE, quantity: 3},
268
+ ],
269
+ stats: [
270
+ {key: 'strength', sourceComponentId: ITEM_DRILL_SHAFT, sourceStatKey: 'strength'},
271
+ {key: 'tolerance', sourceComponentId: ITEM_DRILL_SHAFT, sourceStatKey: 'tolerance'},
272
+ {key: 'reflectivity', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'reflectivity'},
273
+ {key: 'conductivity', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'conductivity'},
274
+ {key: 'reflectivity_drill', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'reflectivity'},
275
+ ],
276
+ },
277
+ {
278
+ id: 'loader-t1',
279
+ name: 'Loader Module T1',
280
+ description: 'Basic cargo handling system. Loads and unloads cargo with articulated arms.',
281
+ color: '#6B8E5A',
282
+ itemId: ITEM_LOADER_T1,
283
+ moduleType: MODULE_LOADER,
284
+ recipe: [
285
+ {itemId: ITEM_CARGO_LINING, quantity: 3},
286
+ {itemId: ITEM_CARGO_ARM, quantity: 3},
287
+ ],
288
+ stats: [
289
+ {key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
290
+ {key: 'plasticity', sourceComponentId: ITEM_CARGO_ARM, sourceStatKey: 'plasticity'},
291
+ ],
292
+ },
293
+ {
294
+ id: 'manufacturing-t1',
295
+ name: 'Manufacturing Module T1',
296
+ description: 'Basic crafting system. Processes materials using reaction chambers and cutting tools.',
297
+ color: '#7EC8E3',
298
+ itemId: ITEM_MANUFACTURING_T1,
299
+ moduleType: MODULE_CRAFTER,
300
+ recipe: [
301
+ {itemId: ITEM_TOOL_BIT, quantity: 3},
302
+ {itemId: ITEM_REACTION_CHAMBER, quantity: 3},
303
+ ],
304
+ stats: [
305
+ {key: 'reactivity', sourceComponentId: ITEM_REACTION_CHAMBER, sourceStatKey: 'reactivity'},
306
+ {key: 'clarity', sourceComponentId: ITEM_TOOL_BIT, sourceStatKey: 'clarity'},
307
+ ],
308
+ },
309
+ ]
310
+
311
+ export function getModuleRecipe(id: string): ModuleRecipe | undefined {
312
+ return moduleRecipes.find((r) => r.id === id)
313
+ }
314
+
315
+ export function getModuleRecipeByItemId(itemId: number): ModuleRecipe | undefined {
316
+ return moduleRecipes.find((r) => r.itemId === itemId)
317
+ }
318
+
319
+ export function getComponentById(id: number): ComponentDefinition | undefined {
320
+ return components.find((c) => c.id === id)
321
+ }
322
+
323
+ export function getEntityRecipe(id: string): EntityRecipe | undefined {
324
+ return entityRecipes.find((r) => r.id === id)
325
+ }
326
+
327
+ export function getEntityRecipeByItemId(itemId: number): EntityRecipe | undefined {
328
+ return entityRecipes.find((r) => r.packedItemId === itemId)
329
+ }
330
+
331
+ export function getAllCraftableItems(): CraftableItem[] {
332
+ const items: CraftableItem[] = []
333
+ for (const comp of components) {
334
+ items.push({type: 'component', id: comp.id, name: comp.name, description: comp.description, color: comp.color})
335
+ }
336
+ for (const entity of entityRecipes) {
337
+ items.push({type: 'entity', id: entity.id, name: entity.name, description: entity.description, color: entity.color})
338
+ }
339
+ for (const mod of moduleRecipes) {
340
+ items.push({type: 'module', id: mod.id, name: mod.name, description: mod.description, color: mod.color})
341
+ }
342
+ return items
343
+ }
344
+
345
+ export function getComponentsForCategory(category: ResourceCategory): ComponentDefinition[] {
346
+ return components.filter((c) => c.recipe.some((r) => r.category === category))
347
+ }
348
+
349
+ export function getComponentsForStat(statKey: string): ComponentDefinition[] {
350
+ return components.filter((c) => c.stats.some((s) => s.key === statKey))
351
+ }
@@ -0,0 +1,142 @@
1
+ import {UInt64} from '@wharfkit/antelope'
2
+ import type {ResourceCategory} from '../types'
3
+ import {
4
+ entityRecipes,
5
+ getComponentById,
6
+ getEntityRecipe,
7
+ getModuleRecipe,
8
+ moduleRecipes,
9
+ } from '../data/recipes'
10
+ import {deriveResourceStats} from './stratum'
11
+
12
+ export interface StackInput {
13
+ quantity: number
14
+ stats: Record<string, number>
15
+ }
16
+
17
+ export interface CategoryStacks {
18
+ category: ResourceCategory
19
+ stacks: StackInput[]
20
+ }
21
+
22
+ export function encodeStats(values: number[]): bigint {
23
+ let seed = 0n
24
+ for (let i = 0; i < values.length && i < 6; i++) {
25
+ seed |= BigInt(values[i] & 0x3ff) << BigInt(i * 10)
26
+ }
27
+ return seed
28
+ }
29
+
30
+ export function decodeStats(seed: bigint, count: number): number[] {
31
+ const stats: number[] = []
32
+ for (let i = 0; i < count; i++) {
33
+ stats.push(Number((seed >> BigInt(i * 10)) & 0x3ffn))
34
+ }
35
+ return stats
36
+ }
37
+
38
+ function mapStatsToKeys(seed: bigint, statDefs: {key: string}[]): Record<string, number> {
39
+ const values = decodeStats(seed, statDefs.length)
40
+ const result: Record<string, number> = {}
41
+ for (let i = 0; i < statDefs.length; i++) {
42
+ result[statDefs[i].key] = values[i]
43
+ }
44
+ return result
45
+ }
46
+
47
+ export function decodeCraftedItemStats(itemId: number, seed: bigint): Record<string, number> {
48
+ const comp = getComponentById(itemId)
49
+ if (comp) return mapStatsToKeys(seed, comp.stats)
50
+
51
+ const entityRecipe = entityRecipes.find((r) => r.packedItemId === itemId)
52
+ if (entityRecipe) return mapStatsToKeys(seed, entityRecipe.stats)
53
+
54
+ const moduleRecipe = moduleRecipes.find((r) => r.itemId === itemId)
55
+ if (moduleRecipe) return mapStatsToKeys(seed, moduleRecipe.stats)
56
+
57
+ return {}
58
+ }
59
+
60
+ export function blendStacks(stacks: StackInput[], statKey: string): number {
61
+ let totalQty = 0
62
+ let weightedSum = 0
63
+ for (const stack of stacks) {
64
+ const val = stack.stats[statKey] ?? 0
65
+ weightedSum += val * stack.quantity
66
+ totalQty += stack.quantity
67
+ }
68
+ if (totalQty === 0) return 0
69
+ return Math.floor(weightedSum / totalQty)
70
+ }
71
+
72
+ export function computeComponentStats(
73
+ componentId: number,
74
+ categoryStacks: CategoryStacks[]
75
+ ): {key: string; value: number}[] {
76
+ const comp = getComponentById(componentId)
77
+ if (!comp) return []
78
+
79
+ return comp.stats.map((statDef) => {
80
+ const matching = categoryStacks.find((cs) => cs.category === statDef.source)
81
+ const value = matching ? blendStacks(matching.stacks, statDef.key) : 0
82
+ return {key: statDef.key, value: Math.max(1, Math.min(999, value))}
83
+ })
84
+ }
85
+
86
+ export function blendComponentStacks(
87
+ stacks: {quantity: number; stats: Record<string, number>}[]
88
+ ): Record<string, number> {
89
+ if (stacks.length === 0) return {}
90
+ const allKeys = new Set<string>()
91
+ for (const s of stacks) {
92
+ for (const k of Object.keys(s.stats)) allKeys.add(k)
93
+ }
94
+ const result: Record<string, number> = {}
95
+ for (const key of allKeys) {
96
+ result[key] = blendStacks(
97
+ stacks.map((s) => ({quantity: s.quantity, stats: s.stats})),
98
+ key
99
+ )
100
+ }
101
+ return result
102
+ }
103
+
104
+ export function computeEntityStats(
105
+ entityRecipeId: string,
106
+ componentStacks: Record<number, {quantity: number; stats: Record<string, number>}[]>
107
+ ): {key: string; value: number}[] {
108
+ const recipe = getEntityRecipe(entityRecipeId) ?? getModuleRecipe(entityRecipeId)
109
+ if (!recipe) return []
110
+
111
+ const blendedByComponent: Record<number, Record<string, number>> = {}
112
+ for (const [compId, stacks] of Object.entries(componentStacks)) {
113
+ blendedByComponent[Number(compId)] = blendComponentStacks(stacks)
114
+ }
115
+
116
+ return recipe.stats.map((stat) => {
117
+ const blended = blendedByComponent[stat.sourceComponentId] ?? {}
118
+ const value = blended[stat.sourceStatKey] ?? 0
119
+ return {key: stat.key, value: Math.max(1, Math.min(999, value))}
120
+ })
121
+ }
122
+
123
+ function decodeStackStats(itemId: number, seed: UInt64): Record<string, number> {
124
+ if (itemId >= 10000) {
125
+ return decodeCraftedItemStats(itemId, BigInt(seed.toString()))
126
+ }
127
+ const raw = deriveResourceStats(BigInt(seed.toString()))
128
+ return {stat1: raw.stat1, stat2: raw.stat2, stat3: raw.stat3}
129
+ }
130
+
131
+ export function blendCargoStacks(
132
+ itemId: number,
133
+ stacks: {quantity: number; seed: UInt64}[]
134
+ ): UInt64 {
135
+ const decoded = stacks.map((s) => ({
136
+ quantity: s.quantity,
137
+ stats: decodeStackStats(itemId, s.seed),
138
+ }))
139
+ const allKeys = Object.keys(decoded[0]?.stats ?? {})
140
+ const blended = allKeys.map((key) => Math.max(1, Math.min(999, blendStacks(decoded, key))))
141
+ return UInt64.from(encodeStats(blended))
142
+ }
@@ -25,3 +25,4 @@ export {
25
25
  } from './resources'
26
26
 
27
27
  export * from './stats'
28
+ export * from './crafting'