@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
@@ -1,20 +1,35 @@
1
- import {Name, NameType, UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
1
+ import {UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
2
2
  import {ServerContract} from '../contracts'
3
- import {Coordinates, CoordinatesType, PRECISION, TaskType} from '../types'
4
- import {distanceBetweenCoordinates, lerp} from '../travel/travel'
3
+ import {Coordinates, CoordinatesType} from '../types'
4
+ import {
5
+ getDestinationLocation,
6
+ getPositionAt,
7
+ getFlightOrigin as travelGetFlightOrigin,
8
+ } from '../travel/travel'
9
+ import {
10
+ ProjectedEntity,
11
+ projectEntity as sharedProjectEntity,
12
+ projectEntityAt as sharedProjectEntityAt,
13
+ } from '../scheduling/projection'
5
14
  import {Location} from './location'
6
- import {getGood} from '../market/goods'
7
- import * as schedule from '../scheduling/schedule'
8
- import {Scheduleable} from '../scheduling/schedule'
15
+ import {ScheduleAccessor} from '../scheduling/accessor'
16
+ import {InventoryAccessor} from './inventory-accessor'
9
17
  import {EntityInventory} from './entity-inventory'
10
- import {ProjectedEntity} from '../scheduling/projection'
18
+ import {
19
+ energyPercent as calcEnergyPercent,
20
+ needsRecharge as calcNeedsRecharge,
21
+ hasEnergyForDistance,
22
+ maxTravelDistance,
23
+ } from '../capabilities/movement'
24
+ import * as cargoUtils from './cargo-utils'
25
+ import * as schedule from '../scheduling/schedule'
11
26
 
12
27
  export interface ShipStateInput {
13
28
  id: UInt64Type
14
- owner: NameType
29
+ owner: string
15
30
  name: string
16
- location: CoordinatesType | {x: number; y: number; z?: number}
17
- mass: number
31
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
32
+ hullmass: number
18
33
  capacity: number
19
34
  energy: number
20
35
  engines: ServerContract.Types.movement_stats
@@ -24,382 +39,102 @@ export interface ShipStateInput {
24
39
  cargo?: ServerContract.Types.cargo_item[]
25
40
  }
26
41
 
27
- export class Ship extends ServerContract.Types.entity_info implements Scheduleable {
28
- static fromState(state: ShipStateInput): Ship {
29
- const entityInfo = ServerContract.Types.entity_info.from({
30
- type: Name.from('ship'),
31
- id: UInt64.from(state.id),
32
- owner: Name.from(state.owner),
33
- entity_name: state.name,
34
- location: ServerContract.Types.coordinates.from(state.location),
35
- mass: UInt32.from(state.mass),
36
- capacity: UInt32.from(state.capacity),
37
- energy: UInt16.from(state.energy),
38
- cargomass: UInt32.from(0),
39
- cargo: state.cargo || [],
40
- is_idle: !state.schedule,
41
- current_task_elapsed: UInt32.from(0),
42
- current_task_remaining: UInt32.from(0),
43
- pending_tasks: [],
44
- engines: state.engines,
45
- generator: state.generator,
46
- loaders: state.loaders,
47
- schedule: state.schedule,
48
- })
49
- return new Ship(entityInfo)
50
- }
51
-
52
- private _location?: Location
53
- private _inventory?: EntityInventory[]
42
+ type MovementEntity = {
43
+ engines: ServerContract.Types.movement_stats
44
+ generator: ServerContract.Types.energy_stats
45
+ energy: UInt16
46
+ }
47
+
48
+ export class Ship extends ServerContract.Types.entity_info {
49
+ private _sched?: ScheduleAccessor
50
+ private _inv?: InventoryAccessor
54
51
 
55
52
  get name(): string {
56
53
  return this.entity_name
57
54
  }
58
55
 
56
+ get inv(): InventoryAccessor {
57
+ return (this._inv ??= new InventoryAccessor(this))
58
+ }
59
+
59
60
  get inventory(): EntityInventory[] {
60
- if (!this._inventory) {
61
- this._inventory = this.cargo.map((item) => new EntityInventory(item))
62
- }
63
- return this._inventory
61
+ return this.inv.items
64
62
  }
65
63
 
66
- get maxDistance(): UInt32 {
67
- if (!this.generator || !this.engines) return UInt32.from(0)
68
- return UInt32.from(this.generator.capacity)
69
- .dividing(this.engines.drain)
70
- .multiplying(PRECISION)
64
+ get sched(): ScheduleAccessor {
65
+ return (this._sched ??= new ScheduleAccessor(this))
71
66
  }
72
67
 
73
- get hasSchedule(): boolean {
74
- return schedule.hasSchedule(this)
68
+ get maxDistance(): UInt32 {
69
+ if (!this.generator || !this.engines) return UInt32.from(0)
70
+ return maxTravelDistance(this as MovementEntity)
75
71
  }
76
72
 
77
73
  get isIdle(): boolean {
78
74
  return this.is_idle
79
75
  }
80
76
 
81
- get tasks(): ServerContract.Types.task[] {
82
- return schedule.getTasks(this)
83
- }
84
-
85
- scheduleDuration(): number {
86
- return schedule.scheduleDuration(this)
87
- }
88
-
89
- scheduleElapsed(now: Date): number {
90
- return schedule.scheduleElapsed(this, now)
91
- }
92
-
93
- scheduleRemaining(now: Date): number {
94
- return schedule.scheduleRemaining(this, now)
95
- }
96
-
97
- scheduleComplete(now: Date): boolean {
98
- return schedule.scheduleComplete(this, now)
99
- }
100
-
101
- currentTaskIndex(now: Date): number {
102
- return schedule.currentTaskIndex(this, now)
103
- }
104
-
105
- currentTask(now: Date): ServerContract.Types.task | undefined {
106
- return schedule.currentTask(this, now)
107
- }
108
-
109
- currentTaskType(now: Date): TaskType | undefined {
110
- return schedule.currentTaskType(this, now)
111
- }
112
-
113
- getTaskStartTime(index: number): number {
114
- return schedule.getTaskStartTime(this, index)
115
- }
116
-
117
- getTaskElapsed(index: number, now: Date): number {
118
- return schedule.getTaskElapsed(this, index, now)
119
- }
120
-
121
- getTaskRemaining(index: number, now: Date): number {
122
- return schedule.getTaskRemaining(this, index, now)
123
- }
124
-
125
- isTaskComplete(index: number, now: Date): boolean {
126
- return schedule.isTaskComplete(this, index, now)
127
- }
128
-
129
- isTaskInProgress(index: number, now: Date): boolean {
130
- return schedule.isTaskInProgress(this, index, now)
131
- }
132
-
133
- currentTaskProgress(now: Date): number {
134
- return schedule.currentTaskProgress(this, now)
135
- }
136
-
137
- scheduleProgress(now: Date): number {
138
- return schedule.scheduleProgress(this, now)
139
- }
140
-
141
77
  getFlightOrigin(flightTaskIndex: number): Coordinates {
142
- if (!this.schedule) return this.location
143
-
144
- let origin: Coordinates = this.location
145
- for (let i = 0; i < flightTaskIndex && i < this.schedule.tasks.length; i++) {
146
- const task = this.schedule.tasks[i]
147
- if (task.type.equals(TaskType.FLIGHT) && task.location) {
148
- origin = task.location
149
- }
150
- }
151
- return origin
78
+ return Coordinates.from(travelGetFlightOrigin(this, flightTaskIndex))
152
79
  }
153
80
 
154
81
  destinationLocation(): Coordinates | undefined {
155
- if (!this.schedule) return undefined
156
-
157
- for (let i = this.schedule.tasks.length - 1; i >= 0; i--) {
158
- const task = this.schedule.tasks[i]
159
- if (task.type.equals(TaskType.FLIGHT) && task.location) {
160
- return task.location
161
- }
162
- }
163
- return undefined
82
+ const dest = getDestinationLocation(this)
83
+ return dest ? Coordinates.from(dest) : undefined
164
84
  }
165
85
 
166
86
  positionAt(now: Date): Coordinates {
167
- if (!this.schedule || this.schedule.tasks.length === 0) {
168
- return this.location
169
- }
170
-
171
- const taskIndex = this.currentTaskIndex(now)
172
- if (taskIndex < 0) return this.location
173
-
174
- const task = this.schedule.tasks[taskIndex]
175
-
176
- if (!task.type.equals(TaskType.FLIGHT) || !task.location) {
177
- return this.getFlightOrigin(taskIndex)
178
- }
179
-
180
- const origin = this.getFlightOrigin(taskIndex)
181
- const destination = task.location
182
- const progress = this.currentTaskProgress(now)
183
-
184
- const interpolated = lerp(origin, destination, progress)
185
- return Coordinates.from({
186
- x: Math.round(interpolated.x),
187
- y: Math.round(interpolated.y),
188
- })
87
+ const taskIndex = this.sched.currentTaskIndex(now)
88
+ const progress = this.sched.currentTaskProgress(now)
89
+ return Coordinates.from(getPositionAt(this, taskIndex, progress))
189
90
  }
190
91
 
191
92
  isInFlight(now: Date): boolean {
192
- const taskType = this.currentTaskType(now)
193
- return taskType === TaskType.FLIGHT
93
+ return schedule.isInFlight(this, now)
194
94
  }
195
95
 
196
96
  isRecharging(now: Date): boolean {
197
- const taskType = this.currentTaskType(now)
198
- return taskType === TaskType.RECHARGE
97
+ return schedule.isRecharging(this, now)
199
98
  }
200
99
 
201
100
  isLoading(now: Date): boolean {
202
- const taskType = this.currentTaskType(now)
203
- return taskType === TaskType.LOAD
101
+ return schedule.isLoading(this, now)
204
102
  }
205
103
 
206
104
  isUnloading(now: Date): boolean {
207
- const taskType = this.currentTaskType(now)
208
- return taskType === TaskType.UNLOAD
105
+ return schedule.isUnloading(this, now)
209
106
  }
210
107
 
211
- calcCargoMass(): UInt64 {
212
- let mass = UInt64.from(0)
213
- for (const item of this.cargo) {
214
- const good = getGood(item.good_id)
215
- mass = mass.adding(good.mass.multiplying(item.quantity))
216
- }
217
- return mass
108
+ isExtracting(now: Date): boolean {
109
+ return schedule.isExtracting(this, now)
218
110
  }
219
111
 
220
- private createProjectedEntity(cargoMass: UInt64): ProjectedEntity {
221
- const shipMass = UInt32.from(this.mass)
222
- const loaders = this.loaders
223
- return {
224
- location: Coordinates.from(this.location),
225
- energy: UInt16.from(this.energy),
226
- cargoMass,
227
- shipMass,
228
- engines: this.engines,
229
- generator: this.generator,
230
- loaders,
231
- get totalMass() {
232
- let mass = UInt64.from(this.shipMass).adding(this.cargoMass)
233
- if (this.loaders) {
234
- mass = mass.adding(this.loaders.mass.multiplying(this.loaders.quantity))
235
- }
236
- return mass
237
- },
238
- }
112
+ get hasExtractor(): boolean {
113
+ return this.extractor !== undefined
239
114
  }
240
115
 
241
116
  project(): ProjectedEntity {
242
- const cargoMass = this.calcCargoMass()
243
- const projected = this.createProjectedEntity(cargoMass)
244
-
245
- if (!this.schedule) {
246
- return projected
247
- }
248
-
249
- for (const task of this.schedule.tasks) {
250
- switch (task.type.toNumber()) {
251
- case TaskType.RECHARGE:
252
- if (projected.generator) {
253
- projected.energy = UInt16.from(projected.generator.capacity)
254
- }
255
- break
256
- case TaskType.FLIGHT: {
257
- if (task.location) {
258
- const distance = distanceBetweenCoordinates(
259
- projected.location,
260
- task.location
261
- )
262
- if (projected.engines) {
263
- const energyUsage = distance
264
- .dividing(PRECISION)
265
- .multiplying(projected.engines.drain)
266
- projected.energy = projected.energy.gt(energyUsage)
267
- ? UInt16.from(projected.energy.subtracting(energyUsage))
268
- : UInt16.from(0)
269
- }
270
- projected.location = Coordinates.from(task.location)
271
- }
272
- break
273
- }
274
- case TaskType.LOAD:
275
- for (const item of task.cargo) {
276
- const good = getGood(item.good_id)
277
- projected.cargoMass = projected.cargoMass.adding(
278
- good.mass.multiplying(item.quantity)
279
- )
280
- }
281
- break
282
- case TaskType.UNLOAD:
283
- for (const item of task.cargo) {
284
- const good = getGood(item.good_id)
285
- const cargoMass = good.mass.multiplying(item.quantity)
286
- projected.cargoMass = projected.cargoMass.gt(cargoMass)
287
- ? projected.cargoMass.subtracting(cargoMass)
288
- : UInt64.from(0)
289
- }
290
- break
291
- }
292
- }
293
-
294
- return projected
117
+ return sharedProjectEntity(this)
295
118
  }
296
119
 
297
120
  projectAt(now: Date): ProjectedEntity {
298
- const cargoMass = this.calcCargoMass()
299
- const projected = this.createProjectedEntity(cargoMass)
300
-
301
- if (!this.schedule || this.schedule.tasks.length === 0) {
302
- return projected
303
- }
304
-
305
- for (let i = 0; i < this.schedule.tasks.length; i++) {
306
- const task = this.schedule.tasks[i]
307
- const taskComplete = this.isTaskComplete(i, now)
308
- const taskInProgress = this.isTaskInProgress(i, now)
309
-
310
- if (!taskComplete && !taskInProgress) {
311
- break
312
- }
313
-
314
- switch (task.type.toNumber()) {
315
- case TaskType.RECHARGE:
316
- if (projected.generator) {
317
- if (taskComplete) {
318
- projected.energy = UInt16.from(projected.generator.capacity)
319
- } else if (taskInProgress) {
320
- const progress = this.getTaskElapsed(i, now) / task.duration.toNumber()
321
- const capacity = Number(projected.generator.capacity)
322
- const currentEnergy = Number(projected.energy)
323
- const rechargeAmount = (capacity - currentEnergy) * progress
324
- projected.energy = UInt16.from(
325
- Math.min(capacity, currentEnergy + rechargeAmount)
326
- )
327
- }
328
- }
329
- break
330
- case TaskType.FLIGHT: {
331
- if (task.location && projected.engines) {
332
- const origin = projected.location
333
- const destination = Coordinates.from(task.location)
334
- const distance = distanceBetweenCoordinates(origin, task.location)
335
- const energyUsage = distance
336
- .dividing(PRECISION)
337
- .multiplying(projected.engines.drain)
338
-
339
- if (taskComplete) {
340
- projected.energy = projected.energy.gt(energyUsage)
341
- ? UInt16.from(projected.energy.subtracting(energyUsage))
342
- : UInt16.from(0)
343
- projected.location = destination
344
- } else if (taskInProgress) {
345
- const progress = this.getTaskElapsed(i, now) / task.duration.toNumber()
346
- const interpolated = lerp(origin, destination, progress)
347
- projected.location = Coordinates.from({
348
- x: Math.round(interpolated.x),
349
- y: Math.round(interpolated.y),
350
- })
351
- const partialEnergy = UInt64.from(
352
- Math.floor(Number(energyUsage) * progress)
353
- )
354
- projected.energy = projected.energy.gt(partialEnergy)
355
- ? UInt16.from(projected.energy.subtracting(partialEnergy))
356
- : UInt16.from(0)
357
- }
358
- }
359
- break
360
- }
361
- case TaskType.LOAD:
362
- if (taskComplete) {
363
- for (const item of task.cargo) {
364
- const good = getGood(item.good_id)
365
- projected.cargoMass = projected.cargoMass.adding(
366
- good.mass.multiplying(item.quantity)
367
- )
368
- }
369
- }
370
- break
371
- case TaskType.UNLOAD:
372
- if (taskComplete) {
373
- for (const item of task.cargo) {
374
- const good = getGood(item.good_id)
375
- const cargoMass = good.mass.multiplying(item.quantity)
376
- projected.cargoMass = projected.cargoMass.gt(cargoMass)
377
- ? projected.cargoMass.subtracting(cargoMass)
378
- : UInt64.from(0)
379
- }
380
- }
381
- break
382
- }
383
- }
384
-
385
- return projected
121
+ return sharedProjectEntityAt(this, now)
386
122
  }
387
123
 
388
- get currentLocation(): Coordinates {
389
- return this.location
124
+ get location(): Location {
125
+ return Location.from(this.coordinates)
390
126
  }
391
127
 
392
128
  get totalCargoMass(): UInt64 {
393
- return this.inventory.reduce((sum, c) => sum.adding(c.totalMass), UInt64.from(0))
129
+ return this.inv.totalMass
394
130
  }
395
131
 
396
132
  get cargoValue(): UInt64 {
397
- return this.inventory.reduce((sum, c) => sum.adding(c.totalCost), UInt64.from(0))
133
+ return this.inv.totalValue
398
134
  }
399
135
 
400
136
  get totalMass(): UInt64 {
401
- const cargoMass = this.totalCargoMass
402
- let mass = UInt64.from(this.mass ?? 0).adding(cargoMass)
137
+ let mass = UInt64.from(this.hullmass ?? 0).adding(this.totalCargoMass)
403
138
  if (this.loaders) {
404
139
  mass = mass.adding(UInt64.from(this.loaders.mass).multiplying(this.loaders.quantity))
405
140
  }
@@ -411,43 +146,29 @@ export class Ship extends ServerContract.Types.entity_info implements Scheduleab
411
146
  }
412
147
 
413
148
  hasSpace(goodMass: UInt64, quantity: number): boolean {
414
- const additionalMass = goodMass.multiplying(quantity)
415
- const newTotal = this.totalMass.adding(additionalMass)
416
- return newTotal.lte(this.maxCapacity)
149
+ return this.totalMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity)
417
150
  }
418
151
 
419
152
  get availableCapacity(): UInt64 {
420
- if (this.totalMass.gte(this.maxCapacity)) {
421
- return UInt64.from(0)
422
- }
423
- return this.maxCapacity.subtracting(this.totalMass)
424
- }
425
-
426
- get locationObject(): Location {
427
- if (!this._location) {
428
- this._location = Location.from(this.location)
429
- }
430
- return this._location
431
- }
432
-
433
- setLocation(location: Location): void {
434
- this._location = location
153
+ return this.totalMass.gte(this.maxCapacity)
154
+ ? UInt64.from(0)
155
+ : this.maxCapacity.subtracting(this.totalMass)
435
156
  }
436
157
 
437
158
  getCargoForGood(goodId: UInt64Type): EntityInventory | undefined {
438
- return this.inventory.find((c) => c.good_id.equals(goodId))
159
+ return this.inv.forGood(goodId)
439
160
  }
440
161
 
441
162
  get sellableCargo(): EntityInventory[] {
442
- return this.inventory.filter((c) => c.hasCargo)
163
+ return this.inv.sellable
443
164
  }
444
165
 
445
166
  get hasSellableCargo(): boolean {
446
- return this.inventory.some((c) => c.hasCargo)
167
+ return this.inv.hasSellable
447
168
  }
448
169
 
449
170
  get sellableGoodsCount(): number {
450
- return this.inventory.filter((c) => c.hasCargo).length
171
+ return this.inv.sellableCount
451
172
  }
452
173
 
453
174
  get isFull(): boolean {
@@ -455,105 +176,33 @@ export class Ship extends ServerContract.Types.entity_info implements Scheduleab
455
176
  }
456
177
 
457
178
  get energyPercent(): number {
458
- if (!this.generator) return 0
459
- return (Number(this.energy ?? 0) / Number(this.generator.capacity)) * 100
179
+ if (!this.generator || this.energy === undefined) return 0
180
+ return calcEnergyPercent(this as MovementEntity)
460
181
  }
461
182
 
462
183
  get needsRecharge(): boolean {
463
- if (!this.generator) return false
464
- return UInt64.from(this.energy ?? 0).lt(this.generator.capacity)
184
+ if (!this.generator || this.energy === undefined) return false
185
+ return calcNeedsRecharge(this as MovementEntity)
465
186
  }
466
187
 
467
188
  hasEnergyFor(distance: UInt64): boolean {
468
- if (!this.engines) return false
469
- const energyNeeded = distance.dividing(PRECISION).multiplying(this.engines.drain)
470
- return UInt64.from(this.energy ?? 0).gte(energyNeeded)
471
- }
472
-
473
- calculateSaleValue(prices: Map<number, UInt64>): {
474
- revenue: UInt64
475
- profit: UInt64
476
- cost: UInt64
477
- } {
478
- if (this.cargo.length === 0) {
479
- return {revenue: UInt64.from(0), profit: UInt64.from(0), cost: UInt64.from(0)}
480
- }
481
-
482
- let revenue = UInt64.from(0)
483
- let cost = UInt64.from(0)
484
-
485
- for (const item of this.cargo) {
486
- if (UInt32.from(item.quantity).equals(UInt32.from(0))) continue
487
-
488
- const goodId = Number(item.good_id)
489
- const salePrice = prices.get(goodId)
490
-
491
- if (salePrice) {
492
- revenue = revenue.adding(salePrice.multiplying(item.quantity))
493
- }
494
-
495
- cost = cost.adding(item.unit_cost.multiplying(item.quantity))
496
- }
497
-
498
- const profit = revenue.gte(cost) ? revenue.subtracting(cost) : UInt64.from(0)
189
+ if (!this.engines || !this.generator || this.energy === undefined) return false
190
+ return hasEnergyForDistance(this as MovementEntity, distance)
191
+ }
499
192
 
500
- return {
501
- revenue,
502
- profit,
503
- cost,
504
- }
193
+ calculateSaleValue(prices: Map<number, UInt64>): cargoUtils.SaleValue {
194
+ return cargoUtils.calculateSaleValue(this.cargo, prices)
505
195
  }
506
196
 
507
- calculateSaleValueFromArray(prices: UInt64[]): {
508
- revenue: UInt64
509
- profit: UInt64
510
- cost: UInt64
511
- } {
512
- const priceMap = new Map<number, UInt64>()
513
- prices.forEach((price, index) => {
514
- priceMap.set(index, price)
515
- })
516
- return this.calculateSaleValue(priceMap)
197
+ calculateSaleValueFromArray(prices: UInt64[]): cargoUtils.SaleValue {
198
+ return cargoUtils.calculateSaleValueFromArray(this.cargo, prices)
517
199
  }
518
200
 
519
201
  afterSellGoods(goodsToSell: Array<{goodId: number; quantity: number}>): EntityInventory[] {
520
- if (this.cargo.length === 0) {
521
- return []
522
- }
523
-
524
- return this.cargo.map((item) => {
525
- const saleItem = goodsToSell.find((s) => Number(item.good_id) === s.goodId)
526
- if (!saleItem) {
527
- return new EntityInventory(item)
528
- }
529
-
530
- const currentQty = Number(item.quantity)
531
- const newQty = Math.max(0, currentQty - saleItem.quantity)
532
-
533
- return new EntityInventory(
534
- ServerContract.Types.cargo_item.from({
535
- good_id: item.good_id,
536
- quantity: UInt32.from(newQty),
537
- unit_cost: item.unit_cost,
538
- })
539
- )
540
- })
202
+ return cargoUtils.afterSellGoods(this.cargo, goodsToSell)
541
203
  }
542
204
 
543
205
  afterSellAllGoods(): EntityInventory[] {
544
- if (this.cargo.length === 0) {
545
- return []
546
- }
547
-
548
- return this.cargo.map(
549
- (item) =>
550
- new EntityInventory(
551
- ServerContract.Types.cargo_item.from({
552
- good_id: item.good_id,
553
- quantity: UInt32.from(0),
554
- unit_cost: item.unit_cost,
555
- })
556
- )
557
- )
206
+ return cargoUtils.afterSellAllGoods(this.cargo)
558
207
  }
559
208
  }