@shipload/sdk 0.7.0 → 2.0.0-rc1
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/lib/shipload.d.ts +1651 -226
- package/lib/shipload.js +4960 -1972
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +4789 -1941
- package/lib/shipload.m.js.map +1 -1
- package/package.json +5 -4
- package/src/contracts/platform.ts +30 -30
- package/src/contracts/server.ts +635 -253
- package/src/data/goods.json +23 -0
- package/src/data/syllables.json +1184 -0
- package/src/entities/cargo-utils.ts +47 -0
- package/src/entities/entity-inventory.ts +39 -0
- package/src/entities/gamestate.ts +152 -0
- package/src/entities/location.ts +241 -0
- package/src/entities/player.ts +287 -0
- package/src/entities/ship.ts +559 -0
- package/src/entities/warehouse.ts +205 -0
- package/src/errors.ts +46 -9
- package/src/index-module.ts +119 -7
- package/src/managers/actions.ts +168 -0
- package/src/managers/base.ts +25 -0
- package/src/managers/context.ts +104 -0
- package/src/managers/entities.ts +86 -0
- package/src/managers/epochs.ts +47 -0
- package/src/managers/index.ts +9 -0
- package/src/managers/locations.ts +103 -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} +32 -37
- package/src/{rolls.ts → market/rolls.ts} +3 -3
- package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
- package/src/scheduling/projection.ts +218 -0
- package/src/scheduling/schedule.ts +155 -0
- package/src/shipload.ts +39 -157
- package/src/trading/collect.ts +939 -0
- package/src/trading/deal.ts +208 -0
- package/src/trading/trade.ts +203 -0
- package/src/travel/travel.ts +425 -0
- package/src/types.ts +60 -25
- package/src/utils/system.ts +27 -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 -36
- package/src/travel.ts +0 -259
- /package/src/{hash.ts → utils/hash.ts} +0 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import {UInt16, UInt32, UInt64} from '@wharfkit/antelope'
|
|
2
|
+
import {ServerContract} from '../contracts'
|
|
3
|
+
import {Coordinates, PRECISION, TaskType} from '../types'
|
|
4
|
+
import {distanceBetweenCoordinates, lerp} from '../travel/travel'
|
|
5
|
+
import {getGood} from '../market/goods'
|
|
6
|
+
import * as schedule from './schedule'
|
|
7
|
+
import {ScheduleData} from './schedule'
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Projected state of an entity after scheduled tasks complete.
|
|
11
|
+
* Mirrors contract's projected_entity struct.
|
|
12
|
+
*/
|
|
13
|
+
export interface ProjectedEntity {
|
|
14
|
+
location: Coordinates
|
|
15
|
+
energy: UInt16
|
|
16
|
+
cargoMass: UInt64
|
|
17
|
+
shipMass: UInt32
|
|
18
|
+
capacity?: UInt64
|
|
19
|
+
engines?: ServerContract.Types.movement_stats
|
|
20
|
+
loaders?: ServerContract.Types.loader_stats
|
|
21
|
+
generator?: ServerContract.Types.energy_stats
|
|
22
|
+
readonly totalMass: UInt64
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Interface for entities that can be projected.
|
|
27
|
+
* Ships and Warehouses both implement this.
|
|
28
|
+
*/
|
|
29
|
+
export interface Projectable extends ScheduleData {
|
|
30
|
+
location: Coordinates
|
|
31
|
+
energy: UInt16
|
|
32
|
+
mass: UInt32
|
|
33
|
+
generator?: ServerContract.Types.energy_stats
|
|
34
|
+
engines?: ServerContract.Types.movement_stats
|
|
35
|
+
loaders?: ServerContract.Types.loader_stats
|
|
36
|
+
capacity?: UInt64
|
|
37
|
+
calcCargoMass(): UInt64
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Create initial projected entity state from a projectable entity.
|
|
42
|
+
*/
|
|
43
|
+
export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
44
|
+
const cargoMass = entity.calcCargoMass()
|
|
45
|
+
const shipMass = UInt32.from(entity.mass)
|
|
46
|
+
const loaders = entity.loaders
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
location: Coordinates.from(entity.location),
|
|
50
|
+
energy: UInt16.from(entity.energy),
|
|
51
|
+
cargoMass,
|
|
52
|
+
shipMass,
|
|
53
|
+
capacity: entity.capacity,
|
|
54
|
+
engines: entity.engines,
|
|
55
|
+
generator: entity.generator,
|
|
56
|
+
loaders,
|
|
57
|
+
get totalMass() {
|
|
58
|
+
let mass = UInt64.from(this.shipMass).adding(this.cargoMass)
|
|
59
|
+
if (this.loaders) {
|
|
60
|
+
mass = mass.adding(this.loaders.mass.multiplying(this.loaders.quantity))
|
|
61
|
+
}
|
|
62
|
+
return mass
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Apply a recharge task to projected state.
|
|
69
|
+
*/
|
|
70
|
+
function applyRechargeTask(
|
|
71
|
+
projected: ProjectedEntity,
|
|
72
|
+
_task: ServerContract.Types.task,
|
|
73
|
+
options: {complete: boolean; progress?: number}
|
|
74
|
+
): void {
|
|
75
|
+
if (!projected.generator) return
|
|
76
|
+
|
|
77
|
+
if (options.complete) {
|
|
78
|
+
projected.energy = UInt16.from(projected.generator.capacity)
|
|
79
|
+
} else if (options.progress !== undefined) {
|
|
80
|
+
const capacity = Number(projected.generator.capacity)
|
|
81
|
+
const currentEnergy = Number(projected.energy)
|
|
82
|
+
const rechargeAmount = (capacity - currentEnergy) * options.progress
|
|
83
|
+
projected.energy = UInt16.from(Math.min(capacity, currentEnergy + rechargeAmount))
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Apply a flight task to projected state.
|
|
89
|
+
*/
|
|
90
|
+
function applyFlightTask(
|
|
91
|
+
projected: ProjectedEntity,
|
|
92
|
+
task: ServerContract.Types.task,
|
|
93
|
+
options: {complete: boolean; progress?: number}
|
|
94
|
+
): void {
|
|
95
|
+
if (!task.location || !projected.engines) return
|
|
96
|
+
|
|
97
|
+
const origin = projected.location
|
|
98
|
+
const destination = Coordinates.from(task.location)
|
|
99
|
+
const distance = distanceBetweenCoordinates(origin, task.location)
|
|
100
|
+
const energyUsage = distance.dividing(PRECISION).multiplying(projected.engines.drain)
|
|
101
|
+
|
|
102
|
+
if (options.complete) {
|
|
103
|
+
projected.energy = projected.energy.gt(energyUsage)
|
|
104
|
+
? UInt16.from(projected.energy.subtracting(energyUsage))
|
|
105
|
+
: UInt16.from(0)
|
|
106
|
+
projected.location = destination
|
|
107
|
+
} else if (options.progress !== undefined) {
|
|
108
|
+
const interpolated = lerp(origin, destination, options.progress)
|
|
109
|
+
projected.location = Coordinates.from({
|
|
110
|
+
x: Math.round(interpolated.x),
|
|
111
|
+
y: Math.round(interpolated.y),
|
|
112
|
+
})
|
|
113
|
+
const partialEnergy = UInt64.from(Math.floor(Number(energyUsage) * options.progress))
|
|
114
|
+
projected.energy = projected.energy.gt(partialEnergy)
|
|
115
|
+
? UInt16.from(projected.energy.subtracting(partialEnergy))
|
|
116
|
+
: UInt16.from(0)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Apply a load task to projected state.
|
|
122
|
+
*/
|
|
123
|
+
function applyLoadTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
124
|
+
for (const item of task.cargo) {
|
|
125
|
+
const good = getGood(item.good_id)
|
|
126
|
+
projected.cargoMass = projected.cargoMass.adding(good.mass.multiplying(item.quantity))
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Apply an unload task to projected state.
|
|
132
|
+
*/
|
|
133
|
+
function applyUnloadTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
134
|
+
for (const item of task.cargo) {
|
|
135
|
+
const good = getGood(item.good_id)
|
|
136
|
+
const cargoMass = good.mass.multiplying(item.quantity)
|
|
137
|
+
projected.cargoMass = projected.cargoMass.gt(cargoMass)
|
|
138
|
+
? projected.cargoMass.subtracting(cargoMass)
|
|
139
|
+
: UInt64.from(0)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Project entity state after all scheduled tasks complete.
|
|
145
|
+
* Mirrors contract's project_ship/project_warehouse methods.
|
|
146
|
+
*/
|
|
147
|
+
export function projectEntity(entity: Projectable): ProjectedEntity {
|
|
148
|
+
const projected = createProjectedEntity(entity)
|
|
149
|
+
|
|
150
|
+
if (!entity.schedule) {
|
|
151
|
+
return projected
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
for (const task of entity.schedule.tasks) {
|
|
155
|
+
switch (task.type.toNumber()) {
|
|
156
|
+
case TaskType.RECHARGE:
|
|
157
|
+
applyRechargeTask(projected, task, {complete: true})
|
|
158
|
+
break
|
|
159
|
+
case TaskType.FLIGHT:
|
|
160
|
+
applyFlightTask(projected, task, {complete: true})
|
|
161
|
+
break
|
|
162
|
+
case TaskType.LOAD:
|
|
163
|
+
applyLoadTask(projected, task)
|
|
164
|
+
break
|
|
165
|
+
case TaskType.UNLOAD:
|
|
166
|
+
applyUnloadTask(projected, task)
|
|
167
|
+
break
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return projected
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Project entity state at a specific time (partial task execution).
|
|
176
|
+
*/
|
|
177
|
+
export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity {
|
|
178
|
+
const projected = createProjectedEntity(entity)
|
|
179
|
+
|
|
180
|
+
if (!entity.schedule || entity.schedule.tasks.length === 0) {
|
|
181
|
+
return projected
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
for (let i = 0; i < entity.schedule.tasks.length; i++) {
|
|
185
|
+
const task = entity.schedule.tasks[i]
|
|
186
|
+
const taskComplete = schedule.isTaskComplete(entity, i, now)
|
|
187
|
+
const taskInProgress = schedule.isTaskInProgress(entity, i, now)
|
|
188
|
+
|
|
189
|
+
if (!taskComplete && !taskInProgress) {
|
|
190
|
+
break
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const progress = taskInProgress
|
|
194
|
+
? schedule.getTaskElapsed(entity, i, now) / task.duration.toNumber()
|
|
195
|
+
: undefined
|
|
196
|
+
|
|
197
|
+
switch (task.type.toNumber()) {
|
|
198
|
+
case TaskType.RECHARGE:
|
|
199
|
+
applyRechargeTask(projected, task, {complete: taskComplete, progress})
|
|
200
|
+
break
|
|
201
|
+
case TaskType.FLIGHT:
|
|
202
|
+
applyFlightTask(projected, task, {complete: taskComplete, progress})
|
|
203
|
+
break
|
|
204
|
+
case TaskType.LOAD:
|
|
205
|
+
if (taskComplete) {
|
|
206
|
+
applyLoadTask(projected, task)
|
|
207
|
+
}
|
|
208
|
+
break
|
|
209
|
+
case TaskType.UNLOAD:
|
|
210
|
+
if (taskComplete) {
|
|
211
|
+
applyUnloadTask(projected, task)
|
|
212
|
+
}
|
|
213
|
+
break
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
return projected
|
|
218
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {ServerContract} from '../contracts'
|
|
2
|
+
import {TaskType} from '../types'
|
|
3
|
+
|
|
4
|
+
type Schedule = ServerContract.Types.schedule
|
|
5
|
+
type Task = ServerContract.Types.task
|
|
6
|
+
|
|
7
|
+
export interface ScheduleData {
|
|
8
|
+
schedule?: Schedule
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Scheduleable extends ScheduleData {
|
|
12
|
+
hasSchedule: boolean
|
|
13
|
+
isIdle: boolean
|
|
14
|
+
tasks: Task[]
|
|
15
|
+
scheduleDuration(): number
|
|
16
|
+
scheduleElapsed(now: Date): number
|
|
17
|
+
scheduleRemaining(now: Date): number
|
|
18
|
+
scheduleComplete(now: Date): boolean
|
|
19
|
+
currentTaskIndex(now: Date): number
|
|
20
|
+
currentTask(now: Date): Task | undefined
|
|
21
|
+
currentTaskType(now: Date): TaskType | undefined
|
|
22
|
+
getTaskStartTime(index: number): number
|
|
23
|
+
getTaskElapsed(index: number, now: Date): number
|
|
24
|
+
getTaskRemaining(index: number, now: Date): number
|
|
25
|
+
isTaskComplete(index: number, now: Date): boolean
|
|
26
|
+
isTaskInProgress(index: number, now: Date): boolean
|
|
27
|
+
currentTaskProgress(now: Date): number
|
|
28
|
+
scheduleProgress(now: Date): number
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function hasSchedule(entity: ScheduleData): boolean {
|
|
32
|
+
return !!entity.schedule && entity.schedule.tasks.length > 0
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isIdle(entity: ScheduleData): boolean {
|
|
36
|
+
return !hasSchedule(entity)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function getTasks(entity: ScheduleData): Task[] {
|
|
40
|
+
return entity.schedule?.tasks || []
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function scheduleDuration(entity: ScheduleData): number {
|
|
44
|
+
if (!entity.schedule) return 0
|
|
45
|
+
return entity.schedule.tasks.reduce((sum, task) => sum + task.duration.toNumber(), 0)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function scheduleElapsed(entity: ScheduleData, now: Date): number {
|
|
49
|
+
if (!entity.schedule) return 0
|
|
50
|
+
const started = entity.schedule.started.toDate()
|
|
51
|
+
const elapsed = Math.floor((now.getTime() - started.getTime()) / 1000)
|
|
52
|
+
return Math.max(0, elapsed)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function scheduleRemaining(entity: ScheduleData, now: Date): number {
|
|
56
|
+
if (!entity.schedule) return 0
|
|
57
|
+
const duration = scheduleDuration(entity)
|
|
58
|
+
const elapsed = scheduleElapsed(entity, now)
|
|
59
|
+
return Math.max(0, duration - elapsed)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function scheduleComplete(entity: ScheduleData, now: Date): boolean {
|
|
63
|
+
return hasSchedule(entity) && scheduleRemaining(entity, now) === 0
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function currentTaskIndex(entity: ScheduleData, now: Date): number {
|
|
67
|
+
if (!entity.schedule || entity.schedule.tasks.length === 0) return -1
|
|
68
|
+
|
|
69
|
+
const elapsed = scheduleElapsed(entity, now)
|
|
70
|
+
let timeAccum = 0
|
|
71
|
+
|
|
72
|
+
for (let i = 0; i < entity.schedule.tasks.length; i++) {
|
|
73
|
+
const taskDuration = entity.schedule.tasks[i].duration.toNumber()
|
|
74
|
+
if (elapsed < timeAccum + taskDuration) {
|
|
75
|
+
return i
|
|
76
|
+
}
|
|
77
|
+
timeAccum += taskDuration
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return entity.schedule.tasks.length - 1
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function currentTask(entity: ScheduleData, now: Date): Task | undefined {
|
|
84
|
+
const index = currentTaskIndex(entity, now)
|
|
85
|
+
if (index < 0 || !entity.schedule) return undefined
|
|
86
|
+
return entity.schedule.tasks[index]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function currentTaskType(entity: ScheduleData, now: Date): TaskType | undefined {
|
|
90
|
+
const task = currentTask(entity, now)
|
|
91
|
+
if (!task) return undefined
|
|
92
|
+
return task.type.toNumber() as TaskType
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function getTaskStartTime(entity: ScheduleData, index: number): number {
|
|
96
|
+
if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return 0
|
|
97
|
+
let timeAccum = 0
|
|
98
|
+
for (let i = 0; i < index; i++) {
|
|
99
|
+
timeAccum += entity.schedule.tasks[i].duration.toNumber()
|
|
100
|
+
}
|
|
101
|
+
return timeAccum
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function getTaskElapsed(entity: ScheduleData, index: number, now: Date): number {
|
|
105
|
+
if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return 0
|
|
106
|
+
|
|
107
|
+
const elapsed = scheduleElapsed(entity, now)
|
|
108
|
+
const taskStart = getTaskStartTime(entity, index)
|
|
109
|
+
const taskDuration = entity.schedule.tasks[index].duration.toNumber()
|
|
110
|
+
|
|
111
|
+
if (elapsed <= taskStart) return 0
|
|
112
|
+
const elapsedInTask = elapsed - taskStart
|
|
113
|
+
return Math.min(elapsedInTask, taskDuration)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function getTaskRemaining(entity: ScheduleData, index: number, now: Date): number {
|
|
117
|
+
if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return 0
|
|
118
|
+
|
|
119
|
+
const taskDuration = entity.schedule.tasks[index].duration.toNumber()
|
|
120
|
+
const taskElapsed = getTaskElapsed(entity, index, now)
|
|
121
|
+
return Math.max(0, taskDuration - taskElapsed)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function isTaskComplete(entity: ScheduleData, index: number, now: Date): boolean {
|
|
125
|
+
if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return false
|
|
126
|
+
|
|
127
|
+
const taskDuration = entity.schedule.tasks[index].duration.toNumber()
|
|
128
|
+
const taskElapsed = getTaskElapsed(entity, index, now)
|
|
129
|
+
return taskElapsed >= taskDuration
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function isTaskInProgress(entity: ScheduleData, index: number, now: Date): boolean {
|
|
133
|
+
if (!entity.schedule || index < 0 || index >= entity.schedule.tasks.length) return false
|
|
134
|
+
|
|
135
|
+
const taskElapsed = getTaskElapsed(entity, index, now)
|
|
136
|
+
const taskDuration = entity.schedule.tasks[index].duration.toNumber()
|
|
137
|
+
return taskElapsed > 0 && taskElapsed < taskDuration
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function currentTaskProgress(entity: ScheduleData, now: Date): number {
|
|
141
|
+
const task = currentTask(entity, now)
|
|
142
|
+
if (!task) return 0
|
|
143
|
+
const index = currentTaskIndex(entity, now)
|
|
144
|
+
const elapsed = getTaskElapsed(entity, index, now)
|
|
145
|
+
const duration = task.duration.toNumber()
|
|
146
|
+
if (duration === 0) return 1
|
|
147
|
+
return Math.min(1, elapsed / duration)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function scheduleProgress(entity: ScheduleData, now: Date): number {
|
|
151
|
+
const duration = scheduleDuration(entity)
|
|
152
|
+
if (duration === 0) return hasSchedule(entity) ? 1 : 0
|
|
153
|
+
const elapsed = scheduleElapsed(entity, now)
|
|
154
|
+
return Math.min(1, elapsed / duration)
|
|
155
|
+
}
|
package/src/shipload.ts
CHANGED
|
@@ -1,25 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
APIClient,
|
|
3
|
-
Bytes,
|
|
4
|
-
Checksum256,
|
|
5
|
-
Name,
|
|
6
|
-
NameType,
|
|
7
|
-
Serializer,
|
|
8
|
-
UInt16Type,
|
|
9
|
-
UInt64,
|
|
10
|
-
UInt64Type,
|
|
11
|
-
} from '@wharfkit/antelope'
|
|
12
|
-
import {Coordinates, Distance, GoodPrice} from './types'
|
|
13
|
-
import {marketprice, marketprices} from './market'
|
|
1
|
+
import {APIClient} from '@wharfkit/antelope'
|
|
14
2
|
import {PlatformContract, ServerContract} from './contracts'
|
|
15
|
-
import {ERROR_SYSTEM_NOT_INITIALIZED} from './errors'
|
|
16
3
|
import {ChainDefinition} from '@wharfkit/session'
|
|
17
4
|
import ContractKit, {Contract} from '@wharfkit/contract'
|
|
18
|
-
import {findNearbyPlanets, travelplan} from './travel'
|
|
19
5
|
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
6
|
+
import {GameContext} from './managers/context'
|
|
7
|
+
import {EntitiesManager} from './managers/entities'
|
|
8
|
+
import {PlayersManager} from './managers/players'
|
|
9
|
+
import {LocationsManager} from './managers/locations'
|
|
10
|
+
import {TradesManager} from './managers/trades'
|
|
11
|
+
import {EpochsManager} from './managers/epochs'
|
|
12
|
+
import {ActionsManager} from './managers/actions'
|
|
13
|
+
import {GameState} from './entities/gamestate'
|
|
23
14
|
|
|
24
15
|
interface ShiploadOptions {
|
|
25
16
|
platformContractName?: string
|
|
@@ -33,22 +24,21 @@ interface ShiploadConstructorOptions extends ShiploadOptions {
|
|
|
33
24
|
}
|
|
34
25
|
|
|
35
26
|
export class Shipload {
|
|
36
|
-
|
|
37
|
-
public server: Contract
|
|
38
|
-
public platform: Contract
|
|
39
|
-
public game: PlatformContract.Types.game_row | undefined
|
|
27
|
+
private readonly _context: GameContext
|
|
40
28
|
|
|
41
29
|
constructor(chain: ChainDefinition, constructorOptions?: ShiploadConstructorOptions) {
|
|
42
30
|
const {client, platformContract, serverContract} = constructorOptions || {}
|
|
43
|
-
|
|
31
|
+
const apiClient = client || new APIClient({url: chain.url})
|
|
44
32
|
|
|
45
|
-
|
|
33
|
+
const platform = platformContract
|
|
46
34
|
? platformContract
|
|
47
|
-
: new PlatformContract.Contract({client:
|
|
35
|
+
: new PlatformContract.Contract({client: apiClient})
|
|
48
36
|
|
|
49
|
-
|
|
37
|
+
const server = serverContract
|
|
50
38
|
? serverContract
|
|
51
|
-
: new ServerContract.Contract({client:
|
|
39
|
+
: new ServerContract.Contract({client: apiClient})
|
|
40
|
+
|
|
41
|
+
this._context = new GameContext(apiClient, server, platform)
|
|
52
42
|
}
|
|
53
43
|
|
|
54
44
|
static async load(
|
|
@@ -80,155 +70,47 @@ export class Shipload {
|
|
|
80
70
|
})
|
|
81
71
|
}
|
|
82
72
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return this.game
|
|
86
|
-
}
|
|
87
|
-
const game = await this.platform.table('games').get()
|
|
88
|
-
if (!game) {
|
|
89
|
-
throw new Error(ERROR_SYSTEM_NOT_INITIALIZED)
|
|
90
|
-
}
|
|
91
|
-
this.game = game
|
|
92
|
-
return game
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async getState(): Promise<ServerContract.Types.state_row> {
|
|
96
|
-
const state = await this.server.table('state').get()
|
|
97
|
-
if (!state) {
|
|
98
|
-
throw new Error(ERROR_SYSTEM_NOT_INITIALIZED)
|
|
99
|
-
}
|
|
100
|
-
return state
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async getShip(ship_id: UInt64Type): Promise<Ship> {
|
|
104
|
-
const ship = await this.server.table('ship').get(UInt64.from(ship_id))
|
|
105
|
-
if (!ship) {
|
|
106
|
-
throw new Error('No ship found')
|
|
107
|
-
}
|
|
108
|
-
return new Ship(ship)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
async getShips(player: NameType | ServerContract.Types.player_row): Promise<Ship[]> {
|
|
112
|
-
let account: Name
|
|
113
|
-
if (player instanceof ServerContract.Types.player_row) {
|
|
114
|
-
account = player.owner
|
|
115
|
-
} else {
|
|
116
|
-
account = Name.from(player)
|
|
117
|
-
}
|
|
118
|
-
const from = Serializer.decode({
|
|
119
|
-
data:
|
|
120
|
-
Serializer.encode({object: UInt64.from(UInt64.min)}).hexString +
|
|
121
|
-
Serializer.encode({object: Name.from(account)}).hexString,
|
|
122
|
-
type: 'uint128',
|
|
123
|
-
})
|
|
124
|
-
const to = Serializer.decode({
|
|
125
|
-
data:
|
|
126
|
-
Serializer.encode({object: UInt64.from(UInt64.max)}).hexString +
|
|
127
|
-
Serializer.encode({object: Name.from(account)}).hexString,
|
|
128
|
-
type: 'uint128',
|
|
129
|
-
})
|
|
130
|
-
const ships = await this.server
|
|
131
|
-
.table('ship')
|
|
132
|
-
.query({
|
|
133
|
-
key_type: 'i128',
|
|
134
|
-
index_position: 'secondary',
|
|
135
|
-
from,
|
|
136
|
-
to,
|
|
137
|
-
})
|
|
138
|
-
.all()
|
|
139
|
-
return ships.map((ship) => new Ship(ship))
|
|
73
|
+
get client(): APIClient {
|
|
74
|
+
return this._context.client
|
|
140
75
|
}
|
|
141
76
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
good_id: number
|
|
145
|
-
): Promise<GoodPrice> {
|
|
146
|
-
const game = await this.getGame()
|
|
147
|
-
const state = await this.getState()
|
|
148
|
-
return marketprice(location, good_id, game.config.seed, state)
|
|
77
|
+
get server(): Contract {
|
|
78
|
+
return this._context.server
|
|
149
79
|
}
|
|
150
80
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
): Promise<GoodPrice[]> {
|
|
154
|
-
const game = await this.getGame()
|
|
155
|
-
const state = await this.getState()
|
|
156
|
-
return marketprices(location, game.config.seed, state)
|
|
81
|
+
get platform(): Contract {
|
|
82
|
+
return this._context.platform
|
|
157
83
|
}
|
|
158
84
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
return hasSystem(game.config.seed, location)
|
|
85
|
+
get entities(): EntitiesManager {
|
|
86
|
+
return this._context.entities
|
|
162
87
|
}
|
|
163
88
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
maxDistance: UInt16Type = 20
|
|
167
|
-
): Promise<Distance[]> {
|
|
168
|
-
const game = await this.getGame()
|
|
169
|
-
return findNearbyPlanets(game.config.seed, origin, maxDistance)
|
|
89
|
+
get players(): PlayersManager {
|
|
90
|
+
return this._context.players
|
|
170
91
|
}
|
|
171
92
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
origin: ServerContract.ActionParams.Type.coordinates,
|
|
175
|
-
destination: ServerContract.ActionParams.Type.coordinates,
|
|
176
|
-
recharge = false
|
|
177
|
-
): Promise<ServerContract.Types.travel_plan> {
|
|
178
|
-
const game = await this.getGame()
|
|
179
|
-
const cargos = await this.server.table('cargo').all({
|
|
180
|
-
from: ship.id,
|
|
181
|
-
to: ship.id,
|
|
182
|
-
index_position: 'secondary',
|
|
183
|
-
})
|
|
184
|
-
return travelplan(game, ship, cargos, origin, destination, recharge)
|
|
93
|
+
get locations(): LocationsManager {
|
|
94
|
+
return this._context.locations
|
|
185
95
|
}
|
|
186
96
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
): Promise<ServerContract.Types.cargo_row[]> {
|
|
190
|
-
let shipId: UInt64
|
|
191
|
-
if (ship instanceof ServerContract.Types.ship_row) {
|
|
192
|
-
shipId = UInt64.from(ship.id)
|
|
193
|
-
} else {
|
|
194
|
-
shipId = UInt64.from(ship)
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const cargoItems = await this.server
|
|
198
|
-
.table('cargo')
|
|
199
|
-
.query({
|
|
200
|
-
key_type: 'i64',
|
|
201
|
-
index_position: 'secondary',
|
|
202
|
-
from: shipId,
|
|
203
|
-
to: shipId,
|
|
204
|
-
})
|
|
205
|
-
.all()
|
|
206
|
-
|
|
207
|
-
return cargoItems
|
|
97
|
+
get trades(): TradesManager {
|
|
98
|
+
return this._context.trades
|
|
208
99
|
}
|
|
209
100
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return getCurrentEpoch(game)
|
|
101
|
+
get epochs(): EpochsManager {
|
|
102
|
+
return this._context.epochs
|
|
213
103
|
}
|
|
214
104
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const epoch = await this.getCurrentEpochHeight()
|
|
218
|
-
return getEpochInfo(game, epoch)
|
|
105
|
+
get actions(): ActionsManager {
|
|
106
|
+
return this._context.actions
|
|
219
107
|
}
|
|
220
108
|
|
|
221
|
-
async
|
|
222
|
-
|
|
223
|
-
return getEpochInfo(game, UInt64.from(height))
|
|
109
|
+
async getGame(reload = false): Promise<PlatformContract.Types.game_row> {
|
|
110
|
+
return this._context.getGame(reload)
|
|
224
111
|
}
|
|
225
112
|
|
|
226
|
-
async
|
|
227
|
-
|
|
228
|
-
return this.server.table('location').all({
|
|
229
|
-
index_position: 'secondary',
|
|
230
|
-
from: hash,
|
|
231
|
-
to: hash,
|
|
232
|
-
})
|
|
113
|
+
async getState(reload = false): Promise<GameState> {
|
|
114
|
+
return this._context.getState(reload)
|
|
233
115
|
}
|
|
234
116
|
}
|