@shipload/sdk 0.7.1 → 1.0.0-next.0

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 (94) hide show
  1. package/lib/shipload.d.ts +2730 -287
  2. package/lib/shipload.js +10862 -2229
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +10434 -2171
  5. package/lib/shipload.m.js.map +1 -1
  6. package/package.json +11 -20
  7. package/src/capabilities/crafting.ts +22 -0
  8. package/src/capabilities/gathering.ts +36 -0
  9. package/src/capabilities/guards.ts +38 -0
  10. package/src/capabilities/hauling.ts +22 -0
  11. package/src/capabilities/index.ts +8 -0
  12. package/src/capabilities/loading.ts +8 -0
  13. package/src/capabilities/modules.ts +86 -0
  14. package/src/capabilities/movement.ts +29 -0
  15. package/src/capabilities/storage.ts +159 -0
  16. package/src/contracts/server.ts +1389 -285
  17. package/src/data/capabilities.ts +408 -0
  18. package/src/data/catalog.ts +135 -0
  19. package/src/data/categories.ts +55 -0
  20. package/src/data/colors.ts +84 -0
  21. package/src/data/entities.json +50 -0
  22. package/src/data/item-ids.ts +75 -0
  23. package/src/data/items.json +252 -0
  24. package/src/data/locations.ts +53 -0
  25. package/src/data/metadata.ts +208 -0
  26. package/src/data/nebula-adjectives.json +211 -0
  27. package/src/data/nebula-nouns.json +151 -0
  28. package/src/data/recipes-runtime.ts +65 -0
  29. package/src/data/recipes.json +878 -0
  30. package/src/data/syllables.json +1790 -0
  31. package/src/data/tiers.ts +45 -0
  32. package/src/derivation/crafting.ts +350 -0
  33. package/src/derivation/index.ts +32 -0
  34. package/src/derivation/location-size.ts +15 -0
  35. package/src/derivation/resources.ts +112 -0
  36. package/src/derivation/stats.ts +146 -0
  37. package/src/derivation/strata.ts +43 -0
  38. package/src/derivation/stratum.ts +134 -0
  39. package/src/derivation/tiers.ts +54 -0
  40. package/src/entities/cargo-utils.ts +84 -0
  41. package/src/entities/container.ts +108 -0
  42. package/src/entities/entity-inventory.ts +39 -0
  43. package/src/entities/gamestate.ts +152 -0
  44. package/src/entities/inventory-accessor.ts +42 -0
  45. package/src/entities/location.ts +60 -0
  46. package/src/entities/makers.ts +196 -0
  47. package/src/entities/player.ts +15 -0
  48. package/src/entities/ship-deploy.ts +258 -0
  49. package/src/entities/ship.ts +204 -0
  50. package/src/entities/warehouse.ts +119 -0
  51. package/src/errors.ts +100 -9
  52. package/src/format.ts +12 -0
  53. package/src/index-module.ts +317 -7
  54. package/src/managers/actions.ts +250 -0
  55. package/src/managers/base.ts +25 -0
  56. package/src/managers/context.ts +114 -0
  57. package/src/managers/entities.ts +103 -0
  58. package/src/managers/epochs.ts +47 -0
  59. package/src/managers/index.ts +9 -0
  60. package/src/managers/locations.ts +68 -0
  61. package/src/managers/players.ts +13 -0
  62. package/src/nft/description.ts +176 -0
  63. package/src/nft/deserializers.ts +83 -0
  64. package/src/nft/index.ts +2 -0
  65. package/src/resolution/describe-module.ts +166 -0
  66. package/src/resolution/display-name.ts +39 -0
  67. package/src/resolution/resolve-item.ts +358 -0
  68. package/src/scheduling/accessor.ts +82 -0
  69. package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
  70. package/src/scheduling/projection.ts +463 -0
  71. package/src/scheduling/schedule.ts +179 -0
  72. package/src/shipload.ts +47 -160
  73. package/src/subscriptions/connection.ts +154 -0
  74. package/src/subscriptions/debug.ts +17 -0
  75. package/src/subscriptions/index.ts +5 -0
  76. package/src/subscriptions/manager.ts +240 -0
  77. package/src/subscriptions/mappers.ts +28 -0
  78. package/src/subscriptions/types.ts +143 -0
  79. package/src/travel/travel.ts +500 -0
  80. package/src/types/capabilities.ts +76 -0
  81. package/src/types/entity-traits.ts +69 -0
  82. package/src/types/entity.ts +39 -0
  83. package/src/types/index.ts +3 -0
  84. package/src/types.ts +140 -35
  85. package/src/{hash.ts → utils/hash.ts} +2 -2
  86. package/src/utils/system.ts +168 -0
  87. package/src/goods.ts +0 -124
  88. package/src/market.ts +0 -214
  89. package/src/rolls.ts +0 -8
  90. package/src/ship.ts +0 -36
  91. package/src/state.ts +0 -0
  92. package/src/syllables.ts +0 -1184
  93. package/src/system.ts +0 -37
  94. package/src/travel.ts +0 -259
@@ -0,0 +1,39 @@
1
+ import type {ResolvedItem} from './resolve-item'
2
+ import type {ResourceCategory} from '../types'
3
+ import {CATEGORY_LABELS, TIER_ADJECTIVES} from '../types'
4
+ import {formatMass as defaultFormatMass} from '../format'
5
+
6
+ export interface DisplayNameInput {
7
+ itemType: 'resource' | 'component' | 'module' | 'entity' | string
8
+ tier: number
9
+ category?: ResourceCategory
10
+ name: string
11
+ }
12
+
13
+ export function displayName(resolved: DisplayNameInput): string {
14
+ if (resolved.itemType === 'resource') {
15
+ const adj = TIER_ADJECTIVES[resolved.tier] ?? 'Unknown'
16
+ const cat = resolved.category ? CATEGORY_LABELS[resolved.category] : 'Resource'
17
+ return `${adj} ${cat}`
18
+ }
19
+ return resolved.name
20
+ }
21
+
22
+ export interface DescribeOptions {
23
+ translate?: (key: string) => string
24
+ formatNumber?: (n: number) => string
25
+ formatMass?: (kg: number) => string
26
+ }
27
+
28
+ export function describeItem(resolved: ResolvedItem, opts?: DescribeOptions): string {
29
+ const massFmt = opts?.formatMass ?? defaultFormatMass
30
+ const mass = massFmt(resolved.mass)
31
+ const tier = `T${resolved.tier}`
32
+ if (resolved.itemType === 'resource') {
33
+ const cat = resolved.category ? CATEGORY_LABELS[resolved.category] : 'Resource'
34
+ const header = `${tier} ${cat}`
35
+ const stats = resolved.stats?.map((s) => `${s.label} ${s.value}`).join(', ')
36
+ return [header, stats, mass].filter(Boolean).join(' · ')
37
+ }
38
+ return `${tier} ${resolved.name} · ${mass}`
39
+ }
@@ -0,0 +1,358 @@
1
+ import {UInt16, UInt64} from '@wharfkit/antelope'
2
+ import type {UInt16Type, UInt64Type} from '@wharfkit/antelope'
3
+ import type {ResourceCategory} from '../types'
4
+ import {getItem} from '../data/catalog'
5
+ import {getEntityLayout} from '../data/recipes-runtime'
6
+ import {entityMetadata, itemMetadata} from '../data/metadata'
7
+ import {
8
+ getModuleCapabilityType,
9
+ isModuleItem,
10
+ MODULE_CRAFTER,
11
+ MODULE_ENGINE,
12
+ MODULE_GATHERER,
13
+ MODULE_GENERATOR,
14
+ MODULE_HAULER,
15
+ MODULE_LOADER,
16
+ MODULE_STORAGE,
17
+ } from '../capabilities/modules'
18
+ import {decodeCraftedItemStats, decodeStat} from '../derivation/crafting'
19
+ import {getStatDefinitions} from '../derivation/stats'
20
+ import {
21
+ computeCrafterCapabilities,
22
+ computeEngineCapabilities,
23
+ computeGathererCapabilities,
24
+ computeGeneratorCapabilities,
25
+ computeHaulerCapabilities,
26
+ computeLoaderCapabilities,
27
+ computeShipHullCapabilities,
28
+ computeWarehouseHullCapabilities,
29
+ } from '../entities/ship-deploy'
30
+ import {computeContainerCapabilities, computeContainerT2Capabilities} from '../entities/container'
31
+ import {
32
+ categoryColors,
33
+ categoryIcons,
34
+ componentIcon,
35
+ itemAbbreviations,
36
+ moduleIcon,
37
+ } from '../data/colors'
38
+ import type {ServerContract} from '../contracts'
39
+ import {
40
+ ITEM_CONTAINER_T1_PACKED,
41
+ ITEM_CONTAINER_T2_PACKED,
42
+ ITEM_SHIP_T1_PACKED,
43
+ ITEM_WAREHOUSE_T1_PACKED,
44
+ } from '../data/item-ids'
45
+
46
+ export interface ResolvedItemStat {
47
+ key: string
48
+ label: string
49
+ abbreviation: string
50
+ value: number
51
+ color: string
52
+ category?: ResourceCategory
53
+ inverted?: boolean
54
+ }
55
+
56
+ export interface ResolvedAttributeGroup {
57
+ capability: string
58
+ attributes: {label: string; value: number}[]
59
+ }
60
+
61
+ export type ResolvedItemType = 'resource' | 'component' | 'module' | 'entity'
62
+
63
+ export interface ResolvedModuleSlot {
64
+ name?: string
65
+ installed: boolean
66
+ attributes?: {label: string; value: number}[]
67
+ }
68
+
69
+ export interface ResolvedItem {
70
+ itemId: number
71
+ name: string
72
+ icon: string
73
+ abbreviation: string | null
74
+ category?: ResourceCategory
75
+ tier: number
76
+ mass: number
77
+ itemType: ResolvedItemType
78
+ stats?: ResolvedItemStat[]
79
+ attributes?: ResolvedAttributeGroup[]
80
+ moduleSlots?: ResolvedModuleSlot[]
81
+ }
82
+
83
+ function toNum(v: UInt16Type): number {
84
+ return Number(UInt16.from(v).value.toString())
85
+ }
86
+
87
+ function toBigStats(v: UInt64Type): bigint {
88
+ return BigInt(UInt64.from(v).toString())
89
+ }
90
+
91
+ function resolveResource(id: number, stats?: UInt64Type): ResolvedItem {
92
+ const item = getItem(id)
93
+ const cat = item.category
94
+ let resolvedStats: ResolvedItemStat[] | undefined
95
+ if (stats !== undefined && cat) {
96
+ const bigStats = toBigStats(stats)
97
+ const defs = getStatDefinitions(cat)
98
+ const values = [decodeStat(bigStats, 0), decodeStat(bigStats, 1), decodeStat(bigStats, 2)]
99
+ resolvedStats = defs.map((d, i) => ({
100
+ key: d.key,
101
+ label: d.label,
102
+ abbreviation: d.abbreviation,
103
+ value: values[i] ?? 0,
104
+ color: categoryColors[cat],
105
+ category: cat,
106
+ inverted: d.inverted,
107
+ }))
108
+ }
109
+ return {
110
+ itemId: id,
111
+ name: item.name,
112
+ icon: cat ? categoryIcons[cat] : '⬡',
113
+ abbreviation: null,
114
+ category: cat,
115
+ tier: item.tier,
116
+ mass: item.mass,
117
+ itemType: 'resource',
118
+ stats: resolvedStats,
119
+ }
120
+ }
121
+
122
+ function resolveComponent(id: number, stats?: UInt64Type): ResolvedItem {
123
+ const item = getItem(id)
124
+ let resolvedStats: ResolvedItemStat[] | undefined
125
+ if (stats !== undefined) {
126
+ const decoded = decodeCraftedItemStats(id, toBigStats(stats))
127
+ resolvedStats = Object.entries(decoded).map(([key, value]) => {
128
+ const allDefs = getStatDefinitions('ore')
129
+ .concat(getStatDefinitions('crystal'))
130
+ .concat(getStatDefinitions('gas'))
131
+ .concat(getStatDefinitions('regolith'))
132
+ .concat(getStatDefinitions('biomass'))
133
+ const def = allDefs.find((d) => d.key === key)
134
+ return {
135
+ key,
136
+ label: def?.label ?? key,
137
+ abbreviation: def?.abbreviation ?? key.slice(0, 3).toUpperCase(),
138
+ value,
139
+ color: '#9BADB8',
140
+ inverted: def?.inverted,
141
+ }
142
+ })
143
+ }
144
+ return {
145
+ itemId: id,
146
+ name: item.name,
147
+ icon: itemAbbreviations[id] ?? componentIcon,
148
+ abbreviation: itemAbbreviations[id] ?? null,
149
+ tier: item.tier,
150
+ mass: item.mass,
151
+ itemType: 'component',
152
+ stats: resolvedStats,
153
+ }
154
+ }
155
+
156
+ function computeCapabilityGroup(
157
+ moduleType: number,
158
+ stats: Record<string, number>
159
+ ): ResolvedAttributeGroup | undefined {
160
+ switch (moduleType) {
161
+ case MODULE_ENGINE: {
162
+ const caps = computeEngineCapabilities(stats)
163
+ return {
164
+ capability: 'Engine',
165
+ attributes: [
166
+ {label: 'Thrust', value: caps.thrust},
167
+ {label: 'Drain', value: caps.drain},
168
+ ],
169
+ }
170
+ }
171
+ case MODULE_GENERATOR: {
172
+ const caps = computeGeneratorCapabilities(stats)
173
+ return {
174
+ capability: 'Generator',
175
+ attributes: [
176
+ {label: 'Capacity', value: caps.capacity},
177
+ {label: 'Recharge', value: caps.recharge},
178
+ ],
179
+ }
180
+ }
181
+ case MODULE_GATHERER: {
182
+ const caps = computeGathererCapabilities(stats)
183
+ return {
184
+ capability: 'Gatherer',
185
+ attributes: [
186
+ {label: 'Yield', value: caps.yield},
187
+ {label: 'Drain', value: caps.drain},
188
+ {label: 'Depth', value: caps.depth},
189
+ {label: 'Speed', value: caps.speed},
190
+ ],
191
+ }
192
+ }
193
+ case MODULE_LOADER: {
194
+ const caps = computeLoaderCapabilities(stats)
195
+ return {
196
+ capability: 'Loader',
197
+ attributes: [
198
+ {label: 'Mass', value: caps.mass},
199
+ {label: 'Thrust', value: caps.thrust},
200
+ {label: 'Quantity', value: caps.quantity},
201
+ ],
202
+ }
203
+ }
204
+ case MODULE_CRAFTER: {
205
+ const caps = computeCrafterCapabilities(stats)
206
+ return {
207
+ capability: 'Crafter',
208
+ attributes: [
209
+ {label: 'Speed', value: caps.speed},
210
+ {label: 'Drain', value: caps.drain},
211
+ ],
212
+ }
213
+ }
214
+ case MODULE_HAULER: {
215
+ const caps = computeHaulerCapabilities(stats)
216
+ return {
217
+ capability: 'Hauler',
218
+ attributes: [
219
+ {label: 'Capacity', value: caps.capacity},
220
+ {label: 'Efficiency', value: caps.efficiency},
221
+ {label: 'Drain', value: caps.drain},
222
+ ],
223
+ }
224
+ }
225
+ case MODULE_STORAGE: {
226
+ const str = stats.strength ?? 500
227
+ const hrd = stats.hardness ?? 500
228
+ const sat = stats.saturation ?? 500
229
+ const statSum = str + hrd + sat
230
+ const pct = 10 + Math.floor((statSum * 10) / 2997)
231
+ return {capability: 'Storage', attributes: [{label: 'Capacity Bonus', value: pct}]}
232
+ }
233
+ default:
234
+ return undefined
235
+ }
236
+ }
237
+
238
+ function resolveModule(id: number, stats?: UInt64Type): ResolvedItem {
239
+ const item = getItem(id)
240
+ let attributes: ResolvedAttributeGroup[] | undefined
241
+ if (stats !== undefined) {
242
+ const decoded = decodeCraftedItemStats(id, toBigStats(stats))
243
+ const modType = getModuleCapabilityType(id)
244
+ const group = computeCapabilityGroup(modType, decoded)
245
+ if (group) attributes = [group]
246
+ }
247
+ return {
248
+ itemId: id,
249
+ name: item.name,
250
+ icon: itemAbbreviations[id] ?? moduleIcon,
251
+ abbreviation: itemAbbreviations[id] ?? null,
252
+ tier: item.tier,
253
+ mass: item.mass,
254
+ itemType: 'module',
255
+ attributes,
256
+ }
257
+ }
258
+
259
+ function hullCapsForEntity(
260
+ itemId: number,
261
+ decoded: Record<string, number>
262
+ ): {
263
+ hullmass: number
264
+ capacity: number
265
+ } {
266
+ switch (itemId) {
267
+ case ITEM_SHIP_T1_PACKED:
268
+ return computeShipHullCapabilities(decoded)
269
+ case ITEM_WAREHOUSE_T1_PACKED:
270
+ return computeWarehouseHullCapabilities(decoded)
271
+ case ITEM_CONTAINER_T1_PACKED:
272
+ return computeContainerCapabilities(decoded)
273
+ case ITEM_CONTAINER_T2_PACKED:
274
+ return computeContainerT2Capabilities(decoded)
275
+ default:
276
+ throw new Error(`resolveItem: no capacity formula wired for entity item ${itemId}`)
277
+ }
278
+ }
279
+
280
+ function resolveEntity(
281
+ id: number,
282
+ stats?: UInt64Type,
283
+ modules?: ServerContract.Types.module_entry[]
284
+ ): ResolvedItem {
285
+ const item = getItem(id)
286
+ const layout = getEntityLayout(id)
287
+ let attributes: ResolvedAttributeGroup[] | undefined
288
+ let moduleSlots: ResolvedModuleSlot[] | undefined
289
+
290
+ if (stats !== undefined) {
291
+ const decoded = decodeCraftedItemStats(id, toBigStats(stats))
292
+ const hullCaps = hullCapsForEntity(id, decoded)
293
+ attributes = [
294
+ {
295
+ capability: 'Hull',
296
+ attributes: [
297
+ {label: 'Mass', value: hullCaps.hullmass},
298
+ {label: 'Capacity', value: hullCaps.capacity},
299
+ ],
300
+ },
301
+ ]
302
+ }
303
+
304
+ if (layout && layout.slots.length > 0) {
305
+ const slotLabels = entityMetadata[id]?.moduleSlotLabels ?? []
306
+ moduleSlots = layout.slots.map((slot, i) => {
307
+ const mod = modules?.[i]
308
+ if (mod?.installed) {
309
+ const modItemId = Number(mod.installed.item_id.value.toString())
310
+ const modStats = BigInt(mod.installed.stats.toString())
311
+ const decodedStats = decodeCraftedItemStats(modItemId, modStats)
312
+ const modType = getModuleCapabilityType(modItemId)
313
+ const group = computeCapabilityGroup(modType, decodedStats)
314
+ let modName = 'Module'
315
+ try {
316
+ modName = getItem(modItemId).name
317
+ } catch {
318
+ modName = itemMetadata[modItemId]?.name ?? 'Module'
319
+ }
320
+ return {
321
+ name: modName,
322
+ installed: true,
323
+ attributes: group?.attributes,
324
+ }
325
+ }
326
+ return {
327
+ name: slotLabels[i] ?? slot.type,
328
+ installed: false,
329
+ }
330
+ })
331
+ }
332
+
333
+ return {
334
+ itemId: id,
335
+ name: item.name,
336
+ icon: itemAbbreviations[id] ?? componentIcon,
337
+ abbreviation: itemAbbreviations[id] ?? null,
338
+ tier: item.tier,
339
+ mass: item.mass,
340
+ itemType: 'entity',
341
+ attributes,
342
+ moduleSlots,
343
+ }
344
+ }
345
+
346
+ export function resolveItem(
347
+ itemId: UInt16Type,
348
+ stats?: UInt64Type,
349
+ modules?: ServerContract.Types.module_entry[]
350
+ ): ResolvedItem {
351
+ const id = toNum(itemId)
352
+ const item = getItem(id)
353
+
354
+ if (item.type === 'module' || isModuleItem(id)) return resolveModule(id, stats)
355
+ if (item.type === 'component') return resolveComponent(id, stats)
356
+ if (item.type === 'entity') return resolveEntity(id, stats, modules)
357
+ return resolveResource(id, stats)
358
+ }
@@ -0,0 +1,82 @@
1
+ import type {ServerContract} from '../contracts'
2
+ import type {TaskType} from '../types'
3
+ import type {ScheduleData} from './schedule'
4
+ import * as schedule from './schedule'
5
+
6
+ type Task = ServerContract.Types.task
7
+
8
+ export class ScheduleAccessor {
9
+ constructor(private entity: ScheduleData) {}
10
+
11
+ get hasSchedule(): boolean {
12
+ return schedule.hasSchedule(this.entity)
13
+ }
14
+
15
+ get isIdle(): boolean {
16
+ return schedule.isIdle(this.entity)
17
+ }
18
+
19
+ get tasks(): Task[] {
20
+ return schedule.getTasks(this.entity)
21
+ }
22
+
23
+ duration(): number {
24
+ return schedule.scheduleDuration(this.entity)
25
+ }
26
+
27
+ elapsed(now: Date): number {
28
+ return schedule.scheduleElapsed(this.entity, now)
29
+ }
30
+
31
+ remaining(now: Date): number {
32
+ return schedule.scheduleRemaining(this.entity, now)
33
+ }
34
+
35
+ complete(now: Date): boolean {
36
+ return schedule.scheduleComplete(this.entity, now)
37
+ }
38
+
39
+ currentTaskIndex(now: Date): number {
40
+ return schedule.currentTaskIndex(this.entity, now)
41
+ }
42
+
43
+ currentTask(now: Date): Task | undefined {
44
+ return schedule.currentTask(this.entity, now)
45
+ }
46
+
47
+ currentTaskType(now: Date): TaskType | undefined {
48
+ return schedule.currentTaskType(this.entity, now)
49
+ }
50
+
51
+ taskStartTime(index: number): number {
52
+ return schedule.getTaskStartTime(this.entity, index)
53
+ }
54
+
55
+ taskElapsed(index: number, now: Date): number {
56
+ return schedule.getTaskElapsed(this.entity, index, now)
57
+ }
58
+
59
+ taskRemaining(index: number, now: Date): number {
60
+ return schedule.getTaskRemaining(this.entity, index, now)
61
+ }
62
+
63
+ taskComplete(index: number, now: Date): boolean {
64
+ return schedule.isTaskComplete(this.entity, index, now)
65
+ }
66
+
67
+ taskInProgress(index: number, now: Date): boolean {
68
+ return schedule.isTaskInProgress(this.entity, index, now)
69
+ }
70
+
71
+ currentTaskProgress(now: Date): number {
72
+ return schedule.currentTaskProgress(this.entity, now)
73
+ }
74
+
75
+ progress(now: Date): number {
76
+ return schedule.scheduleProgress(this.entity, now)
77
+ }
78
+ }
79
+
80
+ export function createScheduleAccessor(entity: ScheduleData): ScheduleAccessor {
81
+ return new ScheduleAccessor(entity)
82
+ }
@@ -1,5 +1,5 @@
1
1
  import {UInt64} from '@wharfkit/antelope'
2
- import {PlatformContract} from './contracts'
2
+ import type {PlatformContract} from '../contracts'
3
3
 
4
4
  export interface EpochInfo {
5
5
  epoch: UInt64