@shipload/sdk 1.0.0-next.6 → 1.0.0-next.60

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 (155) hide show
  1. package/lib/scan.d.ts +52 -0
  2. package/lib/scan.js +162 -0
  3. package/lib/scan.js.map +1 -0
  4. package/lib/scan.m.js +152 -0
  5. package/lib/scan.m.js.map +1 -0
  6. package/lib/shipload.d.ts +3589 -1363
  7. package/lib/shipload.js +15700 -5454
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +15423 -5402
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +1173 -0
  12. package/lib/testing.js +4947 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +4941 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.test.ts +82 -0
  18. package/src/capabilities/craftable.ts +82 -0
  19. package/src/capabilities/crafting.test.ts +35 -0
  20. package/src/capabilities/crafting.ts +34 -7
  21. package/src/capabilities/gathering.test.ts +29 -0
  22. package/src/capabilities/gathering.ts +37 -19
  23. package/src/capabilities/hauling.ts +0 -5
  24. package/src/capabilities/index.ts +0 -1
  25. package/src/capabilities/modules.ts +42 -0
  26. package/src/capabilities/movement.ts +1 -1
  27. package/src/capabilities/storage.ts +16 -1
  28. package/src/contracts/platform.ts +231 -3
  29. package/src/contracts/server.ts +1518 -501
  30. package/src/coordinates/address.ts +88 -0
  31. package/src/coordinates/constants.test.ts +15 -0
  32. package/src/coordinates/constants.ts +23 -0
  33. package/src/coordinates/index.ts +15 -0
  34. package/src/coordinates/memo.test.ts +47 -0
  35. package/src/coordinates/memo.ts +20 -0
  36. package/src/coordinates/permutation.ts +77 -0
  37. package/src/coordinates/regions.ts +48 -0
  38. package/src/coordinates/sectors.ts +115 -0
  39. package/src/data/capabilities.ts +49 -18
  40. package/src/data/capability-formulas.ts +26 -14
  41. package/src/data/catalog.ts +0 -5
  42. package/src/data/colors.ts +13 -47
  43. package/src/data/entities.json +379 -14
  44. package/src/data/item-ids.ts +48 -12
  45. package/src/data/items.json +301 -74
  46. package/src/data/kind-registry.json +195 -0
  47. package/src/data/kind-registry.ts +182 -0
  48. package/src/data/metadata.ts +277 -48
  49. package/src/data/recipes-runtime.ts +6 -23
  50. package/src/data/recipes.json +2074 -173
  51. package/src/derivation/build-methods.test.ts +13 -0
  52. package/src/derivation/build-methods.ts +48 -0
  53. package/src/derivation/capabilities.test.ts +348 -0
  54. package/src/derivation/capabilities.ts +692 -0
  55. package/src/derivation/capability-mappings.ts +60 -16
  56. package/src/derivation/crafting.test.ts +17 -0
  57. package/src/derivation/crafting.ts +56 -33
  58. package/src/derivation/index.ts +27 -2
  59. package/src/derivation/recipe-usage.test.ts +88 -0
  60. package/src/derivation/recipe-usage.ts +141 -0
  61. package/src/derivation/reserve-regen.ts +34 -0
  62. package/src/derivation/resources.ts +9 -1
  63. package/src/derivation/rollups.test.ts +55 -0
  64. package/src/derivation/rollups.ts +72 -0
  65. package/src/derivation/stars.test.ts +67 -0
  66. package/src/derivation/stars.ts +25 -0
  67. package/src/derivation/stat-scaling.ts +12 -0
  68. package/src/derivation/stats.ts +6 -6
  69. package/src/derivation/stratum.ts +26 -22
  70. package/src/derivation/tiers.ts +40 -7
  71. package/src/derivation/upgrades.ts +14 -0
  72. package/src/derivation/wormhole.ts +154 -0
  73. package/src/entities/entity.ts +102 -0
  74. package/src/entities/gamestate.ts +3 -28
  75. package/src/entities/makers.ts +141 -135
  76. package/src/entities/slot-multiplier.ts +43 -0
  77. package/src/errors.ts +12 -16
  78. package/src/format.ts +26 -4
  79. package/src/index-module.ts +333 -35
  80. package/src/managers/actions.ts +668 -103
  81. package/src/managers/base.ts +6 -2
  82. package/src/managers/cluster.test.ts +39 -0
  83. package/src/managers/cluster.ts +53 -0
  84. package/src/managers/construction-types.ts +80 -0
  85. package/src/managers/construction.ts +443 -0
  86. package/src/managers/context.ts +29 -1
  87. package/src/managers/coordinates.ts +14 -0
  88. package/src/managers/entities.ts +27 -66
  89. package/src/managers/epochs.ts +40 -0
  90. package/src/managers/index.ts +20 -1
  91. package/src/managers/locations.ts +25 -29
  92. package/src/managers/nft.test.ts +14 -0
  93. package/src/managers/nft.ts +70 -0
  94. package/src/managers/players.ts +25 -0
  95. package/src/managers/plot.ts +122 -0
  96. package/src/nft/atomicassets.abi.json +1342 -0
  97. package/src/nft/atomicassets.ts +237 -0
  98. package/src/nft/atomicdata.ts +130 -0
  99. package/src/nft/buildImmutableData.ts +385 -0
  100. package/src/nft/description.ts +225 -52
  101. package/src/nft/index.ts +3 -0
  102. package/src/planner/index.ts +242 -0
  103. package/src/planner/planner.test.ts +334 -0
  104. package/src/resolution/describe-module.ts +43 -25
  105. package/src/resolution/display-name.ts +38 -10
  106. package/src/resolution/resolve-item.test.ts +48 -0
  107. package/src/resolution/resolve-item.ts +112 -58
  108. package/src/scan/index.ts +244 -0
  109. package/src/scan/scan-wasm.base64.ts +2 -0
  110. package/src/scheduling/accessor.ts +65 -23
  111. package/src/scheduling/availability.test.ts +204 -0
  112. package/src/scheduling/availability.ts +211 -0
  113. package/src/scheduling/cancel.test.ts +542 -0
  114. package/src/scheduling/cancel.ts +254 -0
  115. package/src/scheduling/cluster-stock.test.ts +31 -0
  116. package/src/scheduling/cluster-stock.ts +15 -0
  117. package/src/scheduling/energy.ts +47 -0
  118. package/src/scheduling/idle-resolve.ts +45 -0
  119. package/src/scheduling/jobs.ts +71 -0
  120. package/src/scheduling/lane-core.ts +128 -0
  121. package/src/scheduling/lanes.test.ts +250 -0
  122. package/src/scheduling/lanes.ts +227 -0
  123. package/src/scheduling/projection.ts +257 -133
  124. package/src/scheduling/schedule.test.ts +119 -0
  125. package/src/scheduling/schedule.ts +257 -117
  126. package/src/scheduling/task-cargo.test.ts +44 -0
  127. package/src/scheduling/task-cargo.ts +46 -0
  128. package/src/scheduling/unwrap.test.ts +86 -0
  129. package/src/scheduling/unwrap.ts +190 -0
  130. package/src/shipload.ts +26 -1
  131. package/src/subscriptions/manager.cluster.test.ts +51 -0
  132. package/src/subscriptions/manager.ts +245 -172
  133. package/src/subscriptions/mappers.ts +5 -8
  134. package/src/subscriptions/types.ts +28 -3
  135. package/src/testing/catalog-hash.ts +19 -0
  136. package/src/testing/index.ts +2 -0
  137. package/src/testing/projection-parity.ts +167 -0
  138. package/src/travel/reach.ts +21 -0
  139. package/src/travel/route-planner.ts +288 -0
  140. package/src/travel/route-simulator.ts +170 -0
  141. package/src/travel/travel.ts +188 -122
  142. package/src/types/capabilities.ts +37 -8
  143. package/src/types/entity.ts +3 -3
  144. package/src/types/index.ts +0 -1
  145. package/src/types.ts +51 -16
  146. package/src/utils/cargo.test.ts +14 -0
  147. package/src/utils/cargo.ts +29 -0
  148. package/src/utils/display-name.ts +70 -0
  149. package/src/utils/system.ts +15 -16
  150. package/src/capabilities/loading.ts +0 -8
  151. package/src/entities/container.ts +0 -123
  152. package/src/entities/ship-deploy.ts +0 -295
  153. package/src/entities/ship.ts +0 -221
  154. package/src/entities/warehouse.ts +0 -127
  155. package/src/types/entity-traits.ts +0 -69
@@ -0,0 +1,385 @@
1
+ import {Serializer} from '@wharfkit/antelope'
2
+ import {getItem} from '../data/catalog'
3
+ import {
4
+ getModuleCapabilityType,
5
+ MODULE_BATTERY,
6
+ MODULE_BUILDER,
7
+ MODULE_CRAFTER,
8
+ MODULE_ENGINE,
9
+ MODULE_GATHERER,
10
+ MODULE_GENERATOR,
11
+ MODULE_HAULER,
12
+ MODULE_LOADER,
13
+ MODULE_STORAGE,
14
+ MODULE_WARP,
15
+ } from '../capabilities/modules'
16
+ import {decodeStat, decodeCraftedItemStats} from '../derivation/crafting'
17
+ import {computeGathererYield} from '../derivation/capabilities'
18
+ import {computeEffectiveModuleStat} from '../derivation/stat-scaling'
19
+ import {getStatDefinitions} from '../derivation/stats'
20
+ import type {ResourceCategory} from '../types'
21
+ import {Types as ServerTypes} from '../contracts/server'
22
+ import {
23
+ buildEntityDescription,
24
+ computeBuilderDrain,
25
+ computeBuilderSpeed,
26
+ computeCrafterDrain,
27
+ computeCrafterSpeed,
28
+ computeEngineDrain,
29
+ computeEngineThrust,
30
+ computeGathererDepth,
31
+ computeGathererDrain,
32
+ computeGeneratorCap,
33
+ computeGeneratorRech,
34
+ computeCargoBayCapacity,
35
+ computeCargoBayDrain,
36
+ computeBatteryBankCapacity,
37
+ computeHaulerCapacity,
38
+ computeHaulerDrain,
39
+ computeHaulerEfficiency,
40
+ computeLoaderMass,
41
+ computeLoaderThrust,
42
+ computeWarpRange,
43
+ } from './description'
44
+
45
+ export type AtomicAttributeType =
46
+ | 'string'
47
+ | 'uint8'
48
+ | 'uint16'
49
+ | 'uint32'
50
+ | 'uint64'
51
+ | 'int32'
52
+ | 'image'
53
+ | 'ipfs'
54
+ | 'UINT16_VEC'
55
+ | 'UINT64_VEC'
56
+
57
+ export interface ImmutableEntry {
58
+ first: string
59
+ second: [AtomicAttributeType, unknown]
60
+ }
61
+
62
+ export interface ImmutableModuleSlot {
63
+ type?: number | string | bigint
64
+ installed?: {item_id: number | string | bigint; stats: number | string | bigint}
65
+ }
66
+
67
+ export function moduleSlotsForImmutable(
68
+ modules: ServerTypes.module_entry[]
69
+ ): ImmutableModuleSlot[] {
70
+ return modules.map((m) => ({
71
+ type: Number(m.type.toString()),
72
+ installed: m.installed
73
+ ? {
74
+ item_id: Number(m.installed.item_id.toString()),
75
+ stats: BigInt(m.installed.stats.toString()),
76
+ }
77
+ : undefined,
78
+ }))
79
+ }
80
+
81
+ const IMAGE_HOST_URL = 'https://item.shiploadgame.com/item'
82
+
83
+ function toWholeEnergy(milli: number): number {
84
+ return Math.floor((milli + 500) / 1000)
85
+ }
86
+
87
+ function bytesToBase64Url(bytes: Uint8Array): string {
88
+ let binary = ''
89
+ for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]!)
90
+ const b64 = btoa(binary)
91
+ return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
92
+ }
93
+
94
+ export function computeNftImageUrl(
95
+ item: {item_id: number; stats: bigint; modules: ImmutableModuleSlot[]; quantity: number},
96
+ originX: number,
97
+ originY: number
98
+ ): string {
99
+ const payload = ServerTypes.nft_item_payload.from({
100
+ item: {
101
+ item_id: item.item_id,
102
+ stats: String(item.stats),
103
+ modules: item.modules,
104
+ quantity: item.quantity,
105
+ },
106
+ location: {x: String(originX), y: String(originY)},
107
+ })
108
+ const bytes = Serializer.encode({object: payload}).array
109
+ return `${IMAGE_HOST_URL}/${bytesToBase64Url(bytes)}.png`
110
+ }
111
+
112
+ function commonBaseImmutable(
113
+ quantity: number,
114
+ stats: bigint,
115
+ originX: number,
116
+ originY: number,
117
+ img: string
118
+ ): ImmutableEntry[] {
119
+ return [
120
+ {first: 'quantity', second: ['uint32', quantity]},
121
+ {first: 'stats', second: ['uint64', String(stats)]},
122
+ {first: 'origin_x', second: ['int32', originX]},
123
+ {first: 'origin_y', second: ['int32', originY]},
124
+ {first: 'img', second: ['string', img]},
125
+ {first: 'deposit_amount', second: ['uint64', '0']},
126
+ {first: 'deposit_token', second: ['uint64', '0']},
127
+ {first: 'deposit_symbol', second: ['uint64', '0']},
128
+ ]
129
+ }
130
+
131
+ export function buildResourceImmutable(
132
+ itemId: number,
133
+ quantity: number,
134
+ stats: bigint,
135
+ originX: number,
136
+ originY: number
137
+ ): ImmutableEntry[] {
138
+ const item = getItem(itemId)
139
+ const cat = item.category
140
+ if (!cat) throw new Error(`Resource item ${itemId} has no category`)
141
+ const definitions = getStatDefinitions(cat as ResourceCategory)
142
+ const img = computeNftImageUrl(
143
+ {item_id: itemId, stats, modules: [], quantity},
144
+ originX,
145
+ originY
146
+ )
147
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
148
+ base.push({first: definitions[0].key, second: ['uint16', decodeStat(stats, 0)]})
149
+ base.push({first: definitions[1].key, second: ['uint16', decodeStat(stats, 1)]})
150
+ base.push({first: definitions[2].key, second: ['uint16', decodeStat(stats, 2)]})
151
+ return base
152
+ }
153
+
154
+ export function buildComponentImmutable(
155
+ itemId: number,
156
+ quantity: number,
157
+ stats: bigint,
158
+ originX: number,
159
+ originY: number
160
+ ): ImmutableEntry[] {
161
+ const img = computeNftImageUrl(
162
+ {item_id: itemId, stats, modules: [], quantity},
163
+ originX,
164
+ originY
165
+ )
166
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
167
+ const decoded = decodeCraftedItemStats(itemId, stats)
168
+ for (const [key, value] of Object.entries(decoded)) {
169
+ base.push({first: key, second: ['uint16', value]})
170
+ }
171
+ return base
172
+ }
173
+
174
+ export function buildModuleImmutable(
175
+ itemId: number,
176
+ quantity: number,
177
+ stats: bigint,
178
+ originX: number,
179
+ originY: number
180
+ ): ImmutableEntry[] {
181
+ const img = computeNftImageUrl(
182
+ {item_id: itemId, stats, modules: [], quantity},
183
+ originX,
184
+ originY
185
+ )
186
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
187
+ const subtype = getModuleCapabilityType(itemId)
188
+ const item = getItem(itemId)
189
+ switch (subtype) {
190
+ case MODULE_ENGINE: {
191
+ const vol = decodeStat(stats, 0)
192
+ const thm = decodeStat(stats, 1)
193
+ base.push({first: 'volatility', second: ['uint16', vol]})
194
+ base.push({first: 'thermal', second: ['uint16', thm]})
195
+ base.push({
196
+ first: 'thrust',
197
+ second: ['uint32', computeEngineThrust(computeEffectiveModuleStat(vol), item.tier)],
198
+ })
199
+ base.push({
200
+ first: 'drain',
201
+ second: ['uint16', computeEngineDrain(computeEffectiveModuleStat(thm))],
202
+ })
203
+ break
204
+ }
205
+ case MODULE_GENERATOR: {
206
+ const res = decodeStat(stats, 0)
207
+ const ref = decodeStat(stats, 1)
208
+ base.push({first: 'resonance', second: ['uint16', res]})
209
+ base.push({first: 'reflectivity', second: ['uint16', ref]})
210
+ base.push({
211
+ first: 'capacity',
212
+ second: [
213
+ 'uint16',
214
+ toWholeEnergy(computeGeneratorCap(computeEffectiveModuleStat(res), item.tier)),
215
+ ],
216
+ })
217
+ base.push({
218
+ first: 'recharge',
219
+ second: [
220
+ 'uint16',
221
+ toWholeEnergy(computeGeneratorRech(computeEffectiveModuleStat(ref), item.tier)),
222
+ ],
223
+ })
224
+ break
225
+ }
226
+ case MODULE_GATHERER: {
227
+ const str = decodeStat(stats, 0)
228
+ const hrd = decodeStat(stats, 1)
229
+ const sat = decodeStat(stats, 2)
230
+ base.push({first: 'strength', second: ['uint16', str]})
231
+ base.push({first: 'hardness', second: ['uint16', hrd]})
232
+ base.push({first: 'saturation', second: ['uint16', sat]})
233
+ base.push({
234
+ first: 'yield',
235
+ second: ['uint16', computeGathererYield(str, item.tier)],
236
+ })
237
+ base.push({
238
+ first: 'drain',
239
+ second: ['uint16', toWholeEnergy(computeGathererDrain(sat))],
240
+ })
241
+ base.push({first: 'depth', second: ['uint16', computeGathererDepth(hrd, item.tier)]})
242
+ break
243
+ }
244
+ case MODULE_LOADER: {
245
+ const fin = decodeStat(stats, 0)
246
+ const pla = decodeStat(stats, 1)
247
+ base.push({first: 'fineness', second: ['uint16', fin]})
248
+ base.push({first: 'plasticity', second: ['uint16', pla]})
249
+ base.push({first: 'mass', second: ['uint32', computeLoaderMass(fin)]})
250
+ base.push({first: 'thrust', second: ['uint16', computeLoaderThrust(pla, item.tier)]})
251
+ break
252
+ }
253
+ case MODULE_WARP: {
254
+ const ref = decodeStat(stats, 0)
255
+ base.push({first: 'reflectivity', second: ['uint16', ref]})
256
+ base.push({first: 'range', second: ['uint32', computeWarpRange(ref, item.tier)]})
257
+ break
258
+ }
259
+ case MODULE_CRAFTER: {
260
+ const fin = decodeStat(stats, 0)
261
+ const con = decodeStat(stats, 1)
262
+ base.push({first: 'fineness', second: ['uint16', fin]})
263
+ base.push({first: 'conductivity', second: ['uint16', con]})
264
+ base.push({first: 'speed', second: ['uint16', computeCrafterSpeed(fin, item.tier)]})
265
+ base.push({first: 'drain', second: ['uint16', toWholeEnergy(computeCrafterDrain(con))]})
266
+ break
267
+ }
268
+ case MODULE_BUILDER: {
269
+ const res = decodeStat(stats, 0)
270
+ const fin = decodeStat(stats, 1)
271
+ base.push({first: 'resonance', second: ['uint16', res]})
272
+ base.push({first: 'fineness', second: ['uint16', fin]})
273
+ base.push({first: 'speed', second: ['uint16', computeBuilderSpeed(res, item.tier)]})
274
+ base.push({first: 'drain', second: ['uint16', toWholeEnergy(computeBuilderDrain(fin))]})
275
+ break
276
+ }
277
+ case MODULE_STORAGE: {
278
+ const str = decodeStat(stats, 0)
279
+ const den = decodeStat(stats, 1)
280
+ const hrd = decodeStat(stats, 2)
281
+ const com = decodeStat(stats, 3)
282
+ base.push({first: 'strength', second: ['uint16', str]})
283
+ base.push({first: 'density', second: ['uint16', den]})
284
+ base.push({first: 'hardness', second: ['uint16', hrd]})
285
+ base.push({first: 'cohesion', second: ['uint16', com]})
286
+ base.push({
287
+ first: 'capacity',
288
+ second: ['uint32', computeCargoBayCapacity(str, den, hrd)],
289
+ })
290
+ base.push({
291
+ first: 'drain',
292
+ second: ['uint16', toWholeEnergy(computeCargoBayDrain(com, item.tier))],
293
+ })
294
+ break
295
+ }
296
+ case MODULE_BATTERY: {
297
+ const vol = decodeStat(stats, 0)
298
+ const thm = decodeStat(stats, 1)
299
+ const pla = decodeStat(stats, 2)
300
+ const ins = decodeStat(stats, 3)
301
+ base.push({first: 'volatility', second: ['uint16', vol]})
302
+ base.push({first: 'thermal', second: ['uint16', thm]})
303
+ base.push({first: 'plasticity', second: ['uint16', pla]})
304
+ base.push({first: 'insulation', second: ['uint16', ins]})
305
+ base.push({
306
+ first: 'capacity',
307
+ second: ['uint32', toWholeEnergy(computeBatteryBankCapacity(vol, thm, pla, ins))],
308
+ })
309
+ break
310
+ }
311
+ case MODULE_HAULER: {
312
+ const res = decodeStat(stats, 0)
313
+ const pla = decodeStat(stats, 1)
314
+ const con = decodeStat(stats, 2)
315
+ base.push({first: 'resonance', second: ['uint16', res]})
316
+ base.push({first: 'plasticity', second: ['uint16', pla]})
317
+ base.push({first: 'conductivity', second: ['uint16', con]})
318
+ base.push({first: 'capacity', second: ['uint8', computeHaulerCapacity(res, item.tier)]})
319
+ base.push({first: 'efficiency', second: ['uint16', computeHaulerEfficiency(pla)]})
320
+ base.push({
321
+ first: 'drain',
322
+ second: ['uint16', toWholeEnergy(computeHaulerDrain(con, item.tier))],
323
+ })
324
+ break
325
+ }
326
+ }
327
+ return base
328
+ }
329
+
330
+ export function buildEntityImmutable(
331
+ itemId: number,
332
+ quantity: number,
333
+ stats: bigint,
334
+ originX: number,
335
+ originY: number,
336
+ modules: ImmutableModuleSlot[]
337
+ ): ImmutableEntry[] {
338
+ const moduleItems: number[] = []
339
+ const moduleStats: string[] = []
340
+ for (const m of modules) {
341
+ if (m.installed) {
342
+ moduleItems.push(Number(m.installed.item_id))
343
+ moduleStats.push(String(m.installed.stats))
344
+ } else {
345
+ moduleItems.push(0)
346
+ moduleStats.push('0')
347
+ }
348
+ }
349
+ const img = computeNftImageUrl({item_id: itemId, stats, modules, quantity}, originX, originY)
350
+ const base = commonBaseImmutable(quantity, stats, originX, originY, img)
351
+ base.push({first: 'module_items', second: ['UINT16_VEC', moduleItems]})
352
+ base.push({first: 'module_stats', second: ['UINT64_VEC', moduleStats]})
353
+ const description = buildEntityDescription(
354
+ itemId,
355
+ stats,
356
+ moduleItems,
357
+ moduleStats.map((s) => BigInt(s))
358
+ )
359
+ base.push({first: 'description', second: ['string', description]})
360
+ return base
361
+ }
362
+
363
+ export function buildImmutableData(
364
+ itemId: number,
365
+ quantity: number,
366
+ stats: bigint,
367
+ originX: number,
368
+ originY: number,
369
+ modules: ImmutableModuleSlot[] = []
370
+ ): ImmutableEntry[] {
371
+ const item = getItem(itemId)
372
+ if (item.type === 'resource') {
373
+ return buildResourceImmutable(itemId, quantity, stats, originX, originY)
374
+ }
375
+ if (item.type === 'component') {
376
+ return buildComponentImmutable(itemId, quantity, stats, originX, originY)
377
+ }
378
+ if (item.type === 'module') {
379
+ return buildModuleImmutable(itemId, quantity, stats, originX, originY)
380
+ }
381
+ if (item.type === 'entity') {
382
+ return buildEntityImmutable(itemId, quantity, stats, originX, originY, modules)
383
+ }
384
+ throw new Error(`Unsupported item type for wrap: ${item.type}`)
385
+ }