@shipload/sdk 1.0.0-next.4 → 1.0.0-next.40
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 +2473 -973
- package/lib/shipload.js +11529 -5211
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +11338 -5162
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +970 -0
- package/lib/testing.js +4013 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +4007 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +15 -2
- package/src/capabilities/craftable.ts +51 -0
- package/src/capabilities/crafting.test.ts +7 -0
- package/src/capabilities/crafting.ts +5 -6
- package/src/capabilities/gathering.test.ts +16 -0
- package/src/capabilities/gathering.ts +35 -18
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +9 -0
- package/src/capabilities/storage.ts +16 -1
- package/src/contracts/platform.ts +231 -3
- package/src/contracts/server.ts +1021 -481
- package/src/coordinates/address.ts +88 -0
- package/src/coordinates/constants.test.ts +15 -0
- package/src/coordinates/constants.ts +23 -0
- package/src/coordinates/index.ts +15 -0
- package/src/coordinates/memo.test.ts +47 -0
- package/src/coordinates/memo.ts +20 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/data/capabilities.ts +12 -5
- package/src/data/capability-formulas.ts +14 -7
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +14 -47
- package/src/data/entities.json +76 -10
- package/src/data/item-ids.ts +18 -12
- package/src/data/items.json +321 -38
- package/src/data/kind-registry.json +109 -0
- package/src/data/kind-registry.ts +165 -0
- package/src/data/metadata.ts +119 -33
- package/src/data/recipes-runtime.ts +3 -23
- package/src/data/recipes.json +238 -117
- package/src/derivation/build-methods.ts +45 -0
- package/src/derivation/capabilities.test.ts +151 -0
- package/src/derivation/capabilities.ts +512 -0
- package/src/derivation/capability-mappings.ts +9 -12
- package/src/derivation/crafting.ts +23 -24
- package/src/derivation/index.ts +25 -2
- package/src/derivation/recipe-usage.test.ts +78 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +125 -38
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +56 -0
- package/src/derivation/stars.test.ts +51 -0
- package/src/derivation/stars.ts +15 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/stratum.ts +17 -20
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/wormhole.ts +136 -0
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +124 -134
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/errors.ts +12 -16
- package/src/format.ts +26 -4
- package/src/index-module.ts +267 -47
- package/src/managers/actions.ts +528 -95
- package/src/managers/base.ts +6 -2
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +412 -0
- package/src/managers/context.ts +20 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +18 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/index.ts +17 -1
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +14 -0
- package/src/managers/nft.ts +70 -0
- package/src/managers/plot.ts +122 -0
- package/src/nft/atomicassets.abi.json +1342 -0
- package/src/nft/atomicassets.ts +237 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +338 -0
- package/src/nft/description.ts +98 -24
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +127 -0
- package/src/planner/planner.test.ts +319 -0
- package/src/resolution/describe-module.ts +18 -13
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.test.ts +37 -0
- package/src/resolution/resolve-item.ts +55 -24
- package/src/scheduling/accessor.ts +68 -22
- package/src/scheduling/availability.ts +108 -0
- package/src/scheduling/cancel.test.ts +348 -0
- package/src/scheduling/cancel.ts +209 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +249 -0
- package/src/scheduling/lanes.ts +198 -0
- package/src/scheduling/projection.ts +209 -105
- package/src/scheduling/schedule.ts +241 -104
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/shipload.ts +21 -1
- package/src/subscriptions/manager.ts +229 -142
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +11 -3
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +167 -0
- package/src/travel/reach.ts +23 -0
- package/src/travel/route-planner.ts +196 -0
- package/src/travel/travel.ts +200 -112
- package/src/types/capabilities.ts +29 -6
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +28 -13
- package/src/utils/cargo.ts +27 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/system.ts +36 -24
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -108
- package/src/entities/ship-deploy.ts +0 -259
- package/src/entities/ship.ts +0 -204
- package/src/entities/warehouse.ts +0 -119
- package/src/types/entity-traits.ts +0 -69
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
BoundingBox,
|
|
4
4
|
BoundsDeltaMessage,
|
|
5
5
|
ClientMessage,
|
|
6
|
+
EntityDeletedMessage,
|
|
6
7
|
ServerMessage,
|
|
7
8
|
SnapshotMessage,
|
|
8
9
|
SubscribeEntityMessage,
|
|
@@ -13,12 +14,10 @@ import type {
|
|
|
13
14
|
WireEntity,
|
|
14
15
|
} from './types'
|
|
15
16
|
import {mapEntity, parseWireEntity} from './mappers'
|
|
16
|
-
import type {
|
|
17
|
-
import type {Warehouse} from '../entities/warehouse'
|
|
18
|
-
import type {Container} from '../entities/container'
|
|
17
|
+
import type {Entity} from '../entities/entity'
|
|
19
18
|
|
|
20
|
-
export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container'
|
|
21
|
-
export type EntityInstance =
|
|
19
|
+
export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container' | 'nexus'
|
|
20
|
+
export type EntityInstance = Entity
|
|
22
21
|
|
|
23
22
|
export interface SubscriptionsOptions {
|
|
24
23
|
url: string
|
|
@@ -27,44 +26,73 @@ export interface SubscriptionsOptions {
|
|
|
27
26
|
pongTimeoutMs?: number
|
|
28
27
|
}
|
|
29
28
|
|
|
30
|
-
export
|
|
29
|
+
export type ExactEntitySubscriptionFilter = {
|
|
30
|
+
id: string | number
|
|
31
|
+
owner?: never
|
|
32
|
+
bounds?: never
|
|
33
|
+
prioritizeOwner?: never
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export type BroadEntitySubscriptionFilter = {
|
|
37
|
+
id?: undefined
|
|
38
|
+
owner?: string
|
|
39
|
+
bounds?: BoundingBox
|
|
40
|
+
prioritizeOwner?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type EntitySubscriptionFilter = ExactEntitySubscriptionFilter | BroadEntitySubscriptionFilter
|
|
44
|
+
|
|
45
|
+
export interface EntitySubscriptionMeta {
|
|
46
|
+
seq?: number
|
|
47
|
+
truncated?: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface EntitySubscriptionHandlers {
|
|
51
|
+
onSnapshot?: (entities: EntityInstance[], meta: EntitySubscriptionMeta) => void
|
|
52
|
+
onUpdate?: (entity: EntityInstance, meta: EntitySubscriptionMeta) => void
|
|
53
|
+
onBoundsDelta?: (
|
|
54
|
+
entered: EntityInstance[],
|
|
55
|
+
exited: number[],
|
|
56
|
+
meta: EntitySubscriptionMeta
|
|
57
|
+
) => void
|
|
58
|
+
onDeleted?: (id: string, meta: EntitySubscriptionMeta) => void
|
|
59
|
+
onError?: (error: Error) => void
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface EntitiesSubscriptionHandle {
|
|
31
63
|
readonly subId: string
|
|
64
|
+
readonly filter: EntitySubscriptionFilter
|
|
32
65
|
unsubscribe(): void
|
|
33
|
-
updateBounds(bounds: BoundingBox): void
|
|
34
66
|
current: Map<number, EntityInstance>
|
|
35
67
|
}
|
|
36
68
|
|
|
37
|
-
export
|
|
38
|
-
readonly
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
69
|
+
export type BoundsSubscriptionHandle = EntitiesSubscriptionHandle & {
|
|
70
|
+
readonly filter: BroadEntitySubscriptionFilter & {bounds: BoundingBox}
|
|
71
|
+
updateBounds(bounds: BoundingBox): void
|
|
72
|
+
}
|
|
73
|
+
export type OwnerSubscriptionHandle = EntitiesSubscriptionHandle & {
|
|
74
|
+
readonly filter: BroadEntitySubscriptionFilter
|
|
75
|
+
}
|
|
76
|
+
export type EntitySubscriptionHandle = EntitiesSubscriptionHandle & {
|
|
77
|
+
readonly filter: ExactEntitySubscriptionFilter
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
type EntitiesSubscriptionEntry = {
|
|
81
|
+
filter: InternalEntitySubscriptionFilter
|
|
82
|
+
handlers: EntitySubscriptionHandlers
|
|
83
|
+
handle: EntitiesSubscriptionHandle
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
type InternalEntitySubscriptionFilter = {
|
|
87
|
+
id?: string | number
|
|
88
|
+
owner?: string
|
|
89
|
+
bounds?: BoundingBox
|
|
90
|
+
prioritizeOwner?: string
|
|
43
91
|
}
|
|
44
92
|
|
|
45
93
|
export class SubscriptionsManager {
|
|
46
94
|
private readonly conn: WebSocketConnection
|
|
47
|
-
private readonly entitySubs = new Map<
|
|
48
|
-
string,
|
|
49
|
-
{
|
|
50
|
-
type: SubscriptionEntityType
|
|
51
|
-
id: string
|
|
52
|
-
onUpdate: (e: EntityInstance) => void
|
|
53
|
-
handle: EntitySubscriptionHandle
|
|
54
|
-
}
|
|
55
|
-
>()
|
|
56
|
-
private readonly boundsSubs = new Map<
|
|
57
|
-
string,
|
|
58
|
-
{
|
|
59
|
-
bounds?: BoundingBox
|
|
60
|
-
owner?: string
|
|
61
|
-
prioritizeOwner?: string
|
|
62
|
-
onSnapshot?: (entities: EntityInstance[]) => void
|
|
63
|
-
onUpdate?: (entity: EntityInstance) => void
|
|
64
|
-
onBoundsDelta?: (entered: EntityInstance[], exited: number[]) => void
|
|
65
|
-
handle: BoundsSubscriptionHandle
|
|
66
|
-
}
|
|
67
|
-
>()
|
|
95
|
+
private readonly entitySubs = new Map<string, EntitiesSubscriptionEntry>()
|
|
68
96
|
private subCounter = 0
|
|
69
97
|
private hasConnected = false
|
|
70
98
|
|
|
@@ -93,83 +121,162 @@ export class SubscriptionsManager {
|
|
|
93
121
|
this.conn.send(msg)
|
|
94
122
|
}
|
|
95
123
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
124
|
+
subscribeEntities(
|
|
125
|
+
filter: BroadEntitySubscriptionFilter & {bounds: BoundingBox},
|
|
126
|
+
handlers?: EntitySubscriptionHandlers
|
|
127
|
+
): BoundsSubscriptionHandle
|
|
128
|
+
subscribeEntities(
|
|
129
|
+
filter: ExactEntitySubscriptionFilter,
|
|
130
|
+
handlers?: EntitySubscriptionHandlers
|
|
131
|
+
): EntitySubscriptionHandle
|
|
132
|
+
subscribeEntities(
|
|
133
|
+
filter: BroadEntitySubscriptionFilter,
|
|
134
|
+
handlers?: EntitySubscriptionHandlers
|
|
135
|
+
): EntitiesSubscriptionHandle
|
|
136
|
+
subscribeEntities(
|
|
137
|
+
filter: EntitySubscriptionFilter,
|
|
138
|
+
handlers?: EntitySubscriptionHandlers
|
|
139
|
+
): EntitiesSubscriptionHandle
|
|
140
|
+
subscribeEntities(
|
|
141
|
+
filter: EntitySubscriptionFilter,
|
|
142
|
+
handlers: EntitySubscriptionHandlers = {}
|
|
143
|
+
): EntitiesSubscriptionHandle {
|
|
144
|
+
const storedFilter = this.normalizeFilter(filter)
|
|
145
|
+
const subId = this.generateSubID(this.subscriptionPrefix(storedFilter))
|
|
146
|
+
const handle: EntitiesSubscriptionHandle = {
|
|
109
147
|
subId,
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
148
|
+
get filter() {
|
|
149
|
+
return SubscriptionsManager.publicFilter(storedFilter)
|
|
150
|
+
},
|
|
151
|
+
unsubscribe: () => this.unsubscribeEntities(subId),
|
|
152
|
+
current: new Map(),
|
|
114
153
|
}
|
|
115
|
-
|
|
116
|
-
|
|
154
|
+
if (storedFilter.id === undefined && storedFilter.bounds) {
|
|
155
|
+
;(handle as BoundsSubscriptionHandle).updateBounds = (bounds) =>
|
|
156
|
+
this.updateBounds(subId, bounds)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
this.entitySubs.set(subId, {filter: storedFilter, handlers, handle})
|
|
160
|
+
this.sendMessage(this.subscribeMessage(subId, storedFilter))
|
|
117
161
|
return handle
|
|
118
162
|
}
|
|
119
163
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
164
|
+
subscribeEntity(
|
|
165
|
+
id: string | number,
|
|
166
|
+
handlers: EntitySubscriptionHandlers
|
|
167
|
+
): EntitySubscriptionHandle {
|
|
168
|
+
return this.subscribeEntities({id}, handlers)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
subscribeOwner(
|
|
172
|
+
owner: string,
|
|
173
|
+
handlers: EntitySubscriptionHandlers = {}
|
|
174
|
+
): OwnerSubscriptionHandle {
|
|
175
|
+
return this.subscribeEntities({owner}, handlers) as OwnerSubscriptionHandle
|
|
126
176
|
}
|
|
127
177
|
|
|
128
178
|
subscribeBounds(
|
|
129
179
|
bounds: BoundingBox,
|
|
130
|
-
handlers: {
|
|
131
|
-
onSnapshot?: (entities: EntityInstance[]) => void
|
|
132
|
-
onUpdate?: (entity: EntityInstance) => void
|
|
133
|
-
onBoundsDelta?: (entered: EntityInstance[], exited: number[]) => void
|
|
180
|
+
handlers: EntitySubscriptionHandlers & {
|
|
134
181
|
owner?: string
|
|
135
182
|
prioritizeOwner?: string
|
|
136
|
-
}
|
|
183
|
+
} = {}
|
|
137
184
|
): BoundsSubscriptionHandle {
|
|
138
|
-
|
|
139
|
-
|
|
185
|
+
return this.subscribeEntities(
|
|
186
|
+
{bounds, owner: handlers.owner, prioritizeOwner: handlers.prioritizeOwner},
|
|
187
|
+
handlers
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
subscribeAllEntities(handlers: EntitySubscriptionHandlers = {}): EntitiesSubscriptionHandle {
|
|
192
|
+
return this.subscribeEntities({}, handlers)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private normalizeFilter(filter: EntitySubscriptionFilter): InternalEntitySubscriptionFilter {
|
|
196
|
+
const raw = filter as InternalEntitySubscriptionFilter
|
|
197
|
+
if (
|
|
198
|
+
raw.id !== undefined &&
|
|
199
|
+
(raw.owner !== undefined ||
|
|
200
|
+
raw.bounds !== undefined ||
|
|
201
|
+
raw.prioritizeOwner !== undefined)
|
|
202
|
+
) {
|
|
203
|
+
throw new Error(
|
|
204
|
+
'Exact entity subscription filters cannot include owner, bounds, or prioritizeOwner'
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
if (raw.id !== undefined) {
|
|
208
|
+
return {id: raw.id}
|
|
209
|
+
}
|
|
210
|
+
return {
|
|
211
|
+
owner: raw.owner,
|
|
212
|
+
bounds: raw.bounds ? this.cloneBounds(raw.bounds) : undefined,
|
|
213
|
+
prioritizeOwner: raw.prioritizeOwner,
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private static publicFilter(
|
|
218
|
+
filter: InternalEntitySubscriptionFilter
|
|
219
|
+
): EntitySubscriptionFilter {
|
|
220
|
+
if (filter.id !== undefined) {
|
|
221
|
+
return Object.freeze({id: filter.id}) as ExactEntitySubscriptionFilter
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return Object.freeze({
|
|
225
|
+
owner: filter.owner,
|
|
226
|
+
bounds: filter.bounds ? (Object.freeze({...filter.bounds}) as BoundingBox) : undefined,
|
|
227
|
+
prioritizeOwner: filter.prioritizeOwner,
|
|
228
|
+
}) as BroadEntitySubscriptionFilter
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
private cloneBounds(bounds: BoundingBox): BoundingBox {
|
|
232
|
+
return {...bounds}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private subscriptionPrefix(filter: InternalEntitySubscriptionFilter): string {
|
|
236
|
+
if (filter.id !== undefined) return 'ent'
|
|
237
|
+
if (filter.bounds) return 'bnd'
|
|
238
|
+
if (filter.owner) return 'own'
|
|
239
|
+
return 'all'
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
private subscribeMessage(
|
|
243
|
+
subId: string,
|
|
244
|
+
filter: InternalEntitySubscriptionFilter
|
|
245
|
+
): SubscribeEntityMessage | SubscribeMessage {
|
|
246
|
+
if (filter.id !== undefined) {
|
|
247
|
+
return {
|
|
248
|
+
type: 'subscribe_entity',
|
|
249
|
+
sub_id: subId,
|
|
250
|
+
entity_id: String(filter.id),
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return {
|
|
140
255
|
type: 'subscribe',
|
|
141
256
|
sub_id: subId,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
prioritize_owner:
|
|
145
|
-
}
|
|
146
|
-
const handle: BoundsSubscriptionHandle = {
|
|
147
|
-
subId,
|
|
148
|
-
unsubscribe: () => this.unsubscribeBounds(subId),
|
|
149
|
-
updateBounds: (b) => this.updateBounds(subId, b),
|
|
150
|
-
current: new Map(),
|
|
257
|
+
owner: filter.owner,
|
|
258
|
+
bounds: filter.bounds,
|
|
259
|
+
prioritize_owner: filter.prioritizeOwner,
|
|
151
260
|
}
|
|
152
|
-
this.boundsSubs.set(subId, {
|
|
153
|
-
bounds,
|
|
154
|
-
owner: handlers.owner,
|
|
155
|
-
prioritizeOwner: handlers.prioritizeOwner,
|
|
156
|
-
onSnapshot: handlers.onSnapshot,
|
|
157
|
-
onUpdate: handlers.onUpdate,
|
|
158
|
-
onBoundsDelta: handlers.onBoundsDelta,
|
|
159
|
-
handle,
|
|
160
|
-
})
|
|
161
|
-
this.sendMessage(msg)
|
|
162
|
-
return handle
|
|
163
261
|
}
|
|
164
262
|
|
|
165
|
-
private
|
|
166
|
-
this.
|
|
263
|
+
private unsubscribeEntities(subId: string) {
|
|
264
|
+
const entry = this.entitySubs.get(subId)
|
|
265
|
+
if (!entry) return
|
|
266
|
+
this.entitySubs.delete(subId)
|
|
267
|
+
if (entry.filter.id !== undefined) {
|
|
268
|
+
const msg: UnsubscribeEntityMessage = {type: 'unsubscribe_entity', sub_id: subId}
|
|
269
|
+
this.sendMessage(msg)
|
|
270
|
+
return
|
|
271
|
+
}
|
|
167
272
|
this.sendMessage({type: 'unsubscribe', sub_id: subId})
|
|
168
273
|
}
|
|
169
274
|
|
|
170
275
|
private updateBounds(subId: string, bounds: BoundingBox) {
|
|
171
|
-
const entry = this.
|
|
172
|
-
if (entry)
|
|
276
|
+
const entry = this.entitySubs.get(subId)
|
|
277
|
+
if (!entry) return
|
|
278
|
+
if (entry.filter.id !== undefined || !entry.filter.bounds) return
|
|
279
|
+
entry.filter.bounds = this.cloneBounds(bounds)
|
|
173
280
|
const msg: UpdateBoundsMessage = {type: 'update_bounds', sub_id: subId, bounds}
|
|
174
281
|
this.sendMessage(msg)
|
|
175
282
|
}
|
|
@@ -181,23 +288,7 @@ export class SubscriptionsManager {
|
|
|
181
288
|
return
|
|
182
289
|
}
|
|
183
290
|
for (const [subId, entry] of this.entitySubs) {
|
|
184
|
-
|
|
185
|
-
type: 'subscribe_entity',
|
|
186
|
-
sub_id: subId,
|
|
187
|
-
entity_type: entry.type,
|
|
188
|
-
entity_id: entry.id,
|
|
189
|
-
}
|
|
190
|
-
this.sendMessage(msg)
|
|
191
|
-
}
|
|
192
|
-
for (const [subId, entry] of this.boundsSubs) {
|
|
193
|
-
const msg: SubscribeMessage = {
|
|
194
|
-
type: 'subscribe',
|
|
195
|
-
sub_id: subId,
|
|
196
|
-
bounds: entry.bounds,
|
|
197
|
-
owner: entry.owner,
|
|
198
|
-
prioritize_owner: entry.prioritizeOwner,
|
|
199
|
-
}
|
|
200
|
-
this.sendMessage(msg)
|
|
291
|
+
this.sendMessage(this.subscribeMessage(subId, entry.filter))
|
|
201
292
|
}
|
|
202
293
|
}
|
|
203
294
|
|
|
@@ -212,6 +303,9 @@ export class SubscriptionsManager {
|
|
|
212
303
|
case 'bounds_delta':
|
|
213
304
|
this.handleBoundsDelta(msg)
|
|
214
305
|
break
|
|
306
|
+
case 'entity_deleted':
|
|
307
|
+
this.handleEntityDeleted(msg)
|
|
308
|
+
break
|
|
215
309
|
case 'error':
|
|
216
310
|
this.handleError(msg)
|
|
217
311
|
break
|
|
@@ -224,60 +318,53 @@ export class SubscriptionsManager {
|
|
|
224
318
|
}
|
|
225
319
|
|
|
226
320
|
private handleSnapshot(msg: SnapshotMessage) {
|
|
227
|
-
const
|
|
228
|
-
if (
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const boundsSub = this.boundsSubs.get(msg.sub_id)
|
|
237
|
-
if (boundsSub) {
|
|
238
|
-
const ents = msg.entities.map((e) => this.parseEntity(e))
|
|
239
|
-
boundsSub.handle.current.clear()
|
|
240
|
-
for (const e of ents) boundsSub.handle.current.set(Number(e.id), e)
|
|
241
|
-
boundsSub.onSnapshot?.(ents)
|
|
321
|
+
const sub = this.entitySubs.get(msg.sub_id)
|
|
322
|
+
if (!sub) return
|
|
323
|
+
const meta = {seq: msg.seq, truncated: msg.truncated === true}
|
|
324
|
+
const ents = msg.entities.map((e) => this.parseEntity(e))
|
|
325
|
+
sub.handle.current.clear()
|
|
326
|
+
for (const e of ents) sub.handle.current.set(Number(e.id), e)
|
|
327
|
+
sub.handlers.onSnapshot?.(ents, meta)
|
|
328
|
+
if (sub.filter.id !== undefined && ents[0]) {
|
|
329
|
+
sub.handlers.onUpdate?.(ents[0], {seq: msg.seq})
|
|
242
330
|
}
|
|
243
331
|
}
|
|
244
332
|
|
|
245
333
|
private handleUpdate(msg: UpdateMessage) {
|
|
246
334
|
const ent = this.parseEntity(msg.entity)
|
|
247
335
|
for (const subId of msg.sub_ids) {
|
|
248
|
-
const
|
|
249
|
-
if (
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
continue
|
|
253
|
-
}
|
|
254
|
-
const boundsSub = this.boundsSubs.get(subId)
|
|
255
|
-
if (boundsSub) {
|
|
256
|
-
boundsSub.handle.current.set(msg.entity_id, ent)
|
|
257
|
-
boundsSub.onUpdate?.(ent)
|
|
258
|
-
}
|
|
336
|
+
const sub = this.entitySubs.get(subId)
|
|
337
|
+
if (!sub) continue
|
|
338
|
+
sub.handle.current.set(msg.entity_id, ent)
|
|
339
|
+
sub.handlers.onUpdate?.(ent, {seq: msg.seq})
|
|
259
340
|
}
|
|
260
341
|
}
|
|
261
342
|
|
|
262
343
|
private handleBoundsDelta(msg: BoundsDeltaMessage) {
|
|
263
|
-
const sub = this.
|
|
344
|
+
const sub = this.entitySubs.get(msg.sub_id)
|
|
264
345
|
if (!sub) return
|
|
346
|
+
const meta = {seq: msg.seq, truncated: msg.truncated === true}
|
|
265
347
|
const entered = msg.entered.map((e) => this.parseEntity(e))
|
|
266
348
|
for (const e of entered) sub.handle.current.set(Number(e.id), e)
|
|
267
349
|
for (const id of msg.exited) sub.handle.current.delete(id)
|
|
268
|
-
sub.onBoundsDelta?.(entered, msg.exited)
|
|
350
|
+
sub.handlers.onBoundsDelta?.(entered, msg.exited, meta)
|
|
269
351
|
}
|
|
270
352
|
|
|
271
353
|
private handleError(msg: {sub_id?: string; error: string}) {
|
|
272
354
|
if (!msg.sub_id) return
|
|
273
|
-
const
|
|
274
|
-
if (
|
|
355
|
+
const sub = this.entitySubs.get(msg.sub_id)
|
|
356
|
+
if (!sub) return
|
|
357
|
+
this.entitySubs.delete(msg.sub_id)
|
|
358
|
+
sub.handlers.onError?.(new Error(msg.error))
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
private handleEntityDeleted(msg: EntityDeletedMessage) {
|
|
362
|
+
const sub = this.entitySubs.get(msg.sub_id)
|
|
363
|
+
if (!sub) return
|
|
364
|
+
sub.handle.current.delete(msg.entity_id)
|
|
365
|
+
if (sub.filter.id !== undefined) {
|
|
275
366
|
this.entitySubs.delete(msg.sub_id)
|
|
276
|
-
return
|
|
277
|
-
}
|
|
278
|
-
const boundsSub = this.boundsSubs.get(msg.sub_id)
|
|
279
|
-
if (boundsSub) {
|
|
280
|
-
this.boundsSubs.delete(msg.sub_id)
|
|
281
367
|
}
|
|
368
|
+
sub.handlers.onDeleted?.(String(msg.entity_id), {seq: msg.seq})
|
|
282
369
|
}
|
|
283
370
|
}
|
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import {ServerContract} from '../contracts'
|
|
2
|
-
import {
|
|
3
|
-
import {Warehouse} from '../entities/warehouse'
|
|
4
|
-
import {Container} from '../entities/container'
|
|
2
|
+
import {Entity} from '../entities/entity'
|
|
5
3
|
import type {WireEntity} from './types'
|
|
6
4
|
|
|
7
|
-
export function mapEntity(ei: ServerContract.Types.entity_info):
|
|
8
|
-
|
|
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()}`)
|
|
5
|
+
export function mapEntity(ei: ServerContract.Types.entity_info): Entity {
|
|
6
|
+
return new Entity(ei)
|
|
12
7
|
}
|
|
13
8
|
|
|
14
9
|
export function parseWireEntity(raw: WireEntity): ServerContract.Types.entity_info {
|
|
@@ -24,5 +19,7 @@ export function parseWireEntity(raw: WireEntity): ServerContract.Types.entity_in
|
|
|
24
19
|
}
|
|
25
20
|
delete shaped.name
|
|
26
21
|
|
|
22
|
+
if (shaped.holds === undefined) shaped.holds = []
|
|
23
|
+
|
|
27
24
|
return ServerContract.Types.entity_info.from(shaped)
|
|
28
25
|
}
|
|
@@ -39,7 +39,6 @@ export type UnsubscribeMessage = {
|
|
|
39
39
|
export type SubscribeEntityMessage = {
|
|
40
40
|
type: 'subscribe_entity'
|
|
41
41
|
sub_id: string
|
|
42
|
-
entity_type: 'ship' | 'warehouse' | 'container'
|
|
43
42
|
entity_id: string
|
|
44
43
|
}
|
|
45
44
|
|
|
@@ -79,11 +78,12 @@ export type AckMessage = {
|
|
|
79
78
|
}
|
|
80
79
|
|
|
81
80
|
export type WireEntity = Record<string, unknown> & {
|
|
82
|
-
type: number
|
|
83
|
-
type_name
|
|
81
|
+
type: number | string
|
|
82
|
+
type_name?: string
|
|
84
83
|
id: string | number
|
|
85
84
|
owner: string
|
|
86
85
|
coordinates: WireCoordinates
|
|
86
|
+
item_id: number
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
export type SnapshotMessage = {
|
|
@@ -111,6 +111,13 @@ export type BoundsDeltaMessage = {
|
|
|
111
111
|
truncated?: boolean
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
+
export type EntityDeletedMessage = {
|
|
115
|
+
type: 'entity_deleted'
|
|
116
|
+
sub_id: string
|
|
117
|
+
entity_id: number
|
|
118
|
+
seq: number
|
|
119
|
+
}
|
|
120
|
+
|
|
114
121
|
export type EventMessage = {
|
|
115
122
|
type: 'event'
|
|
116
123
|
sub_id: string
|
|
@@ -137,6 +144,7 @@ export type ServerMessage =
|
|
|
137
144
|
| SnapshotMessage
|
|
138
145
|
| UpdateMessage
|
|
139
146
|
| BoundsDeltaMessage
|
|
147
|
+
| EntityDeletedMessage
|
|
140
148
|
| EventMessage
|
|
141
149
|
| EventCatchupCompleteMessage
|
|
142
150
|
| PongMessage
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto'
|
|
2
|
+
import {readFileSync} from 'node:fs'
|
|
3
|
+
|
|
4
|
+
export const CATALOG_FILES_REL = [
|
|
5
|
+
'items.json',
|
|
6
|
+
'recipes.json',
|
|
7
|
+
'entities.json',
|
|
8
|
+
'kind-registry.json',
|
|
9
|
+
'item-ids.ts',
|
|
10
|
+
] as const
|
|
11
|
+
|
|
12
|
+
export function computeCatalogHash(filePaths: ReadonlyArray<string>): string {
|
|
13
|
+
const hash = createHash('sha256')
|
|
14
|
+
for (const p of filePaths) {
|
|
15
|
+
hash.update(readFileSync(p))
|
|
16
|
+
hash.update('\0')
|
|
17
|
+
}
|
|
18
|
+
return hash.digest('hex')
|
|
19
|
+
}
|