@shipload/sdk 2.0.0-rc10 → 2.0.0-rc12
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/lib/shipload.d.ts +144 -72
- package/lib/shipload.js +2537 -2238
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2505 -2224
- package/lib/shipload.m.js.map +1 -1
- package/package.json +2 -2
- package/src/capabilities/gathering.ts +36 -0
- package/src/capabilities/guards.ts +3 -3
- package/src/capabilities/index.ts +1 -1
- package/src/capabilities/modules.ts +4 -4
- package/src/capabilities/storage.ts +92 -2
- package/src/contracts/server.ts +53 -16
- package/src/data/capabilities.ts +28 -28
- package/src/data/categories.ts +1 -1
- package/src/data/colors.ts +1 -0
- package/src/data/recipes.ts +25 -25
- package/src/derivation/crafting.ts +76 -0
- package/src/derivation/index.ts +3 -1
- package/src/derivation/resources.ts +1 -7
- package/src/derivation/stratum.ts +21 -17
- package/src/derivation/tiers.ts +54 -0
- package/src/entities/location.ts +3 -3
- package/src/entities/ship-deploy.ts +17 -17
- package/src/entities/ship.ts +4 -4
- package/src/errors.ts +5 -0
- package/src/index-module.ts +22 -13
- package/src/managers/actions.ts +6 -3
- package/src/market/items.ts +69 -10
- package/src/nft/description.ts +11 -11
- package/src/resolution/resolve-item.ts +7 -7
- package/src/scheduling/projection.ts +86 -77
- package/src/scheduling/schedule.ts +2 -2
- package/src/types/capabilities.ts +5 -5
- package/src/types/entity.ts +1 -1
- package/src/types.ts +3 -2
- package/src/utils/system.ts +14 -1
- package/src/capabilities/extraction.ts +0 -36
package/src/data/capabilities.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const capabilityNames: string[] = [
|
|
|
17
17
|
'Movement',
|
|
18
18
|
'Energy',
|
|
19
19
|
'Loader',
|
|
20
|
-
'
|
|
20
|
+
'Gathering',
|
|
21
21
|
'Warp',
|
|
22
22
|
'Manufacturing',
|
|
23
23
|
'Launch',
|
|
@@ -33,10 +33,10 @@ export const capabilityAttributes: CapabilityAttribute[] = [
|
|
|
33
33
|
{capability: 'Energy', attribute: 'recharge', description: 'Energy regeneration rate'},
|
|
34
34
|
{capability: 'Loader', attribute: 'mass', description: 'Weight of the loader unit itself'},
|
|
35
35
|
{capability: 'Loader', attribute: 'thrust', description: 'Loading speed/force'},
|
|
36
|
-
{capability: '
|
|
37
|
-
{capability: '
|
|
38
|
-
{capability: '
|
|
39
|
-
{capability: '
|
|
36
|
+
{capability: 'Gathering', attribute: 'yield', description: 'Mass gathered per second'},
|
|
37
|
+
{capability: 'Gathering', attribute: 'drain', description: 'Energy consumed per gather'},
|
|
38
|
+
{capability: 'Gathering', attribute: 'depth', description: 'Maximum gather depth'},
|
|
39
|
+
{capability: 'Gathering', attribute: 'speed', description: 'Gathering speed/penetration'},
|
|
40
40
|
{capability: 'Warp', attribute: 'range', description: 'Maximum warp distance'},
|
|
41
41
|
{capability: 'Manufacturing', attribute: 'speed', description: 'Crafting time per item'},
|
|
42
42
|
{
|
|
@@ -68,9 +68,9 @@ export const capabilityAttributes: CapabilityAttribute[] = [
|
|
|
68
68
|
export const statMappings: StatMapping[] = [
|
|
69
69
|
{
|
|
70
70
|
stat: 'Strength',
|
|
71
|
-
capability: '
|
|
72
|
-
attribute: '
|
|
73
|
-
rationale: 'Raw mechanical force drives faster
|
|
71
|
+
capability: 'Gathering',
|
|
72
|
+
attribute: 'yield',
|
|
73
|
+
rationale: 'Raw mechanical force drives faster gathering',
|
|
74
74
|
},
|
|
75
75
|
{
|
|
76
76
|
stat: 'Strength',
|
|
@@ -98,7 +98,7 @@ export const statMappings: StatMapping[] = [
|
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
100
|
stat: 'Tolerance',
|
|
101
|
-
capability: '
|
|
101
|
+
capability: 'Gathering',
|
|
102
102
|
attribute: 'depth',
|
|
103
103
|
rationale: 'Housing withstands pressure/heat at extreme depths',
|
|
104
104
|
},
|
|
@@ -134,9 +134,9 @@ export const statMappings: StatMapping[] = [
|
|
|
134
134
|
},
|
|
135
135
|
{
|
|
136
136
|
stat: 'Conductivity',
|
|
137
|
-
capability: '
|
|
137
|
+
capability: 'Gathering',
|
|
138
138
|
attribute: 'drain',
|
|
139
|
-
rationale: 'Efficient energy transfer reduces
|
|
139
|
+
rationale: 'Efficient energy transfer reduces gathering energy cost',
|
|
140
140
|
},
|
|
141
141
|
{
|
|
142
142
|
stat: 'Conductivity',
|
|
@@ -158,9 +158,9 @@ export const statMappings: StatMapping[] = [
|
|
|
158
158
|
},
|
|
159
159
|
{
|
|
160
160
|
stat: 'Ductility',
|
|
161
|
-
capability: '
|
|
162
|
-
attribute: '
|
|
163
|
-
rationale: 'Precisely shaped
|
|
161
|
+
capability: 'Gathering',
|
|
162
|
+
attribute: 'yield',
|
|
163
|
+
rationale: 'Precisely shaped conduit components gather faster',
|
|
164
164
|
},
|
|
165
165
|
{
|
|
166
166
|
stat: 'Ductility',
|
|
@@ -176,7 +176,7 @@ export const statMappings: StatMapping[] = [
|
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
stat: 'Reflectivity',
|
|
179
|
-
capability: '
|
|
179
|
+
capability: 'Gathering',
|
|
180
180
|
attribute: 'depth',
|
|
181
181
|
rationale: 'Reflective heat shielding protects equipment at depth',
|
|
182
182
|
},
|
|
@@ -188,9 +188,9 @@ export const statMappings: StatMapping[] = [
|
|
|
188
188
|
},
|
|
189
189
|
{
|
|
190
190
|
stat: 'Volatility',
|
|
191
|
-
capability: '
|
|
192
|
-
attribute: '
|
|
193
|
-
rationale: 'Energy release powers faster
|
|
191
|
+
capability: 'Gathering',
|
|
192
|
+
attribute: 'yield',
|
|
193
|
+
rationale: 'Energy release powers faster gathering',
|
|
194
194
|
},
|
|
195
195
|
{
|
|
196
196
|
stat: 'Volatility',
|
|
@@ -218,9 +218,9 @@ export const statMappings: StatMapping[] = [
|
|
|
218
218
|
},
|
|
219
219
|
{
|
|
220
220
|
stat: 'Reactivity',
|
|
221
|
-
capability: '
|
|
222
|
-
attribute: '
|
|
223
|
-
rationale: 'Reactive gases manage heat/friction during
|
|
221
|
+
capability: 'Gathering',
|
|
222
|
+
attribute: 'speed',
|
|
223
|
+
rationale: 'Reactive gases manage heat/friction during gathering',
|
|
224
224
|
},
|
|
225
225
|
{
|
|
226
226
|
stat: 'Reactivity',
|
|
@@ -236,9 +236,9 @@ export const statMappings: StatMapping[] = [
|
|
|
236
236
|
},
|
|
237
237
|
{
|
|
238
238
|
stat: 'Thermal',
|
|
239
|
-
capability: '
|
|
239
|
+
capability: 'Gathering',
|
|
240
240
|
attribute: 'drain',
|
|
241
|
-
rationale: 'Thermal management reduces energy waste during
|
|
241
|
+
rationale: 'Thermal management reduces energy waste during gathering',
|
|
242
242
|
},
|
|
243
243
|
{
|
|
244
244
|
stat: 'Thermal',
|
|
@@ -326,9 +326,9 @@ export const statMappings: StatMapping[] = [
|
|
|
326
326
|
},
|
|
327
327
|
{
|
|
328
328
|
stat: 'Insulation',
|
|
329
|
-
capability: '
|
|
329
|
+
capability: 'Gathering',
|
|
330
330
|
attribute: 'drain',
|
|
331
|
-
rationale: 'Better insulation reduces energy loss during
|
|
331
|
+
rationale: 'Better insulation reduces energy loss during gathering',
|
|
332
332
|
},
|
|
333
333
|
{
|
|
334
334
|
stat: 'Insulation',
|
|
@@ -350,9 +350,9 @@ export const statMappings: StatMapping[] = [
|
|
|
350
350
|
},
|
|
351
351
|
{
|
|
352
352
|
stat: 'Purity',
|
|
353
|
-
capability: '
|
|
354
|
-
attribute: '
|
|
355
|
-
rationale: 'Purer bio-lubricants reduce friction during
|
|
353
|
+
capability: 'Gathering',
|
|
354
|
+
attribute: 'speed',
|
|
355
|
+
rationale: 'Purer bio-lubricants reduce friction during gathering',
|
|
356
356
|
},
|
|
357
357
|
{
|
|
358
358
|
stat: 'Purity',
|
package/src/data/categories.ts
CHANGED
|
@@ -20,7 +20,7 @@ const categories: CategoryInfo[] = [
|
|
|
20
20
|
{
|
|
21
21
|
id: 'precious',
|
|
22
22
|
name: 'Precious Metals',
|
|
23
|
-
label: 'Precious',
|
|
23
|
+
label: 'Precious Metal',
|
|
24
24
|
description:
|
|
25
25
|
'Conductive, corrosion-resistant — electronics, energy systems, precision components',
|
|
26
26
|
color: categoryColors.precious,
|
package/src/data/colors.ts
CHANGED
package/src/data/recipes.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ITEM_ENGINE_T1,
|
|
3
|
-
|
|
3
|
+
ITEM_GATHERER_T1,
|
|
4
4
|
ITEM_GENERATOR_T1,
|
|
5
5
|
ITEM_HAULER_T1,
|
|
6
6
|
ITEM_LOADER_T1,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
MODULE_ANY,
|
|
10
10
|
MODULE_CRAFTER,
|
|
11
11
|
MODULE_ENGINE,
|
|
12
|
-
|
|
12
|
+
MODULE_GATHERER,
|
|
13
13
|
MODULE_GENERATOR,
|
|
14
14
|
MODULE_HAULER,
|
|
15
15
|
MODULE_LOADER,
|
|
@@ -20,15 +20,15 @@ import type {ResourceCategory} from '../types'
|
|
|
20
20
|
export {
|
|
21
21
|
ITEM_ENGINE_T1,
|
|
22
22
|
ITEM_GENERATOR_T1,
|
|
23
|
-
|
|
23
|
+
ITEM_GATHERER_T1,
|
|
24
24
|
ITEM_LOADER_T1,
|
|
25
25
|
ITEM_MANUFACTURING_T1,
|
|
26
26
|
ITEM_STORAGE_T1,
|
|
27
27
|
ITEM_HAULER_T1,
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export const
|
|
31
|
-
export const
|
|
30
|
+
export const ITEM_MATTER_CONDUIT = 10005
|
|
31
|
+
export const ITEM_SURVEY_PROBE = 10006
|
|
32
32
|
export const ITEM_CARGO_ARM = 10007
|
|
33
33
|
export const ITEM_TOOL_BIT = 10008
|
|
34
34
|
export const ITEM_REACTION_CHAMBER = 10009
|
|
@@ -158,9 +158,9 @@ export const components: ComponentDefinition[] = [
|
|
|
158
158
|
usedIn: [{type: 'module', name: 'Generator'}],
|
|
159
159
|
},
|
|
160
160
|
{
|
|
161
|
-
id:
|
|
162
|
-
name: '
|
|
163
|
-
description: 'Heavy-duty metal shaft used in
|
|
161
|
+
id: ITEM_MATTER_CONDUIT,
|
|
162
|
+
name: 'Matter Conduit',
|
|
163
|
+
description: 'Heavy-duty metal shaft used in gathering equipment.',
|
|
164
164
|
color: '#7B8D9E',
|
|
165
165
|
mass: 50000,
|
|
166
166
|
stats: [
|
|
@@ -168,11 +168,11 @@ export const components: ComponentDefinition[] = [
|
|
|
168
168
|
{key: 'tolerance', source: 'metal'},
|
|
169
169
|
],
|
|
170
170
|
recipe: [{category: 'metal' as ResourceCategory, quantity: 15}],
|
|
171
|
-
usedIn: [{type: 'module', name: '
|
|
171
|
+
usedIn: [{type: 'module', name: 'Gatherer'}],
|
|
172
172
|
},
|
|
173
173
|
{
|
|
174
|
-
id:
|
|
175
|
-
name: '
|
|
174
|
+
id: ITEM_SURVEY_PROBE,
|
|
175
|
+
name: 'Survey Probe',
|
|
176
176
|
description: 'Precious metal sensor array for deep resource detection.',
|
|
177
177
|
color: '#D4A843',
|
|
178
178
|
mass: 30000,
|
|
@@ -181,7 +181,7 @@ export const components: ComponentDefinition[] = [
|
|
|
181
181
|
{key: 'reflectivity', source: 'precious'},
|
|
182
182
|
],
|
|
183
183
|
recipe: [{category: 'precious' as ResourceCategory, quantity: 10}],
|
|
184
|
-
usedIn: [{type: 'module', name: '
|
|
184
|
+
usedIn: [{type: 'module', name: 'Gatherer'}],
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
id: ITEM_CARGO_ARM,
|
|
@@ -395,32 +395,32 @@ export const moduleRecipes: ModuleRecipe[] = [
|
|
|
395
395
|
],
|
|
396
396
|
},
|
|
397
397
|
{
|
|
398
|
-
id: '
|
|
399
|
-
name: '
|
|
400
|
-
description: 'Basic
|
|
398
|
+
id: 'gatherer-t1',
|
|
399
|
+
name: 'Gatherer',
|
|
400
|
+
description: 'Basic gathering system. Probes and conduits for raw resources.',
|
|
401
401
|
color: '#7B8D9E',
|
|
402
|
-
itemId:
|
|
403
|
-
moduleType:
|
|
402
|
+
itemId: ITEM_GATHERER_T1,
|
|
403
|
+
moduleType: MODULE_GATHERER,
|
|
404
404
|
recipe: [
|
|
405
|
-
{itemId:
|
|
406
|
-
{itemId:
|
|
405
|
+
{itemId: ITEM_MATTER_CONDUIT, quantity: 4},
|
|
406
|
+
{itemId: ITEM_SURVEY_PROBE, quantity: 3},
|
|
407
407
|
],
|
|
408
408
|
stats: [
|
|
409
|
-
{key: 'strength', sourceComponentId:
|
|
410
|
-
{key: 'tolerance', sourceComponentId:
|
|
409
|
+
{key: 'strength', sourceComponentId: ITEM_MATTER_CONDUIT, sourceStatKey: 'strength'},
|
|
410
|
+
{key: 'tolerance', sourceComponentId: ITEM_MATTER_CONDUIT, sourceStatKey: 'tolerance'},
|
|
411
411
|
{
|
|
412
412
|
key: 'reflectivity',
|
|
413
|
-
sourceComponentId:
|
|
413
|
+
sourceComponentId: ITEM_SURVEY_PROBE,
|
|
414
414
|
sourceStatKey: 'reflectivity',
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
417
|
key: 'conductivity',
|
|
418
|
-
sourceComponentId:
|
|
418
|
+
sourceComponentId: ITEM_SURVEY_PROBE,
|
|
419
419
|
sourceStatKey: 'conductivity',
|
|
420
420
|
},
|
|
421
421
|
{
|
|
422
|
-
key: '
|
|
423
|
-
sourceComponentId:
|
|
422
|
+
key: 'reflectivity_speed',
|
|
423
|
+
sourceComponentId: ITEM_SURVEY_PROBE,
|
|
424
424
|
sourceStatKey: 'reflectivity',
|
|
425
425
|
},
|
|
426
426
|
],
|
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
entityRecipes,
|
|
5
5
|
getComponentById,
|
|
6
6
|
getEntityRecipe,
|
|
7
|
+
getEntityRecipeByItemId,
|
|
7
8
|
getModuleRecipe,
|
|
8
9
|
moduleRecipes,
|
|
9
10
|
} from '../data/recipes'
|
|
11
|
+
import {getStatDefinitions} from './stats'
|
|
10
12
|
import {deriveResourceStats} from './stratum'
|
|
11
13
|
|
|
12
14
|
export interface StackInput {
|
|
@@ -195,3 +197,77 @@ export function blendCargoStacks(
|
|
|
195
197
|
const blended = allKeys.map((key) => Math.max(1, Math.min(999, blendStacks(decoded, key))))
|
|
196
198
|
return UInt64.from(encodeStats(blended))
|
|
197
199
|
}
|
|
200
|
+
|
|
201
|
+
export interface RecipeSlotInput {
|
|
202
|
+
itemId: number
|
|
203
|
+
category: ResourceCategory | undefined
|
|
204
|
+
stacks: {quantity: number; seed: bigint}[]
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function decodeRawStackToCategoryStats(
|
|
208
|
+
seed: bigint,
|
|
209
|
+
category: ResourceCategory
|
|
210
|
+
): Record<string, number> {
|
|
211
|
+
const raw = deriveResourceStats(seed)
|
|
212
|
+
const defs = getStatDefinitions(category)
|
|
213
|
+
const result: Record<string, number> = {}
|
|
214
|
+
if (defs[0]) result[defs[0].key] = raw.stat1
|
|
215
|
+
if (defs[1]) result[defs[1].key] = raw.stat2
|
|
216
|
+
if (defs[2]) result[defs[2].key] = raw.stat3
|
|
217
|
+
return result
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
export function computeCraftedOutputSeed(
|
|
221
|
+
outputItemId: number,
|
|
222
|
+
slotInputs: RecipeSlotInput[]
|
|
223
|
+
): UInt64 {
|
|
224
|
+
const component = getComponentById(outputItemId)
|
|
225
|
+
if (component) {
|
|
226
|
+
const categoryStacks: CategoryStacks[] = []
|
|
227
|
+
for (const slot of slotInputs) {
|
|
228
|
+
if (!slot.category) continue
|
|
229
|
+
const slotIsComponent = getComponentById(slot.itemId) !== undefined
|
|
230
|
+
const stacks: StackInput[] = slot.stacks.map((s) => ({
|
|
231
|
+
quantity: s.quantity,
|
|
232
|
+
stats: slotIsComponent
|
|
233
|
+
? decodeCraftedItemStats(slot.itemId, s.seed)
|
|
234
|
+
: decodeRawStackToCategoryStats(s.seed, slot.category!),
|
|
235
|
+
}))
|
|
236
|
+
categoryStacks.push({category: slot.category, stacks})
|
|
237
|
+
}
|
|
238
|
+
const stats = computeComponentStats(outputItemId, categoryStacks)
|
|
239
|
+
const ordered = component.stats.map((statDef) => {
|
|
240
|
+
const found = stats.find((s) => s.key === statDef.key)
|
|
241
|
+
return found ? found.value : 0
|
|
242
|
+
})
|
|
243
|
+
return UInt64.from(encodeStats(ordered))
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const entityRecipe = getEntityRecipeByItemId(outputItemId)
|
|
247
|
+
if (entityRecipe) {
|
|
248
|
+
const componentStacks: Record<number, {quantity: number; stats: Record<string, number>}[]> =
|
|
249
|
+
{}
|
|
250
|
+
for (const slot of slotInputs) {
|
|
251
|
+
if (slot.category !== undefined) {
|
|
252
|
+
throw new Error(
|
|
253
|
+
`entity recipe ${entityRecipe.id} expects component inputs but slot itemId=${slot.itemId} has category=${slot.category}`
|
|
254
|
+
)
|
|
255
|
+
}
|
|
256
|
+
const list = (componentStacks[slot.itemId] ??= [])
|
|
257
|
+
for (const s of slot.stacks) {
|
|
258
|
+
list.push({
|
|
259
|
+
quantity: s.quantity,
|
|
260
|
+
stats: decodeCraftedItemStats(slot.itemId, s.seed),
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
const stats = computeEntityStats(entityRecipe.id, componentStacks)
|
|
265
|
+
const ordered = entityRecipe.stats.map((statDef) => {
|
|
266
|
+
const found = stats.find((s) => s.key === statDef.key)
|
|
267
|
+
return found ? found.value : 0
|
|
268
|
+
})
|
|
269
|
+
return UInt64.from(encodeStats(ordered))
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
throw new Error(`computeCraftedOutputSeed: no recipe found for outputItemId=${outputItemId}`)
|
|
273
|
+
}
|
package/src/derivation/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export {
|
|
|
7
7
|
getLocationCandidates,
|
|
8
8
|
getDepthThreshold,
|
|
9
9
|
getResourceTier,
|
|
10
|
-
depthScaleFactor,
|
|
11
10
|
DEPTH_THRESHOLD_T1,
|
|
12
11
|
DEPTH_THRESHOLD_T2,
|
|
13
12
|
DEPTH_THRESHOLD_T3,
|
|
@@ -24,5 +23,8 @@ export {
|
|
|
24
23
|
PLANET_SUBTYPE_INDUSTRIAL,
|
|
25
24
|
} from './resources'
|
|
26
25
|
|
|
26
|
+
export {RESERVE_TIERS, TIER_ROLL_MAX, rollTier, rollWithinTier} from './tiers'
|
|
27
|
+
export type {ReserveTier, TierRange} from './tiers'
|
|
28
|
+
|
|
27
29
|
export * from './stats'
|
|
28
30
|
export * from './crafting'
|
|
@@ -9,7 +9,7 @@ export const DEPTH_THRESHOLD_T5 = 55000
|
|
|
9
9
|
export const LOCATION_MIN_DEPTH = 500
|
|
10
10
|
export const LOCATION_MAX_DEPTH = 65535
|
|
11
11
|
|
|
12
|
-
export const YIELD_THRESHOLD = Math.floor(0.
|
|
12
|
+
export const YIELD_THRESHOLD = Math.floor(0.001 * 0xffffffff)
|
|
13
13
|
|
|
14
14
|
export const PLANET_SUBTYPE_GAS_GIANT = 0
|
|
15
15
|
export const PLANET_SUBTYPE_ROCKY = 1
|
|
@@ -134,9 +134,3 @@ export function getEligibleResources(
|
|
|
134
134
|
return stratum >= threshold
|
|
135
135
|
})
|
|
136
136
|
}
|
|
137
|
-
|
|
138
|
-
export function depthScaleFactor(stratum: number): number {
|
|
139
|
-
if (stratum <= 1) return 1.0
|
|
140
|
-
const logScale = Math.log(stratum) / Math.log(65535)
|
|
141
|
-
return 1.0 + logScale * 2.0
|
|
142
|
-
}
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import {Bytes, Checksum256, Checksum256Type} from '@wharfkit/antelope'
|
|
2
2
|
import {hash512} from '../utils/hash'
|
|
3
3
|
import {Coordinates, CoordinatesType} from '../types'
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
getEligibleResources,
|
|
7
|
-
getResourceWeight,
|
|
8
|
-
YIELD_THRESHOLD,
|
|
9
|
-
} from './resources'
|
|
4
|
+
import {getEligibleResources, getResourceWeight, YIELD_THRESHOLD} from './resources'
|
|
5
|
+
import {RESERVE_TIERS, rollTier, rollWithinTier} from './tiers'
|
|
10
6
|
|
|
11
7
|
export interface StratumInfo {
|
|
12
8
|
itemId: number
|
|
@@ -39,9 +35,10 @@ export function deriveStratum(
|
|
|
39
35
|
|
|
40
36
|
let reserve = 0
|
|
41
37
|
if (rawReserve <= YIELD_THRESHOLD) {
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
38
|
+
const tierRoll = ((bytes[18] << 8) | bytes[19]) >>> 0
|
|
39
|
+
const withinRoll = ((bytes[20] << 8) | bytes[21]) >>> 0
|
|
40
|
+
const tier = rollTier(tierRoll, stratum)
|
|
41
|
+
reserve = rollWithinTier(withinRoll, RESERVE_TIERS[tier])
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
if (reserve === 0) return {itemId: 0, seed: 0n, richness: 0, reserve: 0}
|
|
@@ -94,25 +91,32 @@ export function deriveStratum(
|
|
|
94
91
|
|
|
95
92
|
export function deriveResourceStats(seed: bigint): ResourceStats {
|
|
96
93
|
const seedBytes = new Uint8Array(8)
|
|
97
|
-
for (let i =
|
|
94
|
+
for (let i = 0; i < 8; i++) {
|
|
98
95
|
seedBytes[i] = Number(seed & 0xffn)
|
|
99
96
|
seed >>= 8n
|
|
100
97
|
}
|
|
101
98
|
const hashResult = Checksum256.hash(Bytes.from(seedBytes))
|
|
102
99
|
const hashBytes = hashResult.array
|
|
103
100
|
|
|
104
|
-
const
|
|
101
|
+
const extractU32 = (offset: number): number =>
|
|
102
|
+
(hashBytes[offset] * 0x1000000 +
|
|
103
|
+
(hashBytes[offset + 1] << 16) +
|
|
104
|
+
(hashBytes[offset + 2] << 8) +
|
|
105
|
+
hashBytes[offset + 3]) >>>
|
|
106
|
+
0
|
|
105
107
|
|
|
106
108
|
const weibull = (raw: number): number => {
|
|
107
|
-
const u = raw /
|
|
108
|
-
let x = 0.
|
|
109
|
+
const u = raw / 4294967296
|
|
110
|
+
let x = 0.24 * Math.sqrt(-Math.log(1 - u))
|
|
109
111
|
if (x > 1) x = 1
|
|
110
|
-
|
|
112
|
+
let val = Math.floor(x * 999) + 1
|
|
113
|
+
if (val > 999) val = 999
|
|
114
|
+
return val
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
return {
|
|
114
|
-
stat1: weibull(
|
|
115
|
-
stat2: weibull(
|
|
116
|
-
stat3: weibull(
|
|
118
|
+
stat1: weibull(extractU32(0)),
|
|
119
|
+
stat2: weibull(extractU32(4)),
|
|
120
|
+
stat3: weibull(extractU32(8)),
|
|
117
121
|
}
|
|
118
122
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
export type ReserveTier = 'small' | 'medium' | 'large' | 'massive' | 'motherlode'
|
|
2
|
+
|
|
3
|
+
export interface TierRange {
|
|
4
|
+
min: number
|
|
5
|
+
max: number
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const RESERVE_TIERS: Record<ReserveTier, TierRange> = {
|
|
9
|
+
small: {min: 15, max: 60},
|
|
10
|
+
medium: {min: 100, max: 200},
|
|
11
|
+
large: {min: 400, max: 700},
|
|
12
|
+
massive: {min: 1000, max: 2500},
|
|
13
|
+
motherlode: {min: 4000, max: 10000},
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const SHALLOW_THRESHOLDS = {
|
|
17
|
+
small: 0.8,
|
|
18
|
+
medium: 0.991946,
|
|
19
|
+
large: 0.999946,
|
|
20
|
+
massive: 0.999996,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const DEEP_THRESHOLDS = {
|
|
24
|
+
small: 0.5,
|
|
25
|
+
medium: 0.95892,
|
|
26
|
+
large: 0.99892,
|
|
27
|
+
massive: 0.99992,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const TIER_ROLL_MAX = 0x10000 // 65536
|
|
31
|
+
|
|
32
|
+
function lerp(a: number, b: number, t: number): number {
|
|
33
|
+
return a + (b - a) * t
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function rollTier(tierRoll: number, stratum: number): ReserveTier {
|
|
37
|
+
const d = Math.min(stratum, 65535) / 65535
|
|
38
|
+
const smallMax = lerp(SHALLOW_THRESHOLDS.small, DEEP_THRESHOLDS.small, d) * TIER_ROLL_MAX
|
|
39
|
+
const mediumMax = lerp(SHALLOW_THRESHOLDS.medium, DEEP_THRESHOLDS.medium, d) * TIER_ROLL_MAX
|
|
40
|
+
const largeMax = lerp(SHALLOW_THRESHOLDS.large, DEEP_THRESHOLDS.large, d) * TIER_ROLL_MAX
|
|
41
|
+
const massiveMax = lerp(SHALLOW_THRESHOLDS.massive, DEEP_THRESHOLDS.massive, d) * TIER_ROLL_MAX
|
|
42
|
+
|
|
43
|
+
if (tierRoll < smallMax) return 'small'
|
|
44
|
+
if (tierRoll < mediumMax) return 'medium'
|
|
45
|
+
if (tierRoll < largeMax) return 'large'
|
|
46
|
+
if (tierRoll < massiveMax) return 'massive'
|
|
47
|
+
return 'motherlode'
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function rollWithinTier(withinRoll: number, range: TierRange): number {
|
|
51
|
+
const u = withinRoll / 65535
|
|
52
|
+
const skewed = u * u
|
|
53
|
+
return Math.floor(range.min + skewed * (range.max - range.min))
|
|
54
|
+
}
|
package/src/entities/location.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Checksum256, Checksum256Type, UInt16Type, UInt64} from '@wharfkit/antelope'
|
|
2
2
|
import {Coordinates, CoordinatesType, Distance, LocationType} from '../types'
|
|
3
|
-
import {getLocationType, hasSystem,
|
|
3
|
+
import {getLocationType, hasSystem, isGatherableLocation} from '../utils/system'
|
|
4
4
|
import {findNearbyPlanets} from '../travel/travel'
|
|
5
5
|
|
|
6
6
|
export class Location {
|
|
@@ -30,8 +30,8 @@ export class Location {
|
|
|
30
30
|
return getLocationType(gameSeed, this.coordinates)
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
return
|
|
33
|
+
isGatherableAt(gameSeed: Checksum256Type): boolean {
|
|
34
|
+
return isGatherableLocation(this.getLocationTypeAt(gameSeed))
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
findNearby(gameSeed: Checksum256Type, maxDistance: UInt16Type = 20): Distance[] {
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
getModuleCapabilityType,
|
|
4
4
|
MODULE_CRAFTER,
|
|
5
5
|
MODULE_ENGINE,
|
|
6
|
-
|
|
6
|
+
MODULE_GATHERER,
|
|
7
7
|
MODULE_GENERATOR,
|
|
8
8
|
MODULE_HAULER,
|
|
9
9
|
MODULE_LOADER,
|
|
@@ -52,11 +52,11 @@ export function computeGeneratorCapabilities(stats: Record<string, number>): {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
export function
|
|
56
|
-
|
|
55
|
+
export function computeGathererCapabilities(stats: Record<string, number>): {
|
|
56
|
+
yield: number
|
|
57
57
|
drain: number
|
|
58
58
|
depth: number
|
|
59
|
-
|
|
59
|
+
speed: number
|
|
60
60
|
} {
|
|
61
61
|
const str = stats.strength ?? 500
|
|
62
62
|
const con = stats.conductivity ?? 500
|
|
@@ -64,10 +64,10 @@ export function computeExtractorCapabilities(stats: Record<string, number>): {
|
|
|
64
64
|
const tol = stats.tolerance ?? 500
|
|
65
65
|
|
|
66
66
|
return {
|
|
67
|
-
|
|
67
|
+
yield: 200 + str,
|
|
68
68
|
drain: Math.max(10, 50 - Math.floor(con / 20)),
|
|
69
69
|
depth: 200 + Math.floor((tol * 3) / 2),
|
|
70
|
-
|
|
70
|
+
speed: 100 + Math.floor((ref * 4) / 5),
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -153,7 +153,7 @@ export function computeWarehouseHullCapabilities(stats: Record<string, number>):
|
|
|
153
153
|
export interface ShipCapabilities {
|
|
154
154
|
engines?: {thrust: number; drain: number}
|
|
155
155
|
generator?: {capacity: number; recharge: number}
|
|
156
|
-
|
|
156
|
+
gatherer?: {yield: number; drain: number; depth: number; speed: number}
|
|
157
157
|
hauler?: {capacity: number; efficiency: number; drain: number}
|
|
158
158
|
loaders?: {mass: number; thrust: number; quantity: number}
|
|
159
159
|
crafter?: {speed: number; drain: number}
|
|
@@ -190,22 +190,22 @@ export function computeShipCapabilities(
|
|
|
190
190
|
ship.generator = {capacity: totalCapacity, recharge: totalRecharge}
|
|
191
191
|
}
|
|
192
192
|
|
|
193
|
-
const
|
|
194
|
-
(m) => getModuleCapabilityType(m.itemId) ===
|
|
193
|
+
const gathererModules = modules.filter(
|
|
194
|
+
(m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER
|
|
195
195
|
)
|
|
196
|
-
if (
|
|
197
|
-
let
|
|
196
|
+
if (gathererModules.length > 0) {
|
|
197
|
+
let totalYield = 0
|
|
198
198
|
let totalDrain = 0
|
|
199
199
|
let totalDepth = 0
|
|
200
|
-
let
|
|
201
|
-
for (const m of
|
|
202
|
-
const caps =
|
|
203
|
-
|
|
200
|
+
let totalSpeed = 0
|
|
201
|
+
for (const m of gathererModules) {
|
|
202
|
+
const caps = computeGathererCapabilities(decodeCraftedItemStats(m.itemId, m.seed))
|
|
203
|
+
totalYield += caps.yield
|
|
204
204
|
totalDrain += caps.drain
|
|
205
205
|
totalDepth += caps.depth
|
|
206
|
-
|
|
206
|
+
totalSpeed += caps.speed
|
|
207
207
|
}
|
|
208
|
-
ship.
|
|
208
|
+
ship.gatherer = {yield: totalYield, drain: totalDrain, depth: totalDepth, speed: totalSpeed}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
const haulerModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_HAULER)
|
package/src/entities/ship.ts
CHANGED
|
@@ -104,8 +104,8 @@ export class Ship extends ServerContract.Types.entity_info {
|
|
|
104
104
|
return schedule.isUnloading(this, now)
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
|
|
108
|
-
return schedule.
|
|
107
|
+
isGathering(now: Date): boolean {
|
|
108
|
+
return schedule.isGathering(this, now)
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
get hasEngines(): boolean {
|
|
@@ -116,8 +116,8 @@ export class Ship extends ServerContract.Types.entity_info {
|
|
|
116
116
|
return this.generator !== undefined
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
-
get
|
|
120
|
-
return this.
|
|
119
|
+
get hasGatherer(): boolean {
|
|
120
|
+
return this.gatherer !== undefined
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
get hasWarp(): boolean {
|
package/src/errors.ts
CHANGED
|
@@ -44,3 +44,8 @@ export const SHIP_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.'
|
|
|
44
44
|
export const WAREHOUSE_NOT_FOUND = 'Cannot find warehouse for given id.'
|
|
45
45
|
export const WAREHOUSE_ALREADY_AT_LOCATION = 'Warehouse already exists at this location.'
|
|
46
46
|
export const WAREHOUSE_CAPACITY_EXCEEDED = 'Warehouse capacity would be exceeded.'
|
|
47
|
+
export const ENTITY_CAPACITY_EXCEEDED = 'Entity cargo capacity would be exceeded.'
|
|
48
|
+
export const RECIPE_INPUTS_INSUFFICIENT = 'Insufficient inputs for recipe.'
|
|
49
|
+
export const RECIPE_INPUTS_INVALID = 'Input cargo does not match recipe requirements.'
|
|
50
|
+
export const RECIPE_INPUTS_EXCESS = 'Provided inputs exceed recipe requirements.'
|
|
51
|
+
export const RECIPE_INPUTS_MIXED = 'All stacks for a recipe input must be the same resource.'
|