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