@shipload/sdk 1.0.0-next.15 → 1.0.0-next.17

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 (40) hide show
  1. package/lib/shipload.d.ts +273 -101
  2. package/lib/shipload.js +3419 -2914
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +3397 -2902
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +45 -39
  7. package/lib/testing.js +171 -143
  8. package/lib/testing.js.map +1 -1
  9. package/lib/testing.m.js +171 -143
  10. package/lib/testing.m.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/capabilities/gathering.ts +15 -6
  13. package/src/capabilities/modules.ts +6 -0
  14. package/src/contracts/platform.ts +1 -1
  15. package/src/contracts/server.ts +212 -111
  16. package/src/data/capabilities.ts +6 -1
  17. package/src/data/capability-formulas.ts +7 -1
  18. package/src/data/colors.ts +12 -12
  19. package/src/data/item-ids.ts +13 -12
  20. package/src/data/items.json +7 -0
  21. package/src/data/metadata.ts +36 -23
  22. package/src/data/recipes.json +49 -0
  23. package/src/derivation/capabilities.ts +18 -7
  24. package/src/derivation/capability-mappings.ts +2 -0
  25. package/src/derivation/stratum.ts +5 -9
  26. package/src/index-module.ts +18 -2
  27. package/src/managers/actions.ts +124 -12
  28. package/src/managers/context.ts +9 -0
  29. package/src/managers/index.ts +2 -0
  30. package/src/managers/nft.ts +28 -0
  31. package/src/nft/atomicassets.ts +124 -1
  32. package/src/nft/buildImmutableData.ts +316 -0
  33. package/src/nft/description.ts +1 -3
  34. package/src/nft/index.ts +1 -0
  35. package/src/resolution/describe-module.ts +3 -4
  36. package/src/resolution/resolve-item.ts +0 -1
  37. package/src/scheduling/projection.ts +0 -4
  38. package/src/scheduling/task-cargo.ts +0 -1
  39. package/src/shipload.ts +5 -0
  40. package/src/types.ts +1 -2
@@ -8,6 +8,7 @@ import {PlayersManager} from './players'
8
8
  import {LocationsManager} from './locations'
9
9
  import {EpochsManager} from './epochs'
10
10
  import {ActionsManager} from './actions'
11
+ import {NftManager} from './nft'
11
12
  import {SubscriptionsManager} from '../subscriptions/manager'
12
13
 
13
14
  export class GameContext {
@@ -16,6 +17,7 @@ export class GameContext {
16
17
  private _locations?: LocationsManager
17
18
  private _epochs?: EpochsManager
18
19
  private _actions?: ActionsManager
20
+ private _nft?: NftManager
19
21
  private _subscriptions?: SubscriptionsManager
20
22
  private _subscriptionsUrl?: string
21
23
 
@@ -63,6 +65,13 @@ export class GameContext {
63
65
  return this._actions
64
66
  }
65
67
 
68
+ get nft(): NftManager {
69
+ if (!this._nft) {
70
+ this._nft = new NftManager(this)
71
+ }
72
+ return this._nft
73
+ }
74
+
66
75
  setSubscriptionsUrl(url: string) {
67
76
  this._subscriptionsUrl = url
68
77
  }
@@ -7,3 +7,5 @@ export {LocationsManager} from './locations'
7
7
  export type {LocationStratum} from './locations'
8
8
  export {EpochsManager} from './epochs'
9
9
  export {ActionsManager} from './actions'
10
+ export {NftManager} from './nft'
11
+ export type {NftConfigForItem} from './nft'
@@ -0,0 +1,28 @@
1
+ import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
+ import {BaseManager} from './base'
3
+ import type {ServerContract} from '../contracts'
4
+
5
+ export interface NftConfigForItem {
6
+ templateId: number
7
+ schemaName: string
8
+ }
9
+
10
+ export class NftManager extends BaseManager {
11
+ private cache = new Map<string, NftConfigForItem | null>()
12
+
13
+ async getNftConfigForItem(itemId: UInt64Type): Promise<NftConfigForItem | undefined> {
14
+ const id = UInt64.from(itemId)
15
+ const key = id.toString()
16
+ if (this.cache.has(key)) {
17
+ return this.cache.get(key) ?? undefined
18
+ }
19
+ const row = (await this.server.table('nftconfig').get(id)) as
20
+ | ServerContract.Types.nftconfig_row
21
+ | undefined
22
+ const result: NftConfigForItem | null = row
23
+ ? {templateId: Number(row.template_id), schemaName: String(row.schema_name)}
24
+ : null
25
+ this.cache.set(key, result)
26
+ return result ?? undefined
27
+ }
28
+ }
@@ -1,10 +1,133 @@
1
- import {type APIClient, Name, type NameType, UInt64} from '@wharfkit/antelope'
1
+ import {
2
+ ABI,
3
+ type ABIDef,
4
+ Action,
5
+ type APIClient,
6
+ type NameType,
7
+ Name,
8
+ PermissionLevel,
9
+ UInt64,
10
+ } from '@wharfkit/antelope'
2
11
  import {deserializeAtomicData, type SchemaField} from './atomicdata'
3
12
  import {deserializeAsset, type NFTCargoItem, type NFTModuleSlot} from './deserializers'
13
+ import type {ImmutableEntry} from './buildImmutableData'
14
+
15
+ const PLACEHOLDER_AUTH = PermissionLevel.from({
16
+ actor: '............1',
17
+ permission: '............2',
18
+ })
4
19
 
5
20
  export const ATOMICASSETS_ACCOUNT = 'atomicassets'
6
21
  export const SHIPLOAD_COLLECTION = 'shipload'
7
22
 
23
+ const ATOMIC_ATTRIBUTE_VARIANT_NAME =
24
+ 'variant_int8_int16_int32_int64_uint8_uint16_uint32_uint64_float32_float64_string_INT8_VEC_INT16_VEC_INT32_VEC_INT64_VEC_UINT8_VEC_UINT16_VEC_UINT32_VEC_UINT64_VEC_FLOAT_VEC_DOUBLE_VEC_STRING_VEC'
25
+
26
+ const MINTASSET_ABI_DEF: ABIDef = {
27
+ version: 'eosio::abi/1.2',
28
+ types: [
29
+ {new_type_name: 'ATOMIC_ATTRIBUTE', type: ATOMIC_ATTRIBUTE_VARIANT_NAME},
30
+ {new_type_name: 'ATTRIBUTE_MAP', type: 'pair_string_ATOMIC_ATTRIBUTE[]'},
31
+ {new_type_name: 'INT8_VEC', type: 'bytes'},
32
+ {new_type_name: 'INT16_VEC', type: 'int16[]'},
33
+ {new_type_name: 'INT32_VEC', type: 'int32[]'},
34
+ {new_type_name: 'INT64_VEC', type: 'int64[]'},
35
+ {new_type_name: 'UINT8_VEC', type: 'bytes'},
36
+ {new_type_name: 'UINT16_VEC', type: 'uint16[]'},
37
+ {new_type_name: 'UINT32_VEC', type: 'uint32[]'},
38
+ {new_type_name: 'UINT64_VEC', type: 'uint64[]'},
39
+ {new_type_name: 'FLOAT_VEC', type: 'float32[]'},
40
+ {new_type_name: 'DOUBLE_VEC', type: 'float64[]'},
41
+ {new_type_name: 'STRING_VEC', type: 'string[]'},
42
+ ],
43
+ structs: [
44
+ {
45
+ name: 'pair_string_ATOMIC_ATTRIBUTE',
46
+ base: '',
47
+ fields: [
48
+ {name: 'first', type: 'string'},
49
+ {name: 'second', type: 'ATOMIC_ATTRIBUTE'},
50
+ ],
51
+ },
52
+ {
53
+ name: 'mintasset',
54
+ base: '',
55
+ fields: [
56
+ {name: 'authorized_minter', type: 'name'},
57
+ {name: 'collection_name', type: 'name'},
58
+ {name: 'schema_name', type: 'name'},
59
+ {name: 'template_id', type: 'int32'},
60
+ {name: 'new_asset_owner', type: 'name'},
61
+ {name: 'immutable_data', type: 'ATTRIBUTE_MAP'},
62
+ {name: 'mutable_data', type: 'ATTRIBUTE_MAP'},
63
+ {name: 'tokens_to_back', type: 'asset[]'},
64
+ ],
65
+ },
66
+ ],
67
+ actions: [{name: 'mintasset', type: 'mintasset', ricardian_contract: ''}],
68
+ variants: [
69
+ {
70
+ name: ATOMIC_ATTRIBUTE_VARIANT_NAME,
71
+ types: [
72
+ 'int8',
73
+ 'int16',
74
+ 'int32',
75
+ 'int64',
76
+ 'uint8',
77
+ 'uint16',
78
+ 'uint32',
79
+ 'uint64',
80
+ 'float32',
81
+ 'float64',
82
+ 'string',
83
+ 'INT8_VEC',
84
+ 'INT16_VEC',
85
+ 'INT32_VEC',
86
+ 'INT64_VEC',
87
+ 'UINT8_VEC',
88
+ 'UINT16_VEC',
89
+ 'UINT32_VEC',
90
+ 'UINT64_VEC',
91
+ 'FLOAT_VEC',
92
+ 'DOUBLE_VEC',
93
+ 'STRING_VEC',
94
+ ],
95
+ },
96
+ ],
97
+ }
98
+
99
+ export interface MintAssetParams {
100
+ authorizedMinter: NameType
101
+ collectionName: NameType
102
+ schemaName: NameType
103
+ templateId: number
104
+ newAssetOwner: NameType
105
+ immutableData: ImmutableEntry[]
106
+ }
107
+
108
+ const MINTASSET_ABI = ABI.from(MINTASSET_ABI_DEF)
109
+
110
+ export function buildMintAssetAction(params: MintAssetParams): Action {
111
+ return Action.from(
112
+ {
113
+ account: Name.from(ATOMICASSETS_ACCOUNT),
114
+ name: Name.from('mintasset'),
115
+ authorization: [PLACEHOLDER_AUTH],
116
+ data: {
117
+ authorized_minter: Name.from(params.authorizedMinter),
118
+ collection_name: Name.from(params.collectionName),
119
+ schema_name: Name.from(params.schemaName),
120
+ template_id: params.templateId,
121
+ new_asset_owner: Name.from(params.newAssetOwner),
122
+ immutable_data: params.immutableData,
123
+ mutable_data: [],
124
+ tokens_to_back: [],
125
+ },
126
+ },
127
+ MINTASSET_ABI
128
+ )
129
+ }
130
+
8
131
  export interface AtomicAssetRow {
9
132
  asset_id: string
10
133
  collection_name: string
@@ -0,0 +1,316 @@
1
+ import {Serializer} from '@wharfkit/antelope'
2
+ import {getItem} from '../data/catalog'
3
+ import {
4
+ getModuleCapabilityType,
5
+ MODULE_CRAFTER,
6
+ MODULE_ENGINE,
7
+ MODULE_GATHERER,
8
+ MODULE_GENERATOR,
9
+ MODULE_HAULER,
10
+ MODULE_LOADER,
11
+ MODULE_STORAGE,
12
+ MODULE_WARP,
13
+ } from '../capabilities/modules'
14
+ import {decodeStat, decodeCraftedItemStats} from '../derivation/crafting'
15
+ import {getStatDefinitions} from '../derivation/stats'
16
+ import type {ResourceCategory} from '../types'
17
+ import {Types as ServerTypes} from '../contracts/server'
18
+ import {
19
+ buildEntityDescription,
20
+ computeCrafterDrain,
21
+ computeCrafterSpeed,
22
+ computeEngineDrain,
23
+ computeEngineThrust,
24
+ computeGathererDepth,
25
+ computeGathererDrain,
26
+ computeGathererYield,
27
+ computeGeneratorCap,
28
+ computeGeneratorRech,
29
+ computeHaulerCapacity,
30
+ computeHaulerDrain,
31
+ computeHaulerEfficiency,
32
+ computeLoaderMass,
33
+ computeLoaderThrust,
34
+ computeWarpRange,
35
+ } from './description'
36
+
37
+ export type AtomicAttributeType =
38
+ | 'string'
39
+ | 'uint8'
40
+ | 'uint16'
41
+ | 'uint32'
42
+ | 'uint64'
43
+ | 'int32'
44
+ | 'image'
45
+ | 'ipfs'
46
+ | 'UINT16_VEC'
47
+ | 'UINT64_VEC'
48
+
49
+ export interface ImmutableEntry {
50
+ first: string
51
+ second: [AtomicAttributeType, unknown]
52
+ }
53
+
54
+ export interface ImmutableModuleSlot {
55
+ type?: number | string | bigint
56
+ installed?: {item_id: number | string | bigint; stats: number | string | bigint}
57
+ }
58
+
59
+ export function moduleSlotsForImmutable(
60
+ modules: ServerTypes.module_entry[]
61
+ ): ImmutableModuleSlot[] {
62
+ return modules.map((m) => ({
63
+ type: Number(m.type.toString()),
64
+ installed: m.installed
65
+ ? {
66
+ item_id: Number(m.installed.item_id.toString()),
67
+ stats: BigInt(m.installed.stats.toString()),
68
+ }
69
+ : undefined,
70
+ }))
71
+ }
72
+
73
+ const IMAGE_HOST_URL = 'https://item.shiploadgame.com/item'
74
+
75
+ function bytesToBase64Url(bytes: Uint8Array): string {
76
+ let binary = ''
77
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]!)
78
+ const b64 = btoa(binary)
79
+ return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
80
+ }
81
+
82
+ export function computeNftImageUrl(
83
+ item: {item_id: number; stats: bigint; modules: ImmutableModuleSlot[]; quantity: number},
84
+ originX: number,
85
+ originY: number
86
+ ): string {
87
+ const payload = ServerTypes.nft_item_payload.from({
88
+ item: {
89
+ item_id: item.item_id,
90
+ stats: String(item.stats),
91
+ modules: item.modules,
92
+ quantity: item.quantity,
93
+ },
94
+ location: {x: String(originX), y: String(originY)},
95
+ })
96
+ const bytes = Serializer.encode({object: payload}).array
97
+ return `${IMAGE_HOST_URL}/${bytesToBase64Url(bytes)}.png`
98
+ }
99
+
100
+ function commonBaseImmutable(
101
+ quantity: number,
102
+ stats: bigint,
103
+ originX: number,
104
+ originY: number,
105
+ img: string
106
+ ): ImmutableEntry[] {
107
+ return [
108
+ {first: 'quantity', second: ['uint32', quantity]},
109
+ {first: 'stats', second: ['uint64', String(stats)]},
110
+ {first: 'origin_x', second: ['int32', originX]},
111
+ {first: 'origin_y', second: ['int32', originY]},
112
+ {first: 'img', second: ['string', img]},
113
+ ]
114
+ }
115
+
116
+ export function buildResourceImmutable(
117
+ itemId: number,
118
+ quantity: number,
119
+ stats: bigint,
120
+ originX: number,
121
+ originY: number
122
+ ): ImmutableEntry[] {
123
+ const item = getItem(itemId)
124
+ const cat = item.category
125
+ if (!cat) throw new Error(`Resource item ${itemId} has no category`)
126
+ const definitions = getStatDefinitions(cat as ResourceCategory)
127
+ const img = computeNftImageUrl(
128
+ {item_id: itemId, stats, modules: [], quantity},
129
+ originX,
130
+ originY
131
+ )
132
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
133
+ base.push({first: definitions[0].key, second: ['uint16', decodeStat(stats, 0)]})
134
+ base.push({first: definitions[1].key, second: ['uint16', decodeStat(stats, 1)]})
135
+ base.push({first: definitions[2].key, second: ['uint16', decodeStat(stats, 2)]})
136
+ return base
137
+ }
138
+
139
+ export function buildComponentImmutable(
140
+ itemId: number,
141
+ quantity: number,
142
+ stats: bigint,
143
+ originX: number,
144
+ originY: number
145
+ ): ImmutableEntry[] {
146
+ const img = computeNftImageUrl(
147
+ {item_id: itemId, stats, modules: [], quantity},
148
+ originX,
149
+ originY
150
+ )
151
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
152
+ const decoded = decodeCraftedItemStats(itemId, stats)
153
+ for (const [key, value] of Object.entries(decoded)) {
154
+ base.push({first: key, second: ['uint16', value]})
155
+ }
156
+ return base
157
+ }
158
+
159
+ export function buildModuleImmutable(
160
+ itemId: number,
161
+ quantity: number,
162
+ stats: bigint,
163
+ originX: number,
164
+ originY: number
165
+ ): ImmutableEntry[] {
166
+ const img = computeNftImageUrl(
167
+ {item_id: itemId, stats, modules: [], quantity},
168
+ originX,
169
+ originY
170
+ )
171
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
172
+ const subtype = getModuleCapabilityType(itemId)
173
+ const item = getItem(itemId)
174
+ switch (subtype) {
175
+ case MODULE_ENGINE: {
176
+ const vol = decodeStat(stats, 0)
177
+ const thm = decodeStat(stats, 1)
178
+ base.push({first: 'volatility', second: ['uint16', vol]})
179
+ base.push({first: 'thermal', second: ['uint16', thm]})
180
+ base.push({first: 'thrust', second: ['uint32', computeEngineThrust(vol)]})
181
+ base.push({first: 'drain', second: ['uint16', computeEngineDrain(thm)]})
182
+ break
183
+ }
184
+ case MODULE_GENERATOR: {
185
+ const res = decodeStat(stats, 0)
186
+ const ref = decodeStat(stats, 1)
187
+ base.push({first: 'resonance', second: ['uint16', res]})
188
+ base.push({first: 'reflectivity', second: ['uint16', ref]})
189
+ base.push({first: 'capacity', second: ['uint16', computeGeneratorCap(res)]})
190
+ base.push({first: 'recharge', second: ['uint16', computeGeneratorRech(ref)]})
191
+ break
192
+ }
193
+ case MODULE_GATHERER: {
194
+ const str = decodeStat(stats, 0)
195
+ const tol = decodeStat(stats, 1)
196
+ const con = decodeStat(stats, 3)
197
+ base.push({first: 'strength', second: ['uint16', str]})
198
+ base.push({first: 'tolerance', second: ['uint16', tol]})
199
+ base.push({first: 'conductivity', second: ['uint16', con]})
200
+ base.push({first: 'yield', second: ['uint16', computeGathererYield(str)]})
201
+ base.push({first: 'drain', second: ['uint16', computeGathererDrain(con)]})
202
+ base.push({first: 'depth', second: ['uint16', computeGathererDepth(tol, item.tier)]})
203
+ break
204
+ }
205
+ case MODULE_LOADER: {
206
+ const fin = decodeStat(stats, 0)
207
+ const pla = decodeStat(stats, 1)
208
+ base.push({first: 'fineness', second: ['uint16', fin]})
209
+ base.push({first: 'plasticity', second: ['uint16', pla]})
210
+ base.push({first: 'mass', second: ['uint32', computeLoaderMass(fin)]})
211
+ base.push({first: 'thrust', second: ['uint16', computeLoaderThrust(pla)]})
212
+ break
213
+ }
214
+ case MODULE_WARP: {
215
+ const res = decodeStat(stats, 0)
216
+ base.push({first: 'resonance', second: ['uint16', res]})
217
+ base.push({first: 'range', second: ['uint32', computeWarpRange(res)]})
218
+ break
219
+ }
220
+ case MODULE_CRAFTER: {
221
+ const rea = decodeStat(stats, 0)
222
+ const com = decodeStat(stats, 1)
223
+ base.push({first: 'reactivity', second: ['uint16', rea]})
224
+ base.push({first: 'composition', second: ['uint16', com]})
225
+ base.push({first: 'speed', second: ['uint16', computeCrafterSpeed(rea)]})
226
+ base.push({first: 'drain', second: ['uint16', computeCrafterDrain(com)]})
227
+ break
228
+ }
229
+ case MODULE_STORAGE: {
230
+ const str = decodeStat(stats, 0)
231
+ const fin = decodeStat(stats, 1)
232
+ const sat = decodeStat(stats, 2)
233
+ const sum = str + fin + sat
234
+ base.push({first: 'strength', second: ['uint16', str]})
235
+ base.push({first: 'fineness', second: ['uint16', fin]})
236
+ base.push({first: 'saturation', second: ['uint16', sat]})
237
+ base.push({
238
+ first: 'capacity_bonus_pct',
239
+ second: ['uint16', 10 + Math.floor((sum * 10) / 2997)],
240
+ })
241
+ break
242
+ }
243
+ case MODULE_HAULER: {
244
+ const com = decodeStat(stats, 0)
245
+ const con = decodeStat(stats, 1)
246
+ const fin = decodeStat(stats, 2)
247
+ const res = decodeStat(stats, 3)
248
+ base.push({first: 'composition', second: ['uint16', com]})
249
+ base.push({first: 'conductivity', second: ['uint16', con]})
250
+ base.push({first: 'fineness', second: ['uint16', fin]})
251
+ base.push({first: 'resonance', second: ['uint16', res]})
252
+ base.push({first: 'capacity', second: ['uint8', computeHaulerCapacity(com)]})
253
+ base.push({first: 'efficiency', second: ['uint16', computeHaulerEfficiency(con)]})
254
+ base.push({first: 'drain', second: ['uint16', computeHaulerDrain(fin)]})
255
+ break
256
+ }
257
+ }
258
+ return base
259
+ }
260
+
261
+ export function buildEntityImmutable(
262
+ itemId: number,
263
+ quantity: number,
264
+ stats: bigint,
265
+ originX: number,
266
+ originY: number,
267
+ modules: ImmutableModuleSlot[]
268
+ ): ImmutableEntry[] {
269
+ const moduleItems: number[] = []
270
+ const moduleStats: string[] = []
271
+ for (const m of modules) {
272
+ if (m.installed) {
273
+ moduleItems.push(Number(m.installed.item_id))
274
+ moduleStats.push(String(m.installed.stats))
275
+ } else {
276
+ moduleItems.push(0)
277
+ moduleStats.push('0')
278
+ }
279
+ }
280
+ const img = computeNftImageUrl({item_id: itemId, stats, modules, quantity}, originX, originY)
281
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
282
+ base.push({first: 'module_items', second: ['UINT16_VEC', moduleItems]})
283
+ base.push({first: 'module_stats', second: ['UINT64_VEC', moduleStats]})
284
+ const description = buildEntityDescription(
285
+ itemId,
286
+ stats,
287
+ moduleItems,
288
+ moduleStats.map((s) => BigInt(s))
289
+ )
290
+ base.push({first: 'description', second: ['string', description]})
291
+ return base
292
+ }
293
+
294
+ export function buildImmutableData(
295
+ itemId: number,
296
+ quantity: number,
297
+ stats: bigint,
298
+ originX: number,
299
+ originY: number,
300
+ modules: ImmutableModuleSlot[] = []
301
+ ): ImmutableEntry[] {
302
+ const item = getItem(itemId)
303
+ if (item.type === 'resource') {
304
+ return buildResourceImmutable(itemId, quantity, stats, originX, originY)
305
+ }
306
+ if (item.type === 'component') {
307
+ return buildComponentImmutable(itemId, quantity, stats, originX, originY)
308
+ }
309
+ if (item.type === 'module') {
310
+ return buildModuleImmutable(itemId, quantity, stats, originX, originY)
311
+ }
312
+ if (item.type === 'entity') {
313
+ return buildEntityImmutable(itemId, quantity, stats, originX, originY, modules)
314
+ }
315
+ throw new Error(`Unsupported item type for wrap: ${item.type}`)
316
+ }
@@ -56,7 +56,6 @@ export const computeGathererDrain = (con: number): number =>
56
56
  Math.max(250, 1250 - idiv(con * 25, 20))
57
57
  export const computeGathererDepth = (tol: number, tier: number): number =>
58
58
  gathererDepthForTier(tol, tier)
59
- export const computeGathererSpeed = (ref: number): number => 100 + idiv(ref * 4, 5)
60
59
  export const computeLoaderMass = (ins: number): number => Math.max(200, 2000 - ins * 2)
61
60
  export const computeLoaderThrust = (pla: number): number => 1 + idiv(pla, 500)
62
61
  export const computeCrafterSpeed = (rea: number): number => 100 + idiv(rea * 4, 5)
@@ -133,12 +132,11 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
133
132
  const str = decodeStat(stats, 0)
134
133
  const tol = decodeStat(stats, 1)
135
134
  const con = decodeStat(stats, 3)
136
- const ref = decodeStat(stats, 4)
137
135
  const tier = getItem(itemId).tier
138
136
  out += ` Yield ${computeGathererYield(str)} Depth ${computeGathererDepth(
139
137
  tol,
140
138
  tier
141
- )} Speed ${computeGathererSpeed(ref)} Drain ${computeGathererDrain(con)}`
139
+ )} Drain ${computeGathererDrain(con)}`
142
140
  break
143
141
  }
144
142
  case MODULE_LOADER: {
package/src/nft/index.ts CHANGED
@@ -2,3 +2,4 @@ export * from './deserializers'
2
2
  export * from './description'
3
3
  export * from './atomicdata'
4
4
  export * from './atomicassets'
5
+ export * from './buildImmutableData'
@@ -53,14 +53,13 @@ const TEMPLATES: Record<string, TemplateSpec> = {
53
53
  gatherer: {
54
54
  id: 'module.gatherer.description',
55
55
  template:
56
- 'mines resources at {yield} speed to a max depth of {depth} with {speed} gather speed while draining {drain} energy per second',
56
+ 'mines resources at {yield} yield to a max depth of {depth} while draining {drain} energy per second',
57
57
  params: [
58
58
  ['yield', 'Yield'],
59
- ['drain', 'Drain'],
60
59
  ['depth', 'Depth'],
61
- ['speed', 'Speed'],
60
+ ['drain', 'Drain'],
62
61
  ],
63
- highlightKeys: ['yield', 'depth', 'speed', 'drain'],
62
+ highlightKeys: ['yield', 'depth', 'drain'],
64
63
  },
65
64
  loader: {
66
65
  id: 'module.loader.description',
@@ -189,7 +189,6 @@ function computeCapabilityGroup(
189
189
  {label: 'Yield', value: caps.yield},
190
190
  {label: 'Drain', value: caps.drain},
191
191
  {label: 'Depth', value: caps.depth},
192
- {label: 'Speed', value: caps.speed},
193
192
  ],
194
193
  }
195
194
  }
@@ -255,7 +255,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
255
255
  applyAddCargoTask(projected, task)
256
256
  break
257
257
  case TaskType.UNLOAD:
258
- case TaskType.WRAP:
259
258
  applyRemoveCargoTask(projected, task)
260
259
  break
261
260
  case TaskType.GATHER:
@@ -268,7 +267,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
268
267
  applyDeployTask(projected, task)
269
268
  break
270
269
  case TaskType.UNDEPLOY:
271
- case TaskType.WRAP_ENTITY:
272
270
  case TaskType.DEMOLISH:
273
271
  break
274
272
  }
@@ -440,7 +438,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
440
438
  if (taskComplete) applyAddCargoTask(projected, task)
441
439
  break
442
440
  case TaskType.UNLOAD:
443
- case TaskType.WRAP:
444
441
  if (taskComplete) applyRemoveCargoTask(projected, task)
445
442
  break
446
443
  case TaskType.GATHER:
@@ -453,7 +450,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
453
450
  if (taskComplete) applyDeployTask(projected, task)
454
451
  break
455
452
  case TaskType.UNDEPLOY:
456
- case TaskType.WRAP_ENTITY:
457
453
  case TaskType.DEMOLISH:
458
454
  break
459
455
  }
@@ -34,7 +34,6 @@ export function taskCargoChanges(task: ServerContract.Types.task): TaskCargoChan
34
34
  case TaskType.GATHER:
35
35
  return task.entitytarget ? [] : items.map((i) => toChange(i, 'in'))
36
36
  case TaskType.UNLOAD:
37
- case TaskType.WRAP:
38
37
  return items.map((i) => toChange(i, 'out'))
39
38
  case TaskType.CRAFT:
40
39
  return [
package/src/shipload.ts CHANGED
@@ -9,6 +9,7 @@ import type {PlayersManager} from './managers/players'
9
9
  import type {LocationsManager} from './managers/locations'
10
10
  import type {EpochsManager} from './managers/epochs'
11
11
  import type {ActionsManager} from './managers/actions'
12
+ import type {NftManager} from './managers/nft'
12
13
  import type {SubscriptionsManager} from './subscriptions/manager'
13
14
  import type {GameState} from './entities/gamestate'
14
15
 
@@ -107,6 +108,10 @@ export class Shipload {
107
108
  return this._context.actions
108
109
  }
109
110
 
111
+ get nft(): NftManager {
112
+ return this._context.nft
113
+ }
114
+
110
115
  get subscriptions(): SubscriptionsManager {
111
116
  return this._context.subscriptions
112
117
  }
package/src/types.ts CHANGED
@@ -50,10 +50,8 @@ export enum TaskType {
50
50
  WARP = 6,
51
51
  CRAFT = 7,
52
52
  DEPLOY = 8,
53
- WRAP = 9,
54
53
  UNWRAP = 10,
55
54
  UNDEPLOY = 11,
56
- WRAP_ENTITY = 12,
57
55
  DEMOLISH = 13,
58
56
  }
59
57
 
@@ -119,6 +117,7 @@ export type ModuleType =
119
117
  | 'launcher'
120
118
  | 'storage'
121
119
  | 'hauler'
120
+ | 'battery'
122
121
 
123
122
  export const RESOURCE_TIER_ADJECTIVES: Record<number, string> = {
124
123
  1: 'Crude',