@shipload/sdk 1.0.0-next.60 → 1.0.0-next.61
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 +37 -26
- package/lib/shipload.js +466 -302
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +465 -303
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.js +69 -45
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +69 -45
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/modules.ts +3 -48
- package/src/data/catalog.ts +7 -3
- package/src/data/colors.ts +3 -3
- package/src/data/entities.json +4 -4
- package/src/data/item-ids.ts +24 -22
- package/src/data/items.json +37 -23
- package/src/data/kind-registry.json +4 -4
- package/src/data/metadata.ts +36 -25
- package/src/data/recipes.json +242 -56
- package/src/data/tiers.ts +9 -6
- package/src/derivation/capabilities.ts +36 -35
- package/src/derivation/crafting.ts +1 -1
- package/src/derivation/recipe-usage.test.ts +2 -0
- package/src/nft/buildImmutableData.ts +5 -2
- package/src/nft/description.ts +77 -134
- package/src/resolution/resolve-item.ts +1 -1
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
ITEM_CRAFTER_T1,
|
|
16
16
|
ITEM_BUILDER_T1,
|
|
17
17
|
ITEM_EXTRACTOR_T1_PACKED,
|
|
18
|
+
ITEM_WORKSHOP_T1_PACKED,
|
|
18
19
|
ITEM_ROUSTABOUT_T1A_PACKED,
|
|
19
20
|
ITEM_PROSPECTOR_T1A_PACKED,
|
|
20
21
|
ITEM_TENDER_T1A_PACKED,
|
|
@@ -36,6 +37,7 @@ test('getRecipeConsumers lists every recipe that consumes Sensor', () => {
|
|
|
36
37
|
ITEM_CRAFTER_T1,
|
|
37
38
|
ITEM_BUILDER_T1,
|
|
38
39
|
ITEM_EXTRACTOR_T1_PACKED,
|
|
40
|
+
ITEM_WORKSHOP_T1_PACKED,
|
|
39
41
|
ITEM_ROUSTABOUT_T1A_PACKED,
|
|
40
42
|
].sort((a, b) => a - b)
|
|
41
43
|
)
|
|
@@ -285,7 +285,7 @@ export function buildModuleImmutable(
|
|
|
285
285
|
base.push({first: 'cohesion', second: ['uint16', com]})
|
|
286
286
|
base.push({
|
|
287
287
|
first: 'capacity',
|
|
288
|
-
second: ['uint32', computeCargoBayCapacity(str, den, hrd)],
|
|
288
|
+
second: ['uint32', computeCargoBayCapacity(str, den, hrd, item.tier)],
|
|
289
289
|
})
|
|
290
290
|
base.push({
|
|
291
291
|
first: 'drain',
|
|
@@ -304,7 +304,10 @@ export function buildModuleImmutable(
|
|
|
304
304
|
base.push({first: 'insulation', second: ['uint16', ins]})
|
|
305
305
|
base.push({
|
|
306
306
|
first: 'capacity',
|
|
307
|
-
second: [
|
|
307
|
+
second: [
|
|
308
|
+
'uint32',
|
|
309
|
+
toWholeEnergy(computeBatteryBankCapacity(vol, thm, pla, ins, item.tier)),
|
|
310
|
+
],
|
|
308
311
|
})
|
|
309
312
|
break
|
|
310
313
|
}
|
package/src/nft/description.ts
CHANGED
|
@@ -11,44 +11,7 @@ import {
|
|
|
11
11
|
MODULE_STORAGE,
|
|
12
12
|
MODULE_WARP,
|
|
13
13
|
} from '../capabilities/modules'
|
|
14
|
-
import {
|
|
15
|
-
ITEM_CONTAINER_T1_PACKED,
|
|
16
|
-
ITEM_CONTAINER_T2_PACKED,
|
|
17
|
-
ITEM_CONSTRUCTION_DOCK_T1_PACKED,
|
|
18
|
-
ITEM_BUILDER_T1,
|
|
19
|
-
ITEM_BUILDER_T2,
|
|
20
|
-
ITEM_CRAFTER_T1,
|
|
21
|
-
ITEM_CRAFTER_T2,
|
|
22
|
-
ITEM_ENGINE_T1,
|
|
23
|
-
ITEM_ENGINE_T2,
|
|
24
|
-
ITEM_EXTRACTOR_T1_PACKED,
|
|
25
|
-
ITEM_FACTORY_T1_PACKED,
|
|
26
|
-
ITEM_GATHERER_T1,
|
|
27
|
-
ITEM_GATHERER_T2,
|
|
28
|
-
ITEM_GENERATOR_T1,
|
|
29
|
-
ITEM_GENERATOR_T2,
|
|
30
|
-
ITEM_HAULER_T1,
|
|
31
|
-
ITEM_HAULER_T2,
|
|
32
|
-
ITEM_BATTERY_T1,
|
|
33
|
-
ITEM_LAUNCHER_T1,
|
|
34
|
-
ITEM_LOADER_T1,
|
|
35
|
-
ITEM_LOADER_T2,
|
|
36
|
-
ITEM_PROSPECTOR_T1A_PACKED,
|
|
37
|
-
ITEM_PROSPECTOR_T2A_PACKED,
|
|
38
|
-
ITEM_PROSPECTOR_T2B_PACKED,
|
|
39
|
-
ITEM_ROUSTABOUT_T1A_PACKED,
|
|
40
|
-
ITEM_SHIP_T1_PACKED,
|
|
41
|
-
ITEM_SMITH_T1A_PACKED,
|
|
42
|
-
ITEM_STORAGE_T1,
|
|
43
|
-
ITEM_TENDER_T1A_PACKED,
|
|
44
|
-
ITEM_TUG_T1A_PACKED,
|
|
45
|
-
ITEM_PORTER_T1A_PACKED,
|
|
46
|
-
ITEM_WRIGHT_T1A_PACKED,
|
|
47
|
-
ITEM_DREDGER_T2A_PACKED,
|
|
48
|
-
ITEM_WAREHOUSE_T1_PACKED,
|
|
49
|
-
ITEM_WARP_T1,
|
|
50
|
-
ITEM_WARP_T2,
|
|
51
|
-
} from '../data/item-ids'
|
|
14
|
+
import {getKindMeta, getTemplateMeta} from '../data/kind-registry'
|
|
52
15
|
import {decodeStat} from '../derivation/crafting'
|
|
53
16
|
import {
|
|
54
17
|
gathererDepthForTier,
|
|
@@ -61,8 +24,11 @@ import {
|
|
|
61
24
|
BUILDER_SPEED_TIER_PCT,
|
|
62
25
|
WARP_RANGE_TIER_PCT,
|
|
63
26
|
LOADER_THRUST_TIER_PCT,
|
|
27
|
+
CARGO_BAY_CAPACITY_TIER_PCT,
|
|
28
|
+
BATTERY_CAPACITY_TIER_PCT,
|
|
64
29
|
} from '../derivation/capabilities'
|
|
65
|
-
import {getItem} from '../data/catalog'
|
|
30
|
+
import {getItem, tryGetItem} from '../data/catalog'
|
|
31
|
+
import type {ModuleType} from '../types'
|
|
66
32
|
import {ENTITY_SHIP, getPackedEntityType} from '../data/kind-registry'
|
|
67
33
|
import {getBaseHullmassFor} from '../derivation/capabilities'
|
|
68
34
|
import {computeEffectiveModuleStat} from '../derivation/stat-scaling'
|
|
@@ -75,6 +41,11 @@ export function toWholeEnergy(milli: number): number {
|
|
|
75
41
|
return idiv(milli + 500, 1000)
|
|
76
42
|
}
|
|
77
43
|
|
|
44
|
+
export function formatMassTonnes(kg: number): string {
|
|
45
|
+
const tenths = idiv(kg + 50, 100)
|
|
46
|
+
return `${idiv(tenths, 10)}.${tenths % 10} t`
|
|
47
|
+
}
|
|
48
|
+
|
|
78
49
|
function isShipHull(itemId: number): boolean {
|
|
79
50
|
return getPackedEntityType(itemId)?.equals(ENTITY_SHIP) ?? false
|
|
80
51
|
}
|
|
@@ -109,6 +80,29 @@ export function computeBaseCapacityWarehouse(stats: bigint): number {
|
|
|
109
80
|
return Math.floor(100_000_000 * 6 ** (s / 1998))
|
|
110
81
|
}
|
|
111
82
|
|
|
83
|
+
export function computeBaseCapacityWorkshop(stats: bigint): number {
|
|
84
|
+
const s = decodeStat(stats, 0) + decodeStat(stats, 2)
|
|
85
|
+
return Math.floor(5_000_000 * 6 ** (s / 1998))
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const CAPACITY_FN_BY_KIND: Record<string, (stats: bigint) => number> = {
|
|
89
|
+
ship: computeBaseCapacityShip,
|
|
90
|
+
warehouse: computeBaseCapacityWarehouse,
|
|
91
|
+
workshop: computeBaseCapacityWorkshop,
|
|
92
|
+
extractor: computeBaseCapacityContainer,
|
|
93
|
+
factory: computeBaseCapacityContainer,
|
|
94
|
+
builddock: computeBaseCapacityContainer,
|
|
95
|
+
mdriver: computeBaseCapacityContainer,
|
|
96
|
+
mcatcher: computeBaseCapacityContainer,
|
|
97
|
+
container: computeBaseCapacityContainer,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function computeBaseCapacityForEntity(itemId: number, stats: bigint): number {
|
|
101
|
+
const kind = getTemplateMeta(itemId)?.kind
|
|
102
|
+
if (!kind) return 0
|
|
103
|
+
return CAPACITY_FN_BY_KIND[kind.toString()]?.(stats) ?? 0
|
|
104
|
+
}
|
|
105
|
+
|
|
112
106
|
export const computeEngineThrust = (vol: number, tier: number): number =>
|
|
113
107
|
idiv((400 + idiv(vol * 3, 4)) * moduleTierPct(ENGINE_THRUST_TIER_PCT, tier), 100)
|
|
114
108
|
export const computeEngineDrain = (thm: number): number => 2 * Math.max(30, 50 - idiv(thm, 70))
|
|
@@ -159,91 +153,52 @@ export const computeWarpRange = (stat: number, tier: number): number =>
|
|
|
159
153
|
export const computeCargoBayCapacity = (
|
|
160
154
|
strength: number,
|
|
161
155
|
density: number,
|
|
162
|
-
hardness: number
|
|
163
|
-
|
|
156
|
+
hardness: number,
|
|
157
|
+
tier: number
|
|
158
|
+
): number =>
|
|
159
|
+
idiv(
|
|
160
|
+
(10_000_000 + idiv((strength + density + hardness) * 50_000_000, 2997)) *
|
|
161
|
+
moduleTierPct(CARGO_BAY_CAPACITY_TIER_PCT, tier),
|
|
162
|
+
100
|
|
163
|
+
)
|
|
164
164
|
export const computeBatteryBankCapacity = (
|
|
165
165
|
volatility: number,
|
|
166
166
|
thermal: number,
|
|
167
167
|
plasticity: number,
|
|
168
|
-
insulation: number
|
|
169
|
-
|
|
168
|
+
insulation: number,
|
|
169
|
+
tier: number
|
|
170
|
+
): number =>
|
|
171
|
+
idiv(
|
|
172
|
+
(2_500_000 + idiv((volatility + thermal + plasticity + insulation) * 7_500_000, 3996)) *
|
|
173
|
+
moduleTierPct(BATTERY_CAPACITY_TIER_PCT, tier),
|
|
174
|
+
100
|
|
175
|
+
)
|
|
170
176
|
|
|
171
177
|
export function entityDisplayName(itemId: number): string {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return 'Warehouse'
|
|
191
|
-
case ITEM_EXTRACTOR_T1_PACKED:
|
|
192
|
-
return 'Mining Rig'
|
|
193
|
-
case ITEM_FACTORY_T1_PACKED:
|
|
194
|
-
return 'Factory'
|
|
195
|
-
case ITEM_CONSTRUCTION_DOCK_T1_PACKED:
|
|
196
|
-
return 'Construction Dock'
|
|
197
|
-
case ITEM_CONTAINER_T1_PACKED:
|
|
198
|
-
return 'Container'
|
|
199
|
-
case ITEM_CONTAINER_T2_PACKED:
|
|
200
|
-
return 'Container'
|
|
201
|
-
case ITEM_PROSPECTOR_T2A_PACKED:
|
|
202
|
-
return 'Prospector'
|
|
203
|
-
case ITEM_PROSPECTOR_T2B_PACKED:
|
|
204
|
-
return 'Prospector'
|
|
205
|
-
case ITEM_DREDGER_T2A_PACKED:
|
|
206
|
-
return 'Dredger'
|
|
207
|
-
default:
|
|
208
|
-
return 'Entity'
|
|
209
|
-
}
|
|
178
|
+
const template = getTemplateMeta(itemId)
|
|
179
|
+
if (!template) return 'Entity'
|
|
180
|
+
if (template.displayLabel) return template.displayLabel
|
|
181
|
+
return getKindMeta(template.kind)?.defaultLabel || 'Entity'
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const MODULE_DISPLAY_NAME_BY_TYPE: Partial<Record<ModuleType, string>> = {
|
|
185
|
+
engine: 'Engine',
|
|
186
|
+
generator: 'Power Core',
|
|
187
|
+
gatherer: 'Limpet Bay',
|
|
188
|
+
loader: 'Shuttle Bay',
|
|
189
|
+
crafter: 'Fabricator',
|
|
190
|
+
storage: 'Cargo Hold',
|
|
191
|
+
hauler: 'Tractor Beam',
|
|
192
|
+
warp: 'Warp Drive',
|
|
193
|
+
battery: 'Battery Bank',
|
|
194
|
+
launcher: 'Drive Coil',
|
|
195
|
+
builder: 'Assembly Arm',
|
|
210
196
|
}
|
|
211
197
|
|
|
212
198
|
export function moduleDisplayName(itemId: number): string {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
return 'Engine'
|
|
217
|
-
case ITEM_GENERATOR_T1:
|
|
218
|
-
case ITEM_GENERATOR_T2:
|
|
219
|
-
return 'Power Core'
|
|
220
|
-
case ITEM_GATHERER_T1:
|
|
221
|
-
case ITEM_GATHERER_T2:
|
|
222
|
-
return 'Limpet Bay'
|
|
223
|
-
case ITEM_LOADER_T1:
|
|
224
|
-
case ITEM_LOADER_T2:
|
|
225
|
-
return 'Shuttle Bay'
|
|
226
|
-
case ITEM_CRAFTER_T1:
|
|
227
|
-
case ITEM_CRAFTER_T2:
|
|
228
|
-
return 'Fabricator'
|
|
229
|
-
case ITEM_BUILDER_T1:
|
|
230
|
-
case ITEM_BUILDER_T2:
|
|
231
|
-
return 'Assembly Arm'
|
|
232
|
-
case ITEM_STORAGE_T1:
|
|
233
|
-
return 'Cargo Hold'
|
|
234
|
-
case ITEM_HAULER_T1:
|
|
235
|
-
case ITEM_HAULER_T2:
|
|
236
|
-
return 'Tractor Beam'
|
|
237
|
-
case ITEM_WARP_T1:
|
|
238
|
-
case ITEM_WARP_T2:
|
|
239
|
-
return 'Warp Drive'
|
|
240
|
-
case ITEM_BATTERY_T1:
|
|
241
|
-
return 'Battery Bank'
|
|
242
|
-
case ITEM_LAUNCHER_T1:
|
|
243
|
-
return 'Drive Coil'
|
|
244
|
-
default:
|
|
245
|
-
return 'Module'
|
|
246
|
-
}
|
|
199
|
+
const item = tryGetItem(itemId)
|
|
200
|
+
if (item?.type !== 'module' || !item.moduleType) return 'Module'
|
|
201
|
+
return MODULE_DISPLAY_NAME_BY_TYPE[item.moduleType] ?? 'Module'
|
|
247
202
|
}
|
|
248
203
|
|
|
249
204
|
export function formatModuleLine(slot: number, itemId: number, stats: bigint): string {
|
|
@@ -288,7 +243,7 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
|
|
|
288
243
|
const fin = decodeStat(stats, 0)
|
|
289
244
|
const pla = decodeStat(stats, 1)
|
|
290
245
|
const tier = getItem(itemId).tier
|
|
291
|
-
out += ` Mass ${computeLoaderMass(fin)} Thrust ${computeLoaderThrust(pla, tier)}`
|
|
246
|
+
out += ` Mass ${formatMassTonnes(computeLoaderMass(fin))} Thrust ${computeLoaderThrust(pla, tier)}`
|
|
292
247
|
break
|
|
293
248
|
}
|
|
294
249
|
case MODULE_CRAFTER: {
|
|
@@ -311,7 +266,7 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
|
|
|
311
266
|
const hrd = decodeStat(stats, 2)
|
|
312
267
|
const coh = decodeStat(stats, 3)
|
|
313
268
|
const tier = getItem(itemId).tier
|
|
314
|
-
out += ` Cargo Capacity ${computeCargoBayCapacity(str, den, hrd)} Drain ${toWholeEnergy(computeCargoBayDrain(coh, tier))}`
|
|
269
|
+
out += ` Cargo Capacity ${formatMassTonnes(computeCargoBayCapacity(str, den, hrd, tier))} Drain ${toWholeEnergy(computeCargoBayDrain(coh, tier))}`
|
|
315
270
|
break
|
|
316
271
|
}
|
|
317
272
|
case MODULE_HAULER: {
|
|
@@ -333,7 +288,8 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
|
|
|
333
288
|
const thm = decodeStat(stats, 1)
|
|
334
289
|
const pla = decodeStat(stats, 2)
|
|
335
290
|
const ins = decodeStat(stats, 3)
|
|
336
|
-
|
|
291
|
+
const tier = getItem(itemId).tier
|
|
292
|
+
out += ` Energy Capacity ${toWholeEnergy(computeBatteryBankCapacity(vol, thm, pla, ins, tier))}`
|
|
337
293
|
break
|
|
338
294
|
}
|
|
339
295
|
}
|
|
@@ -347,25 +303,12 @@ export function buildEntityDescription(
|
|
|
347
303
|
moduleStats: bigint[]
|
|
348
304
|
): string {
|
|
349
305
|
const hullMass = computeBaseHullmass(itemId, hullStats)
|
|
350
|
-
|
|
351
|
-
if (isShipHull(itemId)) {
|
|
352
|
-
baseCapacity = computeBaseCapacityShip(hullStats)
|
|
353
|
-
} else if (itemId === ITEM_WAREHOUSE_T1_PACKED) {
|
|
354
|
-
baseCapacity = computeBaseCapacityWarehouse(hullStats)
|
|
355
|
-
} else if (
|
|
356
|
-
itemId === ITEM_EXTRACTOR_T1_PACKED ||
|
|
357
|
-
itemId === ITEM_FACTORY_T1_PACKED ||
|
|
358
|
-
itemId === ITEM_CONSTRUCTION_DOCK_T1_PACKED ||
|
|
359
|
-
itemId === ITEM_CONTAINER_T1_PACKED ||
|
|
360
|
-
itemId === ITEM_CONTAINER_T2_PACKED
|
|
361
|
-
) {
|
|
362
|
-
baseCapacity = computeBaseCapacityContainer(hullStats)
|
|
363
|
-
}
|
|
306
|
+
const baseCapacity = computeBaseCapacityForEntity(itemId, hullStats)
|
|
364
307
|
|
|
365
308
|
let out = entityDisplayName(itemId)
|
|
366
|
-
out += ` - Hull ${hullMass}
|
|
309
|
+
out += ` - Hull ${formatMassTonnes(hullMass)}`
|
|
367
310
|
if (baseCapacity > 0) {
|
|
368
|
-
out += ` * ${baseCapacity} capacity`
|
|
311
|
+
out += ` * ${formatMassTonnes(baseCapacity)} capacity`
|
|
369
312
|
}
|
|
370
313
|
out += '\n\n'
|
|
371
314
|
|