@shipload/sdk 1.0.0-next.10 → 1.0.0-next.11

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipload/sdk",
3
3
  "description": "SDKs for Shipload",
4
- "version": "1.0.0-next.10",
4
+ "version": "1.0.0-next.11",
5
5
  "homepage": "https://github.com/shipload/toolkit/tree/master/packages/sdk",
6
6
  "repository": {
7
7
  "type": "git",
@@ -66,6 +66,19 @@
66
66
  }
67
67
  ]
68
68
  },
69
+ {
70
+ "entityItemId": 10204,
71
+ "slots": [
72
+ {
73
+ "type": "generator",
74
+ "outputPct": 100
75
+ },
76
+ {
77
+ "type": "crafter",
78
+ "outputPct": 100
79
+ }
80
+ ]
81
+ },
69
82
  {
70
83
  "entityItemId": 20200,
71
84
  "slots": []
@@ -72,6 +72,7 @@ export const ITEM_CONTAINER_T1_PACKED = 10200
72
72
  export const ITEM_SHIP_T1_PACKED = 10201
73
73
  export const ITEM_WAREHOUSE_T1_PACKED = 10202
74
74
  export const ITEM_EXTRACTOR_T1_PACKED = 10203
75
+ export const ITEM_FACTORY_T1_PACKED = 10204
75
76
  export const ITEM_HULL_PLATES_T2 = 20001
76
77
  export const ITEM_CARGO_LINING_T2 = 20002
77
78
  export const ITEM_CONTAINER_T2_PACKED = 20200
@@ -489,6 +489,12 @@
489
489
  "type": "entity",
490
490
  "tier": 1
491
491
  },
492
+ {
493
+ "id": 10204,
494
+ "mass": 800000,
495
+ "type": "entity",
496
+ "tier": 1
497
+ },
492
498
  {
493
499
  "id": 20001,
494
500
  "mass": 50000,
@@ -229,6 +229,11 @@ export const itemMetadata: Record<number, ItemMetadata> = {
229
229
  'Planetary resource extraction facility with generator and gatherer module slots.',
230
230
  color: '#D4726F',
231
231
  },
232
+ 10204: {
233
+ name: 'Factory',
234
+ description: 'Planetary fabrication facility with generator and crafter module slots.',
235
+ color: '#7BA7D4',
236
+ },
232
237
 
233
238
  // === Components (T2) ===
234
239
  20001: {
@@ -255,6 +260,7 @@ export const entityMetadata: Record<number, EntityMetadata> = {
255
260
  10201: {moduleSlotLabels: ['Engine', 'Generator', 'Gatherer', 'Loader', 'Storage']},
256
261
  10202: {moduleSlotLabels: ['Loader', 'Storage', 'Storage', 'Storage', 'Storage']},
257
262
  10203: {moduleSlotLabels: ['Generator', 'Gatherer']},
263
+ 10204: {moduleSlotLabels: ['Generator', 'Crafter']},
258
264
  }
259
265
 
260
266
  for (const item of items as Array<{id: number}>) {
@@ -801,6 +801,63 @@
801
801
  ],
802
802
  "blendWeights": []
803
803
  },
804
+ {
805
+ "outputItemId": 10204,
806
+ "outputMass": 800000,
807
+ "inputs": [
808
+ {
809
+ "itemId": 10001,
810
+ "quantity": 15
811
+ },
812
+ {
813
+ "itemId": 10002,
814
+ "quantity": 6
815
+ },
816
+ {
817
+ "itemId": 10008,
818
+ "quantity": 4
819
+ },
820
+ {
821
+ "itemId": 10009,
822
+ "quantity": 4
823
+ }
824
+ ],
825
+ "statSlots": [
826
+ {
827
+ "sources": [
828
+ {
829
+ "inputIndex": 0,
830
+ "statIndex": 0
831
+ }
832
+ ]
833
+ },
834
+ {
835
+ "sources": [
836
+ {
837
+ "inputIndex": 0,
838
+ "statIndex": 1
839
+ }
840
+ ]
841
+ },
842
+ {
843
+ "sources": [
844
+ {
845
+ "inputIndex": 1,
846
+ "statIndex": 0
847
+ }
848
+ ]
849
+ },
850
+ {
851
+ "sources": [
852
+ {
853
+ "inputIndex": 1,
854
+ "statIndex": 1
855
+ }
856
+ ]
857
+ }
858
+ ],
859
+ "blendWeights": []
860
+ },
804
861
  {
805
862
  "outputItemId": 20001,
806
863
  "outputMass": 50000,
@@ -25,8 +25,8 @@ export class Container extends ServerContract.Types.entity_info {
25
25
  return this.entity_name
26
26
  }
27
27
 
28
- get entityClass(): 'mobile' {
29
- return 'mobile'
28
+ get entityClass(): 'orbital' {
29
+ return 'orbital'
30
30
  }
31
31
 
32
32
  get canUndeploy(): boolean {
@@ -34,8 +34,8 @@ export class Extractor extends ServerContract.Types.entity_info {
34
34
  return this.entity_name
35
35
  }
36
36
 
37
- get entityClass(): 'building' {
38
- return 'building'
37
+ get entityClass(): 'planetary' {
38
+ return 'planetary'
39
39
  }
40
40
 
41
41
  get canDemolish(): boolean {
@@ -0,0 +1,135 @@
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_CRAFTER, MODULE_GENERATOR} from '../capabilities/modules'
11
+ import {computeCrafterCapabilities, computeGeneratorCapabilities} from './ship-deploy'
12
+ import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
13
+ import type {EntitySlot} from '../data/recipes-runtime'
14
+
15
+ export interface FactoryStateInput {
16
+ id: UInt64Type
17
+ owner: string
18
+ name: string
19
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
20
+ hullmass?: number
21
+ capacity?: number
22
+ energy?: number
23
+ modules?: PackedModuleInput[]
24
+ schedule?: ServerContract.Types.schedule
25
+ cargo?: ServerContract.Types.cargo_item[]
26
+ }
27
+
28
+ export class Factory extends ServerContract.Types.entity_info {
29
+ private _sched?: ScheduleAccessor
30
+ private _inv?: InventoryAccessor
31
+
32
+ get name(): string {
33
+ return this.entity_name
34
+ }
35
+
36
+ get entityClass(): 'planetary' {
37
+ return 'planetary'
38
+ }
39
+
40
+ get canDemolish(): boolean {
41
+ return true
42
+ }
43
+
44
+ get inv(): InventoryAccessor {
45
+ this._inv ??= new InventoryAccessor(this)
46
+ return this._inv
47
+ }
48
+
49
+ get inventory(): EntityInventory[] {
50
+ return this.inv.items
51
+ }
52
+
53
+ get sched(): ScheduleAccessor {
54
+ this._sched ??= new ScheduleAccessor(this)
55
+ return this._sched
56
+ }
57
+
58
+ get isIdle(): boolean {
59
+ return this.is_idle
60
+ }
61
+
62
+ get location(): Location {
63
+ return Location.from(this.coordinates)
64
+ }
65
+
66
+ get totalCargoMass(): UInt64 {
67
+ return this.inv.totalMass
68
+ }
69
+
70
+ get maxCapacity(): UInt64 {
71
+ return UInt64.from(this.capacity)
72
+ }
73
+
74
+ get availableCapacity(): UInt64 {
75
+ const cargo = this.totalCargoMass
76
+ return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
77
+ }
78
+
79
+ get isFull(): boolean {
80
+ return this.totalCargoMass.gte(this.maxCapacity)
81
+ }
82
+
83
+ get totalMass(): UInt64 {
84
+ const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
85
+ return hull.adding(this.totalCargoMass)
86
+ }
87
+ }
88
+
89
+ export interface FactoryCapabilities {
90
+ generator?: {capacity: number; recharge: number}
91
+ crafter?: {speed: number; drain: number}
92
+ }
93
+
94
+ export function computeFactoryCapabilities(
95
+ modules: InstalledModule[],
96
+ layout: EntitySlot[]
97
+ ): FactoryCapabilities {
98
+ const out: FactoryCapabilities = {}
99
+
100
+ const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
101
+ if (genModules.length > 0) {
102
+ let totalCapacity = 0
103
+ let totalRecharge = 0
104
+ for (const m of genModules) {
105
+ const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
106
+ const amp = getSlotAmp(layout, m.slotIndex)
107
+ totalCapacity += applySlotMultiplier(caps.capacity, amp)
108
+ totalRecharge += applySlotMultiplier(caps.recharge, amp)
109
+ }
110
+ out.generator = {
111
+ capacity: clampUint16(totalCapacity),
112
+ recharge: clampUint16(totalRecharge),
113
+ }
114
+ }
115
+
116
+ const crafterModules = modules.filter(
117
+ (m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
118
+ )
119
+ if (crafterModules.length > 0) {
120
+ let totalSpeed = 0
121
+ let totalDrain = 0
122
+ for (const m of crafterModules) {
123
+ const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
124
+ const amp = getSlotAmp(layout, m.slotIndex)
125
+ totalSpeed += applySlotMultiplier(caps.speed, amp)
126
+ totalDrain += caps.drain
127
+ }
128
+ out.crafter = {
129
+ speed: clampUint16(totalSpeed),
130
+ drain: totalDrain,
131
+ }
132
+ }
133
+
134
+ return out
135
+ }
@@ -3,9 +3,12 @@ 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 {Nexus, type NexusStateInput} from './nexus'
6
7
  import {Extractor, computeExtractorCapabilities, type ExtractorStateInput} from './extractor'
8
+ import {Factory, computeFactoryCapabilities, type FactoryStateInput} from './factory'
7
9
  import {
8
10
  ITEM_EXTRACTOR_T1_PACKED,
11
+ ITEM_FACTORY_T1_PACKED,
9
12
  ITEM_SHIP_T1_PACKED,
10
13
  ITEM_WAREHOUSE_T1_PACKED,
11
14
  } from '../data/item-ids'
@@ -225,6 +228,44 @@ export function makeExtractor(state: ExtractorStateInput): Extractor {
225
228
  return new Extractor(entityInfo)
226
229
  }
227
230
 
231
+ export function makeFactory(state: FactoryStateInput): Factory {
232
+ const info: Record<string, unknown> = {
233
+ type: Name.from('factory'),
234
+ id: UInt64.from(state.id),
235
+ owner: Name.from(state.owner),
236
+ entity_name: state.name,
237
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
238
+ cargomass: UInt32.from(0),
239
+ cargo: state.cargo || [],
240
+ is_idle: !state.schedule,
241
+ current_task_elapsed: UInt32.from(0),
242
+ current_task_remaining: UInt32.from(0),
243
+ pending_tasks: [],
244
+ }
245
+ if (state.hullmass !== undefined) info.hullmass = UInt32.from(state.hullmass)
246
+ if (state.energy !== undefined) info.energy = UInt16.from(state.energy)
247
+ if (state.schedule) info.schedule = state.schedule
248
+ if (state.capacity !== undefined) info.capacity = UInt32.from(state.capacity)
249
+
250
+ const moduleEntries = assignModulesToSlots(
251
+ ITEM_FACTORY_T1_PACKED,
252
+ state.modules ?? [],
253
+ 'Factory T1'
254
+ )
255
+ if (state.modules && state.modules.length > 0) {
256
+ const layout = getEntityLayout(ITEM_FACTORY_T1_PACKED)?.slots ?? []
257
+ const installed = toInstalledModules(moduleEntries)
258
+ const capabilities = computeFactoryCapabilities(installed, layout)
259
+ if (capabilities.generator) info.generator = capabilities.generator
260
+ if (capabilities.crafter) info.crafter = capabilities.crafter
261
+ }
262
+
263
+ info.modules = moduleEntries
264
+
265
+ const entityInfo = ServerContract.Types.entity_info.from(info)
266
+ return new Factory(entityInfo)
267
+ }
268
+
228
269
  export function makeContainer(state: ContainerStateInput): Container {
229
270
  const entityInfo = ServerContract.Types.entity_info.from({
230
271
  type: Name.from('container'),
@@ -245,3 +286,21 @@ export function makeContainer(state: ContainerStateInput): Container {
245
286
  })
246
287
  return new Container(entityInfo)
247
288
  }
289
+
290
+ export function makeNexus(state: NexusStateInput): Nexus {
291
+ const entityInfo = ServerContract.Types.entity_info.from({
292
+ type: Name.from('nexus'),
293
+ id: UInt64.from(state.id),
294
+ owner: Name.from(state.owner),
295
+ entity_name: state.name,
296
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
297
+ cargomass: UInt32.from(0),
298
+ cargo: [],
299
+ modules: [],
300
+ is_idle: true,
301
+ current_task_elapsed: UInt32.from(0),
302
+ current_task_remaining: UInt32.from(0),
303
+ pending_tasks: [],
304
+ })
305
+ return new Nexus(entityInfo)
306
+ }
@@ -0,0 +1,29 @@
1
+ import type {UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import type {CoordinatesType} from '../types'
4
+ import {Location} from './location'
5
+
6
+ export interface NexusStateInput {
7
+ id: UInt64Type
8
+ owner: string
9
+ name: string
10
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
11
+ }
12
+
13
+ export class Nexus extends ServerContract.Types.entity_info {
14
+ get name(): string {
15
+ return this.entity_name
16
+ }
17
+
18
+ get entityClass(): 'orbital' {
19
+ return 'orbital'
20
+ }
21
+
22
+ get location(): Location {
23
+ return Location.from(this.coordinates)
24
+ }
25
+
26
+ get orbitalAltitude(): number {
27
+ return this.coordinates.z?.toNumber() || 0
28
+ }
29
+ }
@@ -57,8 +57,8 @@ export class Ship extends ServerContract.Types.entity_info {
57
57
  return this.entity_name
58
58
  }
59
59
 
60
- get entityClass(): 'mobile' {
61
- return 'mobile'
60
+ get entityClass(): 'orbital' {
61
+ return 'orbital'
62
62
  }
63
63
 
64
64
  get canUndeploy(): boolean {
@@ -33,8 +33,8 @@ export class Warehouse extends ServerContract.Types.entity_info {
33
33
  return this.entity_name
34
34
  }
35
35
 
36
- get entityClass(): 'building' {
37
- return 'building'
36
+ get entityClass(): 'planetary' {
37
+ return 'planetary'
38
38
  }
39
39
 
40
40
  get canDemolish(): boolean {
package/src/errors.ts CHANGED
@@ -18,18 +18,18 @@ export const PLAYER_NOT_JOINED = 'Player has not joined the game.'
18
18
  export const PLAYER_NOT_FOUND = 'Cannot find player for given account name.'
19
19
  export const STARTER_ALREADY_CLAIMED =
20
20
  'Starter ship already claimed; destroy existing ships to re-claim.'
21
- export const SHIP_ALREADY_THERE = 'Ship cannot travel to the location its already at.'
21
+ export const ENTITY_ALREADY_THERE = 'Entity cannot travel to the location it is already at.'
22
22
  export const SHIP_ALREADY_TRAVELING = 'Ship is already traveling.'
23
23
  export const SHIP_CANNOT_BUY_TRAVELING = 'Ship cannot buy goods while traveling.'
24
24
  export const SHIP_CANNOT_UPDATE_TRAVELING = 'Ship cannot be updated while traveling.'
25
- export const SHIP_INVALID_DESTINATION = 'Ship cannot travel, no system at specified destination.'
26
- export const SHIP_INVALID_TRAVEL_DURATION =
25
+ export const ENTITY_INVALID_DESTINATION = 'Cannot travel: no system at specified destination.'
26
+ export const ENTITY_INVALID_TRAVEL_DURATION =
27
27
  'This trip cannot be made as it would exceed the maximum travel duration.'
28
28
  export const SHIP_NOT_ARRIVED = 'Ship has not yet arrived at its destination.'
29
- export const SHIP_NOT_ENOUGH_ENERGY =
30
- 'Ship does not have enough energy to travel to the destination.'
31
- export const SHIP_NOT_ENOUGH_ENERGY_CAPACITY =
32
- 'Ship does not have enough energy capacity to travel.'
29
+ export const ENTITY_NOT_ENOUGH_ENERGY =
30
+ 'Entity does not have enough energy to travel to the destination.'
31
+ export const ENTITY_NOT_ENOUGH_ENERGY_CAPACITY =
32
+ 'Entity does not have enough energy capacity to travel.'
33
33
  export const SHIP_NOT_FOUND = 'Cannot find ship for given account.'
34
34
  export const SHIP_NOT_OWNED = 'Ship is not owned by this account.'
35
35
  export const NO_SCHEDULE = 'No scheduled tasks.'
@@ -38,16 +38,13 @@ export const SHIP_NO_COMPLETED_TASKS = 'No completed tasks to resolve.'
38
38
  export const RESOLVE_COUNT_EXCEEDS_COMPLETED = 'Requested resolve count exceeds completed tasks.'
39
39
  export const SHIP_CANNOT_CANCEL_TASK = 'Cannot cancel task that is immutable or in progress.'
40
40
  export const SHIP_NO_TASKS_TO_CANCEL = 'No tasks to cancel.'
41
- export const SHIP_INVALID_CARGO = 'Invalid cargo specified for load/unload.'
42
- export const SHIP_CARGO_NOT_OWNED = 'Cannot load cargo that is not owned.'
43
- export const SHIP_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.'
44
- export const SHIP_CAPACITY_EXCEEDED = 'Ship cargo capacity would be exceeded.'
41
+ export const ENTITY_INVALID_CARGO = 'Invalid cargo specified for load/unload.'
42
+ export const ENTITY_CARGO_NOT_OWNED = 'Cannot load cargo that is not owned.'
43
+ export const ENTITY_CARGO_NOT_LOADED = 'Cannot unload cargo that is not loaded.'
45
44
  export const ENTITY_CAPACITY_EXCEEDED = 'Entity cargo capacity would be exceeded.'
46
45
  export const WAREHOUSE_NOT_FOUND = 'Cannot find warehouse for given id.'
47
46
  export const WAREHOUSE_ALREADY_AT_LOCATION = 'Warehouse already exists at this location.'
48
- export const WAREHOUSE_CAPACITY_EXCEEDED = 'Warehouse capacity would be exceeded.'
49
47
  export const CONTAINER_NOT_FOUND = 'Cannot find container for given id.'
50
- export const CONTAINER_CAPACITY_EXCEEDED = 'Container capacity would be exceeded.'
51
48
  export const DESTINATION_CAPACITY_EXCEEDED =
52
49
  'Destination entity does not have enough capacity for the gather.'
53
50
  export const CANCEL_PAIRED_HAS_PENDING = 'Cannot cancel transfer, paired entity has pending tasks.'
@@ -18,9 +18,20 @@ export {Warehouse, computeWarehouseCapabilities} from './entities/warehouse'
18
18
  export type {WarehouseStateInput} from './entities/warehouse'
19
19
  export {Extractor, computeExtractorCapabilities} from './entities/extractor'
20
20
  export type {ExtractorStateInput, ExtractorCapabilities} from './entities/extractor'
21
+ export {Factory, computeFactoryCapabilities} from './entities/factory'
22
+ export type {FactoryStateInput, FactoryCapabilities} from './entities/factory'
21
23
  export {Container} from './entities/container'
22
24
  export type {ContainerStateInput} from './entities/container'
23
- export {makeShip, makeWarehouse, makeExtractor, makeContainer} from './entities/makers'
25
+ export {Nexus} from './entities/nexus'
26
+ export type {NexusStateInput} from './entities/nexus'
27
+ export {
28
+ makeShip,
29
+ makeWarehouse,
30
+ makeExtractor,
31
+ makeFactory,
32
+ makeContainer,
33
+ makeNexus,
34
+ } from './entities/makers'
24
35
 
25
36
  export type movement_stats = ServerContract.Types.movement_stats
26
37
  export type energy_stats = ServerContract.Types.energy_stats
@@ -190,10 +201,12 @@ export {
190
201
  ENTITY_SHIP,
191
202
  ENTITY_WAREHOUSE,
192
203
  ENTITY_EXTRACTOR,
204
+ ENTITY_FACTORY,
193
205
  ENTITY_CONTAINER,
194
206
  shipTraits,
195
207
  warehouseTraits,
196
208
  extractorTraits,
209
+ factoryTraits,
197
210
  containerTraits,
198
211
  getEntityClass,
199
212
  getPackedEntityType,
@@ -201,6 +214,7 @@ export {
201
214
  isShip,
202
215
  isWarehouse,
203
216
  isExtractor,
217
+ isFactory,
204
218
  isContainer,
205
219
  } from './types/entity-traits'
206
220
  export type {EntityTraits, EntityTypeName} from './types/entity-traits'
@@ -4,12 +4,16 @@ import {Ship} from '../entities/ship'
4
4
  import {Warehouse} from '../entities/warehouse'
5
5
  import {Container} from '../entities/container'
6
6
  import {Extractor} from '../entities/extractor'
7
+ import {Factory} from '../entities/factory'
8
+ import {Nexus} from '../entities/nexus'
7
9
  import type {ServerContract} from '../contracts'
8
10
 
9
- export type EntityType = 'ship' | 'warehouse' | 'extractor' | 'container'
11
+ export type EntityType = 'ship' | 'warehouse' | 'extractor' | 'factory' | 'container' | 'nexus'
10
12
 
11
13
  export class EntitiesManager extends BaseManager {
12
- async getEntity(id: UInt64Type): Promise<Ship | Warehouse | Extractor | Container> {
14
+ async getEntity(
15
+ id: UInt64Type
16
+ ): Promise<Ship | Warehouse | Extractor | Factory | Container | Nexus> {
13
17
  const result = await this.server.readonly('getentity', {
14
18
  entity_id: id,
15
19
  })
@@ -20,7 +24,7 @@ export class EntitiesManager extends BaseManager {
20
24
  async getEntities(
21
25
  owner: NameType | ServerContract.Types.player_row,
22
26
  type?: EntityType
23
- ): Promise<(Ship | Warehouse | Extractor | Container)[]> {
27
+ ): Promise<(Ship | Warehouse | Extractor | Factory | Container | Nexus)[]> {
24
28
  const ownerName = this.resolveOwner(owner)
25
29
  const result = await this.server.readonly('getentities', {
26
30
  owner: ownerName,
@@ -58,6 +62,10 @@ export class EntitiesManager extends BaseManager {
58
62
  return (await this.getEntity(id)) as Extractor
59
63
  }
60
64
 
65
+ async getFactory(id: UInt64Type): Promise<Factory> {
66
+ return (await this.getEntity(id)) as Factory
67
+ }
68
+
61
69
  async getShips(owner: NameType | ServerContract.Types.player_row): Promise<Ship[]> {
62
70
  return (await this.getEntities(owner, 'ship')) as Ship[]
63
71
  }
@@ -74,6 +82,10 @@ export class EntitiesManager extends BaseManager {
74
82
  return (await this.getEntities(owner, 'extractor')) as Extractor[]
75
83
  }
76
84
 
85
+ async getFactories(owner: NameType | ServerContract.Types.player_row): Promise<Factory[]> {
86
+ return (await this.getEntities(owner, 'factory')) as Factory[]
87
+ }
88
+
77
89
  async getShipSummaries(
78
90
  owner: NameType | ServerContract.Types.player_row
79
91
  ): Promise<ServerContract.Types.entity_summary[]> {
@@ -98,13 +110,35 @@ export class EntitiesManager extends BaseManager {
98
110
  return this.getSummaries(owner, 'extractor')
99
111
  }
100
112
 
113
+ async getFactorySummaries(
114
+ owner: NameType | ServerContract.Types.player_row
115
+ ): Promise<ServerContract.Types.entity_summary[]> {
116
+ return this.getSummaries(owner, 'factory')
117
+ }
118
+
119
+ async getNexus(id: UInt64Type): Promise<Nexus> {
120
+ return (await this.getEntity(id)) as Nexus
121
+ }
122
+
123
+ async getNexuses(owner: NameType | ServerContract.Types.player_row): Promise<Nexus[]> {
124
+ return (await this.getEntities(owner, 'nexus')) as Nexus[]
125
+ }
126
+
127
+ async getNexusSummaries(
128
+ owner: NameType | ServerContract.Types.player_row
129
+ ): Promise<ServerContract.Types.entity_summary[]> {
130
+ return this.getSummaries(owner, 'nexus')
131
+ }
132
+
101
133
  private wrapEntity(
102
134
  entity: ServerContract.Types.entity_info
103
- ): Ship | Warehouse | Extractor | Container {
135
+ ): Ship | Warehouse | Extractor | Factory | Container | Nexus {
104
136
  if (entity.type.equals('ship')) return new Ship(entity)
105
137
  if (entity.type.equals('warehouse')) return new Warehouse(entity)
106
138
  if (entity.type.equals('extractor')) return new Extractor(entity)
139
+ if (entity.type.equals('factory')) return new Factory(entity)
107
140
  if (entity.type.equals('container')) return new Container(entity)
141
+ if (entity.type.equals('nexus')) return new Nexus(entity)
108
142
  throw new Error(`unknown entity type: ${entity.type}`)
109
143
  }
110
144
 
@@ -96,6 +96,9 @@ export function deserializeAtomicData(
96
96
  case 'uint64':
97
97
  result[field.name] = readVarint64()
98
98
  break
99
+ case 'int32':
100
+ result[field.name] = readZigzagInt64()
101
+ break
99
102
  case 'int64':
100
103
  result[field.name] = readZigzagInt64()
101
104
  break
@@ -14,7 +14,7 @@ import {
14
14
  RECIPE_INPUTS_INSUFFICIENT,
15
15
  RECIPE_INPUTS_INVALID,
16
16
  RECIPE_NOT_FOUND,
17
- SHIP_CARGO_NOT_LOADED,
17
+ ENTITY_CARGO_NOT_LOADED,
18
18
  } from '../errors'
19
19
  import {getRecipe, type RecipeInput} from '../data/recipes-runtime'
20
20
  import {getItem} from '../data/catalog'
@@ -389,7 +389,7 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
389
389
  break
390
390
  }
391
391
  }
392
- if (!found) throw new Error(SHIP_CARGO_NOT_LOADED)
392
+ if (!found) throw new Error(ENTITY_CARGO_NOT_LOADED)
393
393
  }
394
394
  }
395
395
 
@@ -16,9 +16,10 @@ import {mapEntity, parseWireEntity} from './mappers'
16
16
  import type {Ship} from '../entities/ship'
17
17
  import type {Warehouse} from '../entities/warehouse'
18
18
  import type {Container} from '../entities/container'
19
+ import type {Nexus} from '../entities/nexus'
19
20
 
20
- export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container'
21
- export type EntityInstance = Ship | Warehouse | Container
21
+ export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container' | 'nexus'
22
+ export type EntityInstance = Ship | Warehouse | Container | Nexus
22
23
 
23
24
  export interface SubscriptionsOptions {
24
25
  url: string
@@ -2,12 +2,16 @@ import {ServerContract} from '../contracts'
2
2
  import {Ship} from '../entities/ship'
3
3
  import {Warehouse} from '../entities/warehouse'
4
4
  import {Container} from '../entities/container'
5
+ import {Nexus} from '../entities/nexus'
5
6
  import type {WireEntity} from './types'
6
7
 
7
- export function mapEntity(ei: ServerContract.Types.entity_info): Ship | Warehouse | Container {
8
+ export function mapEntity(
9
+ ei: ServerContract.Types.entity_info
10
+ ): Ship | Warehouse | Container | Nexus {
8
11
  if (ei.type.equals('ship')) return new Ship(ei)
9
12
  if (ei.type.equals('warehouse')) return new Warehouse(ei)
10
13
  if (ei.type.equals('container')) return new Container(ei)
14
+ if (ei.type.equals('nexus')) return new Nexus(ei)
11
15
  throw new Error(`mapEntity: unknown entity type ${ei.type.toString()}`)
12
16
  }
13
17