@shipload/sdk 1.0.0-next.52 → 1.0.0-next.53

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@shipload/sdk",
3
3
  "description": "SDKs for Shipload",
4
- "version": "1.0.0-next.52",
4
+ "version": "1.0.0-next.53",
5
5
  "homepage": "https://github.com/shipload/toolkit/tree/master/packages/sdk",
6
6
  "repository": {
7
7
  "type": "git",
@@ -27,6 +27,7 @@ export const capabilityNames: string[] = [
27
27
  'Gathering',
28
28
  'Warp',
29
29
  'Crafting',
30
+ 'Build',
30
31
  'Launch',
31
32
  'Hauling',
32
33
  ]
@@ -73,6 +74,12 @@ export const capabilityAttributes: CapabilityAttribute[] = [
73
74
  description: 'Energy consumed per second while crafting',
74
75
  },
75
76
  {capability: 'Crafting', attribute: 'quality', description: 'Modifier on output quality'},
77
+ {capability: 'Build', attribute: 'speed', description: 'Build progress per second'},
78
+ {
79
+ capability: 'Build',
80
+ attribute: 'drain',
81
+ description: 'Energy consumed per second while building',
82
+ },
76
83
  {capability: 'Launch', attribute: 'range', description: 'Maximum launch distance'},
77
84
  {capability: 'Launch', attribute: 'capacity', description: 'Maximum mass per launch'},
78
85
  {capability: 'Launch', attribute: 'drain', description: 'Energy consumed per launch'},
@@ -9,6 +9,7 @@ export type SlotConsumerKind =
9
9
  | 'gatherer'
10
10
  | 'loader'
11
11
  | 'crafter'
12
+ | 'builder'
12
13
  | 'storage'
13
14
  | 'hauler'
14
15
  | 'warp'
@@ -47,6 +48,10 @@ export const SLOT_FORMULAS: Record<SlotConsumerKind, Record<number, SlotConsumer
47
48
  0: {capability: 'Crafting', attribute: 'speed'},
48
49
  1: {capability: 'Crafting', attribute: 'drain'},
49
50
  },
51
+ builder: {
52
+ 0: {capability: 'Build', attribute: 'speed'},
53
+ 1: {capability: 'Build', attribute: 'drain'},
54
+ },
50
55
  storage: {
51
56
  0: {capability: 'Storage', attribute: 'capacity'},
52
57
  1: {capability: 'Storage', attribute: 'capacity'},
@@ -777,33 +777,40 @@
777
777
  "outputMass": 960000,
778
778
  "inputs": [
779
779
  {
780
- "itemId": 10005,
780
+ "itemId": 10006,
781
781
  "quantity": 300
782
782
  },
783
783
  {
784
- "itemId": 10002,
784
+ "itemId": 10008,
785
785
  "quantity": 300
786
786
  }
787
787
  ],
788
788
  "statSlots": [
789
789
  {
790
790
  "sources": [
791
+ {
792
+ "inputIndex": 0,
793
+ "statIndex": 2
794
+ },
791
795
  {
792
796
  "inputIndex": 1,
793
- "statIndex": 1
797
+ "statIndex": 0
794
798
  }
795
799
  ]
796
800
  },
797
801
  {
798
802
  "sources": [
799
803
  {
800
- "inputIndex": 0,
804
+ "inputIndex": 1,
801
805
  "statIndex": 1
802
806
  }
803
807
  ]
804
808
  }
805
809
  ],
806
- "blendWeights": []
810
+ "blendWeights": [
811
+ 1,
812
+ 1
813
+ ]
807
814
  },
808
815
  {
809
816
  "outputItemId": 10200,
@@ -5,6 +5,7 @@ import {
5
5
  computeGathererCapabilities,
6
6
  computeGeneratorCapabilities,
7
7
  computeCrafterCapabilities,
8
+ computeBuilderCapabilities,
8
9
  computeLoaderCapabilities,
9
10
  computeBaseCapacity,
10
11
  computeContainerCapabilities,
@@ -30,6 +31,7 @@ import {
30
31
  ITEM_WRIGHT_T1_PACKED,
31
32
  ITEM_ENGINE_T1,
32
33
  ITEM_GENERATOR_T1,
34
+ ITEM_BUILDER_T1,
33
35
  } from '../data/item-ids'
34
36
  import type {InstalledModule} from '../entities/slot-multiplier'
35
37
  import type {EntitySlot} from '../data/recipes-runtime'
@@ -48,6 +50,10 @@ function makeLoaderStats(insulation: number, plasticity: number): bigint {
48
50
  return encodeStats([insulation, plasticity])
49
51
  }
50
52
 
53
+ function makeBuilderStats(resonance: number, fineness: number): bigint {
54
+ return encodeStats([resonance, fineness])
55
+ }
56
+
51
57
  test('computeBaseCapacity uses container formula for all container-class entities', () => {
52
58
  const stats = {strength: 300, hardness: 400, density: 100}
53
59
  const expected = computeContainerCapabilities(stats).capacity
@@ -154,6 +160,24 @@ test('computeEntityCapabilities emits crafterLanes alongside legacy crafter sum'
154
160
  expect(result.crafter!.speed).toBe(expectedSpeed)
155
161
  })
156
162
 
163
+ test('builder capabilities read canonical resonance and fineness slots', () => {
164
+ expect(computeBuilderCapabilities({resonance: 500, fineness: 330})).toEqual({
165
+ speed: 500,
166
+ drain: 20_000,
167
+ })
168
+ })
169
+
170
+ test('computeEntityCapabilities emits a Builder lane from resonance and fineness', () => {
171
+ const modules: InstalledModule[] = [
172
+ {slotIndex: 0, itemId: ITEM_BUILDER_T1, stats: makeBuilderStats(500, 330)},
173
+ ]
174
+ const layout: EntitySlot[] = [{type: 'builder', outputPct: 80, maxTier: 1}]
175
+ const result = computeEntityCapabilities({}, ITEM_EXTRACTOR_T1_PACKED, modules, layout)
176
+
177
+ expect(result.builderLanes).toEqual([{slotIndex: 0, speed: 400, drain: 20_000, outputPct: 80}])
178
+ expect(result.builder).toEqual({speed: 400, drain: 20_000})
179
+ })
180
+
157
181
  test('computeEntityCapabilities emits loaderLanes alongside legacy loaders sum', () => {
158
182
  const loaderStats = makeLoaderStats(600, 500)
159
183
 
@@ -147,12 +147,12 @@ export function computeBuilderCapabilities(stats: Record<string, number>): {
147
147
  speed: number
148
148
  drain: number
149
149
  } {
150
- const coh = stats.cohesion
151
- const tol = stats.tolerance
150
+ const resonance = stats.resonance
151
+ const fineness = stats.fineness
152
152
 
153
153
  return {
154
- speed: 100 + Math.floor((coh * 4) / 5),
155
- drain: Math.max(5000, 30000 - Math.floor((tol * 1000) / 33)),
154
+ speed: 100 + Math.floor((resonance * 4) / 5),
155
+ drain: Math.max(5000, 30000 - Math.floor((fineness * 1000) / 33)),
156
156
  }
157
157
  }
158
158
 
@@ -9,6 +9,7 @@ import {
9
9
  ITEM_GATHERER_T1,
10
10
  ITEM_LOADER_T1,
11
11
  ITEM_CRAFTER_T1,
12
+ ITEM_BUILDER_T1,
12
13
  ITEM_STORAGE_T1,
13
14
  ITEM_HAULER_T1,
14
15
  ITEM_WARP_T1,
@@ -27,6 +28,7 @@ export const KIND_TO_ITEM_ID: Record<SlotConsumerKind, number> = {
27
28
  gatherer: ITEM_GATHERER_T1,
28
29
  loader: ITEM_LOADER_T1,
29
30
  crafter: ITEM_CRAFTER_T1,
31
+ builder: ITEM_BUILDER_T1,
30
32
  storage: ITEM_STORAGE_T1,
31
33
  hauler: ITEM_HAULER_T1,
32
34
  warp: ITEM_WARP_T1,
@@ -263,12 +263,12 @@ export function buildModuleImmutable(
263
263
  break
264
264
  }
265
265
  case MODULE_BUILDER: {
266
- const coh = decodeStat(stats, 0)
267
- const tol = decodeStat(stats, 1)
268
- base.push({first: 'cohesion', second: ['uint16', coh]})
269
- base.push({first: 'tolerance', second: ['uint16', tol]})
270
- base.push({first: 'speed', second: ['uint16', computeBuilderSpeed(coh)]})
271
- base.push({first: 'drain', second: ['uint16', toWholeEnergy(computeBuilderDrain(tol))]})
266
+ const res = decodeStat(stats, 0)
267
+ const fin = decodeStat(stats, 1)
268
+ base.push({first: 'resonance', second: ['uint16', res]})
269
+ base.push({first: 'fineness', second: ['uint16', fin]})
270
+ base.push({first: 'speed', second: ['uint16', computeBuilderSpeed(res)]})
271
+ base.push({first: 'drain', second: ['uint16', toWholeEnergy(computeBuilderDrain(fin))]})
272
272
  break
273
273
  }
274
274
  case MODULE_STORAGE: {
@@ -114,9 +114,9 @@ export const computeLoaderThrust = (pla: number): number => 1 + idiv(pla * pla,
114
114
  export const computeCrafterSpeed = (rea: number): number => 100 + idiv(rea * 4, 5)
115
115
  export const computeCrafterDrain = (fin: number): number =>
116
116
  Math.max(5000, 30000 - idiv(fin * 1000, 33))
117
- export const computeBuilderSpeed = (coh: number): number => 100 + idiv(coh * 4, 5)
118
- export const computeBuilderDrain = (tol: number): number =>
119
- Math.max(5000, 30000 - idiv(tol * 1000, 33))
117
+ export const computeBuilderSpeed = (resonance: number): number => 100 + idiv(resonance * 4, 5)
118
+ export const computeBuilderDrain = (fineness: number): number =>
119
+ Math.max(5000, 30000 - idiv(fineness * 1000, 33))
120
120
  export const computeHaulerCapacity = (fin: number, tier: number): number =>
121
121
  Math.max(tier, tier + idiv(fin, 400))
122
122
  export const computeHaulerEfficiency = (con: number): number => 2000 + con * 6
@@ -260,9 +260,9 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
260
260
  break
261
261
  }
262
262
  case MODULE_BUILDER: {
263
- const coh = decodeStat(stats, 0)
264
- const tol = decodeStat(stats, 1)
265
- out += ` Speed ${computeBuilderSpeed(coh)} Drain ${toWholeEnergy(computeBuilderDrain(tol))}`
263
+ const res = decodeStat(stats, 0)
264
+ const fin = decodeStat(stats, 1)
265
+ out += ` Speed ${computeBuilderSpeed(res)} Drain ${toWholeEnergy(computeBuilderDrain(fin))}`
266
266
  break
267
267
  }
268
268
  case MODULE_STORAGE: {
@@ -130,12 +130,12 @@ export function resolveLaneBuilder(
130
130
  const item = getItem(Number(installed.item_id.value ?? installed.item_id))
131
131
  if (item.moduleType !== 'builder') throw new Error('lane module is not a builder')
132
132
  const stats = BigInt(installed.stats.toString())
133
- const coh = decodeStat(stats, 0)
134
- const tol = decodeStat(stats, 1)
133
+ const res = decodeStat(stats, 0)
134
+ const fin = decodeStat(stats, 1)
135
135
  const layout = getEntityLayout(entityItemId)?.slots ?? []
136
136
  const amp = getSlotAmp(layout, idx)
137
- const speed = applySlotMultiplier(computeBuilderSpeed(coh), amp)
138
- const drain = computeBuilderDrain(tol)
137
+ const speed = applySlotMultiplier(computeBuilderSpeed(res), amp)
138
+ const drain = computeBuilderDrain(fin)
139
139
  return {slotIndex: idx, speed, drain, outputPct: amp}
140
140
  }
141
141