@shipload/sdk 2.0.0-rc6 → 2.0.0-rc8
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.
- package/README.md +1 -349
- package/lib/shipload.d.ts +261 -121
- package/lib/shipload.js +889 -214
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +847 -201
- package/lib/shipload.m.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/crafting.ts +18 -0
- package/src/capabilities/extraction.ts +14 -8
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/modules.ts +49 -0
- package/src/contracts/server.ts +164 -129
- package/src/data/colors.ts +47 -0
- package/src/data/items.json +4 -4
- package/src/data/recipes.ts +241 -7
- package/src/derivation/crafting.ts +41 -19
- package/src/entities/makers.ts +10 -9
- package/src/entities/ship-deploy.ts +89 -0
- package/src/entities/ship.ts +14 -6
- package/src/index-module.ts +33 -0
- package/src/managers/actions.ts +47 -6
- package/src/resolution/resolve-item.ts +261 -0
- package/src/travel/travel.ts +3 -3
- package/src/types/entity.ts +3 -3
- package/src/types.ts +1 -18
package/src/data/recipes.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
|
+
import {MODULE_ANY, 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'
|
|
1
2
|
import type {ResourceCategory} from '../types'
|
|
2
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
|
+
|
|
3
12
|
export const ITEM_HULL_PLATES = 10001
|
|
4
13
|
export const ITEM_CARGO_LINING = 10002
|
|
5
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
|
|
6
18
|
|
|
7
19
|
export interface RecipeInput {
|
|
8
20
|
category?: ResourceCategory
|
|
@@ -23,7 +35,11 @@ export interface ComponentDefinition {
|
|
|
23
35
|
mass: number
|
|
24
36
|
stats: ComponentStat[]
|
|
25
37
|
recipe: RecipeInput[]
|
|
26
|
-
usedIn: {type: 'entity'; name: string}[]
|
|
38
|
+
usedIn: {type: 'entity' | 'module'; name: string}[]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ModuleSlot {
|
|
42
|
+
type: number
|
|
27
43
|
}
|
|
28
44
|
|
|
29
45
|
export interface EntityRecipe {
|
|
@@ -34,10 +50,11 @@ export interface EntityRecipe {
|
|
|
34
50
|
packedItemId: number
|
|
35
51
|
recipe: RecipeInput[]
|
|
36
52
|
stats: {key: string; sourceComponentId: number; sourceStatKey: string}[]
|
|
53
|
+
moduleSlots?: ModuleSlot[]
|
|
37
54
|
}
|
|
38
55
|
|
|
39
56
|
export interface CraftableItem {
|
|
40
|
-
type: 'component' | 'entity'
|
|
57
|
+
type: 'component' | 'entity' | 'module'
|
|
41
58
|
id: number | string
|
|
42
59
|
name: string
|
|
43
60
|
description: string
|
|
@@ -55,8 +72,8 @@ export const components: ComponentDefinition[] = [
|
|
|
55
72
|
{key: 'strength', source: 'metal'},
|
|
56
73
|
{key: 'density', source: 'metal'},
|
|
57
74
|
],
|
|
58
|
-
recipe: [{category: 'metal', quantity:
|
|
59
|
-
usedIn: [{type: 'entity', name: 'Container'}],
|
|
75
|
+
recipe: [{category: 'metal', quantity: 15}],
|
|
76
|
+
usedIn: [{type: 'entity', name: 'Container'}, {type: 'entity', name: 'Ship T1'}],
|
|
60
77
|
},
|
|
61
78
|
{
|
|
62
79
|
id: ITEM_CARGO_LINING,
|
|
@@ -70,10 +87,101 @@ export const components: ComponentDefinition[] = [
|
|
|
70
87
|
{key: 'purity', source: 'organic'},
|
|
71
88
|
],
|
|
72
89
|
recipe: [
|
|
73
|
-
{category: 'precious', quantity:
|
|
74
|
-
{category: 'organic', quantity:
|
|
90
|
+
{category: 'precious', quantity: 6},
|
|
91
|
+
{category: 'organic', quantity: 14},
|
|
92
|
+
],
|
|
93
|
+
usedIn: [{type: 'entity', name: 'Container'}, {type: 'entity', name: 'Ship T1'}],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: ITEM_THRUSTER_CORE,
|
|
97
|
+
name: 'Thruster Core',
|
|
98
|
+
description: 'High-energy propulsion component formed from volatile gases.',
|
|
99
|
+
color: '#E86344',
|
|
100
|
+
mass: 50000,
|
|
101
|
+
stats: [
|
|
102
|
+
{key: 'volatility', source: 'gas'},
|
|
103
|
+
{key: 'thermal', source: 'gas'},
|
|
104
|
+
],
|
|
105
|
+
recipe: [{category: 'gas' as ResourceCategory, quantity: 32}],
|
|
106
|
+
usedIn: [{type: 'module', name: 'Engine'}],
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
id: ITEM_POWER_CELL,
|
|
110
|
+
name: 'Power Cell',
|
|
111
|
+
description: 'Crystalline energy storage matrix formed from resonant minerals.',
|
|
112
|
+
color: '#7B5AE8',
|
|
113
|
+
mass: 30000,
|
|
114
|
+
stats: [
|
|
115
|
+
{key: 'resonance', source: 'mineral'},
|
|
116
|
+
{key: 'clarity', source: 'mineral'},
|
|
117
|
+
],
|
|
118
|
+
recipe: [{category: 'mineral' as ResourceCategory, quantity: 20}],
|
|
119
|
+
usedIn: [{type: 'module', name: 'Generator'}],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: ITEM_DRILL_SHAFT,
|
|
123
|
+
name: 'Drill Shaft',
|
|
124
|
+
description: 'Heavy-duty metal shaft used in extraction equipment.',
|
|
125
|
+
color: '#7B8D9E',
|
|
126
|
+
mass: 50000,
|
|
127
|
+
stats: [
|
|
128
|
+
{key: 'strength', source: 'metal'},
|
|
129
|
+
{key: 'tolerance', source: 'metal'},
|
|
130
|
+
],
|
|
131
|
+
recipe: [{category: 'metal' as ResourceCategory, quantity: 15}],
|
|
132
|
+
usedIn: [{type: 'module', name: 'Extractor'}],
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: ITEM_EXTRACTION_PROBE,
|
|
136
|
+
name: 'Extraction Probe',
|
|
137
|
+
description: 'Precious metal sensor array for deep resource detection.',
|
|
138
|
+
color: '#D4A843',
|
|
139
|
+
mass: 30000,
|
|
140
|
+
stats: [
|
|
141
|
+
{key: 'conductivity', source: 'precious'},
|
|
142
|
+
{key: 'reflectivity', source: 'precious'},
|
|
143
|
+
],
|
|
144
|
+
recipe: [{category: 'precious' as ResourceCategory, quantity: 10}],
|
|
145
|
+
usedIn: [{type: 'module', name: 'Extractor'}],
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: ITEM_CARGO_ARM,
|
|
149
|
+
name: 'Cargo Arm',
|
|
150
|
+
description: 'Flexible organic composite arm for cargo handling.',
|
|
151
|
+
color: '#6B8E5A',
|
|
152
|
+
mass: 30000,
|
|
153
|
+
stats: [
|
|
154
|
+
{key: 'plasticity', source: 'organic'},
|
|
155
|
+
{key: 'insulation', source: 'organic'},
|
|
156
|
+
],
|
|
157
|
+
recipe: [{category: 'organic' as ResourceCategory, quantity: 32}],
|
|
158
|
+
usedIn: [{type: 'module', name: 'Loader'}],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
id: ITEM_TOOL_BIT,
|
|
162
|
+
name: 'Tool Bit',
|
|
163
|
+
description: 'Dense mineral cutting head for manufacturing operations.',
|
|
164
|
+
color: '#B8A9C9',
|
|
165
|
+
mass: 30000,
|
|
166
|
+
stats: [
|
|
167
|
+
{key: 'hardness', source: 'mineral'},
|
|
168
|
+
{key: 'clarity', source: 'mineral'},
|
|
169
|
+
],
|
|
170
|
+
recipe: [{category: 'mineral' as ResourceCategory, quantity: 20}],
|
|
171
|
+
usedIn: [{type: 'module', name: 'Manufacturing'}],
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: ITEM_REACTION_CHAMBER,
|
|
175
|
+
name: 'Reaction Chamber',
|
|
176
|
+
description: 'Gas-pressurized vessel for controlled manufacturing reactions.',
|
|
177
|
+
color: '#7EC8E3',
|
|
178
|
+
mass: 50000,
|
|
179
|
+
stats: [
|
|
180
|
+
{key: 'reactivity', source: 'gas'},
|
|
181
|
+
{key: 'thermal', source: 'gas'},
|
|
75
182
|
],
|
|
76
|
-
|
|
183
|
+
recipe: [{category: 'gas' as ResourceCategory, quantity: 32}],
|
|
184
|
+
usedIn: [{type: 'module', name: 'Manufacturing'}],
|
|
77
185
|
},
|
|
78
186
|
]
|
|
79
187
|
|
|
@@ -95,8 +203,131 @@ export const entityRecipes: EntityRecipe[] = [
|
|
|
95
203
|
{key: 'purity', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'purity'},
|
|
96
204
|
],
|
|
97
205
|
},
|
|
206
|
+
{
|
|
207
|
+
id: 'ship-t1',
|
|
208
|
+
name: 'Ship T1',
|
|
209
|
+
description: 'General-purpose vessel with 5 module slots.',
|
|
210
|
+
color: '#4AE898',
|
|
211
|
+
packedItemId: ITEM_SHIP_T1_PACKED,
|
|
212
|
+
recipe: [
|
|
213
|
+
{itemId: ITEM_HULL_PLATES, quantity: 8},
|
|
214
|
+
{itemId: ITEM_CARGO_LINING, quantity: 4},
|
|
215
|
+
],
|
|
216
|
+
stats: [
|
|
217
|
+
{key: 'strength', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'strength'},
|
|
218
|
+
{key: 'density', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'density'},
|
|
219
|
+
{key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
|
|
220
|
+
{key: 'purity', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'purity'},
|
|
221
|
+
],
|
|
222
|
+
moduleSlots: [
|
|
223
|
+
{type: MODULE_ANY},
|
|
224
|
+
{type: MODULE_ANY},
|
|
225
|
+
{type: MODULE_ANY},
|
|
226
|
+
{type: MODULE_ANY},
|
|
227
|
+
{type: MODULE_ANY},
|
|
228
|
+
],
|
|
229
|
+
},
|
|
230
|
+
]
|
|
231
|
+
|
|
232
|
+
export interface ModuleRecipe {
|
|
233
|
+
id: string
|
|
234
|
+
name: string
|
|
235
|
+
description: string
|
|
236
|
+
color: string
|
|
237
|
+
itemId: number
|
|
238
|
+
moduleType: number
|
|
239
|
+
recipe: RecipeInput[]
|
|
240
|
+
stats: {key: string; sourceComponentId: number; sourceStatKey: string}[]
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
export const moduleRecipes: ModuleRecipe[] = [
|
|
244
|
+
{
|
|
245
|
+
id: 'engine-t1',
|
|
246
|
+
name: 'Engine',
|
|
247
|
+
description: 'Basic propulsion system. Converts volatile gases into thrust.',
|
|
248
|
+
color: '#E86344',
|
|
249
|
+
itemId: ITEM_ENGINE_T1,
|
|
250
|
+
moduleType: MODULE_ENGINE,
|
|
251
|
+
recipe: [{itemId: ITEM_THRUSTER_CORE, quantity: 6}],
|
|
252
|
+
stats: [
|
|
253
|
+
{key: 'volatility', sourceComponentId: ITEM_THRUSTER_CORE, sourceStatKey: 'volatility'},
|
|
254
|
+
{key: 'thermal', sourceComponentId: ITEM_THRUSTER_CORE, sourceStatKey: 'thermal'},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
id: 'generator-t1',
|
|
259
|
+
name: 'Generator',
|
|
260
|
+
description: 'Basic energy system. Stores and recharges energy from resonant minerals.',
|
|
261
|
+
color: '#7B5AE8',
|
|
262
|
+
itemId: ITEM_GENERATOR_T1,
|
|
263
|
+
moduleType: MODULE_GENERATOR,
|
|
264
|
+
recipe: [{itemId: ITEM_POWER_CELL, quantity: 5}],
|
|
265
|
+
stats: [
|
|
266
|
+
{key: 'resonance', sourceComponentId: ITEM_POWER_CELL, sourceStatKey: 'resonance'},
|
|
267
|
+
{key: 'clarity', sourceComponentId: ITEM_POWER_CELL, sourceStatKey: 'clarity'},
|
|
268
|
+
],
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
id: 'extractor-t1',
|
|
272
|
+
name: 'Extractor',
|
|
273
|
+
description: 'Basic extraction system. Drills and probes for raw resources.',
|
|
274
|
+
color: '#7B8D9E',
|
|
275
|
+
itemId: ITEM_EXTRACTOR_T1,
|
|
276
|
+
moduleType: MODULE_EXTRACTOR,
|
|
277
|
+
recipe: [
|
|
278
|
+
{itemId: ITEM_DRILL_SHAFT, quantity: 4},
|
|
279
|
+
{itemId: ITEM_EXTRACTION_PROBE, quantity: 3},
|
|
280
|
+
],
|
|
281
|
+
stats: [
|
|
282
|
+
{key: 'strength', sourceComponentId: ITEM_DRILL_SHAFT, sourceStatKey: 'strength'},
|
|
283
|
+
{key: 'tolerance', sourceComponentId: ITEM_DRILL_SHAFT, sourceStatKey: 'tolerance'},
|
|
284
|
+
{key: 'reflectivity', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'reflectivity'},
|
|
285
|
+
{key: 'conductivity', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'conductivity'},
|
|
286
|
+
{key: 'reflectivity_drill', sourceComponentId: ITEM_EXTRACTION_PROBE, sourceStatKey: 'reflectivity'},
|
|
287
|
+
],
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: 'loader-t1',
|
|
291
|
+
name: 'Loader',
|
|
292
|
+
description: 'Basic cargo handling system. Loads and unloads cargo with articulated arms.',
|
|
293
|
+
color: '#6B8E5A',
|
|
294
|
+
itemId: ITEM_LOADER_T1,
|
|
295
|
+
moduleType: MODULE_LOADER,
|
|
296
|
+
recipe: [
|
|
297
|
+
{itemId: ITEM_CARGO_LINING, quantity: 3},
|
|
298
|
+
{itemId: ITEM_CARGO_ARM, quantity: 3},
|
|
299
|
+
],
|
|
300
|
+
stats: [
|
|
301
|
+
{key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
|
|
302
|
+
{key: 'plasticity', sourceComponentId: ITEM_CARGO_ARM, sourceStatKey: 'plasticity'},
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
id: 'manufacturing-t1',
|
|
307
|
+
name: 'Manufacturing',
|
|
308
|
+
description: 'Basic crafting system. Processes materials using reaction chambers and cutting tools.',
|
|
309
|
+
color: '#7EC8E3',
|
|
310
|
+
itemId: ITEM_MANUFACTURING_T1,
|
|
311
|
+
moduleType: MODULE_CRAFTER,
|
|
312
|
+
recipe: [
|
|
313
|
+
{itemId: ITEM_TOOL_BIT, quantity: 3},
|
|
314
|
+
{itemId: ITEM_REACTION_CHAMBER, quantity: 3},
|
|
315
|
+
],
|
|
316
|
+
stats: [
|
|
317
|
+
{key: 'reactivity', sourceComponentId: ITEM_REACTION_CHAMBER, sourceStatKey: 'reactivity'},
|
|
318
|
+
{key: 'clarity', sourceComponentId: ITEM_TOOL_BIT, sourceStatKey: 'clarity'},
|
|
319
|
+
],
|
|
320
|
+
},
|
|
98
321
|
]
|
|
99
322
|
|
|
323
|
+
export function getModuleRecipe(id: string): ModuleRecipe | undefined {
|
|
324
|
+
return moduleRecipes.find((r) => r.id === id)
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export function getModuleRecipeByItemId(itemId: number): ModuleRecipe | undefined {
|
|
328
|
+
return moduleRecipes.find((r) => r.itemId === itemId)
|
|
329
|
+
}
|
|
330
|
+
|
|
100
331
|
export function getComponentById(id: number): ComponentDefinition | undefined {
|
|
101
332
|
return components.find((c) => c.id === id)
|
|
102
333
|
}
|
|
@@ -117,6 +348,9 @@ export function getAllCraftableItems(): CraftableItem[] {
|
|
|
117
348
|
for (const entity of entityRecipes) {
|
|
118
349
|
items.push({type: 'entity', id: entity.id, name: entity.name, description: entity.description, color: entity.color})
|
|
119
350
|
}
|
|
351
|
+
for (const mod of moduleRecipes) {
|
|
352
|
+
items.push({type: 'module', id: mod.id, name: mod.name, description: mod.description, color: mod.color})
|
|
353
|
+
}
|
|
120
354
|
return items
|
|
121
355
|
}
|
|
122
356
|
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import {UInt64} from '@wharfkit/antelope'
|
|
1
2
|
import type {ResourceCategory} from '../types'
|
|
2
3
|
import {
|
|
3
|
-
components,
|
|
4
4
|
entityRecipes,
|
|
5
5
|
getComponentById,
|
|
6
6
|
getEntityRecipe,
|
|
7
|
+
getModuleRecipe,
|
|
8
|
+
moduleRecipes,
|
|
7
9
|
} from '../data/recipes'
|
|
10
|
+
import {deriveResourceStats} from './stratum'
|
|
8
11
|
|
|
9
12
|
export interface StackInput {
|
|
10
13
|
quantity: number
|
|
@@ -32,26 +35,24 @@ export function decodeStats(seed: bigint, count: number): number[] {
|
|
|
32
35
|
return stats
|
|
33
36
|
}
|
|
34
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
|
+
|
|
35
47
|
export function decodeCraftedItemStats(itemId: number, seed: bigint): Record<string, number> {
|
|
36
48
|
const comp = getComponentById(itemId)
|
|
37
|
-
if (comp)
|
|
38
|
-
const values = decodeStats(seed, comp.stats.length)
|
|
39
|
-
const result: Record<string, number> = {}
|
|
40
|
-
for (let i = 0; i < comp.stats.length; i++) {
|
|
41
|
-
result[comp.stats[i].key] = values[i]
|
|
42
|
-
}
|
|
43
|
-
return result
|
|
44
|
-
}
|
|
49
|
+
if (comp) return mapStatsToKeys(seed, comp.stats)
|
|
45
50
|
|
|
46
51
|
const entityRecipe = entityRecipes.find((r) => r.packedItemId === itemId)
|
|
47
|
-
if (entityRecipe)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
result[entityRecipe.stats[i].key] = values[i]
|
|
52
|
-
}
|
|
53
|
-
return result
|
|
54
|
-
}
|
|
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)
|
|
55
56
|
|
|
56
57
|
return {}
|
|
57
58
|
}
|
|
@@ -65,7 +66,7 @@ export function blendStacks(stacks: StackInput[], statKey: string): number {
|
|
|
65
66
|
totalQty += stack.quantity
|
|
66
67
|
}
|
|
67
68
|
if (totalQty === 0) return 0
|
|
68
|
-
return Math.
|
|
69
|
+
return Math.floor(weightedSum / totalQty)
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
export function computeComponentStats(
|
|
@@ -104,7 +105,7 @@ export function computeEntityStats(
|
|
|
104
105
|
entityRecipeId: string,
|
|
105
106
|
componentStacks: Record<number, {quantity: number; stats: Record<string, number>}[]>
|
|
106
107
|
): {key: string; value: number}[] {
|
|
107
|
-
const recipe = getEntityRecipe(entityRecipeId)
|
|
108
|
+
const recipe = getEntityRecipe(entityRecipeId) ?? getModuleRecipe(entityRecipeId)
|
|
108
109
|
if (!recipe) return []
|
|
109
110
|
|
|
110
111
|
const blendedByComponent: Record<number, Record<string, number>> = {}
|
|
@@ -118,3 +119,24 @@ export function computeEntityStats(
|
|
|
118
119
|
return {key: stat.key, value: Math.max(1, Math.min(999, value))}
|
|
119
120
|
})
|
|
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
|
+
}
|
package/src/entities/makers.ts
CHANGED
|
@@ -5,26 +5,27 @@ import {Warehouse, WarehouseStateInput} from './warehouse'
|
|
|
5
5
|
import {Container, ContainerStateInput} from './container'
|
|
6
6
|
|
|
7
7
|
export function makeShip(state: ShipStateInput): Ship {
|
|
8
|
-
const
|
|
8
|
+
const info: Record<string, unknown> = {
|
|
9
9
|
type: Name.from('ship'),
|
|
10
10
|
id: UInt64.from(state.id),
|
|
11
11
|
owner: Name.from(state.owner),
|
|
12
12
|
entity_name: state.name,
|
|
13
13
|
coordinates: ServerContract.Types.coordinates.from(state.coordinates),
|
|
14
|
-
hullmass: UInt32.from(state.hullmass),
|
|
15
|
-
capacity: UInt32.from(state.capacity),
|
|
16
|
-
energy: UInt16.from(state.energy),
|
|
17
14
|
cargomass: UInt32.from(0),
|
|
18
15
|
cargo: state.cargo || [],
|
|
19
16
|
is_idle: !state.schedule,
|
|
20
17
|
current_task_elapsed: UInt32.from(0),
|
|
21
18
|
current_task_remaining: UInt32.from(0),
|
|
22
19
|
pending_tasks: [],
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
}
|
|
21
|
+
if (state.hullmass !== undefined) info.hullmass = UInt32.from(state.hullmass)
|
|
22
|
+
if (state.capacity !== undefined) info.capacity = UInt32.from(state.capacity)
|
|
23
|
+
if (state.energy !== undefined) info.energy = UInt16.from(state.energy)
|
|
24
|
+
if (state.engines) info.engines = state.engines
|
|
25
|
+
if (state.generator) info.generator = state.generator
|
|
26
|
+
if (state.loaders) info.loaders = state.loaders
|
|
27
|
+
if (state.schedule) info.schedule = state.schedule
|
|
28
|
+
const entityInfo = ServerContract.Types.entity_info.from(info)
|
|
28
29
|
return new Ship(entityInfo)
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
export function computeShipHullCapabilities(stats: Record<string, number>): {
|
|
2
|
+
hullmass: number
|
|
3
|
+
capacity: number
|
|
4
|
+
} {
|
|
5
|
+
const density = stats.density ?? 500
|
|
6
|
+
const strength = stats.strength ?? 500
|
|
7
|
+
const ductility = stats.ductility ?? 500
|
|
8
|
+
const purity = stats.purity ?? 500
|
|
9
|
+
|
|
10
|
+
const hullmass = 25000 + 75 * density
|
|
11
|
+
const statSum = strength + ductility + purity
|
|
12
|
+
const exponent = statSum / 2997.0
|
|
13
|
+
const capacity = Math.floor(1000000 * Math.pow(10, exponent))
|
|
14
|
+
|
|
15
|
+
return {hullmass, capacity}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function computeEngineCapabilities(stats: Record<string, number>): {
|
|
19
|
+
thrust: number
|
|
20
|
+
drain: number
|
|
21
|
+
} {
|
|
22
|
+
const vol = stats.volatility ?? 500
|
|
23
|
+
const thm = stats.thermal ?? 500
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
thrust: 400 + Math.floor(vol * 3 / 4),
|
|
27
|
+
drain: Math.max(16, 30 - Math.floor(thm / 70)),
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function computeGeneratorCapabilities(stats: Record<string, number>): {
|
|
32
|
+
capacity: number
|
|
33
|
+
recharge: number
|
|
34
|
+
} {
|
|
35
|
+
const res = stats.resonance ?? 500
|
|
36
|
+
const clr = stats.clarity ?? 500
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
capacity: 300 + Math.floor(res / 6),
|
|
40
|
+
recharge: 5 + Math.floor(clr * 15 / 1000),
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function computeExtractorCapabilities(stats: Record<string, number>): {
|
|
45
|
+
rate: number
|
|
46
|
+
drain: number
|
|
47
|
+
depth: number
|
|
48
|
+
drill: number
|
|
49
|
+
} {
|
|
50
|
+
const str = stats.strength ?? 500
|
|
51
|
+
const con = stats.conductivity ?? 500
|
|
52
|
+
const ref = stats.reflectivity ?? 500
|
|
53
|
+
const tol = stats.tolerance ?? 500
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
rate: 200 + str,
|
|
57
|
+
drain: Math.max(10, 50 - Math.floor(con / 20)),
|
|
58
|
+
depth: 200 + Math.floor(tol * 3 / 2),
|
|
59
|
+
drill: 100 + Math.floor(ref * 4 / 5),
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function computeLoaderCapabilities(stats: Record<string, number>): {
|
|
64
|
+
mass: number
|
|
65
|
+
thrust: number
|
|
66
|
+
quantity: number
|
|
67
|
+
} {
|
|
68
|
+
const duc = stats.ductility ?? 500
|
|
69
|
+
const pla = stats.plasticity ?? 500
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
mass: Math.max(200, 2000 - Math.floor(duc * 2)),
|
|
73
|
+
thrust: 1 + Math.floor(pla / 500),
|
|
74
|
+
quantity: 1,
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function computeManufacturingCapabilities(stats: Record<string, number>): {
|
|
79
|
+
speed: number
|
|
80
|
+
drain: number
|
|
81
|
+
} {
|
|
82
|
+
const rea = stats.reactivity ?? 500
|
|
83
|
+
const clr = stats.clarity ?? 500
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
speed: 100 + Math.floor(rea * 4 / 5),
|
|
87
|
+
drain: Math.max(5, 30 - Math.floor(clr / 33)),
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/entities/ship.ts
CHANGED
|
@@ -28,12 +28,12 @@ export interface ShipStateInput {
|
|
|
28
28
|
owner: string
|
|
29
29
|
name: string
|
|
30
30
|
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
31
|
-
hullmass
|
|
32
|
-
capacity
|
|
33
|
-
energy
|
|
34
|
-
engines
|
|
35
|
-
generator
|
|
36
|
-
loaders
|
|
31
|
+
hullmass?: number
|
|
32
|
+
capacity?: number
|
|
33
|
+
energy?: number
|
|
34
|
+
engines?: ServerContract.Types.movement_stats
|
|
35
|
+
generator?: ServerContract.Types.energy_stats
|
|
36
|
+
loaders?: ServerContract.Types.loader_stats
|
|
37
37
|
schedule?: ServerContract.Types.schedule
|
|
38
38
|
cargo?: ServerContract.Types.cargo_item[]
|
|
39
39
|
}
|
|
@@ -108,6 +108,14 @@ export class Ship extends ServerContract.Types.entity_info {
|
|
|
108
108
|
return schedule.isExtracting(this, now)
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
+
get hasEngines(): boolean {
|
|
112
|
+
return this.engines !== undefined
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
get hasGenerator(): boolean {
|
|
116
|
+
return this.generator !== undefined
|
|
117
|
+
}
|
|
118
|
+
|
|
111
119
|
get hasExtractor(): boolean {
|
|
112
120
|
return this.extractor !== undefined
|
|
113
121
|
}
|
package/src/index-module.ts
CHANGED
|
@@ -141,24 +141,44 @@ export * from './types/capabilities'
|
|
|
141
141
|
export * from './types/entity'
|
|
142
142
|
export * from './capabilities'
|
|
143
143
|
|
|
144
|
+
export {categoryColors, tierColors, categoryIcons, componentIcon, moduleIcon, itemIcons} from './data/colors'
|
|
145
|
+
|
|
144
146
|
export {
|
|
145
147
|
components,
|
|
146
148
|
entityRecipes,
|
|
149
|
+
moduleRecipes,
|
|
147
150
|
getComponentById,
|
|
148
151
|
getEntityRecipe,
|
|
149
152
|
getEntityRecipeByItemId,
|
|
153
|
+
getModuleRecipe,
|
|
154
|
+
getModuleRecipeByItemId,
|
|
150
155
|
getAllCraftableItems,
|
|
151
156
|
getComponentsForCategory,
|
|
152
157
|
getComponentsForStat,
|
|
153
158
|
ITEM_HULL_PLATES,
|
|
154
159
|
ITEM_CARGO_LINING,
|
|
155
160
|
ITEM_CONTAINER_PACKED,
|
|
161
|
+
ITEM_THRUSTER_CORE,
|
|
162
|
+
ITEM_POWER_CELL,
|
|
163
|
+
ITEM_ENGINE_T1,
|
|
164
|
+
ITEM_GENERATOR_T1,
|
|
165
|
+
ITEM_SHIP_T1_PACKED,
|
|
166
|
+
ITEM_DRILL_SHAFT,
|
|
167
|
+
ITEM_EXTRACTION_PROBE,
|
|
168
|
+
ITEM_CARGO_ARM,
|
|
169
|
+
ITEM_TOOL_BIT,
|
|
170
|
+
ITEM_REACTION_CHAMBER,
|
|
171
|
+
ITEM_EXTRACTOR_T1,
|
|
172
|
+
ITEM_LOADER_T1,
|
|
173
|
+
ITEM_MANUFACTURING_T1,
|
|
156
174
|
} from './data/recipes'
|
|
157
175
|
export type {
|
|
158
176
|
ComponentDefinition,
|
|
159
177
|
ComponentStat,
|
|
160
178
|
RecipeInput,
|
|
161
179
|
EntityRecipe,
|
|
180
|
+
ModuleRecipe,
|
|
181
|
+
ModuleSlot,
|
|
162
182
|
CraftableItem,
|
|
163
183
|
} from './data/recipes'
|
|
164
184
|
|
|
@@ -170,7 +190,20 @@ export {
|
|
|
170
190
|
computeComponentStats,
|
|
171
191
|
blendComponentStacks,
|
|
172
192
|
computeEntityStats,
|
|
193
|
+
blendCargoStacks,
|
|
173
194
|
} from './derivation/crafting'
|
|
174
195
|
export type {StackInput, CategoryStacks} from './derivation/crafting'
|
|
175
196
|
|
|
176
197
|
export {computeContainerCapabilities} from './entities/container'
|
|
198
|
+
|
|
199
|
+
export {
|
|
200
|
+
computeShipHullCapabilities,
|
|
201
|
+
computeEngineCapabilities,
|
|
202
|
+
computeGeneratorCapabilities,
|
|
203
|
+
computeExtractorCapabilities,
|
|
204
|
+
computeLoaderCapabilities,
|
|
205
|
+
computeManufacturingCapabilities,
|
|
206
|
+
} from './entities/ship-deploy'
|
|
207
|
+
|
|
208
|
+
export {resolveItem} from './resolution/resolve-item'
|
|
209
|
+
export type {ResolvedItem, ResolvedItemStat, ResolvedAttributeGroup, ResolvedModuleSlot, ResolvedItemType} from './resolution/resolve-item'
|