@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.
- package/README.md +349 -1
- package/lib/shipload.d.ts +2016 -230
- package/lib/shipload.js +5733 -2094
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +5425 -2012
- package/lib/shipload.m.js.map +1 -1
- package/package.json +5 -5
- package/src/capabilities/extraction.ts +37 -0
- package/src/capabilities/guards.ts +43 -0
- package/src/capabilities/index.ts +5 -0
- package/src/capabilities/loading.ts +8 -0
- package/src/capabilities/movement.ts +29 -0
- package/src/capabilities/storage.ts +67 -0
- package/src/contracts/server.ts +788 -202
- package/src/data/goods.json +23 -0
- package/src/data/syllables.json +1184 -0
- package/src/entities/cargo-utils.ts +142 -0
- package/src/entities/container.ts +70 -0
- package/src/entities/entity-inventory.ts +39 -0
- package/src/entities/gamestate.ts +152 -0
- package/src/entities/inventory-accessor.ts +46 -0
- package/src/entities/location.ts +255 -0
- package/src/entities/makers.ts +69 -0
- package/src/entities/player.ts +288 -0
- package/src/entities/ship.ts +208 -0
- package/src/entities/warehouse.ts +89 -0
- package/src/errors.ts +46 -9
- package/src/index-module.ts +152 -7
- package/src/managers/actions.ts +200 -0
- package/src/managers/base.ts +25 -0
- package/src/managers/context.ts +104 -0
- package/src/managers/entities.ts +103 -0
- package/src/managers/epochs.ts +47 -0
- package/src/managers/index.ts +9 -0
- package/src/managers/locations.ts +122 -0
- package/src/managers/players.ts +13 -0
- package/src/managers/trades.ts +119 -0
- package/src/market/goods.ts +31 -0
- package/src/{market.ts → market/market.ts} +31 -37
- package/src/{rolls.ts → market/rolls.ts} +3 -3
- package/src/scheduling/accessor.ts +82 -0
- package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
- package/src/scheduling/projection.ts +290 -0
- package/src/scheduling/schedule.ts +179 -0
- package/src/shipload.ts +39 -157
- package/src/trading/collect.ts +938 -0
- package/src/trading/deal.ts +207 -0
- package/src/trading/trade.ts +203 -0
- package/src/travel/travel.ts +486 -0
- package/src/types/capabilities.ts +79 -0
- package/src/types/entity-traits.ts +70 -0
- package/src/types/entity.ts +36 -0
- package/src/types/index.ts +3 -0
- package/src/types.ts +127 -25
- package/src/{hash.ts → utils/hash.ts} +1 -1
- package/src/utils/system.ts +155 -0
- package/src/goods.ts +0 -124
- package/src/ship.ts +0 -36
- package/src/state.ts +0 -0
- package/src/syllables.ts +0 -1184
- package/src/system.ts +0 -37
- 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
|
+
}
|