@shipload/sdk 1.0.0-next.8 → 1.0.0-next.9

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.
@@ -0,0 +1,144 @@
1
+ import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import type {CoordinatesType} from '../types'
4
+ import {Location} from './location'
5
+ import {ScheduleAccessor} from '../scheduling/accessor'
6
+ import {InventoryAccessor} from './inventory-accessor'
7
+ import type {EntityInventory} from './entity-inventory'
8
+ import type {PackedModuleInput} from './ship'
9
+ import {decodeCraftedItemStats} from '../derivation/crafting'
10
+ import {getModuleCapabilityType, MODULE_GATHERER, MODULE_GENERATOR} from '../capabilities/modules'
11
+ import {computeGathererCapabilities, computeGeneratorCapabilities} from './ship-deploy'
12
+ import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
13
+ import type {EntitySlot} from '../data/recipes-runtime'
14
+ import {getItem} from '../data/catalog'
15
+
16
+ export interface ExtractorStateInput {
17
+ id: UInt64Type
18
+ owner: string
19
+ name: string
20
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
21
+ hullmass?: number
22
+ capacity?: number
23
+ energy?: number
24
+ modules?: PackedModuleInput[]
25
+ schedule?: ServerContract.Types.schedule
26
+ cargo?: ServerContract.Types.cargo_item[]
27
+ }
28
+
29
+ export class Extractor extends ServerContract.Types.entity_info {
30
+ private _sched?: ScheduleAccessor
31
+ private _inv?: InventoryAccessor
32
+
33
+ get name(): string {
34
+ return this.entity_name
35
+ }
36
+
37
+ get entityClass(): 'building' {
38
+ return 'building'
39
+ }
40
+
41
+ get canDemolish(): boolean {
42
+ return true
43
+ }
44
+
45
+ get inv(): InventoryAccessor {
46
+ this._inv ??= new InventoryAccessor(this)
47
+ return this._inv
48
+ }
49
+
50
+ get inventory(): EntityInventory[] {
51
+ return this.inv.items
52
+ }
53
+
54
+ get sched(): ScheduleAccessor {
55
+ this._sched ??= new ScheduleAccessor(this)
56
+ return this._sched
57
+ }
58
+
59
+ get isIdle(): boolean {
60
+ return this.is_idle
61
+ }
62
+
63
+ get location(): Location {
64
+ return Location.from(this.coordinates)
65
+ }
66
+
67
+ get totalCargoMass(): UInt64 {
68
+ return this.inv.totalMass
69
+ }
70
+
71
+ get maxCapacity(): UInt64 {
72
+ return UInt64.from(this.capacity)
73
+ }
74
+
75
+ get availableCapacity(): UInt64 {
76
+ const cargo = this.totalCargoMass
77
+ return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
78
+ }
79
+
80
+ get isFull(): boolean {
81
+ return this.totalCargoMass.gte(this.maxCapacity)
82
+ }
83
+
84
+ get totalMass(): UInt64 {
85
+ const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
86
+ return hull.adding(this.totalCargoMass)
87
+ }
88
+ }
89
+
90
+ export interface ExtractorCapabilities {
91
+ generator?: {capacity: number; recharge: number}
92
+ gatherer?: {yield: number; drain: number; depth: number; speed: number}
93
+ }
94
+
95
+ export function computeExtractorCapabilities(
96
+ modules: InstalledModule[],
97
+ layout: EntitySlot[]
98
+ ): ExtractorCapabilities {
99
+ const out: ExtractorCapabilities = {}
100
+
101
+ const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
102
+ if (genModules.length > 0) {
103
+ let totalCapacity = 0
104
+ let totalRecharge = 0
105
+ for (const m of genModules) {
106
+ const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
107
+ const amp = getSlotAmp(layout, m.slotIndex)
108
+ totalCapacity += applySlotMultiplier(caps.capacity, amp)
109
+ totalRecharge += applySlotMultiplier(caps.recharge, amp)
110
+ }
111
+ out.generator = {
112
+ capacity: clampUint16(totalCapacity),
113
+ recharge: clampUint16(totalRecharge),
114
+ }
115
+ }
116
+
117
+ const gathModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER)
118
+ if (gathModules.length > 0) {
119
+ let totalYield = 0
120
+ let totalDrain = 0
121
+ let maxDepth = 0
122
+ let totalSpeed = 0
123
+ for (const m of gathModules) {
124
+ const tier = getItem(m.itemId).tier
125
+ const caps = computeGathererCapabilities(
126
+ decodeCraftedItemStats(m.itemId, m.stats),
127
+ tier
128
+ )
129
+ const amp = getSlotAmp(layout, m.slotIndex)
130
+ totalYield += applySlotMultiplier(caps.yield, amp)
131
+ totalDrain += caps.drain
132
+ if (caps.depth > maxDepth) maxDepth = caps.depth
133
+ totalSpeed += applySlotMultiplier(caps.speed, amp)
134
+ }
135
+ out.gatherer = {
136
+ yield: clampUint16(totalYield),
137
+ drain: totalDrain,
138
+ depth: maxDepth,
139
+ speed: clampUint16(totalSpeed),
140
+ }
141
+ }
142
+
143
+ return out
144
+ }
@@ -3,8 +3,13 @@ import {ServerContract} from '../contracts'
3
3
  import {type PackedModuleInput, Ship, type ShipStateInput} from './ship'
4
4
  import {computeWarehouseCapabilities, Warehouse, type WarehouseStateInput} from './warehouse'
5
5
  import {Container, type ContainerStateInput} from './container'
6
- import {ITEM_SHIP_T1_PACKED, ITEM_WAREHOUSE_T1_PACKED} from '../data/item-ids'
7
- import {getEntityLayout} from '../data/recipes-runtime'
6
+ import {Extractor, computeExtractorCapabilities, type ExtractorStateInput} from './extractor'
7
+ import {
8
+ ITEM_EXTRACTOR_T1_PACKED,
9
+ ITEM_SHIP_T1_PACKED,
10
+ ITEM_WAREHOUSE_T1_PACKED,
11
+ } from '../data/item-ids'
12
+ import {getEntityLayout, type EntitySlot} from '../data/recipes-runtime'
8
13
  import {itemMetadata} from '../data/metadata'
9
14
  import {getItem} from '../data/catalog'
10
15
  import {
@@ -14,6 +19,7 @@ import {
14
19
  moduleSlotTypeToCode,
15
20
  } from '../capabilities/modules'
16
21
  import {computeShipCapabilities, computeStorageCapabilities} from './ship-deploy'
22
+ import type {InstalledModule} from './slot-multiplier'
17
23
  import {decodeCraftedItemStats} from '../derivation/crafting'
18
24
 
19
25
  function assignModulesToSlots(
@@ -56,19 +62,22 @@ function assignModulesToSlots(
56
62
  )
57
63
  }
58
64
 
59
- function decodePackedInput(m: PackedModuleInput): {itemId: number; stats: bigint} {
60
- return {
61
- itemId: Number(UInt16.from(m.itemId).value.toString()),
62
- stats: BigInt(UInt64.from(m.stats).toString()),
63
- }
65
+ function toInstalledModules(entries: ServerContract.Types.module_entry[]): InstalledModule[] {
66
+ const installed: InstalledModule[] = []
67
+ entries.forEach((entry, slotIndex) => {
68
+ if (!entry.installed) return
69
+ installed.push({
70
+ slotIndex,
71
+ itemId: Number(UInt16.from(entry.installed.item_id).value.toString()),
72
+ stats: BigInt(UInt64.from(entry.installed.stats).toString()),
73
+ })
74
+ })
75
+ return installed
64
76
  }
65
77
 
66
- function computeStorageBonus(
67
- decoded: {itemId: number; stats: bigint}[],
68
- baseCapacity: number
69
- ): number {
78
+ function computeStorageBonus(modules: InstalledModule[], baseCapacity: number): number {
70
79
  let totalBonus = 0
71
- for (const m of decoded) {
80
+ for (const m of modules) {
72
81
  if (getModuleCapabilityType(m.itemId) !== MODULE_STORAGE) continue
73
82
  const stats = decodeCraftedItemStats(m.itemId, m.stats)
74
83
  const {capacityBonus} = computeStorageCapabilities(stats, baseCapacity)
@@ -78,15 +87,16 @@ function computeStorageBonus(
78
87
  }
79
88
 
80
89
  function deriveShipFromModules(
81
- modules: PackedModuleInput[],
90
+ moduleEntries: ServerContract.Types.module_entry[],
91
+ layout: EntitySlot[],
82
92
  baseCapacity: number
83
93
  ): {
84
94
  capabilities: ReturnType<typeof computeShipCapabilities>
85
95
  finalCapacity: number
86
96
  } {
87
- const decoded = modules.map(decodePackedInput)
88
- const capabilities = computeShipCapabilities(decoded)
89
- const totalBonus = computeStorageBonus(decoded, baseCapacity)
97
+ const installed = toInstalledModules(moduleEntries)
98
+ const capabilities = computeShipCapabilities(installed, layout)
99
+ const totalBonus = computeStorageBonus(installed, baseCapacity)
90
100
  return {capabilities, finalCapacity: baseCapacity + totalBonus}
91
101
  }
92
102
 
@@ -109,10 +119,12 @@ export function makeShip(state: ShipStateInput): Ship {
109
119
  if (state.schedule) info.schedule = state.schedule
110
120
 
111
121
  let moduleEntries: ServerContract.Types.module_entry[] = []
122
+ const shipLayout = getEntityLayout(ITEM_SHIP_T1_PACKED)?.slots ?? []
112
123
  if (state.modules && state.modules.length > 0) {
113
124
  moduleEntries = assignModulesToSlots(ITEM_SHIP_T1_PACKED, state.modules, 'Ship T1')
114
125
  const {capabilities, finalCapacity} = deriveShipFromModules(
115
- state.modules,
126
+ moduleEntries,
127
+ shipLayout,
116
128
  state.capacity ?? 0
117
129
  )
118
130
  if (capabilities.engines) info.engines = capabilities.engines
@@ -152,17 +164,18 @@ export function makeWarehouse(state: WarehouseStateInput): Warehouse {
152
164
  if (state.schedule) info.schedule = state.schedule
153
165
 
154
166
  let moduleEntries: ServerContract.Types.module_entry[] = []
167
+ const warehouseLayout = getEntityLayout(ITEM_WAREHOUSE_T1_PACKED)?.slots ?? []
155
168
  if (state.modules && state.modules.length > 0) {
156
169
  moduleEntries = assignModulesToSlots(
157
170
  ITEM_WAREHOUSE_T1_PACKED,
158
171
  state.modules,
159
172
  'Warehouse T1'
160
173
  )
161
- const decoded = state.modules.map(decodePackedInput)
162
- const capabilities = computeWarehouseCapabilities(decoded)
174
+ const installed = toInstalledModules(moduleEntries)
175
+ const capabilities = computeWarehouseCapabilities(installed, warehouseLayout)
163
176
  if (capabilities.loaders) info.loaders = capabilities.loaders
164
177
 
165
- const totalBonus = computeStorageBonus(decoded, state.capacity)
178
+ const totalBonus = computeStorageBonus(installed, state.capacity)
166
179
  info.capacity = UInt32.from(state.capacity + totalBonus)
167
180
  } else {
168
181
  moduleEntries = assignModulesToSlots(ITEM_WAREHOUSE_T1_PACKED, [], 'Warehouse T1')
@@ -174,6 +187,44 @@ export function makeWarehouse(state: WarehouseStateInput): Warehouse {
174
187
  return new Warehouse(entityInfo)
175
188
  }
176
189
 
190
+ export function makeExtractor(state: ExtractorStateInput): Extractor {
191
+ const info: Record<string, unknown> = {
192
+ type: Name.from('extractor'),
193
+ id: UInt64.from(state.id),
194
+ owner: Name.from(state.owner),
195
+ entity_name: state.name,
196
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
197
+ cargomass: UInt32.from(0),
198
+ cargo: state.cargo || [],
199
+ is_idle: !state.schedule,
200
+ current_task_elapsed: UInt32.from(0),
201
+ current_task_remaining: UInt32.from(0),
202
+ pending_tasks: [],
203
+ }
204
+ if (state.hullmass !== undefined) info.hullmass = UInt32.from(state.hullmass)
205
+ if (state.energy !== undefined) info.energy = UInt16.from(state.energy)
206
+ if (state.schedule) info.schedule = state.schedule
207
+ if (state.capacity !== undefined) info.capacity = UInt32.from(state.capacity)
208
+
209
+ const moduleEntries = assignModulesToSlots(
210
+ ITEM_EXTRACTOR_T1_PACKED,
211
+ state.modules ?? [],
212
+ 'Extractor T1'
213
+ )
214
+ if (state.modules && state.modules.length > 0) {
215
+ const layout = getEntityLayout(ITEM_EXTRACTOR_T1_PACKED)?.slots ?? []
216
+ const installed = toInstalledModules(moduleEntries)
217
+ const capabilities = computeExtractorCapabilities(installed, layout)
218
+ if (capabilities.generator) info.generator = capabilities.generator
219
+ if (capabilities.gatherer) info.gatherer = capabilities.gatherer
220
+ }
221
+
222
+ info.modules = moduleEntries
223
+
224
+ const entityInfo = ServerContract.Types.entity_info.from(info)
225
+ return new Extractor(entityInfo)
226
+ }
227
+
177
228
  export function makeContainer(state: ContainerStateInput): Container {
178
229
  const entityInfo = ServerContract.Types.entity_info.from({
179
230
  type: Name.from('container'),
@@ -9,6 +9,10 @@ import {
9
9
  MODULE_LOADER,
10
10
  } from '../capabilities/modules'
11
11
  import {getItem} from '../data/catalog'
12
+ import type {EntitySlot} from '../data/recipes-runtime'
13
+ import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
14
+
15
+ export type {InstalledModule}
12
16
 
13
17
  export function computeShipHullCapabilities(stats: Record<string, number>): {
14
18
  hullmass: number
@@ -193,7 +197,8 @@ export interface ShipCapabilities {
193
197
  }
194
198
 
195
199
  export function computeShipCapabilities(
196
- modules: {itemId: number; stats: bigint}[]
200
+ modules: InstalledModule[],
201
+ layout: EntitySlot[]
197
202
  ): ShipCapabilities {
198
203
  const ship: ShipCapabilities = {}
199
204
 
@@ -203,7 +208,7 @@ export function computeShipCapabilities(
203
208
  let totalDrain = 0
204
209
  for (const m of engineModules) {
205
210
  const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
206
- totalThrust += caps.thrust
211
+ totalThrust += applySlotMultiplier(caps.thrust, getSlotAmp(layout, m.slotIndex))
207
212
  totalDrain += caps.drain
208
213
  }
209
214
  ship.engines = {thrust: totalThrust, drain: totalDrain}
@@ -217,10 +222,14 @@ export function computeShipCapabilities(
217
222
  let totalRecharge = 0
218
223
  for (const m of generatorModules) {
219
224
  const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
220
- totalCapacity += caps.capacity
221
- totalRecharge += caps.recharge
225
+ const amp = getSlotAmp(layout, m.slotIndex)
226
+ totalCapacity += applySlotMultiplier(caps.capacity, amp)
227
+ totalRecharge += applySlotMultiplier(caps.recharge, amp)
228
+ }
229
+ ship.generator = {
230
+ capacity: clampUint16(totalCapacity),
231
+ recharge: clampUint16(totalRecharge),
222
232
  }
223
- ship.generator = {capacity: totalCapacity, recharge: totalRecharge}
224
233
  }
225
234
 
226
235
  const gathererModules = modules.filter(
@@ -237,12 +246,18 @@ export function computeShipCapabilities(
237
246
  decodeCraftedItemStats(m.itemId, m.stats),
238
247
  tier
239
248
  )
240
- totalYield += caps.yield
249
+ const amp = getSlotAmp(layout, m.slotIndex)
250
+ totalYield += applySlotMultiplier(caps.yield, amp)
241
251
  totalDrain += caps.drain
242
252
  if (caps.depth > maxDepth) maxDepth = caps.depth
243
- totalSpeed += caps.speed
253
+ totalSpeed += applySlotMultiplier(caps.speed, amp)
254
+ }
255
+ ship.gatherer = {
256
+ yield: clampUint16(totalYield),
257
+ drain: totalDrain,
258
+ depth: maxDepth,
259
+ speed: clampUint16(totalSpeed),
244
260
  }
245
- ship.gatherer = {yield: totalYield, drain: totalDrain, depth: maxDepth, speed: totalSpeed}
246
261
  }
247
262
 
248
263
  const haulerModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_HAULER)
@@ -252,13 +267,15 @@ export function computeShipCapabilities(
252
267
  let totalDrain = 0
253
268
  for (const m of haulerModules) {
254
269
  const caps = computeHaulerCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
270
+ const eff = applySlotMultiplier(caps.efficiency, getSlotAmp(layout, m.slotIndex))
255
271
  totalCapacity += caps.capacity
256
- weightedEffNum += caps.efficiency * caps.capacity
272
+ weightedEffNum += eff * caps.capacity
257
273
  totalDrain += caps.drain
258
274
  }
275
+ const efficiency = totalCapacity > 0 ? Math.floor(weightedEffNum / totalCapacity) : 0
259
276
  ship.hauler = {
260
277
  capacity: totalCapacity,
261
- efficiency: totalCapacity > 0 ? Math.floor(weightedEffNum / totalCapacity) : 0,
278
+ efficiency: clampUint16(efficiency),
262
279
  drain: totalDrain,
263
280
  }
264
281
  }
@@ -271,10 +288,14 @@ export function computeShipCapabilities(
271
288
  for (const m of loaderModules) {
272
289
  const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
273
290
  totalMass += caps.mass
274
- totalThrust += caps.thrust
291
+ totalThrust += applySlotMultiplier(caps.thrust, getSlotAmp(layout, m.slotIndex))
275
292
  totalQuantity += caps.quantity
276
293
  }
277
- ship.loaders = {mass: totalMass, thrust: totalThrust, quantity: totalQuantity}
294
+ ship.loaders = {
295
+ mass: totalMass,
296
+ thrust: clampUint16(totalThrust),
297
+ quantity: totalQuantity,
298
+ }
278
299
  }
279
300
 
280
301
  const crafterModules = modules.filter(
@@ -285,10 +306,10 @@ export function computeShipCapabilities(
285
306
  let totalDrain = 0
286
307
  for (const m of crafterModules) {
287
308
  const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
288
- totalSpeed += caps.speed
309
+ totalSpeed += applySlotMultiplier(caps.speed, getSlotAmp(layout, m.slotIndex))
289
310
  totalDrain += caps.drain
290
311
  }
291
- ship.crafter = {speed: totalSpeed, drain: totalDrain}
312
+ ship.crafter = {speed: clampUint16(totalSpeed), drain: totalDrain}
292
313
  }
293
314
 
294
315
  return ship
@@ -0,0 +1,21 @@
1
+ import type {EntitySlot} from '../data/recipes-runtime'
2
+
3
+ export const U16_MAX = 65535
4
+
5
+ export interface InstalledModule {
6
+ slotIndex: number
7
+ itemId: number
8
+ stats: bigint
9
+ }
10
+
11
+ export function clampUint16(value: number): number {
12
+ return Math.min(value, U16_MAX)
13
+ }
14
+
15
+ export function applySlotMultiplier(value: number, outputPct: number): number {
16
+ return clampUint16(Math.floor((value * outputPct) / 100))
17
+ }
18
+
19
+ export function getSlotAmp(layout: EntitySlot[], slotIndex: number): number {
20
+ return layout[slotIndex]?.outputPct ?? 100
21
+ }
@@ -10,6 +10,8 @@ import type {PackedModuleInput} from './ship'
10
10
  import {decodeCraftedItemStats} from '../derivation/crafting'
11
11
  import {getModuleCapabilityType, MODULE_LOADER} from '../capabilities/modules'
12
12
  import {computeLoaderCapabilities} from './ship-deploy'
13
+ import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
14
+ import type {EntitySlot} from '../data/recipes-runtime'
13
15
 
14
16
  export interface WarehouseStateInput {
15
17
  id: UInt64Type
@@ -104,7 +106,10 @@ export class Warehouse extends ServerContract.Types.entity_info {
104
106
  }
105
107
  }
106
108
 
107
- export function computeWarehouseCapabilities(modules: {itemId: number; stats: bigint}[]): {
109
+ export function computeWarehouseCapabilities(
110
+ modules: InstalledModule[],
111
+ layout: EntitySlot[]
112
+ ): {
108
113
  loaders?: {mass: number; thrust: number; quantity: number}
109
114
  } {
110
115
  const warehouse: {loaders?: {mass: number; thrust: number; quantity: number}} = {}
@@ -117,10 +122,14 @@ export function computeWarehouseCapabilities(modules: {itemId: number; stats: bi
117
122
  for (const m of loaderModules) {
118
123
  const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
119
124
  totalMass += caps.mass
120
- totalThrust += caps.thrust
125
+ totalThrust += applySlotMultiplier(caps.thrust, getSlotAmp(layout, m.slotIndex))
121
126
  totalQuantity += caps.quantity
122
127
  }
123
- warehouse.loaders = {mass: totalMass, thrust: totalThrust, quantity: totalQuantity}
128
+ warehouse.loaders = {
129
+ mass: totalMass,
130
+ thrust: clampUint16(totalThrust),
131
+ quantity: totalQuantity,
132
+ }
124
133
  }
125
134
 
126
135
  return warehouse
@@ -16,9 +16,11 @@ export {Ship} from './entities/ship'
16
16
  export type {ShipStateInput, PackedModuleInput} from './entities/ship'
17
17
  export {Warehouse, computeWarehouseCapabilities} from './entities/warehouse'
18
18
  export type {WarehouseStateInput} from './entities/warehouse'
19
+ export {Extractor, computeExtractorCapabilities} from './entities/extractor'
20
+ export type {ExtractorStateInput, ExtractorCapabilities} from './entities/extractor'
19
21
  export {Container} from './entities/container'
20
22
  export type {ContainerStateInput} from './entities/container'
21
- export {makeShip, makeWarehouse, makeContainer} from './entities/makers'
23
+ export {makeShip, makeWarehouse, makeExtractor, makeContainer} from './entities/makers'
22
24
 
23
25
  export type movement_stats = ServerContract.Types.movement_stats
24
26
  export type energy_stats = ServerContract.Types.energy_stats
@@ -180,16 +182,29 @@ export type {
180
182
  ProjectionOptions,
181
183
  } from './scheduling/projection'
182
184
 
183
- export {predictTaskCargoEffects} from './scheduling/predict-cargo'
184
- export type {
185
- PredictedCargoAddition,
186
- PredictedCargoTarget,
187
- TaskCargoEffect,
188
- } from './scheduling/predict-cargo'
185
+ export {taskCargoChanges} from './scheduling/task-cargo'
186
+ export type {TaskCargoChange, TaskCargoDirection} from './scheduling/task-cargo'
189
187
 
190
188
  export * from './types/capabilities'
191
189
  export * from './types/entity'
192
- export {EntityClass, getEntityClass, getPackedEntityType} from './types/entity-traits'
190
+ export {
191
+ EntityClass,
192
+ ENTITY_SHIP,
193
+ ENTITY_WAREHOUSE,
194
+ ENTITY_EXTRACTOR,
195
+ ENTITY_CONTAINER,
196
+ shipTraits,
197
+ warehouseTraits,
198
+ extractorTraits,
199
+ containerTraits,
200
+ getEntityClass,
201
+ getPackedEntityType,
202
+ getEntityTraits,
203
+ isShip,
204
+ isWarehouse,
205
+ isExtractor,
206
+ isContainer,
207
+ } from './types/entity-traits'
193
208
  export * from './capabilities'
194
209
 
195
210
  export {
@@ -323,6 +338,8 @@ export {
323
338
  computeLoaderThrust,
324
339
  computeCrafterSpeed,
325
340
  computeCrafterDrain,
341
+ computeHaulerCapacity,
342
+ computeHaulerEfficiency,
326
343
  computeWarpRange,
327
344
  } from './nft/description'
328
345
 
@@ -85,6 +85,13 @@ export class ActionsManager extends BaseManager {
85
85
  })
86
86
  }
87
87
 
88
+ refrshentity(entityType: NameType, entityId: UInt64Type): Action {
89
+ return this.server.action('refrshentity', {
90
+ entity_type: Name.from(entityType),
91
+ entity_id: UInt64.from(entityId),
92
+ })
93
+ }
94
+
88
95
  transfer(
89
96
  sourceType: EntityTypeName,
90
97
  sourceId: UInt64Type,
@@ -14,6 +14,7 @@ import {
14
14
  ITEM_CONTAINER_T2_PACKED,
15
15
  ITEM_CRAFTER_T1,
16
16
  ITEM_ENGINE_T1,
17
+ ITEM_EXTRACTOR_T1_PACKED,
17
18
  ITEM_GATHERER_T1,
18
19
  ITEM_GENERATOR_T1,
19
20
  ITEM_HAULER_T1,
@@ -71,6 +72,8 @@ export function entityDisplayName(itemId: number): string {
71
72
  return 'Ship'
72
73
  case ITEM_WAREHOUSE_T1_PACKED:
73
74
  return 'Warehouse'
75
+ case ITEM_EXTRACTOR_T1_PACKED:
76
+ return 'Extractor'
74
77
  case ITEM_CONTAINER_T1_PACKED:
75
78
  return 'Container'
76
79
  case ITEM_CONTAINER_T2_PACKED:
@@ -187,6 +190,8 @@ export function buildEntityDescription(
187
190
  baseCapacity = computeBaseCapacityShip(hullStats)
188
191
  } else if (itemId === ITEM_WAREHOUSE_T1_PACKED) {
189
192
  baseCapacity = computeBaseCapacityWarehouse(hullStats)
193
+ } else if (itemId === ITEM_EXTRACTOR_T1_PACKED) {
194
+ baseCapacity = computeBaseCapacityShip(hullStats)
190
195
  }
191
196
 
192
197
  let out = entityDisplayName(itemId)
@@ -39,6 +39,7 @@ import type {ServerContract} from '../contracts'
39
39
  import {
40
40
  ITEM_CONTAINER_T1_PACKED,
41
41
  ITEM_CONTAINER_T2_PACKED,
42
+ ITEM_EXTRACTOR_T1_PACKED,
42
43
  ITEM_SHIP_T1_PACKED,
43
44
  ITEM_WAREHOUSE_T1_PACKED,
44
45
  } from '../data/item-ids'
@@ -270,6 +271,8 @@ function hullCapsForEntity(
270
271
  return computeShipHullCapabilities(decoded)
271
272
  case ITEM_WAREHOUSE_T1_PACKED:
272
273
  return computeWarehouseHullCapabilities(decoded)
274
+ case ITEM_EXTRACTOR_T1_PACKED:
275
+ return computeShipHullCapabilities(decoded)
273
276
  case ITEM_CONTAINER_T1_PACKED:
274
277
  return computeContainerCapabilities(decoded)
275
278
  case ITEM_CONTAINER_T2_PACKED:
@@ -0,0 +1,47 @@
1
+ import type {ServerContract} from '../contracts'
2
+ import {TaskType} from '../types'
3
+
4
+ export type TaskCargoDirection = 'in' | 'out'
5
+
6
+ export interface TaskCargoChange {
7
+ direction: TaskCargoDirection
8
+ item_id: number
9
+ stats: bigint
10
+ modules: ServerContract.Types.module_entry[]
11
+ quantity: number
12
+ }
13
+
14
+ function toChange(
15
+ item: ServerContract.Types.cargo_item,
16
+ direction: TaskCargoDirection
17
+ ): TaskCargoChange {
18
+ return {
19
+ direction,
20
+ item_id: Number(item.item_id),
21
+ stats: BigInt(item.stats.toString()),
22
+ modules: item.modules ?? [],
23
+ quantity: Number(item.quantity),
24
+ }
25
+ }
26
+
27
+ export function taskCargoChanges(task: ServerContract.Types.task): TaskCargoChange[] {
28
+ const items = task.cargo ?? []
29
+ if (items.length === 0) return []
30
+ switch (Number(task.type)) {
31
+ case TaskType.LOAD:
32
+ case TaskType.UNWRAP:
33
+ return items.map((i) => toChange(i, 'in'))
34
+ case TaskType.GATHER:
35
+ return task.entitytarget ? [] : items.map((i) => toChange(i, 'in'))
36
+ case TaskType.UNLOAD:
37
+ case TaskType.WRAP:
38
+ return items.map((i) => toChange(i, 'out'))
39
+ case TaskType.CRAFT:
40
+ return [
41
+ ...items.slice(0, -1).map((i) => toChange(i, 'out')),
42
+ toChange(items[items.length - 1], 'in'),
43
+ ]
44
+ default:
45
+ return []
46
+ }
47
+ }