@shipload/sdk 1.0.0-next.43 → 1.0.0-next.44

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.
Files changed (39) hide show
  1. package/lib/shipload.d.ts +141 -172
  2. package/lib/shipload.js +503 -300
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +500 -302
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +50 -67
  7. package/lib/testing.js +168 -208
  8. package/lib/testing.js.map +1 -1
  9. package/lib/testing.m.js +169 -209
  10. package/lib/testing.m.js.map +1 -1
  11. package/package.json +1 -1
  12. package/src/contracts/server.ts +126 -214
  13. package/src/data/capabilities.ts +14 -14
  14. package/src/data/capability-formulas.ts +7 -7
  15. package/src/data/entities.json +4 -0
  16. package/src/data/item-ids.ts +1 -0
  17. package/src/data/items.json +6 -0
  18. package/src/data/kind-registry.json +18 -6
  19. package/src/data/kind-registry.ts +7 -0
  20. package/src/data/metadata.ts +22 -15
  21. package/src/data/recipes.json +170 -19
  22. package/src/derivation/build-methods.test.ts +13 -0
  23. package/src/derivation/build-methods.ts +5 -2
  24. package/src/derivation/capabilities.ts +8 -8
  25. package/src/index-module.ts +5 -0
  26. package/src/managers/actions.ts +25 -8
  27. package/src/managers/cluster.test.ts +39 -0
  28. package/src/managers/cluster.ts +53 -0
  29. package/src/managers/context.ts +9 -0
  30. package/src/managers/index.ts +2 -0
  31. package/src/nft/buildImmutableData.ts +15 -17
  32. package/src/nft/description.ts +8 -8
  33. package/src/resolution/describe-module.ts +6 -6
  34. package/src/resolution/resolve-item.ts +3 -3
  35. package/src/shipload.ts +5 -0
  36. package/src/subscriptions/manager.cluster.test.ts +46 -0
  37. package/src/subscriptions/manager.ts +22 -0
  38. package/src/subscriptions/types.ts +16 -0
  39. package/src/types.ts +7 -0
@@ -198,16 +198,14 @@ export function buildModuleImmutable(
198
198
  }
199
199
  case MODULE_GATHERER: {
200
200
  const str = decodeStat(stats, 0)
201
- const tol = decodeStat(stats, 1)
202
- const con = decodeStat(stats, 2)
203
- const ref = decodeStat(stats, 3)
201
+ const hrd = decodeStat(stats, 1)
202
+ const sat = decodeStat(stats, 2)
204
203
  base.push({first: 'strength', second: ['uint16', str]})
205
- base.push({first: 'tolerance', second: ['uint16', tol]})
206
- base.push({first: 'saturation', second: ['uint16', con]})
207
- base.push({first: 'plasticity', second: ['uint16', ref]})
204
+ base.push({first: 'hardness', second: ['uint16', hrd]})
205
+ base.push({first: 'saturation', second: ['uint16', sat]})
208
206
  base.push({first: 'yield', second: ['uint16', computeGathererYield(str)]})
209
- base.push({first: 'drain', second: ['uint16', computeGathererDrain(con)]})
210
- base.push({first: 'depth', second: ['uint16', computeGathererDepth(tol, item.tier)]})
207
+ base.push({first: 'drain', second: ['uint16', computeGathererDrain(sat)]})
208
+ base.push({first: 'depth', second: ['uint16', computeGathererDepth(hrd, item.tier)]})
211
209
  break
212
210
  }
213
211
  case MODULE_LOADER: {
@@ -220,17 +218,17 @@ export function buildModuleImmutable(
220
218
  break
221
219
  }
222
220
  case MODULE_WARP: {
223
- const res = decodeStat(stats, 0)
224
- base.push({first: 'resonance', second: ['uint16', res]})
225
- base.push({first: 'range', second: ['uint32', computeWarpRange(res)]})
221
+ const ref = decodeStat(stats, 0)
222
+ base.push({first: 'reflectivity', second: ['uint16', ref]})
223
+ base.push({first: 'range', second: ['uint32', computeWarpRange(ref)]})
226
224
  break
227
225
  }
228
226
  case MODULE_CRAFTER: {
229
- const rea = decodeStat(stats, 0)
227
+ const fin = decodeStat(stats, 0)
230
228
  const con = decodeStat(stats, 1)
231
- base.push({first: 'reactivity', second: ['uint16', rea]})
229
+ base.push({first: 'fineness', second: ['uint16', fin]})
232
230
  base.push({first: 'conductivity', second: ['uint16', con]})
233
- base.push({first: 'speed', second: ['uint16', computeCrafterSpeed(rea)]})
231
+ base.push({first: 'speed', second: ['uint16', computeCrafterSpeed(fin)]})
234
232
  base.push({first: 'drain', second: ['uint16', computeCrafterDrain(con)]})
235
233
  break
236
234
  }
@@ -267,13 +265,13 @@ export function buildModuleImmutable(
267
265
  case MODULE_HAULER: {
268
266
  const res = decodeStat(stats, 0)
269
267
  const pla = decodeStat(stats, 1)
270
- const ref = decodeStat(stats, 2)
268
+ const con = decodeStat(stats, 2)
271
269
  base.push({first: 'resonance', second: ['uint16', res]})
272
270
  base.push({first: 'plasticity', second: ['uint16', pla]})
273
- base.push({first: 'reflectivity', second: ['uint16', ref]})
271
+ base.push({first: 'conductivity', second: ['uint16', con]})
274
272
  base.push({first: 'capacity', second: ['uint8', computeHaulerCapacity(res)]})
275
273
  base.push({first: 'efficiency', second: ['uint16', computeHaulerEfficiency(pla)]})
276
- base.push({first: 'drain', second: ['uint16', computeHaulerDrain(ref)]})
274
+ base.push({first: 'drain', second: ['uint16', computeHaulerDrain(con)]})
277
275
  break
278
276
  }
279
277
  }
@@ -107,7 +107,7 @@ export function entityDisplayName(itemId: number): string {
107
107
  case ITEM_WAREHOUSE_T1_PACKED:
108
108
  return 'Warehouse'
109
109
  case ITEM_EXTRACTOR_T1_PACKED:
110
- return 'Extractor'
110
+ return 'Mining Rig'
111
111
  case ITEM_FACTORY_T1_PACKED:
112
112
  return 'Factory'
113
113
  case ITEM_CONTAINER_T1_PACKED:
@@ -124,19 +124,19 @@ export function moduleDisplayName(itemId: number): string {
124
124
  case ITEM_ENGINE_T1:
125
125
  return 'Engine'
126
126
  case ITEM_GENERATOR_T1:
127
- return 'Generator'
127
+ return 'Reactor'
128
128
  case ITEM_GATHERER_T1:
129
- return 'Gatherer'
129
+ return 'Limpet Bay'
130
130
  case ITEM_LOADER_T1:
131
- return 'Loader'
131
+ return 'Shuttle Bay'
132
132
  case ITEM_CRAFTER_T1:
133
- return 'Crafter'
133
+ return 'Fabricator'
134
134
  case ITEM_STORAGE_T1:
135
- return 'Cargo Bay'
135
+ return 'Cargo Hold'
136
136
  case ITEM_HAULER_T1:
137
- return 'Hauler'
137
+ return 'Tractor Beam'
138
138
  case ITEM_WARP_T1:
139
- return 'Warp'
139
+ return 'Warp Drive'
140
140
  case ITEM_BATTERY_T1:
141
141
  return 'Battery Bank'
142
142
  default:
@@ -61,8 +61,8 @@ const TEMPLATES: Record<string, TemplateSpec> = {
61
61
  ],
62
62
  highlightKeys: ['yield', 'depth', 'drain'],
63
63
  },
64
- loader: {
65
- id: 'module.loader.description',
64
+ loading: {
65
+ id: 'module.loading.description',
66
66
  template: 'generates {thrust} thrust with a weight of {mass} per unit',
67
67
  params: [
68
68
  ['thrust', 'Thrust'],
@@ -70,8 +70,8 @@ const TEMPLATES: Record<string, TemplateSpec> = {
70
70
  ],
71
71
  highlightKeys: ['thrust', 'mass'],
72
72
  },
73
- crafter: {
74
- id: 'module.crafter.description',
73
+ crafting: {
74
+ id: 'module.crafting.description',
75
75
  template: 'manufactures items at {speed} speed while draining {drain} energy per second',
76
76
  params: [
77
77
  ['speed', 'Speed'],
@@ -91,8 +91,8 @@ const TEMPLATES: Record<string, TemplateSpec> = {
91
91
  params: [['capacity', 'Energy Capacity']],
92
92
  highlightKeys: ['capacity'],
93
93
  },
94
- hauler: {
95
- id: 'module.hauler.description',
94
+ hauling: {
95
+ id: 'module.hauling.description',
96
96
  template:
97
97
  'locks onto up to {capacity} targets at {efficiency} efficiency while draining {drain} energy per distance travelled per target',
98
98
  params: [
@@ -198,7 +198,7 @@ function computeCapabilityGroup(
198
198
  case MODULE_LOADER: {
199
199
  const caps = computeLoaderCapabilities(stats)
200
200
  return {
201
- capability: 'Loader',
201
+ capability: 'Loading',
202
202
  attributes: [
203
203
  {label: 'Mass', value: caps.mass},
204
204
  {label: 'Thrust', value: caps.thrust},
@@ -209,7 +209,7 @@ function computeCapabilityGroup(
209
209
  case MODULE_CRAFTER: {
210
210
  const caps = computeCrafterCapabilities(stats)
211
211
  return {
212
- capability: 'Crafter',
212
+ capability: 'Crafting',
213
213
  attributes: [
214
214
  {label: 'Speed', value: caps.speed},
215
215
  {label: 'Drain', value: caps.drain},
@@ -219,7 +219,7 @@ function computeCapabilityGroup(
219
219
  case MODULE_HAULER: {
220
220
  const caps = computeHaulerCapabilities(stats)
221
221
  return {
222
- capability: 'Hauler',
222
+ capability: 'Hauling',
223
223
  attributes: [
224
224
  {label: 'Capacity', value: caps.capacity},
225
225
  {label: 'Efficiency', value: caps.efficiency},
package/src/shipload.ts CHANGED
@@ -10,6 +10,7 @@ import type {LocationsManager} from './managers/locations'
10
10
  import type {CoordinatesManager} from './managers/coordinates'
11
11
  import type {EpochsManager} from './managers/epochs'
12
12
  import type {ActionsManager} from './managers/actions'
13
+ import type {ClusterManager} from './managers/cluster'
13
14
  import type {NftManager} from './managers/nft'
14
15
  import type {SubscriptionsManager} from './subscriptions/manager'
15
16
  import type {GameState} from './entities/gamestate'
@@ -123,6 +124,10 @@ export class Shipload {
123
124
  return this._context.actions
124
125
  }
125
126
 
127
+ get clusters(): ClusterManager {
128
+ return this._context.clusters
129
+ }
130
+
126
131
  get nft(): NftManager {
127
132
  return this._context.nft
128
133
  }
@@ -0,0 +1,46 @@
1
+ import {afterEach, describe, expect, test} from 'bun:test'
2
+ import {SubscriptionsManager} from './manager'
3
+ import type {ServerMessage} from './types'
4
+
5
+ function createManager(): SubscriptionsManager {
6
+ return new SubscriptionsManager({url: 'ws://localhost:0'})
7
+ }
8
+
9
+ function deliver(mgr: SubscriptionsManager, msg: ServerMessage) {
10
+ ;(mgr as unknown as {onMessage(m: ServerMessage): void}).onMessage(msg)
11
+ }
12
+
13
+ describe('cluster delta routing', () => {
14
+ let mgr: SubscriptionsManager | undefined
15
+
16
+ afterEach(() => {
17
+ mgr?.close()
18
+ mgr = undefined
19
+ })
20
+
21
+ test('routes a cluster frame to the matching entity subscription onCluster', () => {
22
+ mgr = createManager()
23
+ const received: unknown[] = []
24
+ const handle = mgr.subscribeEntity(42, {
25
+ onCluster: (p) => received.push(p),
26
+ })
27
+ deliver(mgr, {
28
+ type: 'cluster',
29
+ sub_id: handle.subId,
30
+ hub_id: 42,
31
+ seq: 7,
32
+ cells: [{gx: 0, gy: 1, entity: 99}],
33
+ })
34
+ expect(received).toEqual([
35
+ {hubId: 42, seq: 7, cells: [{gx: 0, gy: 1, entity: 99}], erased: false},
36
+ ])
37
+ })
38
+
39
+ test('an erased cluster frame yields cells:null, erased:true', () => {
40
+ mgr = createManager()
41
+ const received: unknown[] = []
42
+ const handle = mgr.subscribeEntity(42, {onCluster: (p) => received.push(p)})
43
+ deliver(mgr, {type: 'cluster', sub_id: handle.subId, hub_id: 42, seq: 8, erased: true})
44
+ expect(received).toEqual([{hubId: 42, seq: 8, cells: null, erased: true}])
45
+ })
46
+ })
@@ -3,6 +3,8 @@ import type {
3
3
  BoundingBox,
4
4
  BoundsDeltaMessage,
5
5
  ClientMessage,
6
+ ClusterCellWire,
7
+ ClusterDeltaMessage,
6
8
  EntityDeletedMessage,
7
9
  ServerMessage,
8
10
  SnapshotMessage,
@@ -57,6 +59,12 @@ export interface EntitySubscriptionHandlers {
57
59
  ) => void
58
60
  onDeleted?: (id: string, meta: EntitySubscriptionMeta) => void
59
61
  onError?: (error: Error) => void
62
+ onCluster?: (payload: {
63
+ hubId: number
64
+ seq: number
65
+ cells: ClusterCellWire[] | null
66
+ erased: boolean
67
+ }) => void
60
68
  }
61
69
 
62
70
  export interface EntitiesSubscriptionHandle {
@@ -306,6 +314,9 @@ export class SubscriptionsManager {
306
314
  case 'entity_deleted':
307
315
  this.handleEntityDeleted(msg)
308
316
  break
317
+ case 'cluster':
318
+ this.handleCluster(msg)
319
+ break
309
320
  case 'error':
310
321
  this.handleError(msg)
311
322
  break
@@ -367,4 +378,15 @@ export class SubscriptionsManager {
367
378
  }
368
379
  sub.handlers.onDeleted?.(String(msg.entity_id), {seq: msg.seq})
369
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
+ })
391
+ }
370
392
  }
@@ -139,6 +139,21 @@ export type ErrorMessage = {
139
139
  sub_id?: string
140
140
  }
141
141
 
142
+ export interface ClusterCellWire {
143
+ gx: number
144
+ gy: number
145
+ entity: number
146
+ }
147
+
148
+ export type ClusterDeltaMessage = {
149
+ type: 'cluster'
150
+ sub_id: string
151
+ hub_id: number
152
+ seq: number
153
+ cells?: ClusterCellWire[]
154
+ erased?: boolean
155
+ }
156
+
142
157
  export type ServerMessage =
143
158
  | AckMessage
144
159
  | SnapshotMessage
@@ -149,3 +164,4 @@ export type ServerMessage =
149
164
  | EventCatchupCompleteMessage
150
165
  | PongMessage
151
166
  | ErrorMessage
167
+ | ClusterDeltaMessage
package/src/types.ts CHANGED
@@ -5,6 +5,7 @@ import {
5
5
  type UInt32,
6
6
  type UInt32Type,
7
7
  UInt64,
8
+ type UInt64Type,
8
9
  } from '@wharfkit/antelope'
9
10
  import {ServerContract} from './contracts'
10
11
 
@@ -25,6 +26,12 @@ export const BASE_ORBITAL_MASS = 100000
25
26
  export const MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE = 100
26
27
  export const MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL = 200
27
28
 
29
+ export interface ClusterSlotType {
30
+ hub: UInt64Type
31
+ gx: number
32
+ gy: number
33
+ }
34
+
28
35
  export interface ShipLike {
29
36
  coordinates: ServerContract.Types.coordinates
30
37
  hullmass?: UInt32