@shipload/sdk 2.0.0-rc1 → 2.0.0-rc2

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 (42) hide show
  1. package/README.md +349 -1
  2. package/lib/shipload.d.ts +609 -248
  3. package/lib/shipload.js +1683 -1031
  4. package/lib/shipload.js.map +1 -1
  5. package/lib/shipload.m.js +1613 -1047
  6. package/lib/shipload.m.js.map +1 -1
  7. package/package.json +1 -2
  8. package/src/capabilities/extraction.ts +37 -0
  9. package/src/capabilities/guards.ts +43 -0
  10. package/src/capabilities/index.ts +5 -0
  11. package/src/capabilities/loading.ts +8 -0
  12. package/src/capabilities/movement.ts +29 -0
  13. package/src/capabilities/storage.ts +67 -0
  14. package/src/contracts/server.ts +340 -136
  15. package/src/data/goods.json +2 -2
  16. package/src/entities/cargo-utils.ts +96 -1
  17. package/src/entities/container.ts +70 -0
  18. package/src/entities/inventory-accessor.ts +46 -0
  19. package/src/entities/location.ts +22 -8
  20. package/src/entities/makers.ts +69 -0
  21. package/src/entities/player.ts +2 -1
  22. package/src/entities/ship.ts +86 -437
  23. package/src/entities/warehouse.ts +28 -144
  24. package/src/index-module.ts +34 -1
  25. package/src/managers/actions.ts +60 -28
  26. package/src/managers/entities.ts +22 -5
  27. package/src/managers/locations.ts +28 -9
  28. package/src/managers/trades.ts +2 -2
  29. package/src/market/market.ts +3 -4
  30. package/src/scheduling/accessor.ts +82 -0
  31. package/src/scheduling/projection.ts +125 -53
  32. package/src/scheduling/schedule.ts +24 -0
  33. package/src/trading/collect.ts +0 -1
  34. package/src/trading/deal.ts +0 -1
  35. package/src/travel/travel.ts +63 -2
  36. package/src/types/capabilities.ts +79 -0
  37. package/src/types/entity-traits.ts +70 -0
  38. package/src/types/entity.ts +36 -0
  39. package/src/types/index.ts +3 -0
  40. package/src/types.ts +75 -8
  41. package/src/utils/hash.ts +1 -1
  42. package/src/utils/system.ts +132 -4
@@ -0,0 +1,82 @@
1
+ import {ServerContract} from '../contracts'
2
+ import {TaskType} from '../types'
3
+ import {ScheduleData} from './schedule'
4
+ import * as schedule from './schedule'
5
+
6
+ type Task = ServerContract.Types.task
7
+
8
+ export class ScheduleAccessor {
9
+ constructor(private entity: ScheduleData) {}
10
+
11
+ get hasSchedule(): boolean {
12
+ return schedule.hasSchedule(this.entity)
13
+ }
14
+
15
+ get isIdle(): boolean {
16
+ return schedule.isIdle(this.entity)
17
+ }
18
+
19
+ get tasks(): Task[] {
20
+ return schedule.getTasks(this.entity)
21
+ }
22
+
23
+ duration(): number {
24
+ return schedule.scheduleDuration(this.entity)
25
+ }
26
+
27
+ elapsed(now: Date): number {
28
+ return schedule.scheduleElapsed(this.entity, now)
29
+ }
30
+
31
+ remaining(now: Date): number {
32
+ return schedule.scheduleRemaining(this.entity, now)
33
+ }
34
+
35
+ complete(now: Date): boolean {
36
+ return schedule.scheduleComplete(this.entity, now)
37
+ }
38
+
39
+ currentTaskIndex(now: Date): number {
40
+ return schedule.currentTaskIndex(this.entity, now)
41
+ }
42
+
43
+ currentTask(now: Date): Task | undefined {
44
+ return schedule.currentTask(this.entity, now)
45
+ }
46
+
47
+ currentTaskType(now: Date): TaskType | undefined {
48
+ return schedule.currentTaskType(this.entity, now)
49
+ }
50
+
51
+ taskStartTime(index: number): number {
52
+ return schedule.getTaskStartTime(this.entity, index)
53
+ }
54
+
55
+ taskElapsed(index: number, now: Date): number {
56
+ return schedule.getTaskElapsed(this.entity, index, now)
57
+ }
58
+
59
+ taskRemaining(index: number, now: Date): number {
60
+ return schedule.getTaskRemaining(this.entity, index, now)
61
+ }
62
+
63
+ taskComplete(index: number, now: Date): boolean {
64
+ return schedule.isTaskComplete(this.entity, index, now)
65
+ }
66
+
67
+ taskInProgress(index: number, now: Date): boolean {
68
+ return schedule.isTaskInProgress(this.entity, index, now)
69
+ }
70
+
71
+ currentTaskProgress(now: Date): number {
72
+ return schedule.currentTaskProgress(this.entity, now)
73
+ }
74
+
75
+ progress(now: Date): number {
76
+ return schedule.scheduleProgress(this.entity, now)
77
+ }
78
+ }
79
+
80
+ export function createScheduleAccessor(entity: ScheduleData): ScheduleAccessor {
81
+ return new ScheduleAccessor(entity)
82
+ }
@@ -1,15 +1,19 @@
1
- import {UInt16, UInt32, UInt64} from '@wharfkit/antelope'
1
+ import {Name, UInt16, UInt32, UInt64} from '@wharfkit/antelope'
2
2
  import {ServerContract} from '../contracts'
3
3
  import {Coordinates, PRECISION, TaskType} from '../types'
4
+ import {
5
+ capsHasLoaders,
6
+ capsHasMovement,
7
+ capsHasStorage,
8
+ EntityCapabilities,
9
+ EntityState,
10
+ } from '../types/capabilities'
4
11
  import {distanceBetweenCoordinates, lerp} from '../travel/travel'
12
+ import {calcCargoMass} from '../capabilities/storage'
5
13
  import {getGood} from '../market/goods'
6
14
  import * as schedule from './schedule'
7
15
  import {ScheduleData} from './schedule'
8
16
 
9
- /**
10
- * Projected state of an entity after scheduled tasks complete.
11
- * Mirrors contract's projected_entity struct.
12
- */
13
17
  export interface ProjectedEntity {
14
18
  location: Coordinates
15
19
  energy: UInt16
@@ -19,41 +23,56 @@ export interface ProjectedEntity {
19
23
  engines?: ServerContract.Types.movement_stats
20
24
  loaders?: ServerContract.Types.loader_stats
21
25
  generator?: ServerContract.Types.energy_stats
26
+ trade?: ServerContract.Types.trade_stats
22
27
  readonly totalMass: UInt64
28
+
29
+ hasMovement(): boolean
30
+ hasStorage(): boolean
31
+ hasLoaders(): boolean
32
+ hasTrade(): boolean
33
+
34
+ capabilities(): EntityCapabilities
35
+ state(): EntityState
23
36
  }
24
37
 
25
- /**
26
- * Interface for entities that can be projected.
27
- * Ships and Warehouses both implement this.
28
- */
29
38
  export interface Projectable extends ScheduleData {
30
- location: Coordinates
31
- energy: UInt16
32
- mass: UInt32
39
+ coordinates: Coordinates | ServerContract.Types.coordinates
40
+ energy?: UInt16
41
+ hullmass?: UInt32
33
42
  generator?: ServerContract.Types.energy_stats
34
43
  engines?: ServerContract.Types.movement_stats
35
44
  loaders?: ServerContract.Types.loader_stats
36
- capacity?: UInt64
37
- calcCargoMass(): UInt64
45
+ trade?: ServerContract.Types.trade_stats
46
+ capacity?: UInt32
47
+ cargo: ServerContract.Types.cargo_item[]
48
+ cargomass: UInt32
49
+ owner?: Name
50
+ }
51
+
52
+ function getHullMass(entity: Projectable): UInt32 {
53
+ return UInt32.from(entity.hullmass ?? 0)
38
54
  }
39
55
 
40
- /**
41
- * Create initial projected entity state from a projectable entity.
42
- */
43
56
  export function createProjectedEntity(entity: Projectable): ProjectedEntity {
44
- const cargoMass = entity.calcCargoMass()
45
- const shipMass = UInt32.from(entity.mass)
57
+ const cargoMass = calcCargoMass(entity)
58
+ const shipMass = getHullMass(entity)
46
59
  const loaders = entity.loaders
60
+ const engines = entity.engines
61
+ const generator = entity.generator
62
+ const trade = entity.trade
63
+ const capacity = entity.capacity
47
64
 
48
- return {
49
- location: Coordinates.from(entity.location),
50
- energy: UInt16.from(entity.energy),
65
+ const projected: ProjectedEntity = {
66
+ location: Coordinates.from(entity.coordinates),
67
+ energy: UInt16.from(entity.energy ?? 0),
51
68
  cargoMass,
52
69
  shipMass,
53
- capacity: entity.capacity,
54
- engines: entity.engines,
55
- generator: entity.generator,
70
+ capacity: capacity ? UInt64.from(capacity) : undefined,
71
+ engines,
72
+ generator,
56
73
  loaders,
74
+ trade,
75
+
57
76
  get totalMass() {
58
77
  let mass = UInt64.from(this.shipMass).adding(this.cargoMass)
59
78
  if (this.loaders) {
@@ -61,12 +80,48 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
61
80
  }
62
81
  return mass
63
82
  },
83
+
84
+ hasMovement() {
85
+ return capsHasMovement(this.capabilities())
86
+ },
87
+
88
+ hasStorage() {
89
+ return capsHasStorage(this.capabilities())
90
+ },
91
+
92
+ hasLoaders() {
93
+ return capsHasLoaders(this.capabilities())
94
+ },
95
+
96
+ hasTrade() {
97
+ return this.trade !== undefined
98
+ },
99
+
100
+ capabilities(): EntityCapabilities {
101
+ return {
102
+ hullmass: this.shipMass,
103
+ capacity: this.capacity ? UInt32.from(this.capacity) : undefined,
104
+ engines: this.engines,
105
+ generator: this.generator,
106
+ loaders: this.loaders,
107
+ trade: this.trade,
108
+ }
109
+ },
110
+
111
+ state(): EntityState {
112
+ return {
113
+ owner: entity.owner ?? Name.from(''),
114
+ location: ServerContract.Types.coordinates.from(this.location),
115
+ energy: this.energy,
116
+ cargomass: UInt32.from(this.cargoMass),
117
+ cargo: entity.cargo,
118
+ }
119
+ },
64
120
  }
121
+
122
+ return projected
65
123
  }
66
124
 
67
- /**
68
- * Apply a recharge task to projected state.
69
- */
70
125
  function applyRechargeTask(
71
126
  projected: ProjectedEntity,
72
127
  _task: ServerContract.Types.task,
@@ -84,19 +139,16 @@ function applyRechargeTask(
84
139
  }
85
140
  }
86
141
 
87
- /**
88
- * Apply a flight task to projected state.
89
- */
90
142
  function applyFlightTask(
91
143
  projected: ProjectedEntity,
92
144
  task: ServerContract.Types.task,
93
145
  options: {complete: boolean; progress?: number}
94
146
  ): void {
95
- if (!task.location || !projected.engines) return
147
+ if (!task.coordinates || !projected.engines) return
96
148
 
97
149
  const origin = projected.location
98
- const destination = Coordinates.from(task.location)
99
- const distance = distanceBetweenCoordinates(origin, task.location)
150
+ const destination = Coordinates.from(task.coordinates)
151
+ const distance = distanceBetweenCoordinates(origin, task.coordinates)
100
152
  const energyUsage = distance.dividing(PRECISION).multiplying(projected.engines.drain)
101
153
 
102
154
  if (options.complete) {
@@ -117,33 +169,48 @@ function applyFlightTask(
117
169
  }
118
170
  }
119
171
 
120
- /**
121
- * Apply a load task to projected state.
122
- */
172
+ function getGoodMass(good_id: UInt16 | number): UInt32 {
173
+ const good = getGood(good_id)
174
+ return good.mass
175
+ }
176
+
123
177
  function applyLoadTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
124
178
  for (const item of task.cargo) {
125
- const good = getGood(item.good_id)
126
- projected.cargoMass = projected.cargoMass.adding(good.mass.multiplying(item.quantity))
179
+ const good_mass = getGoodMass(item.good_id)
180
+ projected.cargoMass = projected.cargoMass.adding(good_mass.multiplying(item.quantity))
127
181
  }
128
182
  }
129
183
 
130
- /**
131
- * Apply an unload task to projected state.
132
- */
133
184
  function applyUnloadTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
134
185
  for (const item of task.cargo) {
135
- const good = getGood(item.good_id)
136
- const cargoMass = good.mass.multiplying(item.quantity)
186
+ const good_mass = getGoodMass(item.good_id)
187
+ const cargoMass = good_mass.multiplying(item.quantity)
137
188
  projected.cargoMass = projected.cargoMass.gt(cargoMass)
138
189
  ? projected.cargoMass.subtracting(cargoMass)
139
190
  : UInt64.from(0)
140
191
  }
141
192
  }
142
193
 
143
- /**
144
- * Project entity state after all scheduled tasks complete.
145
- * Mirrors contract's project_ship/project_warehouse methods.
146
- */
194
+ function applyExtractTask(
195
+ projected: ProjectedEntity,
196
+ task: ServerContract.Types.task,
197
+ options: {complete: boolean}
198
+ ): void {
199
+ if (!options.complete) return
200
+
201
+ if (task.energy_cost) {
202
+ const energyCost = UInt16.from(task.energy_cost)
203
+ projected.energy = projected.energy.gt(energyCost)
204
+ ? UInt16.from(projected.energy.subtracting(energyCost))
205
+ : UInt16.from(0)
206
+ }
207
+
208
+ for (const item of task.cargo) {
209
+ const good_mass = getGoodMass(item.good_id)
210
+ projected.cargoMass = projected.cargoMass.adding(good_mass.multiplying(item.quantity))
211
+ }
212
+ }
213
+
147
214
  export function projectEntity(entity: Projectable): ProjectedEntity {
148
215
  const projected = createProjectedEntity(entity)
149
216
 
@@ -156,7 +223,7 @@ export function projectEntity(entity: Projectable): ProjectedEntity {
156
223
  case TaskType.RECHARGE:
157
224
  applyRechargeTask(projected, task, {complete: true})
158
225
  break
159
- case TaskType.FLIGHT:
226
+ case TaskType.TRAVEL:
160
227
  applyFlightTask(projected, task, {complete: true})
161
228
  break
162
229
  case TaskType.LOAD:
@@ -165,15 +232,15 @@ export function projectEntity(entity: Projectable): ProjectedEntity {
165
232
  case TaskType.UNLOAD:
166
233
  applyUnloadTask(projected, task)
167
234
  break
235
+ case TaskType.EXTRACT:
236
+ applyExtractTask(projected, task, {complete: true})
237
+ break
168
238
  }
169
239
  }
170
240
 
171
241
  return projected
172
242
  }
173
243
 
174
- /**
175
- * Project entity state at a specific time (partial task execution).
176
- */
177
244
  export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity {
178
245
  const projected = createProjectedEntity(entity)
179
246
 
@@ -198,7 +265,7 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
198
265
  case TaskType.RECHARGE:
199
266
  applyRechargeTask(projected, task, {complete: taskComplete, progress})
200
267
  break
201
- case TaskType.FLIGHT:
268
+ case TaskType.TRAVEL:
202
269
  applyFlightTask(projected, task, {complete: taskComplete, progress})
203
270
  break
204
271
  case TaskType.LOAD:
@@ -211,6 +278,11 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
211
278
  applyUnloadTask(projected, task)
212
279
  }
213
280
  break
281
+ case TaskType.EXTRACT:
282
+ if (taskComplete) {
283
+ applyExtractTask(projected, task, {complete: true})
284
+ }
285
+ break
214
286
  }
215
287
  }
216
288
 
@@ -153,3 +153,27 @@ export function scheduleProgress(entity: ScheduleData, now: Date): number {
153
153
  const elapsed = scheduleElapsed(entity, now)
154
154
  return Math.min(1, elapsed / duration)
155
155
  }
156
+
157
+ export function isTaskType(entity: ScheduleData, taskType: TaskType, now: Date): boolean {
158
+ return currentTaskType(entity, now) === taskType
159
+ }
160
+
161
+ export function isInFlight(entity: ScheduleData, now: Date): boolean {
162
+ return isTaskType(entity, TaskType.TRAVEL, now)
163
+ }
164
+
165
+ export function isRecharging(entity: ScheduleData, now: Date): boolean {
166
+ return isTaskType(entity, TaskType.RECHARGE, now)
167
+ }
168
+
169
+ export function isLoading(entity: ScheduleData, now: Date): boolean {
170
+ return isTaskType(entity, TaskType.LOAD, now)
171
+ }
172
+
173
+ export function isUnloading(entity: ScheduleData, now: Date): boolean {
174
+ return isTaskType(entity, TaskType.UNLOAD, now)
175
+ }
176
+
177
+ export function isExtracting(entity: ScheduleData, now: Date): boolean {
178
+ return isTaskType(entity, TaskType.EXTRACT, now)
179
+ }
@@ -10,7 +10,6 @@ import {
10
10
  distanceBetweenCoordinates,
11
11
  EstimatedTravelTime,
12
12
  estimateTravelTime,
13
- hasEnergyForDistance,
14
13
  } from '../travel/travel'
15
14
  import {getGood, getGoods} from '../market/goods'
16
15
  import {getRarity, Rarities} from '../market/market'
@@ -6,7 +6,6 @@ import {
6
6
  distanceBetweenCoordinates,
7
7
  type EstimatedTravelTime,
8
8
  estimateTravelTime,
9
- hasEnergyForDistance,
10
9
  } from '../travel/travel'
11
10
  import {calculateProfitPerSecond, calculateTradeProfit, isProfitable} from './trade'
12
11
 
@@ -29,6 +29,7 @@ import {
29
29
  MIN_ORBITAL_ALTITUDE,
30
30
  PRECISION,
31
31
  ShipLike,
32
+ TaskType,
32
33
  } from '../types'
33
34
  import {getGood} from '../market/goods'
34
35
  import {hasSystem} from '../utils/system'
@@ -133,7 +134,7 @@ export function calc_flighttime(distance: UInt64Type, acceleration: number): UIn
133
134
  }
134
135
 
135
136
  export function calc_loader_flighttime(ship: ShipLike, mass: UInt64, altitude?: number): UInt32 {
136
- const z = altitude ?? ship.location.z?.toNumber() ?? calc_orbital_altitude(Number(mass))
137
+ const z = altitude ?? ship.coordinates.z?.toNumber() ?? calc_orbital_altitude(Number(mass))
137
138
  return calc_flighttime(z, calc_loader_acceleration(ship, mass))
138
139
  }
139
140
 
@@ -157,7 +158,7 @@ export function calc_acceleration(thrust: number, mass: number): number {
157
158
  export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64 {
158
159
  const mass = UInt64.from(0)
159
160
 
160
- mass.add(ship.mass)
161
+ mass.add(ship.hullmass)
161
162
 
162
163
  if (ship.loaders.quantity.gt(UInt32.zero)) {
163
164
  mass.add(ship.loaders.mass.multiplying(ship.loaders.quantity))
@@ -358,6 +359,66 @@ export interface TransferEntity {
358
359
  }
359
360
  }
360
361
 
362
+ export interface HasScheduleAndLocation {
363
+ coordinates: ServerContract.ActionParams.Type.coordinates
364
+ schedule?: ServerContract.Types.schedule
365
+ }
366
+
367
+ export function getFlightOrigin(
368
+ entity: HasScheduleAndLocation,
369
+ flightTaskIndex: number
370
+ ): ServerContract.ActionParams.Type.coordinates {
371
+ if (!entity.schedule) return entity.coordinates
372
+
373
+ let origin = entity.coordinates
374
+ for (let i = 0; i < flightTaskIndex && i < entity.schedule.tasks.length; i++) {
375
+ const task = entity.schedule.tasks[i]
376
+ if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
377
+ origin = task.coordinates
378
+ }
379
+ }
380
+ return origin
381
+ }
382
+
383
+ export function getDestinationLocation(
384
+ entity: HasScheduleAndLocation
385
+ ): ServerContract.ActionParams.Type.coordinates | undefined {
386
+ if (!entity.schedule) return undefined
387
+
388
+ for (let i = entity.schedule.tasks.length - 1; i >= 0; i--) {
389
+ const task = entity.schedule.tasks[i]
390
+ if (task.type.equals(TaskType.TRAVEL) && task.coordinates) {
391
+ return task.coordinates
392
+ }
393
+ }
394
+ return undefined
395
+ }
396
+
397
+ export function getPositionAt(
398
+ entity: HasScheduleAndLocation,
399
+ taskIndex: number,
400
+ taskProgress: number
401
+ ): ServerContract.ActionParams.Type.coordinates {
402
+ if (!entity.schedule || entity.schedule.tasks.length === 0 || taskIndex < 0) {
403
+ return entity.coordinates
404
+ }
405
+
406
+ const task = entity.schedule.tasks[taskIndex]
407
+
408
+ if (!task.type.equals(TaskType.TRAVEL) || !task.coordinates) {
409
+ return getFlightOrigin(entity, taskIndex)
410
+ }
411
+
412
+ const origin = getFlightOrigin(entity, taskIndex)
413
+ const destination = task.coordinates
414
+
415
+ const interpolated = lerp(origin, destination, taskProgress)
416
+ return {
417
+ x: Math.round(interpolated.x),
418
+ y: Math.round(interpolated.y),
419
+ }
420
+ }
421
+
361
422
  export function calc_transfer_duration(
362
423
  source: TransferEntity,
363
424
  dest: TransferEntity,
@@ -0,0 +1,79 @@
1
+ import {Name, UInt16, UInt32} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+
4
+ export interface MovementCapability {
5
+ engines: ServerContract.Types.movement_stats
6
+ generator: ServerContract.Types.energy_stats
7
+ }
8
+
9
+ export interface EnergyCapability {
10
+ energy: UInt16
11
+ }
12
+
13
+ export interface StorageCapability {
14
+ capacity: UInt32
15
+ cargomass: UInt32
16
+ cargo: ServerContract.Types.cargo_item[]
17
+ }
18
+
19
+ export interface LoaderCapability {
20
+ loaders: ServerContract.Types.loader_stats
21
+ }
22
+
23
+ export interface TradeCapability {
24
+ trade: ServerContract.Types.trade_stats
25
+ }
26
+
27
+ export interface ExtractorCapability {
28
+ extractor: ServerContract.Types.extractor_stats
29
+ }
30
+
31
+ export interface MassCapability {
32
+ hullmass: UInt32
33
+ }
34
+
35
+ export interface ScheduleCapability {
36
+ schedule?: ServerContract.Types.schedule
37
+ }
38
+
39
+ export interface EntityCapabilities {
40
+ hullmass?: UInt32
41
+ capacity?: UInt32
42
+ engines?: ServerContract.Types.movement_stats
43
+ generator?: ServerContract.Types.energy_stats
44
+ loaders?: ServerContract.Types.loader_stats
45
+ trade?: ServerContract.Types.trade_stats
46
+ extractor?: ServerContract.Types.extractor_stats
47
+ }
48
+
49
+ export interface EntityState {
50
+ owner: Name
51
+ location: ServerContract.Types.coordinates
52
+ energy?: UInt16
53
+ cargomass: UInt32
54
+ cargo: ServerContract.Types.cargo_item[]
55
+ }
56
+
57
+ export function capsHasMovement(caps: EntityCapabilities): boolean {
58
+ return caps.engines !== undefined && caps.generator !== undefined
59
+ }
60
+
61
+ export function capsHasStorage(caps: EntityCapabilities): boolean {
62
+ return caps.capacity !== undefined
63
+ }
64
+
65
+ export function capsHasLoaders(caps: EntityCapabilities): boolean {
66
+ return caps.loaders !== undefined
67
+ }
68
+
69
+ export function capsHasTrade(caps: EntityCapabilities): boolean {
70
+ return caps.trade !== undefined
71
+ }
72
+
73
+ export function capsHasExtractor(caps: EntityCapabilities): boolean {
74
+ return caps.extractor !== undefined
75
+ }
76
+
77
+ export function capsHasMass(caps: EntityCapabilities): boolean {
78
+ return caps.hullmass !== undefined
79
+ }
@@ -0,0 +1,70 @@
1
+ import {Name} from '@wharfkit/antelope'
2
+
3
+ export const ENTITY_SHIP = Name.from('ship')
4
+ export const ENTITY_WAREHOUSE = Name.from('warehouse')
5
+ export const ENTITY_CONTAINER = Name.from('container')
6
+
7
+ export type EntityTypeName = 'ship' | 'warehouse' | 'container'
8
+
9
+ export interface EntityTraits {
10
+ typeName: Name
11
+ isMovable: boolean
12
+ hasEnergy: boolean
13
+ hasLoaders: boolean
14
+ hasTrade: boolean
15
+ notFoundError: string
16
+ }
17
+
18
+ export const shipTraits: EntityTraits = {
19
+ typeName: ENTITY_SHIP,
20
+ isMovable: true,
21
+ hasEnergy: true,
22
+ hasLoaders: true,
23
+ hasTrade: true,
24
+ notFoundError: 'ship not found',
25
+ }
26
+
27
+ export const warehouseTraits: EntityTraits = {
28
+ typeName: ENTITY_WAREHOUSE,
29
+ isMovable: false,
30
+ hasEnergy: false,
31
+ hasLoaders: true,
32
+ hasTrade: false,
33
+ notFoundError: 'warehouse not found',
34
+ }
35
+
36
+ export const containerTraits: EntityTraits = {
37
+ typeName: ENTITY_CONTAINER,
38
+ isMovable: true,
39
+ hasEnergy: false,
40
+ hasLoaders: false,
41
+ hasTrade: false,
42
+ notFoundError: 'container not found',
43
+ }
44
+
45
+ export function getEntityTraits(entityType: Name | EntityTypeName): EntityTraits {
46
+ const typeName = typeof entityType === 'string' ? entityType : entityType.toString()
47
+
48
+ switch (typeName) {
49
+ case 'ship':
50
+ return shipTraits
51
+ case 'warehouse':
52
+ return warehouseTraits
53
+ case 'container':
54
+ return containerTraits
55
+ default:
56
+ throw new Error(`Unknown entity type: ${typeName}`)
57
+ }
58
+ }
59
+
60
+ export function isShip(entity: {type?: Name}): boolean {
61
+ return entity.type?.equals(ENTITY_SHIP) ?? false
62
+ }
63
+
64
+ export function isWarehouse(entity: {type?: Name}): boolean {
65
+ return entity.type?.equals(ENTITY_WAREHOUSE) ?? false
66
+ }
67
+
68
+ export function isContainer(entity: {type?: Name}): boolean {
69
+ return entity.type?.equals(ENTITY_CONTAINER) ?? false
70
+ }
@@ -0,0 +1,36 @@
1
+ import {Name, UInt64} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import {Coordinates} from '../types'
4
+ import {
5
+ EnergyCapability,
6
+ LoaderCapability,
7
+ MassCapability,
8
+ MovementCapability,
9
+ ScheduleCapability,
10
+ StorageCapability,
11
+ } from './capabilities'
12
+
13
+ export interface Entity {
14
+ id: UInt64
15
+ type: Name
16
+ owner: Name
17
+ entity_name: string
18
+ location: Coordinates | ServerContract.Types.coordinates
19
+ }
20
+
21
+ export type ShipEntity = Entity &
22
+ MovementCapability &
23
+ EnergyCapability &
24
+ StorageCapability &
25
+ LoaderCapability &
26
+ MassCapability &
27
+ ScheduleCapability & {
28
+ trade?: ServerContract.Types.trade_stats
29
+ extractor?: ServerContract.Types.extractor_stats
30
+ }
31
+
32
+ export type WarehouseEntity = Entity & StorageCapability & LoaderCapability & ScheduleCapability
33
+
34
+ export type ContainerEntity = Entity & StorageCapability & MassCapability & ScheduleCapability
35
+
36
+ export type AnyEntity = ShipEntity | WarehouseEntity | ContainerEntity
@@ -0,0 +1,3 @@
1
+ export * from './capabilities'
2
+ export * from './entity'
3
+ export * from './entity-traits'