@shipload/sdk 2.0.0-rc13 → 2.0.0-rc14

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.
@@ -1,4 +1,15 @@
1
- import {Action, Int64, Name, NameType, UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
1
+ import {
2
+ Action,
3
+ Int64,
4
+ Name,
5
+ NameType,
6
+ UInt16,
7
+ UInt16Type,
8
+ UInt32,
9
+ UInt32Type,
10
+ UInt64,
11
+ UInt64Type,
12
+ } from '@wharfkit/antelope'
2
13
  import {BaseManager} from './base'
3
14
  import {CoordinatesType, EntityType, EntityTypeName} from '../types'
4
15
  import {ServerContract} from '../contracts'
@@ -71,7 +82,8 @@ export class ActionsManager extends BaseManager {
71
82
  sourceId: UInt64Type,
72
83
  destType: EntityTypeName,
73
84
  destId: UInt64Type,
74
- goodId: UInt64Type,
85
+ itemId: UInt64Type,
86
+ stats: UInt64Type,
75
87
  quantity: UInt64Type
76
88
  ): Action {
77
89
  return this.server.action('transfer', {
@@ -79,7 +91,8 @@ export class ActionsManager extends BaseManager {
79
91
  source_id: UInt64.from(sourceId),
80
92
  dest_type: destType,
81
93
  dest_id: UInt64.from(destId),
82
- item_id: UInt16.from(goodId),
94
+ item_id: UInt16.from(itemId),
95
+ stats: UInt64.from(stats),
83
96
  quantity: UInt32.from(quantity),
84
97
  })
85
98
  }
@@ -97,10 +110,21 @@ export class ActionsManager extends BaseManager {
97
110
  })
98
111
  }
99
112
 
100
- gather(shipId: UInt64Type, stratum: number, quantity: number): Action {
113
+ gather(
114
+ source: EntityRefInput,
115
+ destination: EntityRefInput,
116
+ stratum: UInt16Type,
117
+ quantity: UInt32Type
118
+ ): Action {
101
119
  return this.server.action('gather', {
102
- entity_type: EntityType.SHIP,
103
- id: UInt64.from(shipId),
120
+ source: ServerContract.Types.entity_ref.from({
121
+ entity_type: source.entityType,
122
+ entity_id: UInt64.from(source.entityId),
123
+ }),
124
+ destination: ServerContract.Types.entity_ref.from({
125
+ entity_type: destination.entityType,
126
+ entity_id: UInt64.from(destination.entityId),
127
+ }),
104
128
  stratum: UInt16.from(stratum),
105
129
  quantity: UInt32.from(quantity),
106
130
  })
@@ -152,14 +176,14 @@ export class ActionsManager extends BaseManager {
152
176
  entityType: EntityTypeName,
153
177
  entityId: UInt64Type,
154
178
  packedItemId: number,
155
- seed: bigint,
179
+ stats: bigint,
156
180
  entityName: string
157
181
  ): Action {
158
182
  return this.server.action('deploy', {
159
183
  entity_type: entityType,
160
184
  id: UInt64.from(entityId),
161
185
  packed_item_id: UInt16.from(packedItemId),
162
- seed: UInt64.from(seed),
186
+ stats: UInt64.from(stats),
163
187
  entity_name: entityName,
164
188
  })
165
189
  }
@@ -194,6 +218,22 @@ export class ActionsManager extends BaseManager {
194
218
  })
195
219
  }
196
220
 
221
+ wrap(
222
+ owner: NameType,
223
+ entityType: EntityTypeName,
224
+ entityId: UInt64Type,
225
+ cargoId: UInt64Type,
226
+ quantity: UInt64Type
227
+ ): Action {
228
+ return this.server.action('wrap', {
229
+ owner: Name.from(owner),
230
+ entity_type: entityType,
231
+ entity_id: UInt64.from(entityId),
232
+ cargo_id: UInt64.from(cargoId),
233
+ quantity: UInt64.from(quantity),
234
+ })
235
+ }
236
+
197
237
  joinGame(account: NameType, companyName: string): Action[] {
198
238
  return [this.foundCompany(account, companyName), this.join(account)]
199
239
  }
@@ -25,27 +25,28 @@ function idiv(a: number, b: number): number {
25
25
  return Math.floor(a / b)
26
26
  }
27
27
 
28
- export function computeBaseHullmass(seed: bigint): number {
29
- const density = decodeStat(seed, 1)
28
+ export function computeBaseHullmass(stats: bigint): number {
29
+ const density = decodeStat(stats, 1)
30
30
  return 25000 + 75 * density
31
31
  }
32
32
 
33
- export function computeBaseCapacityShip(seed: bigint): number {
34
- const s = decodeStat(seed, 0) + decodeStat(seed, 2) + decodeStat(seed, 3)
33
+ export function computeBaseCapacityShip(stats: bigint): number {
34
+ const s = decodeStat(stats, 0) + decodeStat(stats, 2) + decodeStat(stats, 3)
35
35
  return Math.floor(1_000_000 * Math.pow(10, s / 2997))
36
36
  }
37
37
 
38
- export function computeBaseCapacityWarehouse(seed: bigint): number {
39
- const s = decodeStat(seed, 0) + decodeStat(seed, 2) + decodeStat(seed, 3)
38
+ export function computeBaseCapacityWarehouse(stats: bigint): number {
39
+ const s = decodeStat(stats, 0) + decodeStat(stats, 2) + decodeStat(stats, 3)
40
40
  return Math.floor(20_000_000 * Math.pow(10, s / 2997))
41
41
  }
42
42
 
43
43
  export const computeEngineThrust = (vol: number): number => 400 + idiv(vol * 3, 4)
44
44
  export const computeEngineDrain = (thm: number): number => Math.max(30, 50 - idiv(thm, 70))
45
45
  export const computeGeneratorCap = (res: number): number => 300 + idiv(res, 6)
46
- export const computeGeneratorRech = (clr: number): number => 5 + idiv(clr * 15, 1000)
46
+ export const computeGeneratorRech = (clr: number): number => 1 + idiv(clr * 3, 1000)
47
47
  export const computeGathererYield = (str: number): number => 200 + str
48
- export const computeGathererDrain = (con: number): number => Math.max(10, 50 - idiv(con, 20))
48
+ export const computeGathererDrain = (con: number): number =>
49
+ Math.max(250, 1250 - idiv(con * 25, 20))
49
50
  export const computeGathererDepth = (tol: number): number => 200 + idiv(tol * 3, 2)
50
51
  export const computeGathererSpeed = (ref: number): number => 100 + idiv(ref * 4, 5)
51
52
  export const computeLoaderMass = (duc: number): number => Math.max(200, 2000 - duc * 2)
@@ -87,7 +88,7 @@ export function moduleDisplayName(itemId: number): string {
87
88
  }
88
89
  }
89
90
 
90
- export function formatModuleLine(slot: number, itemId: number, seed: bigint): string {
91
+ export function formatModuleLine(slot: number, itemId: number, stats: bigint): string {
91
92
  let out = `Slot ${slot} - `
92
93
  if (itemId === 0) {
93
94
  out += '(empty)'
@@ -99,43 +100,43 @@ export function formatModuleLine(slot: number, itemId: number, seed: bigint): st
99
100
 
100
101
  switch (subtype) {
101
102
  case MODULE_ENGINE: {
102
- const vol = decodeStat(seed, 0)
103
- const thm = decodeStat(seed, 1)
103
+ const vol = decodeStat(stats, 0)
104
+ const thm = decodeStat(stats, 1)
104
105
  out += ` Thrust ${computeEngineThrust(vol)} Drain ${computeEngineDrain(thm)}`
105
106
  break
106
107
  }
107
108
  case MODULE_GENERATOR: {
108
- const res = decodeStat(seed, 0)
109
- const clr = decodeStat(seed, 1)
109
+ const res = decodeStat(stats, 0)
110
+ const clr = decodeStat(stats, 1)
110
111
  out += ` Capacity ${computeGeneratorCap(res)} Recharge ${computeGeneratorRech(clr)}`
111
112
  break
112
113
  }
113
114
  case MODULE_GATHERER: {
114
- const str = decodeStat(seed, 0)
115
- const tol = decodeStat(seed, 1)
116
- const con = decodeStat(seed, 3)
117
- const ref = decodeStat(seed, 4)
115
+ const str = decodeStat(stats, 0)
116
+ const tol = decodeStat(stats, 1)
117
+ const con = decodeStat(stats, 3)
118
+ const ref = decodeStat(stats, 4)
118
119
  out += ` Yield ${computeGathererYield(str)} Depth ${computeGathererDepth(
119
120
  tol
120
121
  )} Speed ${computeGathererSpeed(ref)} Drain ${computeGathererDrain(con)}`
121
122
  break
122
123
  }
123
124
  case MODULE_LOADER: {
124
- const duc = decodeStat(seed, 0)
125
- const pla = decodeStat(seed, 1)
125
+ const duc = decodeStat(stats, 0)
126
+ const pla = decodeStat(stats, 1)
126
127
  out += ` Mass ${computeLoaderMass(duc)} Thrust ${computeLoaderThrust(pla)}`
127
128
  break
128
129
  }
129
130
  case MODULE_CRAFTER: {
130
- const rea = decodeStat(seed, 0)
131
- const clr = decodeStat(seed, 1)
131
+ const rea = decodeStat(stats, 0)
132
+ const clr = decodeStat(stats, 1)
132
133
  out += ` Speed ${computeCrafterSpeed(rea)} Drain ${computeCrafterDrain(clr)}`
133
134
  break
134
135
  }
135
136
  case MODULE_STORAGE: {
136
- const str = decodeStat(seed, 0)
137
- const duc = decodeStat(seed, 1)
138
- const pur = decodeStat(seed, 2)
137
+ const str = decodeStat(stats, 0)
138
+ const duc = decodeStat(stats, 1)
139
+ const pur = decodeStat(stats, 2)
139
140
  const sum = str + duc + pur
140
141
  const pct = 10 + idiv(sum * 10, 2997)
141
142
  out += ` +${pct}% capacity`
@@ -147,16 +148,16 @@ export function formatModuleLine(slot: number, itemId: number, seed: bigint): st
147
148
 
148
149
  export function buildEntityDescription(
149
150
  itemId: number,
150
- hullSeed: bigint,
151
+ hullStats: bigint,
151
152
  moduleItems: number[],
152
- moduleSeeds: bigint[]
153
+ moduleStats: bigint[]
153
154
  ): string {
154
- const hullMass = computeBaseHullmass(hullSeed)
155
+ const hullMass = computeBaseHullmass(hullStats)
155
156
  let baseCapacity = 0
156
157
  if (itemId === ITEM_SHIP_T1_PACKED) {
157
- baseCapacity = computeBaseCapacityShip(hullSeed)
158
+ baseCapacity = computeBaseCapacityShip(hullStats)
158
159
  } else if (itemId === ITEM_WAREHOUSE_T1_PACKED) {
159
- baseCapacity = computeBaseCapacityWarehouse(hullSeed)
160
+ baseCapacity = computeBaseCapacityWarehouse(hullStats)
160
161
  }
161
162
 
162
163
  let out = entityDisplayName(itemId)
@@ -167,7 +168,7 @@ export function buildEntityDescription(
167
168
  out += '\n\n'
168
169
 
169
170
  for (let i = 0; i < moduleItems.length; i++) {
170
- out += formatModuleLine(i, moduleItems[i], moduleSeeds[i] ?? 0n)
171
+ out += formatModuleLine(i, moduleItems[i], moduleStats[i] ?? 0n)
171
172
  out += '\n'
172
173
  }
173
174
 
@@ -9,7 +9,7 @@ import {
9
9
 
10
10
  export interface NFTInstalledModule {
11
11
  item_id: number
12
- seed: string
12
+ stats: string
13
13
  }
14
14
 
15
15
  export interface NFTModuleSlot {
@@ -20,13 +20,13 @@ export interface NFTModuleSlot {
20
20
  export interface NFTCargoItem {
21
21
  item_id: number
22
22
  quantity: number
23
- seed: string
23
+ stats: string
24
24
  modules?: NFTModuleSlot[]
25
25
  }
26
26
 
27
27
  export interface NFTCommonBase {
28
28
  quantity: number
29
- seed: string
29
+ stats: string
30
30
  origin_x: string
31
31
  origin_y: string
32
32
  }
@@ -34,7 +34,7 @@ export interface NFTCommonBase {
34
34
  export function readCommonBase(data: Record<string, any>): NFTCommonBase {
35
35
  return {
36
36
  quantity: Number(data.quantity),
37
- seed: String(data.seed),
37
+ stats: String(data.stats),
38
38
  origin_x: String(data.origin_x),
39
39
  origin_y: String(data.origin_y),
40
40
  }
@@ -42,7 +42,7 @@ export function readCommonBase(data: Record<string, any>): NFTCommonBase {
42
42
 
43
43
  export function deserializeScalar(data: Record<string, any>, itemId: number): NFTCargoItem {
44
44
  const base = readCommonBase(data)
45
- return {item_id: itemId, quantity: base.quantity, seed: base.seed}
45
+ return {item_id: itemId, quantity: base.quantity, stats: base.stats}
46
46
  }
47
47
 
48
48
  export const deserializeResource = deserializeScalar
@@ -52,18 +52,18 @@ export const deserializeModule = deserializeScalar
52
52
  export function deserializeEntity(data: Record<string, any>, itemId: number): NFTCargoItem {
53
53
  const base = readCommonBase(data)
54
54
  const moduleItems: number[] = (data.module_items ?? []).map((v: any) => Number(v))
55
- const moduleSeeds: string[] = (data.module_seeds ?? []).map((v: any) => String(v))
55
+ const moduleStats: string[] = (data.module_stats ?? []).map((v: any) => String(v))
56
56
  const layout = getEntitySlotLayout(itemId)
57
57
 
58
58
  const modules: NFTModuleSlot[] = layout.map((slot, i) => ({
59
59
  type: slot.type,
60
60
  installed:
61
61
  moduleItems[i] && moduleItems[i] !== 0
62
- ? {item_id: moduleItems[i], seed: moduleSeeds[i]}
62
+ ? {item_id: moduleItems[i], stats: moduleStats[i]}
63
63
  : undefined,
64
64
  }))
65
65
 
66
- return {item_id: itemId, quantity: base.quantity, seed: base.seed, modules}
66
+ return {item_id: itemId, quantity: base.quantity, stats: base.stats, modules}
67
67
  }
68
68
 
69
69
  export function deserializeAsset(data: Record<string, any>, itemId: number): NFTCargoItem {
@@ -0,0 +1,165 @@
1
+ import type {ResolvedItem, ResolvedModuleSlot} from './resolve-item'
2
+
3
+ export interface TextSpan {
4
+ text: string
5
+ highlight?: boolean
6
+ }
7
+
8
+ export interface CapabilityInput {
9
+ capability: string
10
+ attributes: {label: string; value: number}[]
11
+ }
12
+
13
+ export interface ModuleDescription {
14
+ id: string
15
+ template: string
16
+ params: Readonly<Record<string, number | string>>
17
+ highlightKeys: readonly string[]
18
+ }
19
+
20
+ export interface RenderDescriptionOptions {
21
+ translate?: (id: string, fallback: string) => string
22
+ formatNumber?: (n: number) => string
23
+ }
24
+
25
+ interface TemplateSpec {
26
+ id: string
27
+ template: string
28
+ params: readonly [string, string][]
29
+ highlightKeys: readonly string[]
30
+ }
31
+
32
+ const TEMPLATES: Record<string, TemplateSpec> = {
33
+ engine: {
34
+ id: 'module.engine.description',
35
+ template:
36
+ 'generates {thrust} thrust for travel while draining {drain} energy per distance travelled',
37
+ params: [
38
+ ['thrust', 'Thrust'],
39
+ ['drain', 'Drain'],
40
+ ],
41
+ highlightKeys: ['thrust', 'drain'],
42
+ },
43
+ generator: {
44
+ id: 'module.generator.description',
45
+ template:
46
+ 'holds {capacity} maximum energy and restores {recharge} per second while recharging',
47
+ params: [
48
+ ['capacity', 'Capacity'],
49
+ ['recharge', 'Recharge'],
50
+ ],
51
+ highlightKeys: ['capacity', 'recharge'],
52
+ },
53
+ gatherer: {
54
+ id: 'module.gatherer.description',
55
+ template:
56
+ 'mines resources at {yield} speed to a max depth of {depth} with {speed} gather speed while draining {drain} energy per second',
57
+ params: [
58
+ ['yield', 'Yield'],
59
+ ['drain', 'Drain'],
60
+ ['depth', 'Depth'],
61
+ ['speed', 'Speed'],
62
+ ],
63
+ highlightKeys: ['yield', 'depth', 'speed', 'drain'],
64
+ },
65
+ loader: {
66
+ id: 'module.loader.description',
67
+ template:
68
+ '{quantity} loader that generates {thrust} thrust with a weight of {mass} per unit',
69
+ params: [
70
+ ['quantity', 'Quantity'],
71
+ ['thrust', 'Thrust'],
72
+ ['mass', 'Mass'],
73
+ ],
74
+ highlightKeys: ['quantity', 'thrust', 'mass'],
75
+ },
76
+ manufacturing: {
77
+ id: 'module.manufacturing.description',
78
+ template: 'manufactures items at {speed} speed while draining {drain} energy per second',
79
+ params: [
80
+ ['speed', 'Speed'],
81
+ ['drain', 'Drain'],
82
+ ],
83
+ highlightKeys: ['speed', 'drain'],
84
+ },
85
+ storage: {
86
+ id: 'module.storage.description',
87
+ template: 'boosts cargo capacity by {bonus}%',
88
+ params: [['bonus', 'Capacity Bonus']],
89
+ highlightKeys: ['bonus'],
90
+ },
91
+ hauler: {
92
+ id: 'module.hauler.description',
93
+ template:
94
+ 'locks onto up to {capacity} targets at {efficiency} efficiency while draining {drain} energy per distance travelled per target',
95
+ params: [
96
+ ['capacity', 'Capacity'],
97
+ ['efficiency', 'Efficiency'],
98
+ ['drain', 'Drain'],
99
+ ],
100
+ highlightKeys: ['capacity', 'efficiency', 'drain'],
101
+ },
102
+ }
103
+
104
+ export function describeModule(input: CapabilityInput): ModuleDescription | null {
105
+ if (!input.attributes || input.attributes.length === 0) return null
106
+ const key = input.capability.toLowerCase()
107
+ const spec = TEMPLATES[key]
108
+ if (!spec) return null
109
+ const params: Record<string, number | string> = {}
110
+ for (const [paramName, attrLabel] of spec.params) {
111
+ const attr = input.attributes.find((a) => a.label === attrLabel)
112
+ if (attr) params[paramName] = attr.value
113
+ }
114
+ return {
115
+ id: spec.id,
116
+ template: spec.template,
117
+ params,
118
+ highlightKeys: spec.highlightKeys,
119
+ }
120
+ }
121
+
122
+ export function describeModuleForItem(resolved: ResolvedItem): ModuleDescription | null {
123
+ if (resolved.itemType !== 'module') return null
124
+ const group = resolved.attributes?.[0]
125
+ if (!group) return null
126
+ return describeModule({capability: group.capability, attributes: group.attributes})
127
+ }
128
+
129
+ export function describeModuleForSlot(slot: ResolvedModuleSlot): ModuleDescription | null {
130
+ if (!slot.installed || !slot.name || !slot.attributes) return null
131
+ return describeModule({capability: slot.name, attributes: slot.attributes})
132
+ }
133
+
134
+ export function renderDescription(
135
+ desc: ModuleDescription,
136
+ options?: RenderDescriptionOptions
137
+ ): TextSpan[] {
138
+ const translate = options?.translate ?? ((_id: string, fallback: string) => fallback)
139
+ const formatNumber = options?.formatNumber ?? ((n: number) => n.toLocaleString('en-US'))
140
+ const tpl = translate(desc.id, desc.template)
141
+
142
+ const spans: TextSpan[] = []
143
+ const regex = /\{([A-Za-z_][A-Za-z0-9_]*)\}/g
144
+ let lastIndex = 0
145
+ let m: RegExpExecArray | null
146
+ while ((m = regex.exec(tpl)) !== null) {
147
+ if (m.index > lastIndex) {
148
+ spans.push({text: tpl.slice(lastIndex, m.index)})
149
+ }
150
+ const paramName = m[1] ?? ''
151
+ const raw = desc.params[paramName]
152
+ if (raw === undefined) {
153
+ spans.push({text: `{${paramName}}`})
154
+ } else {
155
+ const formatted = typeof raw === 'number' ? formatNumber(raw) : raw
156
+ const highlight = (desc.highlightKeys as readonly string[]).includes(paramName)
157
+ spans.push(highlight ? {text: formatted, highlight: true} : {text: formatted})
158
+ }
159
+ lastIndex = m.index + m[0].length
160
+ }
161
+ if (lastIndex < tpl.length) {
162
+ spans.push({text: tpl.slice(lastIndex)})
163
+ }
164
+ return spans
165
+ }