@shipload/sdk 0.7.1 → 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 (62) hide show
  1. package/README.md +349 -1
  2. package/lib/shipload.d.ts +2016 -230
  3. package/lib/shipload.js +5733 -2094
  4. package/lib/shipload.js.map +1 -1
  5. package/lib/shipload.m.js +5425 -2012
  6. package/lib/shipload.m.js.map +1 -1
  7. package/package.json +5 -5
  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 +788 -202
  15. package/src/data/goods.json +23 -0
  16. package/src/data/syllables.json +1184 -0
  17. package/src/entities/cargo-utils.ts +142 -0
  18. package/src/entities/container.ts +70 -0
  19. package/src/entities/entity-inventory.ts +39 -0
  20. package/src/entities/gamestate.ts +152 -0
  21. package/src/entities/inventory-accessor.ts +46 -0
  22. package/src/entities/location.ts +255 -0
  23. package/src/entities/makers.ts +69 -0
  24. package/src/entities/player.ts +288 -0
  25. package/src/entities/ship.ts +208 -0
  26. package/src/entities/warehouse.ts +89 -0
  27. package/src/errors.ts +46 -9
  28. package/src/index-module.ts +152 -7
  29. package/src/managers/actions.ts +200 -0
  30. package/src/managers/base.ts +25 -0
  31. package/src/managers/context.ts +104 -0
  32. package/src/managers/entities.ts +103 -0
  33. package/src/managers/epochs.ts +47 -0
  34. package/src/managers/index.ts +9 -0
  35. package/src/managers/locations.ts +122 -0
  36. package/src/managers/players.ts +13 -0
  37. package/src/managers/trades.ts +119 -0
  38. package/src/market/goods.ts +31 -0
  39. package/src/{market.ts → market/market.ts} +31 -37
  40. package/src/{rolls.ts → market/rolls.ts} +3 -3
  41. package/src/scheduling/accessor.ts +82 -0
  42. package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
  43. package/src/scheduling/projection.ts +290 -0
  44. package/src/scheduling/schedule.ts +179 -0
  45. package/src/shipload.ts +39 -157
  46. package/src/trading/collect.ts +938 -0
  47. package/src/trading/deal.ts +207 -0
  48. package/src/trading/trade.ts +203 -0
  49. package/src/travel/travel.ts +486 -0
  50. package/src/types/capabilities.ts +79 -0
  51. package/src/types/entity-traits.ts +70 -0
  52. package/src/types/entity.ts +36 -0
  53. package/src/types/index.ts +3 -0
  54. package/src/types.ts +127 -25
  55. package/src/{hash.ts → utils/hash.ts} +1 -1
  56. package/src/utils/system.ts +155 -0
  57. package/src/goods.ts +0 -124
  58. package/src/ship.ts +0 -36
  59. package/src/state.ts +0 -0
  60. package/src/syllables.ts +0 -1184
  61. package/src/system.ts +0 -37
  62. package/src/travel.ts +0 -259
@@ -0,0 +1,69 @@
1
+ import {Name, UInt16, UInt32, UInt64} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import {Ship, ShipStateInput} from './ship'
4
+ import {Warehouse, WarehouseStateInput} from './warehouse'
5
+ import {Container, ContainerStateInput} from './container'
6
+
7
+ export function makeShip(state: ShipStateInput): Ship {
8
+ const entityInfo = ServerContract.Types.entity_info.from({
9
+ type: Name.from('ship'),
10
+ id: UInt64.from(state.id),
11
+ owner: Name.from(state.owner),
12
+ entity_name: state.name,
13
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
14
+ hullmass: UInt32.from(state.hullmass),
15
+ capacity: UInt32.from(state.capacity),
16
+ energy: UInt16.from(state.energy),
17
+ cargomass: UInt32.from(0),
18
+ cargo: state.cargo || [],
19
+ is_idle: !state.schedule,
20
+ current_task_elapsed: UInt32.from(0),
21
+ current_task_remaining: UInt32.from(0),
22
+ pending_tasks: [],
23
+ engines: state.engines,
24
+ generator: state.generator,
25
+ loaders: state.loaders,
26
+ schedule: state.schedule,
27
+ })
28
+ return new Ship(entityInfo)
29
+ }
30
+
31
+ export function makeWarehouse(state: WarehouseStateInput): Warehouse {
32
+ const entityInfo = ServerContract.Types.entity_info.from({
33
+ type: Name.from('warehouse'),
34
+ id: UInt64.from(state.id),
35
+ owner: Name.from(state.owner),
36
+ entity_name: state.name,
37
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
38
+ capacity: UInt32.from(state.capacity),
39
+ cargomass: UInt32.from(0),
40
+ cargo: state.cargo || [],
41
+ loaders: state.loaders,
42
+ is_idle: !state.schedule,
43
+ current_task_elapsed: UInt32.from(0),
44
+ current_task_remaining: UInt32.from(0),
45
+ pending_tasks: [],
46
+ schedule: state.schedule,
47
+ })
48
+ return new Warehouse(entityInfo)
49
+ }
50
+
51
+ export function makeContainer(state: ContainerStateInput): Container {
52
+ const entityInfo = ServerContract.Types.entity_info.from({
53
+ type: Name.from('container'),
54
+ id: UInt64.from(state.id),
55
+ owner: Name.from(state.owner),
56
+ entity_name: state.name,
57
+ coordinates: ServerContract.Types.coordinates.from(state.coordinates),
58
+ hullmass: UInt32.from(state.hullmass),
59
+ capacity: UInt32.from(state.capacity),
60
+ cargomass: UInt32.from(state.cargomass || 0),
61
+ cargo: [],
62
+ is_idle: !state.schedule,
63
+ current_task_elapsed: UInt32.from(0),
64
+ current_task_remaining: UInt32.from(0),
65
+ pending_tasks: [],
66
+ schedule: state.schedule,
67
+ })
68
+ return new Container(entityInfo)
69
+ }
@@ -0,0 +1,288 @@
1
+ import {
2
+ Int64,
3
+ Int64Type,
4
+ Name,
5
+ NameType,
6
+ UInt32,
7
+ UInt32Type,
8
+ UInt64,
9
+ UInt64Type,
10
+ } from '@wharfkit/antelope'
11
+ import {ServerContract} from '../contracts'
12
+
13
+ export interface PlayerStateInput {
14
+ owner: NameType
15
+ balance: UInt64Type
16
+ debt: UInt32Type
17
+ networth: Int64Type
18
+ }
19
+
20
+ /**
21
+ * Player helper class extending player_row with computed financial properties.
22
+ * Provides easy access to balance, debt, networth, and loan calculations.
23
+ */
24
+ export class Player extends ServerContract.Types.player_row {
25
+ /**
26
+ * Construct a Player instance from individual state pieces.
27
+ * Used by UI's ReactivePlayer to reconstruct Player from reactive state.
28
+ */
29
+ static fromState(state: PlayerStateInput): Player {
30
+ const playerRow = ServerContract.Types.player_row.from({
31
+ owner: Name.from(state.owner),
32
+ balance: UInt64.from(state.balance),
33
+ debt: UInt32.from(state.debt),
34
+ networth: Int64.from(state.networth),
35
+ })
36
+ return new Player(playerRow)
37
+ }
38
+ // Constants for game rules (match smart contract)
39
+ private static readonly MAX_LOAN = 1000000
40
+ // Contract formula: 2500 * pow(5, sequence - 1) = 500 * pow(5, sequence)
41
+ private static readonly BASE_SHIP_COST = 500
42
+ private static readonly SHIP_COST_MULTIPLIER = 5
43
+
44
+ // Optional ship count for nextShipCost calculation
45
+ private _shipCount?: number
46
+
47
+ /**
48
+ * Set the current ship count (needed for nextShipCost calculation)
49
+ */
50
+ setShipCount(count: number): void {
51
+ this._shipCount = count
52
+ }
53
+
54
+ /**
55
+ * Get the current ship count (if set)
56
+ */
57
+ get shipCount(): number | undefined {
58
+ return this._shipCount
59
+ }
60
+
61
+ /**
62
+ * Calculate the cost of the next ship based on current ship count
63
+ * Matches contract: pow(5, sequence) * 100
64
+ * @param shipCount - Optional ship count (uses cached value if not provided)
65
+ */
66
+ getNextShipCost(shipCount?: number): UInt64 {
67
+ const count = shipCount ?? this._shipCount ?? 0
68
+ const cost = Math.pow(Player.SHIP_COST_MULTIPLIER, count) * Player.BASE_SHIP_COST
69
+ return UInt64.from(Math.floor(cost))
70
+ }
71
+
72
+ /**
73
+ * Get the cost of the next ship based on cached ship count
74
+ */
75
+ get nextShipCost(): UInt64 {
76
+ return this.getNextShipCost()
77
+ }
78
+
79
+ /**
80
+ * Check if player can afford to buy a ship
81
+ * @param shipCount - Optional ship count (uses cached value if not provided)
82
+ */
83
+ canBuyShip(shipCount?: number): boolean {
84
+ return UInt64.from(this.balance).gte(this.getNextShipCost(shipCount))
85
+ }
86
+
87
+ /**
88
+ * Calculate available loan amount (max loan - current debt)
89
+ */
90
+ get availableLoan(): UInt64 {
91
+ const maxLoan = UInt64.from(Player.MAX_LOAN)
92
+ if (UInt64.from(this.debt).gte(maxLoan)) {
93
+ return UInt64.from(0)
94
+ }
95
+ return maxLoan.subtracting(this.debt)
96
+ }
97
+
98
+ /**
99
+ * Check if player can take out a loan
100
+ */
101
+ get canTakeLoan(): boolean {
102
+ return this.availableLoan.gt(UInt64.zero)
103
+ }
104
+
105
+ /**
106
+ * Check if player can pay back loan
107
+ */
108
+ get canPayLoan(): boolean {
109
+ return UInt64.from(this.debt).gt(UInt64.zero) && UInt64.from(this.balance).gt(UInt64.zero)
110
+ }
111
+
112
+ /**
113
+ * Calculate maximum payback amount (min of debt and balance)
114
+ */
115
+ get maxPayback(): UInt64 {
116
+ return UInt64.from(this.debt).lt(this.balance) ? this.debt : this.balance
117
+ }
118
+
119
+ /**
120
+ * Get the maximum loan amount (constant)
121
+ */
122
+ static get MAX_LOAN_LIMIT(): number {
123
+ return Player.MAX_LOAN
124
+ }
125
+
126
+ /**
127
+ * Check if player is in debt
128
+ */
129
+ get hasDebt(): boolean {
130
+ return UInt64.from(this.debt).gt(UInt64.zero)
131
+ }
132
+
133
+ /**
134
+ * Check if player is solvent (positive networth)
135
+ */
136
+ get isSolvent(): boolean {
137
+ return this.networth.gte(Int64.zero)
138
+ }
139
+
140
+ /**
141
+ * Create an optimistic update for balance changes
142
+ * Uses integer math to match contract
143
+ * @param delta - Amount to change (can be negative)
144
+ */
145
+ withBalanceChange(delta: UInt64 | number): Player {
146
+ const newPlayer = Player.from(this)
147
+ const amount = typeof delta === 'number' ? UInt64.from(Math.abs(delta)) : delta
148
+
149
+ if (typeof delta === 'number' && delta < 0) {
150
+ // Subtract, ensuring we don't go below 0
151
+ newPlayer.balance = UInt64.from(this.balance).gte(amount)
152
+ ? this.balance.subtracting(amount)
153
+ : UInt64.from(0)
154
+ } else {
155
+ // Add
156
+ newPlayer.balance = this.balance.adding(amount)
157
+ }
158
+
159
+ // Calculate networth as Int64 (can be negative)
160
+ const balanceInt = Int64.from(newPlayer.balance)
161
+ const debtInt = Int64.from(newPlayer.debt)
162
+ newPlayer.networth = balanceInt.subtracting(debtInt)
163
+ return newPlayer
164
+ }
165
+
166
+ /**
167
+ * Create an optimistic update for debt changes
168
+ * Uses integer math to match contract
169
+ * @param delta - Amount to change (can be negative)
170
+ */
171
+ withDebtChange(delta: UInt64 | number): Player {
172
+ const newPlayer = Player.from(this)
173
+ const amount = typeof delta === 'number' ? UInt64.from(Math.abs(delta)) : delta
174
+
175
+ if (typeof delta === 'number' && delta < 0) {
176
+ // Subtract, ensuring we don't go below 0
177
+ newPlayer.debt = UInt64.from(this.debt).gte(amount)
178
+ ? this.debt.subtracting(amount)
179
+ : UInt64.from(0)
180
+ } else {
181
+ // Add
182
+ newPlayer.debt = this.debt.adding(amount)
183
+ }
184
+
185
+ // Calculate networth as Int64 (can be negative)
186
+ const balanceInt = Int64.from(newPlayer.balance)
187
+ const debtInt = Int64.from(newPlayer.debt)
188
+ newPlayer.networth = balanceInt.subtracting(debtInt)
189
+ return newPlayer
190
+ }
191
+
192
+ /**
193
+ * Create an optimistic update for taking a loan
194
+ */
195
+ withLoan(amount: UInt64): Player {
196
+ const newPlayer = Player.from(this)
197
+ newPlayer.balance = this.balance.adding(amount)
198
+ newPlayer.debt = this.debt.adding(amount)
199
+ // Calculate networth as Int64 (can be negative)
200
+ const balanceInt = Int64.from(newPlayer.balance)
201
+ const debtInt = Int64.from(newPlayer.debt)
202
+ newPlayer.networth = balanceInt.subtracting(debtInt)
203
+ return newPlayer
204
+ }
205
+
206
+ /**
207
+ * Create an optimistic update for paying back a loan
208
+ */
209
+ withLoanPayment(amount: UInt64): Player {
210
+ const actualPayment = this.maxPayback.lt(amount) ? this.maxPayback : amount
211
+ const newPlayer = Player.from(this)
212
+ newPlayer.balance = this.balance.subtracting(actualPayment)
213
+ newPlayer.debt = this.debt.subtracting(actualPayment)
214
+ // Calculate networth as Int64 (can be negative)
215
+ const balanceInt = Int64.from(newPlayer.balance)
216
+ const debtInt = Int64.from(newPlayer.debt)
217
+ newPlayer.networth = balanceInt.subtracting(debtInt)
218
+ return newPlayer
219
+ }
220
+
221
+ /**
222
+ * Simulate networth update from selling goods.
223
+ * Matches contract: networth += (sellPrice - paid * quantity)
224
+ * Contract reference: market.cpp:75
225
+ *
226
+ * @param sellPrice - Total revenue from sale (price * quantity)
227
+ * @param paidPerUnit - Average cost per unit paid (from cargo.paid)
228
+ * @param quantity - Quantity being sold
229
+ * @returns New player with updated networth
230
+ *
231
+ * @example
232
+ * // Sold 10 units at 150 each (revenue=1500), paid 100 per unit
233
+ * const newPlayer = player.withSaleNetworth(
234
+ * UInt64.from(1500),
235
+ * UInt64.from(100),
236
+ * UInt32.from(10)
237
+ * )
238
+ * // Networth increases by: 1500 - (100*10) = 500
239
+ */
240
+ withSaleNetworth(sellPrice: UInt64, paidPerUnit: UInt64, quantity: UInt64): Player {
241
+ // Match contract: price - paid * quantity
242
+ const cost = paidPerUnit.multiplying(quantity)
243
+ const profit = sellPrice.gte(cost) ? sellPrice.subtracting(cost) : Int64.from(0)
244
+
245
+ const newPlayer = Player.from(this)
246
+ newPlayer.networth = Int64.from(this.networth).adding(profit)
247
+ return newPlayer
248
+ }
249
+
250
+ /**
251
+ * Simulate complete sell goods transaction.
252
+ * Updates both balance (adds revenue) and networth (adds profit).
253
+ * Matches contract actions: update_balance + update_networth
254
+ *
255
+ * @param sellPrice - Total revenue from sale (price * quantity)
256
+ * @param paidPerUnit - Average cost per unit paid (from cargo.paid)
257
+ * @param quantity - Quantity being sold
258
+ * @returns New player with updated balance and networth
259
+ */
260
+ withSellGoods(sellPrice: UInt64, paidPerUnit: UInt64, quantity: UInt64): Player {
261
+ const cost = paidPerUnit.multiplying(quantity)
262
+ const profit = sellPrice.gte(cost) ? sellPrice.subtracting(cost) : Int64.from(0)
263
+
264
+ const newPlayer = Player.from(this)
265
+ newPlayer.balance = this.balance.adding(sellPrice)
266
+ newPlayer.networth = Int64.from(this.networth).adding(profit)
267
+ return newPlayer
268
+ }
269
+
270
+ /**
271
+ * Simulate complete buy goods transaction.
272
+ * Updates balance (subtracts cost).
273
+ *
274
+ * @param purchaseCost - Total cost of purchase (price * quantity)
275
+ * @returns New player with updated balance
276
+ */
277
+ withBuyGoods(purchaseCost: UInt64): Player {
278
+ const newPlayer = Player.from(this)
279
+ newPlayer.balance = UInt64.from(this.balance).gte(purchaseCost)
280
+ ? this.balance.subtracting(purchaseCost)
281
+ : UInt64.from(0)
282
+ // Calculate networth as Int64 (can be negative)
283
+ const balanceInt = Int64.from(newPlayer.balance)
284
+ const debtInt = Int64.from(newPlayer.debt)
285
+ newPlayer.networth = balanceInt.subtracting(debtInt)
286
+ return newPlayer
287
+ }
288
+ }
@@ -0,0 +1,208 @@
1
+ import {UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
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'
14
+ import {Location} from './location'
15
+ import {ScheduleAccessor} from '../scheduling/accessor'
16
+ import {InventoryAccessor} from './inventory-accessor'
17
+ import {EntityInventory} from './entity-inventory'
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'
26
+
27
+ export interface ShipStateInput {
28
+ id: UInt64Type
29
+ owner: string
30
+ name: string
31
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
32
+ hullmass: number
33
+ capacity: number
34
+ energy: number
35
+ engines: ServerContract.Types.movement_stats
36
+ generator: ServerContract.Types.energy_stats
37
+ loaders: ServerContract.Types.loader_stats
38
+ schedule?: ServerContract.Types.schedule
39
+ cargo?: ServerContract.Types.cargo_item[]
40
+ }
41
+
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
51
+
52
+ get name(): string {
53
+ return this.entity_name
54
+ }
55
+
56
+ get inv(): InventoryAccessor {
57
+ return (this._inv ??= new InventoryAccessor(this))
58
+ }
59
+
60
+ get inventory(): EntityInventory[] {
61
+ return this.inv.items
62
+ }
63
+
64
+ get sched(): ScheduleAccessor {
65
+ return (this._sched ??= new ScheduleAccessor(this))
66
+ }
67
+
68
+ get maxDistance(): UInt32 {
69
+ if (!this.generator || !this.engines) return UInt32.from(0)
70
+ return maxTravelDistance(this as MovementEntity)
71
+ }
72
+
73
+ get isIdle(): boolean {
74
+ return this.is_idle
75
+ }
76
+
77
+ getFlightOrigin(flightTaskIndex: number): Coordinates {
78
+ return Coordinates.from(travelGetFlightOrigin(this, flightTaskIndex))
79
+ }
80
+
81
+ destinationLocation(): Coordinates | undefined {
82
+ const dest = getDestinationLocation(this)
83
+ return dest ? Coordinates.from(dest) : undefined
84
+ }
85
+
86
+ positionAt(now: Date): Coordinates {
87
+ const taskIndex = this.sched.currentTaskIndex(now)
88
+ const progress = this.sched.currentTaskProgress(now)
89
+ return Coordinates.from(getPositionAt(this, taskIndex, progress))
90
+ }
91
+
92
+ isInFlight(now: Date): boolean {
93
+ return schedule.isInFlight(this, now)
94
+ }
95
+
96
+ isRecharging(now: Date): boolean {
97
+ return schedule.isRecharging(this, now)
98
+ }
99
+
100
+ isLoading(now: Date): boolean {
101
+ return schedule.isLoading(this, now)
102
+ }
103
+
104
+ isUnloading(now: Date): boolean {
105
+ return schedule.isUnloading(this, now)
106
+ }
107
+
108
+ isExtracting(now: Date): boolean {
109
+ return schedule.isExtracting(this, now)
110
+ }
111
+
112
+ get hasExtractor(): boolean {
113
+ return this.extractor !== undefined
114
+ }
115
+
116
+ project(): ProjectedEntity {
117
+ return sharedProjectEntity(this)
118
+ }
119
+
120
+ projectAt(now: Date): ProjectedEntity {
121
+ return sharedProjectEntityAt(this, now)
122
+ }
123
+
124
+ get location(): Location {
125
+ return Location.from(this.coordinates)
126
+ }
127
+
128
+ get totalCargoMass(): UInt64 {
129
+ return this.inv.totalMass
130
+ }
131
+
132
+ get cargoValue(): UInt64 {
133
+ return this.inv.totalValue
134
+ }
135
+
136
+ get totalMass(): UInt64 {
137
+ let mass = UInt64.from(this.hullmass ?? 0).adding(this.totalCargoMass)
138
+ if (this.loaders) {
139
+ mass = mass.adding(UInt64.from(this.loaders.mass).multiplying(this.loaders.quantity))
140
+ }
141
+ return mass
142
+ }
143
+
144
+ get maxCapacity(): UInt64 {
145
+ return UInt64.from(this.capacity)
146
+ }
147
+
148
+ hasSpace(goodMass: UInt64, quantity: number): boolean {
149
+ return this.totalMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity)
150
+ }
151
+
152
+ get availableCapacity(): UInt64 {
153
+ return this.totalMass.gte(this.maxCapacity)
154
+ ? UInt64.from(0)
155
+ : this.maxCapacity.subtracting(this.totalMass)
156
+ }
157
+
158
+ getCargoForGood(goodId: UInt64Type): EntityInventory | undefined {
159
+ return this.inv.forGood(goodId)
160
+ }
161
+
162
+ get sellableCargo(): EntityInventory[] {
163
+ return this.inv.sellable
164
+ }
165
+
166
+ get hasSellableCargo(): boolean {
167
+ return this.inv.hasSellable
168
+ }
169
+
170
+ get sellableGoodsCount(): number {
171
+ return this.inv.sellableCount
172
+ }
173
+
174
+ get isFull(): boolean {
175
+ return this.totalMass.gte(this.maxCapacity)
176
+ }
177
+
178
+ get energyPercent(): number {
179
+ if (!this.generator || this.energy === undefined) return 0
180
+ return calcEnergyPercent(this as MovementEntity)
181
+ }
182
+
183
+ get needsRecharge(): boolean {
184
+ if (!this.generator || this.energy === undefined) return false
185
+ return calcNeedsRecharge(this as MovementEntity)
186
+ }
187
+
188
+ hasEnergyFor(distance: UInt64): boolean {
189
+ if (!this.engines || !this.generator || this.energy === undefined) return false
190
+ return hasEnergyForDistance(this as MovementEntity, distance)
191
+ }
192
+
193
+ calculateSaleValue(prices: Map<number, UInt64>): cargoUtils.SaleValue {
194
+ return cargoUtils.calculateSaleValue(this.cargo, prices)
195
+ }
196
+
197
+ calculateSaleValueFromArray(prices: UInt64[]): cargoUtils.SaleValue {
198
+ return cargoUtils.calculateSaleValueFromArray(this.cargo, prices)
199
+ }
200
+
201
+ afterSellGoods(goodsToSell: Array<{goodId: number; quantity: number}>): EntityInventory[] {
202
+ return cargoUtils.afterSellGoods(this.cargo, goodsToSell)
203
+ }
204
+
205
+ afterSellAllGoods(): EntityInventory[] {
206
+ return cargoUtils.afterSellAllGoods(this.cargo)
207
+ }
208
+ }
@@ -0,0 +1,89 @@
1
+ import {UInt64, UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import {CoordinatesType} from '../types'
4
+ import {Location} from './location'
5
+ import {ScheduleAccessor} from '../scheduling/accessor'
6
+ import {InventoryAccessor} from './inventory-accessor'
7
+ import {EntityInventory} from './entity-inventory'
8
+ import * as schedule from '../scheduling/schedule'
9
+
10
+ export interface WarehouseStateInput {
11
+ id: UInt64Type
12
+ owner: string
13
+ name: string
14
+ coordinates: CoordinatesType | {x: number; y: number; z?: number}
15
+ capacity: number
16
+ loaders: ServerContract.Types.loader_stats
17
+ schedule?: ServerContract.Types.schedule
18
+ cargo?: ServerContract.Types.cargo_item[]
19
+ }
20
+
21
+ export class Warehouse extends ServerContract.Types.entity_info {
22
+ private _sched?: ScheduleAccessor
23
+ private _inv?: InventoryAccessor
24
+
25
+ get name(): string {
26
+ return this.entity_name
27
+ }
28
+
29
+ get inv(): InventoryAccessor {
30
+ return (this._inv ??= new InventoryAccessor(this))
31
+ }
32
+
33
+ get inventory(): EntityInventory[] {
34
+ return this.inv.items
35
+ }
36
+
37
+ get sched(): ScheduleAccessor {
38
+ return (this._sched ??= new ScheduleAccessor(this))
39
+ }
40
+
41
+ get isIdle(): boolean {
42
+ return this.is_idle
43
+ }
44
+
45
+ isLoading(now: Date): boolean {
46
+ return schedule.isLoading(this, now)
47
+ }
48
+
49
+ isUnloading(now: Date): boolean {
50
+ return schedule.isUnloading(this, now)
51
+ }
52
+
53
+ get location(): Location {
54
+ return Location.from(this.coordinates)
55
+ }
56
+
57
+ get totalCargoMass(): UInt64 {
58
+ return this.inv.totalMass
59
+ }
60
+
61
+ get cargoValue(): UInt64 {
62
+ return this.inv.totalValue
63
+ }
64
+
65
+ get maxCapacity(): UInt64 {
66
+ return UInt64.from(this.capacity)
67
+ }
68
+
69
+ get availableCapacity(): UInt64 {
70
+ const cargo = this.totalCargoMass
71
+ return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
72
+ }
73
+
74
+ hasSpace(goodMass: UInt64, quantity: number): boolean {
75
+ return this.totalCargoMass.adding(goodMass.multiplying(quantity)).lte(this.maxCapacity)
76
+ }
77
+
78
+ get isFull(): boolean {
79
+ return this.totalCargoMass.gte(this.maxCapacity)
80
+ }
81
+
82
+ getCargoForGood(goodId: UInt64Type): EntityInventory | undefined {
83
+ return this.inv.forGood(goodId)
84
+ }
85
+
86
+ get orbitalAltitude(): number {
87
+ return this.coordinates.z?.toNumber() || 0
88
+ }
89
+ }