@shipload/sdk 2.0.0-rc1 → 2.0.0-rc10

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 (74) hide show
  1. package/lib/shipload.d.ts +1591 -1101
  2. package/lib/shipload.js +6735 -3491
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +6421 -3275
  5. package/lib/shipload.m.js.map +1 -1
  6. package/package.json +6 -6
  7. package/src/capabilities/crafting.ts +26 -0
  8. package/src/capabilities/extraction.ts +36 -0
  9. package/src/capabilities/guards.ts +38 -0
  10. package/src/capabilities/hauling.ts +22 -0
  11. package/src/capabilities/index.ts +8 -0
  12. package/src/capabilities/loading.ts +8 -0
  13. package/src/capabilities/modules.ts +57 -0
  14. package/src/capabilities/movement.ts +29 -0
  15. package/src/capabilities/storage.ts +72 -0
  16. package/src/contracts/server.ts +890 -309
  17. package/src/data/capabilities.ts +408 -0
  18. package/src/data/categories.ts +58 -0
  19. package/src/data/colors.ts +52 -0
  20. package/src/data/items.json +17 -0
  21. package/src/data/locations.ts +53 -0
  22. package/src/data/nebula-adjectives.json +211 -0
  23. package/src/data/nebula-nouns.json +151 -0
  24. package/src/data/recipes.ts +571 -0
  25. package/src/data/syllables.json +1386 -780
  26. package/src/data/tiers.ts +45 -0
  27. package/src/derivation/crafting.ts +197 -0
  28. package/src/derivation/index.ts +28 -0
  29. package/src/derivation/location-size.ts +15 -0
  30. package/src/derivation/resources.ts +142 -0
  31. package/src/derivation/stats.ts +146 -0
  32. package/src/derivation/stratum.ts +118 -0
  33. package/src/entities/cargo-utils.ts +46 -9
  34. package/src/entities/container.ts +106 -0
  35. package/src/entities/entity-inventory.ts +13 -13
  36. package/src/entities/inventory-accessor.ts +42 -0
  37. package/src/entities/location.ts +7 -188
  38. package/src/entities/makers.ts +72 -0
  39. package/src/entities/player.ts +1 -273
  40. package/src/entities/ship-deploy.ts +263 -0
  41. package/src/entities/ship.ts +93 -453
  42. package/src/entities/warehouse.ts +34 -148
  43. package/src/errors.ts +4 -4
  44. package/src/index-module.ts +225 -42
  45. package/src/managers/actions.ts +107 -78
  46. package/src/managers/context.ts +0 -9
  47. package/src/managers/entities.ts +22 -5
  48. package/src/managers/index.ts +0 -1
  49. package/src/managers/locations.ts +15 -79
  50. package/src/market/items.ts +30 -0
  51. package/src/nft/description.ts +175 -0
  52. package/src/nft/deserializers.ts +81 -0
  53. package/src/nft/index.ts +2 -0
  54. package/src/resolution/resolve-item.ts +313 -0
  55. package/src/scheduling/accessor.ts +82 -0
  56. package/src/scheduling/projection.ts +158 -54
  57. package/src/scheduling/schedule.ts +24 -0
  58. package/src/shipload.ts +0 -5
  59. package/src/travel/travel.ts +93 -19
  60. package/src/types/capabilities.ts +71 -0
  61. package/src/types/entity-traits.ts +69 -0
  62. package/src/types/entity.ts +39 -0
  63. package/src/types/index.ts +3 -0
  64. package/src/types.ts +76 -33
  65. package/src/utils/hash.ts +1 -1
  66. package/src/utils/system.ts +139 -11
  67. package/src/data/goods.json +0 -23
  68. package/src/managers/trades.ts +0 -119
  69. package/src/market/goods.ts +0 -31
  70. package/src/market/market.ts +0 -209
  71. package/src/market/rolls.ts +0 -8
  72. package/src/trading/collect.ts +0 -939
  73. package/src/trading/deal.ts +0 -208
  74. package/src/trading/trade.ts +0 -203
@@ -1,405 +1,147 @@
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 schedule from '../scheduling/schedule'
11
25
 
12
26
  export interface ShipStateInput {
13
27
  id: UInt64Type
14
- owner: NameType
28
+ owner: string
15
29
  name: string
16
- location: CoordinatesType | {x: number; y: number; z?: number}
17
- mass: number
18
- capacity: number
19
- energy: number
20
- engines: ServerContract.Types.movement_stats
21
- generator: ServerContract.Types.energy_stats
22
- loaders: ServerContract.Types.loader_stats
30
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
31
+ hullmass?: number
32
+ capacity?: number
33
+ energy?: number
34
+ engines?: ServerContract.Types.movement_stats
35
+ generator?: ServerContract.Types.energy_stats
36
+ loaders?: ServerContract.Types.loader_stats
23
37
  schedule?: ServerContract.Types.schedule
24
38
  cargo?: ServerContract.Types.cargo_item[]
25
39
  }
26
40
 
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[]
41
+ type MovementEntity = {
42
+ engines: ServerContract.Types.movement_stats
43
+ generator: ServerContract.Types.energy_stats
44
+ energy: UInt16
45
+ }
46
+
47
+ export class Ship extends ServerContract.Types.entity_info {
48
+ private _sched?: ScheduleAccessor
49
+ private _inv?: InventoryAccessor
54
50
 
55
51
  get name(): string {
56
52
  return this.entity_name
57
53
  }
58
54
 
55
+ get inv(): InventoryAccessor {
56
+ return (this._inv ??= new InventoryAccessor(this))
57
+ }
58
+
59
59
  get inventory(): EntityInventory[] {
60
- if (!this._inventory) {
61
- this._inventory = this.cargo.map((item) => new EntityInventory(item))
62
- }
63
- return this._inventory
60
+ return this.inv.items
64
61
  }
65
62
 
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)
63
+ get sched(): ScheduleAccessor {
64
+ return (this._sched ??= new ScheduleAccessor(this))
71
65
  }
72
66
 
73
- get hasSchedule(): boolean {
74
- return schedule.hasSchedule(this)
67
+ get maxDistance(): UInt32 {
68
+ if (!this.generator || !this.engines) return UInt32.from(0)
69
+ return maxTravelDistance(this as MovementEntity)
75
70
  }
76
71
 
77
72
  get isIdle(): boolean {
78
73
  return this.is_idle
79
74
  }
80
75
 
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
76
  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
77
+ return Coordinates.from(travelGetFlightOrigin(this, flightTaskIndex))
152
78
  }
153
79
 
154
80
  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
81
+ const dest = getDestinationLocation(this)
82
+ return dest ? Coordinates.from(dest) : undefined
164
83
  }
165
84
 
166
85
  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
- })
86
+ const taskIndex = this.sched.currentTaskIndex(now)
87
+ const progress = this.sched.currentTaskProgress(now)
88
+ return Coordinates.from(getPositionAt(this, taskIndex, progress))
189
89
  }
190
90
 
191
91
  isInFlight(now: Date): boolean {
192
- const taskType = this.currentTaskType(now)
193
- return taskType === TaskType.FLIGHT
92
+ return schedule.isInFlight(this, now)
194
93
  }
195
94
 
196
95
  isRecharging(now: Date): boolean {
197
- const taskType = this.currentTaskType(now)
198
- return taskType === TaskType.RECHARGE
96
+ return schedule.isRecharging(this, now)
199
97
  }
200
98
 
201
99
  isLoading(now: Date): boolean {
202
- const taskType = this.currentTaskType(now)
203
- return taskType === TaskType.LOAD
100
+ return schedule.isLoading(this, now)
204
101
  }
205
102
 
206
103
  isUnloading(now: Date): boolean {
207
- const taskType = this.currentTaskType(now)
208
- return taskType === TaskType.UNLOAD
104
+ return schedule.isUnloading(this, now)
209
105
  }
210
106
 
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
107
+ isExtracting(now: Date): boolean {
108
+ return schedule.isExtracting(this, now)
218
109
  }
219
110
 
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
- }
111
+ get hasEngines(): boolean {
112
+ return this.engines !== undefined
239
113
  }
240
114
 
241
- project(): ProjectedEntity {
242
- const cargoMass = this.calcCargoMass()
243
- const projected = this.createProjectedEntity(cargoMass)
115
+ get hasGenerator(): boolean {
116
+ return this.generator !== undefined
117
+ }
244
118
 
245
- if (!this.schedule) {
246
- return projected
247
- }
119
+ get hasExtractor(): boolean {
120
+ return this.extractor !== undefined
121
+ }
248
122
 
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
- }
123
+ get hasWarp(): boolean {
124
+ return this.warp !== undefined
125
+ }
293
126
 
294
- return projected
127
+ project(): ProjectedEntity {
128
+ return sharedProjectEntity(this)
295
129
  }
296
130
 
297
131
  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
132
+ return sharedProjectEntityAt(this, now)
386
133
  }
387
134
 
388
- get currentLocation(): Coordinates {
389
- return this.location
135
+ get location(): Location {
136
+ return Location.from(this.coordinates)
390
137
  }
391
138
 
392
139
  get totalCargoMass(): UInt64 {
393
- return this.inventory.reduce((sum, c) => sum.adding(c.totalMass), UInt64.from(0))
394
- }
395
-
396
- get cargoValue(): UInt64 {
397
- return this.inventory.reduce((sum, c) => sum.adding(c.totalCost), UInt64.from(0))
140
+ return this.inv.totalMass
398
141
  }
399
142
 
400
143
  get totalMass(): UInt64 {
401
- const cargoMass = this.totalCargoMass
402
- let mass = UInt64.from(this.mass ?? 0).adding(cargoMass)
144
+ let mass = UInt64.from(this.hullmass ?? 0).adding(this.totalCargoMass)
403
145
  if (this.loaders) {
404
146
  mass = mass.adding(UInt64.from(this.loaders.mass).multiplying(this.loaders.quantity))
405
147
  }
@@ -411,43 +153,29 @@ export class Ship extends ServerContract.Types.entity_info implements Scheduleab
411
153
  }
412
154
 
413
155
  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)
156
+ return this.totalMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity)
417
157
  }
418
158
 
419
159
  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
160
+ return this.totalMass.gte(this.maxCapacity)
161
+ ? UInt64.from(0)
162
+ : this.maxCapacity.subtracting(this.totalMass)
435
163
  }
436
164
 
437
- getCargoForGood(goodId: UInt64Type): EntityInventory | undefined {
438
- return this.inventory.find((c) => c.good_id.equals(goodId))
165
+ getCargoForItem(goodId: UInt64Type): EntityInventory | undefined {
166
+ return this.inv.forItem(goodId)
439
167
  }
440
168
 
441
169
  get sellableCargo(): EntityInventory[] {
442
- return this.inventory.filter((c) => c.hasCargo)
170
+ return this.inv.sellable
443
171
  }
444
172
 
445
173
  get hasSellableCargo(): boolean {
446
- return this.inventory.some((c) => c.hasCargo)
174
+ return this.inv.hasSellable
447
175
  }
448
176
 
449
177
  get sellableGoodsCount(): number {
450
- return this.inventory.filter((c) => c.hasCargo).length
178
+ return this.inv.sellableCount
451
179
  }
452
180
 
453
181
  get isFull(): boolean {
@@ -455,105 +183,17 @@ export class Ship extends ServerContract.Types.entity_info implements Scheduleab
455
183
  }
456
184
 
457
185
  get energyPercent(): number {
458
- if (!this.generator) return 0
459
- return (Number(this.energy ?? 0) / Number(this.generator.capacity)) * 100
186
+ if (!this.generator || this.energy === undefined) return 0
187
+ return calcEnergyPercent(this as MovementEntity)
460
188
  }
461
189
 
462
190
  get needsRecharge(): boolean {
463
- if (!this.generator) return false
464
- return UInt64.from(this.energy ?? 0).lt(this.generator.capacity)
191
+ if (!this.generator || this.energy === undefined) return false
192
+ return calcNeedsRecharge(this as MovementEntity)
465
193
  }
466
194
 
467
195
  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)
499
-
500
- return {
501
- revenue,
502
- profit,
503
- cost,
504
- }
505
- }
506
-
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)
517
- }
518
-
519
- 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
- })
541
- }
542
-
543
- 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
- )
196
+ if (!this.engines || !this.generator || this.energy === undefined) return false
197
+ return hasEnergyForDistance(this as MovementEntity, distance)
558
198
  }
559
199
  }