@shipload/sdk 2.0.0-rc2 → 2.0.0-rc21
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 +1 -349
- package/lib/shipload.d.ts +1729 -1127
- package/lib/shipload.js +7944 -3165
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +7487 -2840
- package/lib/shipload.m.js.map +1 -1
- package/package.json +6 -4
- package/src/capabilities/crafting.ts +22 -0
- package/src/capabilities/gathering.ts +36 -0
- package/src/capabilities/guards.ts +3 -8
- package/src/capabilities/hauling.ts +22 -0
- package/src/capabilities/index.ts +4 -1
- package/src/capabilities/modules.ts +86 -0
- package/src/capabilities/storage.ts +101 -9
- package/src/contracts/server.ts +785 -293
- package/src/data/capabilities.ts +408 -0
- package/src/data/categories.ts +55 -0
- package/src/data/colors.ts +71 -0
- package/src/data/entities.json +50 -0
- package/src/data/item-ids.ts +75 -0
- package/src/data/items.json +252 -0
- package/src/data/locations.ts +53 -0
- package/src/data/metadata.ts +208 -0
- package/src/data/nebula-adjectives.json +211 -0
- package/src/data/nebula-nouns.json +151 -0
- package/src/data/recipes-runtime.ts +65 -0
- package/src/data/recipes.json +878 -0
- package/src/data/syllables.json +1386 -780
- package/src/data/tiers.ts +45 -0
- package/src/derivation/crafting.ts +348 -0
- package/src/derivation/index.ts +30 -0
- package/src/derivation/location-size.ts +15 -0
- package/src/derivation/resources.ts +112 -0
- package/src/derivation/stats.ts +146 -0
- package/src/derivation/stratum.ts +134 -0
- package/src/derivation/tiers.ts +54 -0
- package/src/entities/cargo-utils.ts +10 -68
- package/src/entities/container.ts +37 -0
- package/src/entities/entity-inventory.ts +13 -13
- package/src/entities/inventory-accessor.ts +2 -6
- package/src/entities/location.ts +5 -200
- package/src/entities/makers.ts +144 -17
- package/src/entities/player.ts +1 -274
- package/src/entities/ship-deploy.ts +258 -0
- package/src/entities/ship.ts +28 -34
- package/src/entities/warehouse.ts +35 -7
- package/src/errors.ts +59 -5
- package/src/format.ts +12 -0
- package/src/index-module.ts +188 -50
- package/src/managers/actions.ts +138 -88
- package/src/managers/context.ts +19 -9
- package/src/managers/index.ts +0 -1
- package/src/managers/locations.ts +2 -85
- package/src/market/items.ts +41 -0
- package/src/nft/description.ts +176 -0
- package/src/nft/deserializers.ts +83 -0
- package/src/nft/index.ts +2 -0
- package/src/resolution/describe-module.ts +165 -0
- package/src/resolution/display-name.ts +43 -0
- package/src/resolution/resolve-item.ts +358 -0
- package/src/scheduling/projection.ts +200 -67
- package/src/scheduling/schedule.ts +2 -2
- package/src/shipload.ts +10 -5
- package/src/subscriptions/connection.ts +154 -0
- package/src/subscriptions/debug.ts +17 -0
- package/src/subscriptions/index.ts +5 -0
- package/src/subscriptions/manager.ts +240 -0
- package/src/subscriptions/mappers.ts +28 -0
- package/src/subscriptions/types.ts +143 -0
- package/src/travel/travel.ts +37 -23
- package/src/types/capabilities.ts +11 -14
- package/src/types/entity-traits.ts +3 -4
- package/src/types/entity.ts +9 -6
- package/src/types.ts +72 -72
- package/src/utils/system.ts +66 -53
- package/src/capabilities/extraction.ts +0 -37
- package/src/data/goods.json +0 -23
- package/src/managers/trades.ts +0 -119
- package/src/market/goods.ts +0 -31
- package/src/market/market.ts +0 -208
- package/src/market/rolls.ts +0 -8
- package/src/trading/collect.ts +0 -938
- package/src/trading/deal.ts +0 -207
- package/src/trading/trade.ts +0 -203
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import {WebSocketConnection} from './connection'
|
|
2
|
+
import type {
|
|
3
|
+
BoundingBox,
|
|
4
|
+
BoundsDeltaMessage,
|
|
5
|
+
ClientMessage,
|
|
6
|
+
ServerMessage,
|
|
7
|
+
SnapshotMessage,
|
|
8
|
+
SubscribeEntityMessage,
|
|
9
|
+
SubscribeMessage,
|
|
10
|
+
UnsubscribeEntityMessage,
|
|
11
|
+
UpdateBoundsMessage,
|
|
12
|
+
UpdateMessage,
|
|
13
|
+
WireEntity,
|
|
14
|
+
} from './types'
|
|
15
|
+
import {mapEntity, parseWireEntity} from './mappers'
|
|
16
|
+
import type {Ship} from '../entities/ship'
|
|
17
|
+
import type {Warehouse} from '../entities/warehouse'
|
|
18
|
+
import type {Container} from '../entities/container'
|
|
19
|
+
|
|
20
|
+
export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container'
|
|
21
|
+
export type EntityInstance = Ship | Warehouse | Container
|
|
22
|
+
|
|
23
|
+
export interface SubscriptionsOptions {
|
|
24
|
+
url: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface BoundsSubscriptionHandle {
|
|
28
|
+
readonly subId: string
|
|
29
|
+
unsubscribe(): void
|
|
30
|
+
updateBounds(bounds: BoundingBox): void
|
|
31
|
+
current: Map<number, EntityInstance>
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface EntitySubscriptionHandle {
|
|
35
|
+
readonly subId: string
|
|
36
|
+
readonly entityType: SubscriptionEntityType
|
|
37
|
+
readonly entityId: string
|
|
38
|
+
unsubscribe(): void
|
|
39
|
+
current: EntityInstance | null
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class SubscriptionsManager {
|
|
43
|
+
private readonly conn: WebSocketConnection
|
|
44
|
+
private readonly entitySubs = new Map<
|
|
45
|
+
string,
|
|
46
|
+
{
|
|
47
|
+
type: SubscriptionEntityType
|
|
48
|
+
id: string
|
|
49
|
+
onUpdate: (e: EntityInstance) => void
|
|
50
|
+
handle: EntitySubscriptionHandle
|
|
51
|
+
}
|
|
52
|
+
>()
|
|
53
|
+
private readonly boundsSubs = new Map<
|
|
54
|
+
string,
|
|
55
|
+
{
|
|
56
|
+
onSnapshot?: (entities: EntityInstance[]) => void
|
|
57
|
+
onUpdate?: (entity: EntityInstance) => void
|
|
58
|
+
onBoundsDelta?: (entered: EntityInstance[], exited: number[]) => void
|
|
59
|
+
handle: BoundsSubscriptionHandle
|
|
60
|
+
}
|
|
61
|
+
>()
|
|
62
|
+
private subCounter = 0
|
|
63
|
+
|
|
64
|
+
constructor(opts: SubscriptionsOptions) {
|
|
65
|
+
this.conn = new WebSocketConnection({
|
|
66
|
+
url: opts.url,
|
|
67
|
+
onMessage: (m) => this.onMessage(m),
|
|
68
|
+
})
|
|
69
|
+
this.conn.connect()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
close() {
|
|
73
|
+
this.conn.close()
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private generateSubID(prefix: string): string {
|
|
77
|
+
this.subCounter += 1
|
|
78
|
+
return `${prefix}-${this.subCounter}-${Math.random().toString(36).slice(2, 8)}`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private sendMessage(msg: ClientMessage) {
|
|
82
|
+
this.conn.send(msg)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
subscribeEntity(
|
|
86
|
+
type: SubscriptionEntityType,
|
|
87
|
+
id: string,
|
|
88
|
+
onUpdate: (e: EntityInstance) => void
|
|
89
|
+
): EntitySubscriptionHandle {
|
|
90
|
+
const subId = this.generateSubID('ent')
|
|
91
|
+
const msg: SubscribeEntityMessage = {
|
|
92
|
+
type: 'subscribe_entity',
|
|
93
|
+
sub_id: subId,
|
|
94
|
+
entity_type: type,
|
|
95
|
+
entity_id: id,
|
|
96
|
+
}
|
|
97
|
+
const handle: EntitySubscriptionHandle = {
|
|
98
|
+
subId,
|
|
99
|
+
entityType: type,
|
|
100
|
+
entityId: id,
|
|
101
|
+
unsubscribe: () => this.unsubscribeEntity(subId),
|
|
102
|
+
current: null,
|
|
103
|
+
}
|
|
104
|
+
this.entitySubs.set(subId, {type, id, onUpdate, handle})
|
|
105
|
+
this.sendMessage(msg)
|
|
106
|
+
return handle
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private unsubscribeEntity(subId: string) {
|
|
110
|
+
const entry = this.entitySubs.get(subId)
|
|
111
|
+
if (!entry) return
|
|
112
|
+
this.entitySubs.delete(subId)
|
|
113
|
+
const msg: UnsubscribeEntityMessage = {type: 'unsubscribe_entity', sub_id: subId}
|
|
114
|
+
this.sendMessage(msg)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
subscribeBounds(
|
|
118
|
+
bounds: BoundingBox,
|
|
119
|
+
handlers: {
|
|
120
|
+
onSnapshot?: (entities: EntityInstance[]) => void
|
|
121
|
+
onUpdate?: (entity: EntityInstance) => void
|
|
122
|
+
onBoundsDelta?: (entered: EntityInstance[], exited: number[]) => void
|
|
123
|
+
owner?: string
|
|
124
|
+
prioritizeOwner?: string
|
|
125
|
+
}
|
|
126
|
+
): BoundsSubscriptionHandle {
|
|
127
|
+
const subId = this.generateSubID('bnd')
|
|
128
|
+
const msg: SubscribeMessage = {
|
|
129
|
+
type: 'subscribe',
|
|
130
|
+
sub_id: subId,
|
|
131
|
+
bounds,
|
|
132
|
+
owner: handlers.owner,
|
|
133
|
+
prioritize_owner: handlers.prioritizeOwner,
|
|
134
|
+
}
|
|
135
|
+
const handle: BoundsSubscriptionHandle = {
|
|
136
|
+
subId,
|
|
137
|
+
unsubscribe: () => this.unsubscribeBounds(subId),
|
|
138
|
+
updateBounds: (b) => this.updateBounds(subId, b),
|
|
139
|
+
current: new Map(),
|
|
140
|
+
}
|
|
141
|
+
this.boundsSubs.set(subId, {
|
|
142
|
+
onSnapshot: handlers.onSnapshot,
|
|
143
|
+
onUpdate: handlers.onUpdate,
|
|
144
|
+
onBoundsDelta: handlers.onBoundsDelta,
|
|
145
|
+
handle,
|
|
146
|
+
})
|
|
147
|
+
this.sendMessage(msg)
|
|
148
|
+
return handle
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private unsubscribeBounds(subId: string) {
|
|
152
|
+
this.boundsSubs.delete(subId)
|
|
153
|
+
this.sendMessage({type: 'unsubscribe', sub_id: subId})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
private updateBounds(subId: string, bounds: BoundingBox) {
|
|
157
|
+
const msg: UpdateBoundsMessage = {type: 'update_bounds', sub_id: subId, bounds}
|
|
158
|
+
this.sendMessage(msg)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
private onMessage(msg: ServerMessage) {
|
|
162
|
+
switch (msg.type) {
|
|
163
|
+
case 'snapshot':
|
|
164
|
+
this.handleSnapshot(msg)
|
|
165
|
+
break
|
|
166
|
+
case 'update':
|
|
167
|
+
this.handleUpdate(msg)
|
|
168
|
+
break
|
|
169
|
+
case 'bounds_delta':
|
|
170
|
+
this.handleBoundsDelta(msg)
|
|
171
|
+
break
|
|
172
|
+
case 'error':
|
|
173
|
+
this.handleError(msg)
|
|
174
|
+
break
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private parseEntity(raw: WireEntity): EntityInstance {
|
|
179
|
+
const ei = parseWireEntity(raw)
|
|
180
|
+
return mapEntity(ei)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private handleSnapshot(msg: SnapshotMessage) {
|
|
184
|
+
const entSub = this.entitySubs.get(msg.sub_id)
|
|
185
|
+
if (entSub) {
|
|
186
|
+
if (msg.entities.length > 0) {
|
|
187
|
+
const ent = this.parseEntity(msg.entities[0])
|
|
188
|
+
entSub.handle.current = ent
|
|
189
|
+
entSub.onUpdate(ent)
|
|
190
|
+
}
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
const boundsSub = this.boundsSubs.get(msg.sub_id)
|
|
194
|
+
if (boundsSub) {
|
|
195
|
+
const ents = msg.entities.map((e) => this.parseEntity(e))
|
|
196
|
+
boundsSub.handle.current.clear()
|
|
197
|
+
for (const e of ents) boundsSub.handle.current.set(Number(e.id), e)
|
|
198
|
+
boundsSub.onSnapshot?.(ents)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private handleUpdate(msg: UpdateMessage) {
|
|
203
|
+
const ent = this.parseEntity(msg.entity)
|
|
204
|
+
for (const subId of msg.sub_ids) {
|
|
205
|
+
const entSub = this.entitySubs.get(subId)
|
|
206
|
+
if (entSub) {
|
|
207
|
+
entSub.handle.current = ent
|
|
208
|
+
entSub.onUpdate(ent)
|
|
209
|
+
continue
|
|
210
|
+
}
|
|
211
|
+
const boundsSub = this.boundsSubs.get(subId)
|
|
212
|
+
if (boundsSub) {
|
|
213
|
+
boundsSub.handle.current.set(msg.entity_id, ent)
|
|
214
|
+
boundsSub.onUpdate?.(ent)
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private handleBoundsDelta(msg: BoundsDeltaMessage) {
|
|
220
|
+
const sub = this.boundsSubs.get(msg.sub_id)
|
|
221
|
+
if (!sub) return
|
|
222
|
+
const entered = msg.entered.map((e) => this.parseEntity(e))
|
|
223
|
+
for (const e of entered) sub.handle.current.set(Number(e.id), e)
|
|
224
|
+
for (const id of msg.exited) sub.handle.current.delete(id)
|
|
225
|
+
sub.onBoundsDelta?.(entered, msg.exited)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
private handleError(msg: {sub_id?: string; error: string}) {
|
|
229
|
+
if (!msg.sub_id) return
|
|
230
|
+
const entSub = this.entitySubs.get(msg.sub_id)
|
|
231
|
+
if (entSub) {
|
|
232
|
+
this.entitySubs.delete(msg.sub_id)
|
|
233
|
+
return
|
|
234
|
+
}
|
|
235
|
+
const boundsSub = this.boundsSubs.get(msg.sub_id)
|
|
236
|
+
if (boundsSub) {
|
|
237
|
+
this.boundsSubs.delete(msg.sub_id)
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {ServerContract} from '../contracts'
|
|
2
|
+
import {Ship} from '../entities/ship'
|
|
3
|
+
import {Warehouse} from '../entities/warehouse'
|
|
4
|
+
import {Container} from '../entities/container'
|
|
5
|
+
import type {WireEntity} from './types'
|
|
6
|
+
|
|
7
|
+
export function mapEntity(ei: ServerContract.Types.entity_info): Ship | Warehouse | Container {
|
|
8
|
+
if (ei.type.equals('ship')) return new Ship(ei)
|
|
9
|
+
if (ei.type.equals('warehouse')) return new Warehouse(ei)
|
|
10
|
+
if (ei.type.equals('container')) return new Container(ei)
|
|
11
|
+
throw new Error(`mapEntity: unknown entity type ${ei.type.toString()}`)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function parseWireEntity(raw: WireEntity): ServerContract.Types.entity_info {
|
|
15
|
+
const shaped: Record<string, unknown> = {...raw}
|
|
16
|
+
|
|
17
|
+
if (typeof shaped.type === 'number' && typeof shaped.type_name === 'string') {
|
|
18
|
+
shaped.type = shaped.type_name
|
|
19
|
+
}
|
|
20
|
+
delete shaped.type_name
|
|
21
|
+
|
|
22
|
+
if (shaped.entity_name === undefined && typeof shaped.name === 'string') {
|
|
23
|
+
shaped.entity_name = shaped.name
|
|
24
|
+
}
|
|
25
|
+
delete shaped.name
|
|
26
|
+
|
|
27
|
+
return ServerContract.Types.entity_info.from(shaped)
|
|
28
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import type {ServerContract} from '../contracts'
|
|
2
|
+
|
|
3
|
+
export type EntityInfo = ServerContract.Types.entity_info
|
|
4
|
+
|
|
5
|
+
export interface BoundingBox {
|
|
6
|
+
min_x: number
|
|
7
|
+
min_y: number
|
|
8
|
+
max_x: number
|
|
9
|
+
max_y: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface WireCoordinates {
|
|
13
|
+
x: number
|
|
14
|
+
y: number
|
|
15
|
+
z?: number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// --- Client → Server ---
|
|
19
|
+
|
|
20
|
+
export type SubscribeMessage = {
|
|
21
|
+
type: 'subscribe'
|
|
22
|
+
sub_id: string
|
|
23
|
+
bounds?: BoundingBox
|
|
24
|
+
owner?: string
|
|
25
|
+
prioritize_owner?: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type UpdateBoundsMessage = {
|
|
29
|
+
type: 'update_bounds'
|
|
30
|
+
sub_id: string
|
|
31
|
+
bounds: BoundingBox
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type UnsubscribeMessage = {
|
|
35
|
+
type: 'unsubscribe'
|
|
36
|
+
sub_id: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type SubscribeEntityMessage = {
|
|
40
|
+
type: 'subscribe_entity'
|
|
41
|
+
sub_id: string
|
|
42
|
+
entity_type: 'ship' | 'warehouse' | 'container'
|
|
43
|
+
entity_id: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type UnsubscribeEntityMessage = {
|
|
47
|
+
type: 'unsubscribe_entity'
|
|
48
|
+
sub_id: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type SubscribeEventsMessage = {
|
|
52
|
+
type: 'subscribe_events'
|
|
53
|
+
sub_id: string
|
|
54
|
+
event_filter?: Record<string, unknown>
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type UnsubscribeEventsMessage = {
|
|
58
|
+
type: 'unsubscribe_events'
|
|
59
|
+
sub_id: string
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type PingMessage = {type: 'ping'}
|
|
63
|
+
|
|
64
|
+
export type ClientMessage =
|
|
65
|
+
| SubscribeMessage
|
|
66
|
+
| UpdateBoundsMessage
|
|
67
|
+
| UnsubscribeMessage
|
|
68
|
+
| SubscribeEntityMessage
|
|
69
|
+
| UnsubscribeEntityMessage
|
|
70
|
+
| SubscribeEventsMessage
|
|
71
|
+
| UnsubscribeEventsMessage
|
|
72
|
+
| PingMessage
|
|
73
|
+
|
|
74
|
+
// --- Server → Client ---
|
|
75
|
+
|
|
76
|
+
export type AckMessage = {
|
|
77
|
+
type: 'subscribed' | 'unsubscribed' | 'bounds_updated'
|
|
78
|
+
sub_id: string
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export type WireEntity = Record<string, unknown> & {
|
|
82
|
+
type: number
|
|
83
|
+
type_name: 'ship' | 'warehouse' | 'container'
|
|
84
|
+
id: string | number
|
|
85
|
+
owner: string
|
|
86
|
+
coordinates: WireCoordinates
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export type SnapshotMessage = {
|
|
90
|
+
type: 'snapshot'
|
|
91
|
+
sub_id: string
|
|
92
|
+
seq: number
|
|
93
|
+
entities: WireEntity[]
|
|
94
|
+
truncated?: boolean
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export type UpdateMessage = {
|
|
98
|
+
type: 'update'
|
|
99
|
+
sub_ids: string[]
|
|
100
|
+
entity_id: number
|
|
101
|
+
entity: WireEntity
|
|
102
|
+
seq: number
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export type BoundsDeltaMessage = {
|
|
106
|
+
type: 'bounds_delta'
|
|
107
|
+
sub_id: string
|
|
108
|
+
entered: WireEntity[]
|
|
109
|
+
exited: number[]
|
|
110
|
+
seq: number
|
|
111
|
+
truncated?: boolean
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export type EventMessage = {
|
|
115
|
+
type: 'event'
|
|
116
|
+
sub_id: string
|
|
117
|
+
catchup: boolean
|
|
118
|
+
events: Array<Record<string, unknown>>
|
|
119
|
+
seq?: number
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export type EventCatchupCompleteMessage = {
|
|
123
|
+
type: 'event_catchup_complete'
|
|
124
|
+
sub_id: string
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export type PongMessage = {type: 'pong'}
|
|
128
|
+
|
|
129
|
+
export type ErrorMessage = {
|
|
130
|
+
type: 'error'
|
|
131
|
+
error: string
|
|
132
|
+
sub_id?: string
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export type ServerMessage =
|
|
136
|
+
| AckMessage
|
|
137
|
+
| SnapshotMessage
|
|
138
|
+
| UpdateMessage
|
|
139
|
+
| BoundsDeltaMessage
|
|
140
|
+
| EventMessage
|
|
141
|
+
| EventCatchupCompleteMessage
|
|
142
|
+
| PongMessage
|
|
143
|
+
| ErrorMessage
|
package/src/travel/travel.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
Checksum256,
|
|
15
15
|
Int64,
|
|
16
16
|
Int64Type,
|
|
17
|
+
UInt16,
|
|
17
18
|
UInt32,
|
|
18
19
|
UInt32Type,
|
|
19
20
|
UInt64,
|
|
@@ -22,24 +23,24 @@ import {
|
|
|
22
23
|
|
|
23
24
|
import {ServerContract} from '../contracts'
|
|
24
25
|
import {
|
|
26
|
+
BASE_ORBITAL_MASS,
|
|
25
27
|
CargoMassInfo,
|
|
26
28
|
Distance,
|
|
27
|
-
INITIAL_SHIP_MASS,
|
|
28
29
|
MAX_ORBITAL_ALTITUDE,
|
|
29
30
|
MIN_ORBITAL_ALTITUDE,
|
|
30
31
|
PRECISION,
|
|
31
32
|
ShipLike,
|
|
32
33
|
TaskType,
|
|
33
34
|
} from '../types'
|
|
34
|
-
import {
|
|
35
|
+
import {getItem} from '../market/items'
|
|
35
36
|
import {hasSystem} from '../utils/system'
|
|
36
37
|
|
|
37
38
|
export function calc_orbital_altitude(mass: number): number {
|
|
38
|
-
if (mass <=
|
|
39
|
+
if (mass <= BASE_ORBITAL_MASS) {
|
|
39
40
|
return MIN_ORBITAL_ALTITUDE
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
const ratio = mass /
|
|
43
|
+
const ratio = mass / BASE_ORBITAL_MASS
|
|
43
44
|
const capRatio = 10.0
|
|
44
45
|
let scale = Math.log(ratio) / Math.log(capRatio)
|
|
45
46
|
scale = Math.min(scale, 1.0)
|
|
@@ -126,7 +127,12 @@ export function calc_rechargetime(
|
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
export function calc_ship_rechargetime(ship: ShipLike): UInt32 {
|
|
129
|
-
|
|
130
|
+
if (!ship.generator) return UInt32.from(0)
|
|
131
|
+
return calc_rechargetime(
|
|
132
|
+
ship.generator.capacity,
|
|
133
|
+
ship.energy ?? UInt16.from(0),
|
|
134
|
+
ship.generator.recharge
|
|
135
|
+
)
|
|
130
136
|
}
|
|
131
137
|
|
|
132
138
|
export function calc_flighttime(distance: UInt64Type, acceleration: number): UInt32 {
|
|
@@ -139,7 +145,9 @@ export function calc_loader_flighttime(ship: ShipLike, mass: UInt64, altitude?:
|
|
|
139
145
|
}
|
|
140
146
|
|
|
141
147
|
export function calc_loader_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
142
|
-
|
|
148
|
+
const thrust = ship.loaders ? Number(ship.loaders.thrust) : 0
|
|
149
|
+
const loaderMass = ship.loaders ? Number(ship.loaders.mass) : 0
|
|
150
|
+
return calc_acceleration(thrust, Number(mass) + loaderMass)
|
|
143
151
|
}
|
|
144
152
|
|
|
145
153
|
export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UInt64): UInt32 {
|
|
@@ -148,7 +156,8 @@ export function calc_ship_flighttime(ship: ShipLike, mass: UInt64, distance: UIn
|
|
|
148
156
|
}
|
|
149
157
|
|
|
150
158
|
export function calc_ship_acceleration(ship: ShipLike, mass: UInt64): number {
|
|
151
|
-
|
|
159
|
+
const thrust = ship.engines ? Number(ship.engines.thrust) : 0
|
|
160
|
+
return calc_acceleration(thrust, Number(mass))
|
|
152
161
|
}
|
|
153
162
|
|
|
154
163
|
export function calc_acceleration(thrust: number, mass: number): number {
|
|
@@ -160,12 +169,13 @@ export function calc_ship_mass(ship: ShipLike, cargos: CargoMassInfo[]): UInt64
|
|
|
160
169
|
|
|
161
170
|
mass.add(ship.hullmass)
|
|
162
171
|
|
|
163
|
-
if (ship.loaders.quantity.gt(UInt32.zero)) {
|
|
172
|
+
if (ship.loaders && ship.loaders.quantity.gt(UInt32.zero)) {
|
|
164
173
|
mass.add(ship.loaders.mass.multiplying(ship.loaders.quantity))
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
for (const cargo of cargos) {
|
|
168
|
-
|
|
177
|
+
const cargoMass = getItem(cargo.item_id).mass * Number(UInt32.from(cargo.quantity))
|
|
178
|
+
mass.add(UInt64.from(cargoMass))
|
|
169
179
|
}
|
|
170
180
|
|
|
171
181
|
return mass
|
|
@@ -183,11 +193,11 @@ export function calculateTransferTime(
|
|
|
183
193
|
let mass = UInt64.from(0)
|
|
184
194
|
|
|
185
195
|
for (const cargo of cargos) {
|
|
186
|
-
const qty = quantities?.get(Number(cargo.
|
|
196
|
+
const qty = quantities?.get(Number(cargo.item_id)) ?? 0
|
|
187
197
|
if (qty > 0) {
|
|
188
|
-
const good_mass =
|
|
189
|
-
const cargo_mass = good_mass
|
|
190
|
-
mass = UInt64.from(mass).adding(cargo_mass)
|
|
198
|
+
const good_mass = getItem(cargo.item_id).mass
|
|
199
|
+
const cargo_mass = good_mass * qty
|
|
200
|
+
mass = UInt64.from(mass).adding(UInt64.from(cargo_mass))
|
|
191
201
|
}
|
|
192
202
|
}
|
|
193
203
|
|
|
@@ -195,6 +205,7 @@ export function calculateTransferTime(
|
|
|
195
205
|
return UInt32.from(0)
|
|
196
206
|
}
|
|
197
207
|
|
|
208
|
+
if (!ship.loaders) return UInt32.from(0)
|
|
198
209
|
mass = UInt64.from(mass).adding(ship.loaders.mass)
|
|
199
210
|
const transfer_time = calc_loader_flighttime(ship, mass)
|
|
200
211
|
return transfer_time.dividing(ship.loaders.quantity)
|
|
@@ -231,20 +242,20 @@ export function calculateLoadTimeBreakdown(
|
|
|
231
242
|
let mass_load = UInt64.from(0)
|
|
232
243
|
|
|
233
244
|
for (const cargo of cargos) {
|
|
234
|
-
const goodId = Number(cargo.
|
|
245
|
+
const goodId = Number(cargo.item_id)
|
|
235
246
|
const loadQty = loadQuantities?.get(goodId) ?? 0
|
|
236
247
|
const unloadQty = unloadQuantities?.get(goodId) ?? 0
|
|
237
248
|
|
|
238
249
|
if (loadQty > 0 || unloadQty > 0) {
|
|
239
|
-
const good =
|
|
250
|
+
const good = getItem(cargo.item_id)
|
|
240
251
|
|
|
241
252
|
if (loadQty > 0) {
|
|
242
|
-
const cargo_mass = good.mass
|
|
243
|
-
mass_load = UInt64.from(mass_load).adding(cargo_mass)
|
|
253
|
+
const cargo_mass = good.mass * loadQty
|
|
254
|
+
mass_load = UInt64.from(mass_load).adding(UInt64.from(cargo_mass))
|
|
244
255
|
}
|
|
245
256
|
if (unloadQty > 0) {
|
|
246
|
-
const cargo_mass = good.mass
|
|
247
|
-
mass_unload = UInt64.from(mass_unload).adding(cargo_mass)
|
|
257
|
+
const cargo_mass = good.mass * unloadQty
|
|
258
|
+
mass_unload = UInt64.from(mass_unload).adding(UInt64.from(cargo_mass))
|
|
248
259
|
}
|
|
249
260
|
}
|
|
250
261
|
}
|
|
@@ -252,17 +263,17 @@ export function calculateLoadTimeBreakdown(
|
|
|
252
263
|
let unloadTime = 0
|
|
253
264
|
let loadTime = 0
|
|
254
265
|
|
|
255
|
-
if (mass_unload.gt(UInt64.zero)) {
|
|
266
|
+
if (mass_unload.gt(UInt64.zero) && ship.loaders) {
|
|
256
267
|
const totalMass = UInt64.from(mass_unload).adding(ship.loaders.mass)
|
|
257
268
|
unloadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
258
269
|
}
|
|
259
270
|
|
|
260
|
-
if (mass_load.gt(UInt64.zero)) {
|
|
271
|
+
if (mass_load.gt(UInt64.zero) && ship.loaders) {
|
|
261
272
|
const totalMass = UInt64.from(mass_load).adding(ship.loaders.mass)
|
|
262
273
|
loadTime = Number(calc_loader_flighttime(ship, totalMass))
|
|
263
274
|
}
|
|
264
275
|
|
|
265
|
-
const numLoaders = Number(ship.loaders.quantity)
|
|
276
|
+
const numLoaders = ship.loaders ? Number(ship.loaders.quantity) : 0
|
|
266
277
|
const totalTime = numLoaders > 0 ? (unloadTime + loadTime) / numLoaders : 0
|
|
267
278
|
const unloadTimePerLoader = numLoaders > 0 ? unloadTime / numLoaders : 0
|
|
268
279
|
const loadTimePerLoader = numLoaders > 0 ? loadTime / numLoaders : 0
|
|
@@ -307,6 +318,7 @@ export function estimateTravelTime(
|
|
|
307
318
|
if (
|
|
308
319
|
loadMass &&
|
|
309
320
|
UInt32.from(loadMass).gt(UInt32.zero) &&
|
|
321
|
+
ship.loaders &&
|
|
310
322
|
ship.loaders.quantity.gt(UInt32.zero)
|
|
311
323
|
) {
|
|
312
324
|
const totalMass = UInt64.from(loadMass).adding(ship.loaders.mass)
|
|
@@ -316,6 +328,7 @@ export function estimateTravelTime(
|
|
|
316
328
|
if (
|
|
317
329
|
unloadMass &&
|
|
318
330
|
UInt32.from(unloadMass).gt(UInt32.zero) &&
|
|
331
|
+
ship.loaders &&
|
|
319
332
|
ship.loaders.quantity.gt(UInt32.zero)
|
|
320
333
|
) {
|
|
321
334
|
const totalMass = UInt64.from(unloadMass).adding(ship.loaders.mass)
|
|
@@ -346,8 +359,9 @@ export function estimateDealTravelTime(
|
|
|
346
359
|
}
|
|
347
360
|
|
|
348
361
|
export function hasEnergyForDistance(ship: ShipLike, distance: UInt64Type): boolean {
|
|
362
|
+
if (!ship.engines) return false
|
|
349
363
|
const energyNeeded = UInt64.from(distance).dividing(PRECISION).multiplying(ship.engines.drain)
|
|
350
|
-
return UInt64.from(ship.energy).gte(energyNeeded)
|
|
364
|
+
return UInt64.from(ship.energy ?? 0).gte(energyNeeded)
|
|
351
365
|
}
|
|
352
366
|
|
|
353
367
|
export interface TransferEntity {
|
|
@@ -20,12 +20,8 @@ export interface LoaderCapability {
|
|
|
20
20
|
loaders: ServerContract.Types.loader_stats
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export interface
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface ExtractorCapability {
|
|
28
|
-
extractor: ServerContract.Types.extractor_stats
|
|
23
|
+
export interface GathererCapability {
|
|
24
|
+
gatherer: ServerContract.Types.gatherer_stats
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
export interface MassCapability {
|
|
@@ -42,8 +38,9 @@ export interface EntityCapabilities {
|
|
|
42
38
|
engines?: ServerContract.Types.movement_stats
|
|
43
39
|
generator?: ServerContract.Types.energy_stats
|
|
44
40
|
loaders?: ServerContract.Types.loader_stats
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
gatherer?: ServerContract.Types.gatherer_stats
|
|
42
|
+
crafter?: ServerContract.Types.crafter_stats
|
|
43
|
+
hauler?: ServerContract.Types.hauler_stats
|
|
47
44
|
}
|
|
48
45
|
|
|
49
46
|
export interface EntityState {
|
|
@@ -66,14 +63,14 @@ export function capsHasLoaders(caps: EntityCapabilities): boolean {
|
|
|
66
63
|
return caps.loaders !== undefined
|
|
67
64
|
}
|
|
68
65
|
|
|
69
|
-
export function
|
|
70
|
-
return caps.
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function capsHasExtractor(caps: EntityCapabilities): boolean {
|
|
74
|
-
return caps.extractor !== undefined
|
|
66
|
+
export function capsHasGatherer(caps: EntityCapabilities): boolean {
|
|
67
|
+
return caps.gatherer !== undefined
|
|
75
68
|
}
|
|
76
69
|
|
|
77
70
|
export function capsHasMass(caps: EntityCapabilities): boolean {
|
|
78
71
|
return caps.hullmass !== undefined
|
|
79
72
|
}
|
|
73
|
+
|
|
74
|
+
export function capsHasHauler(caps: EntityCapabilities): boolean {
|
|
75
|
+
return caps.hauler !== undefined
|
|
76
|
+
}
|
|
@@ -11,7 +11,6 @@ export interface EntityTraits {
|
|
|
11
11
|
isMovable: boolean
|
|
12
12
|
hasEnergy: boolean
|
|
13
13
|
hasLoaders: boolean
|
|
14
|
-
hasTrade: boolean
|
|
15
14
|
notFoundError: string
|
|
16
15
|
}
|
|
17
16
|
|
|
@@ -20,7 +19,7 @@ export const shipTraits: EntityTraits = {
|
|
|
20
19
|
isMovable: true,
|
|
21
20
|
hasEnergy: true,
|
|
22
21
|
hasLoaders: true,
|
|
23
|
-
|
|
22
|
+
|
|
24
23
|
notFoundError: 'ship not found',
|
|
25
24
|
}
|
|
26
25
|
|
|
@@ -29,7 +28,7 @@ export const warehouseTraits: EntityTraits = {
|
|
|
29
28
|
isMovable: false,
|
|
30
29
|
hasEnergy: false,
|
|
31
30
|
hasLoaders: true,
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
notFoundError: 'warehouse not found',
|
|
34
33
|
}
|
|
35
34
|
|
|
@@ -38,7 +37,7 @@ export const containerTraits: EntityTraits = {
|
|
|
38
37
|
isMovable: true,
|
|
39
38
|
hasEnergy: false,
|
|
40
39
|
hasLoaders: false,
|
|
41
|
-
|
|
40
|
+
|
|
42
41
|
notFoundError: 'container not found',
|
|
43
42
|
}
|
|
44
43
|
|
package/src/types/entity.ts
CHANGED
|
@@ -19,17 +19,20 @@ export interface Entity {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export type ShipEntity = Entity &
|
|
22
|
-
MovementCapability &
|
|
23
|
-
EnergyCapability &
|
|
22
|
+
Partial<MovementCapability> &
|
|
23
|
+
Partial<EnergyCapability> &
|
|
24
24
|
StorageCapability &
|
|
25
|
-
LoaderCapability &
|
|
25
|
+
Partial<LoaderCapability> &
|
|
26
26
|
MassCapability &
|
|
27
27
|
ScheduleCapability & {
|
|
28
|
-
|
|
29
|
-
extractor?: ServerContract.Types.extractor_stats
|
|
28
|
+
gatherer?: ServerContract.Types.gatherer_stats
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
export type WarehouseEntity = Entity &
|
|
31
|
+
export type WarehouseEntity = Entity &
|
|
32
|
+
StorageCapability &
|
|
33
|
+
Partial<LoaderCapability> &
|
|
34
|
+
MassCapability &
|
|
35
|
+
ScheduleCapability
|
|
33
36
|
|
|
34
37
|
export type ContainerEntity = Entity & StorageCapability & MassCapability & ScheduleCapability
|
|
35
38
|
|