@shipload/sdk 2.0.0-rc14 → 2.0.0-rc15

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.
@@ -8,7 +8,7 @@ export interface StatDefinition {
8
8
  inverted?: boolean
9
9
  }
10
10
 
11
- const METAL_STATS: StatDefinition[] = [
11
+ const ORE_STATS: StatDefinition[] = [
12
12
  {
13
13
  key: 'strength',
14
14
  label: 'Strength',
@@ -30,24 +30,24 @@ const METAL_STATS: StatDefinition[] = [
30
30
  },
31
31
  ]
32
32
 
33
- const PRECIOUS_STATS: StatDefinition[] = [
33
+ const CRYSTAL_STATS: StatDefinition[] = [
34
34
  {
35
35
  key: 'conductivity',
36
36
  label: 'Conductivity',
37
37
  abbreviation: 'CON',
38
- purpose: 'Efficiency of energy/signal transfer',
38
+ purpose: 'Efficiency of energy/signal transfer through crystalline lattice',
39
39
  },
40
40
  {
41
- key: 'ductility',
42
- label: 'Ductility',
43
- abbreviation: 'DUC',
44
- purpose: 'Ability to be worked into fine, precise shapes',
41
+ key: 'resonance',
42
+ label: 'Resonance',
43
+ abbreviation: 'RES',
44
+ purpose: 'Frequency tuning and piezoelectric response storage and amplification',
45
45
  },
46
46
  {
47
47
  key: 'reflectivity',
48
48
  label: 'Reflectivity',
49
49
  abbreviation: 'REF',
50
- purpose: 'Surface quality for heat management and precision optics',
50
+ purpose: 'Optical refraction and reflection lenses, mirrors, focus',
51
51
  },
52
52
  ]
53
53
 
@@ -72,54 +72,54 @@ const GAS_STATS: StatDefinition[] = [
72
72
  },
73
73
  ]
74
74
 
75
- const MINERAL_STATS: StatDefinition[] = [
75
+ const REGOLITH_STATS: StatDefinition[] = [
76
76
  {
77
- key: 'resonance',
78
- label: 'Resonance',
79
- abbreviation: 'RES',
80
- purpose: 'Energy field interaction storage, focusing, projection',
77
+ key: 'composition',
78
+ label: 'Composition',
79
+ abbreviation: 'COM',
80
+ purpose: 'Mineral/metal mixdrives sensor, chip, and optic crafting quality',
81
81
  },
82
82
  {
83
83
  key: 'hardness',
84
84
  label: 'Hardness',
85
85
  abbreviation: 'HRD',
86
- purpose: 'Resistance to wear — cutting surfaces, penetration',
86
+ purpose: 'Particle hardness — cutting surfaces, abrasives, wear resistance',
87
87
  },
88
88
  {
89
- key: 'clarity',
90
- label: 'Clarity',
91
- abbreviation: 'CLR',
92
- purpose: 'Crystalline perfectionprecision optics',
89
+ key: 'fineness',
90
+ label: 'Fineness',
91
+ abbreviation: 'FIN',
92
+ purpose: 'Grain sizefine powder for smooth composites and sintering',
93
93
  },
94
94
  ]
95
95
 
96
- const ORGANIC_STATS: StatDefinition[] = [
96
+ const BIOMASS_STATS: StatDefinition[] = [
97
97
  {
98
98
  key: 'plasticity',
99
99
  label: 'Plasticity',
100
100
  abbreviation: 'PLA',
101
- purpose: 'Ease of reshaping speeds processing',
101
+ purpose: 'Flexibility and deformation under load',
102
102
  },
103
103
  {
104
104
  key: 'insulation',
105
105
  label: 'Insulation',
106
106
  abbreviation: 'INS',
107
- purpose: 'Energy containment reduces energy loss',
107
+ purpose: 'Thermal and electrical blocking capacity',
108
108
  },
109
109
  {
110
- key: 'purity',
111
- label: 'Purity',
112
- abbreviation: 'PUR',
113
- purpose: 'Biological cleanliness better composites and lubricants',
110
+ key: 'saturation',
111
+ label: 'Saturation',
112
+ abbreviation: 'SAT',
113
+ purpose: 'Concentration of useful organic compounds per unit',
114
114
  },
115
115
  ]
116
116
 
117
117
  const STAT_MAP: Record<ResourceCategory, StatDefinition[]> = {
118
- metal: METAL_STATS,
119
- precious: PRECIOUS_STATS,
118
+ ore: ORE_STATS,
119
+ crystal: CRYSTAL_STATS,
120
120
  gas: GAS_STATS,
121
- mineral: MINERAL_STATS,
122
- organic: ORGANIC_STATS,
121
+ regolith: REGOLITH_STATS,
122
+ biomass: BIOMASS_STATS,
123
123
  }
124
124
 
125
125
  export function getStatDefinitions(category: ResourceCategory): StatDefinition[] {
@@ -76,12 +76,12 @@ export function computeContainerCapabilities(stats: Record<string, number>): {
76
76
  } {
77
77
  const density = stats['density'] ?? 500
78
78
  const strength = stats['strength'] ?? 500
79
- const ductility = stats['ductility'] ?? 500
80
- const purity = stats['purity'] ?? 500
79
+ const fineness = stats['fineness'] ?? 500
80
+ const saturation = stats['saturation'] ?? 500
81
81
 
82
82
  const hullmass = 25000 + 75 * density
83
83
 
84
- const statSum = strength + ductility + purity
84
+ const statSum = strength + fineness + saturation
85
85
  const exponent = statSum / 2997
86
86
  const capacity = Math.floor(1000000 * Math.pow(10, exponent))
87
87
 
@@ -94,12 +94,12 @@ export function computeContainerT2Capabilities(stats: Record<string, number>): {
94
94
  } {
95
95
  const strength = stats['strength'] ?? 0
96
96
  const density = stats['density'] ?? 0
97
- const ductility = stats['ductility'] ?? 0
98
- const purity = stats['purity'] ?? 0
97
+ const fineness = stats['fineness'] ?? 0
98
+ const saturation = stats['saturation'] ?? 0
99
99
 
100
100
  const hullmass = 20000 + 50 * density
101
101
 
102
- const statSum = strength + ductility + purity
102
+ const statSum = strength + fineness + saturation
103
103
  const exponent = statSum / 2500
104
104
  const capacity = Math.floor(1500000 * Math.pow(10, exponent))
105
105
 
@@ -15,11 +15,11 @@ export function computeShipHullCapabilities(stats: Record<string, number>): {
15
15
  } {
16
16
  const density = stats.density ?? 500
17
17
  const strength = stats.strength ?? 500
18
- const ductility = stats.ductility ?? 500
19
- const purity = stats.purity ?? 500
18
+ const fineness = stats.fineness ?? 500
19
+ const saturation = stats.saturation ?? 500
20
20
 
21
21
  const hullmass = 25000 + 75 * density
22
- const statSum = strength + ductility + purity
22
+ const statSum = strength + fineness + saturation
23
23
  const exponent = statSum / 2997.0
24
24
  const capacity = Math.floor(1000000 * Math.pow(10, exponent))
25
25
 
@@ -44,11 +44,11 @@ export function computeGeneratorCapabilities(stats: Record<string, number>): {
44
44
  recharge: number
45
45
  } {
46
46
  const res = stats.resonance ?? 500
47
- const clr = stats.clarity ?? 500
47
+ const ref = stats.reflectivity ?? 500
48
48
 
49
49
  return {
50
50
  capacity: 300 + Math.floor(res / 6),
51
- recharge: 1 + Math.floor((clr * 3) / 1000),
51
+ recharge: 1 + Math.floor((ref * 3) / 1000),
52
52
  }
53
53
  }
54
54
 
@@ -76,11 +76,11 @@ export function computeLoaderCapabilities(stats: Record<string, number>): {
76
76
  thrust: number
77
77
  quantity: number
78
78
  } {
79
- const duc = stats.ductility ?? 500
79
+ const fin = stats.fineness ?? 500
80
80
  const pla = stats.plasticity ?? 500
81
81
 
82
82
  return {
83
- mass: Math.max(200, 2000 - Math.floor(duc * 2)),
83
+ mass: Math.max(200, 2000 - Math.floor(fin * 2)),
84
84
  thrust: 1 + Math.floor(pla / 500),
85
85
  quantity: 1,
86
86
  }
@@ -91,11 +91,11 @@ export function computeManufacturingCapabilities(stats: Record<string, number>):
91
91
  drain: number
92
92
  } {
93
93
  const rea = stats.reactivity ?? 500
94
- const clr = stats.clarity ?? 500
94
+ const com = stats.composition ?? 500
95
95
 
96
96
  return {
97
97
  speed: 100 + Math.floor((rea * 4) / 5),
98
- drain: Math.max(5, 30 - Math.floor(clr / 33)),
98
+ drain: Math.max(5, 30 - Math.floor(com / 33)),
99
99
  }
100
100
  }
101
101
 
@@ -106,12 +106,12 @@ export function computeHaulerCapabilities(stats: Record<string, number>): {
106
106
  } {
107
107
  const res = stats.resonance ?? 500
108
108
  const con = stats.conductivity ?? 500
109
- const clr = stats.clarity ?? 500
109
+ const ref = stats.reflectivity ?? 500
110
110
 
111
111
  return {
112
112
  capacity: Math.max(1, 1 + Math.floor(res / 400)),
113
113
  efficiency: 2000 + con * 6,
114
- drain: Math.max(3, 15 - Math.floor(clr / 80)),
114
+ drain: Math.max(3, 15 - Math.floor(ref / 80)),
115
115
  }
116
116
  }
117
117
 
@@ -122,10 +122,10 @@ export function computeStorageCapabilities(
122
122
  capacityBonus: number
123
123
  } {
124
124
  const strength = stats.strength ?? 500
125
- const ductility = stats.ductility ?? 500
126
- const purity = stats.purity ?? 500
125
+ const fineness = stats.fineness ?? 500
126
+ const saturation = stats.saturation ?? 500
127
127
 
128
- const statSum = strength + ductility + purity
128
+ const statSum = strength + fineness + saturation
129
129
  const capacityBonus = Math.floor(
130
130
  (baseCapacity * (10 + Math.floor((statSum * 10) / 2997))) / 100
131
131
  )
@@ -139,11 +139,11 @@ export function computeWarehouseHullCapabilities(stats: Record<string, number>):
139
139
  } {
140
140
  const density = stats.density ?? 500
141
141
  const strength = stats.strength ?? 500
142
- const ductility = stats.ductility ?? 500
143
- const purity = stats.purity ?? 500
142
+ const fineness = stats.fineness ?? 500
143
+ const saturation = stats.saturation ?? 500
144
144
 
145
145
  const hullmass = 25000 + 75 * density
146
- const statSum = strength + ductility + purity
146
+ const statSum = strength + fineness + saturation
147
147
  const exponent = statSum / 2997.0
148
148
  const capacity = Math.floor(20000000 * Math.pow(10, exponent))
149
149
 
package/src/format.ts ADDED
@@ -0,0 +1,12 @@
1
+ export function formatMass(kg: number): string {
2
+ const t = kg / 1000
3
+ const fixed = t.toFixed(2)
4
+ const trimmed = fixed.replace(/\.?0+$/, '')
5
+ return `${trimmed} t`
6
+ }
7
+
8
+ export function formatMassDelta(kg: number): string {
9
+ if (kg === 0) return '0 t'
10
+ const sign = kg > 0 ? '+' : '-'
11
+ return `${sign}${formatMass(Math.abs(kg))}`
12
+ }
@@ -329,3 +329,8 @@ export {
329
329
  ITEM_TYPE_ENTITY,
330
330
  itemTypeCode,
331
331
  } from './data/tiers'
332
+
333
+ export {formatMass, formatMassDelta} from './format'
334
+
335
+ export {displayName, describeItem} from './resolution/display-name'
336
+ export type {DescribeOptions} from './resolution/display-name'
@@ -35,7 +35,7 @@ function synthesizeItem(id: number, source: RecipeSource): Item {
35
35
  name: source.name,
36
36
  description: source.description,
37
37
  mass: source.mass,
38
- category: 'metal',
38
+ category: 'ore',
39
39
  tier: 't1',
40
40
  color: source.color,
41
41
  })
@@ -43,27 +43,27 @@ export function computeBaseCapacityWarehouse(stats: bigint): number {
43
43
  export const computeEngineThrust = (vol: number): number => 400 + idiv(vol * 3, 4)
44
44
  export const computeEngineDrain = (thm: number): number => Math.max(30, 50 - idiv(thm, 70))
45
45
  export const computeGeneratorCap = (res: number): number => 300 + idiv(res, 6)
46
- export const computeGeneratorRech = (clr: number): number => 1 + idiv(clr * 3, 1000)
46
+ export const computeGeneratorRech = (ref: number): number => 1 + idiv(ref * 3, 1000)
47
47
  export const computeGathererYield = (str: number): number => 200 + str
48
48
  export const computeGathererDrain = (con: number): number =>
49
49
  Math.max(250, 1250 - idiv(con * 25, 20))
50
50
  export const computeGathererDepth = (tol: number): number => 200 + idiv(tol * 3, 2)
51
51
  export const computeGathererSpeed = (ref: number): number => 100 + idiv(ref * 4, 5)
52
- export const computeLoaderMass = (duc: number): number => Math.max(200, 2000 - duc * 2)
52
+ export const computeLoaderMass = (fin: number): number => Math.max(200, 2000 - fin * 2)
53
53
  export const computeLoaderThrust = (pla: number): number => 1 + idiv(pla, 500)
54
54
  export const computeCrafterSpeed = (rea: number): number => 100 + idiv(rea * 4, 5)
55
- export const computeCrafterDrain = (clr: number): number => Math.max(5, 30 - idiv(clr, 33))
55
+ export const computeCrafterDrain = (com: number): number => Math.max(5, 30 - idiv(com, 33))
56
56
 
57
57
  export function entityDisplayName(itemId: number): string {
58
58
  switch (itemId) {
59
59
  case ITEM_SHIP_T1_PACKED:
60
- return 'Ship T1'
60
+ return 'Ship'
61
61
  case ITEM_WAREHOUSE_T1_PACKED:
62
- return 'Warehouse T1'
62
+ return 'Warehouse'
63
63
  case ITEM_CONTAINER_T1_PACKED:
64
- return 'Container T1'
64
+ return 'Container'
65
65
  case ITEM_CONTAINER_T2_PACKED:
66
- return 'Container T2'
66
+ return 'Container'
67
67
  default:
68
68
  return 'Entity'
69
69
  }
@@ -72,17 +72,17 @@ export function entityDisplayName(itemId: number): string {
72
72
  export function moduleDisplayName(itemId: number): string {
73
73
  switch (itemId) {
74
74
  case ITEM_ENGINE_T1:
75
- return 'Engine T1'
75
+ return 'Engine'
76
76
  case ITEM_GENERATOR_T1:
77
- return 'Generator T1'
77
+ return 'Generator'
78
78
  case ITEM_GATHERER_T1:
79
- return 'Gatherer T1'
79
+ return 'Gatherer'
80
80
  case ITEM_LOADER_T1:
81
- return 'Loader T1'
81
+ return 'Loader'
82
82
  case ITEM_MANUFACTURING_T1:
83
- return 'Manufacturing T1'
83
+ return 'Manufacturing'
84
84
  case ITEM_STORAGE_T1:
85
- return 'Storage T1'
85
+ return 'Storage'
86
86
  default:
87
87
  return 'Module'
88
88
  }
@@ -107,8 +107,8 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
107
107
  }
108
108
  case MODULE_GENERATOR: {
109
109
  const res = decodeStat(stats, 0)
110
- const clr = decodeStat(stats, 1)
111
- out += ` Capacity ${computeGeneratorCap(res)} Recharge ${computeGeneratorRech(clr)}`
110
+ const ref = decodeStat(stats, 1)
111
+ out += ` Capacity ${computeGeneratorCap(res)} Recharge ${computeGeneratorRech(ref)}`
112
112
  break
113
113
  }
114
114
  case MODULE_GATHERER: {
@@ -122,22 +122,22 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
122
122
  break
123
123
  }
124
124
  case MODULE_LOADER: {
125
- const duc = decodeStat(stats, 0)
125
+ const fin = decodeStat(stats, 0)
126
126
  const pla = decodeStat(stats, 1)
127
- out += ` Mass ${computeLoaderMass(duc)} Thrust ${computeLoaderThrust(pla)}`
127
+ out += ` Mass ${computeLoaderMass(fin)} Thrust ${computeLoaderThrust(pla)}`
128
128
  break
129
129
  }
130
130
  case MODULE_CRAFTER: {
131
131
  const rea = decodeStat(stats, 0)
132
- const clr = decodeStat(stats, 1)
133
- out += ` Speed ${computeCrafterSpeed(rea)} Drain ${computeCrafterDrain(clr)}`
132
+ const com = decodeStat(stats, 1)
133
+ out += ` Speed ${computeCrafterSpeed(rea)} Drain ${computeCrafterDrain(com)}`
134
134
  break
135
135
  }
136
136
  case MODULE_STORAGE: {
137
137
  const str = decodeStat(stats, 0)
138
- const duc = decodeStat(stats, 1)
139
- const pur = decodeStat(stats, 2)
140
- const sum = str + duc + pur
138
+ const fin = decodeStat(stats, 2)
139
+ const sat = decodeStat(stats, 3)
140
+ const sum = str + fin + sat
141
141
  const pct = 10 + idiv(sum * 10, 2997)
142
142
  out += ` +${pct}% capacity`
143
143
  break
@@ -0,0 +1,57 @@
1
+ import type {ResolvedItem} from './resolve-item'
2
+ import type {ResourceCategory} from '../types'
3
+ import {formatMass as defaultFormatMass} from '../format'
4
+
5
+ const TIER_ADJECTIVES: Record<number, string> = {
6
+ 1: 'Crude',
7
+ 2: 'Dense',
8
+ 3: 'Pure',
9
+ 4: 'Prime',
10
+ 5: 'Pristine',
11
+ 6: 'Radiant',
12
+ 7: 'Exotic',
13
+ 8: 'Mythic',
14
+ 9: 'Cosmic',
15
+ 10: 'Ascendant',
16
+ }
17
+
18
+ const CATEGORY_LABELS: Record<ResourceCategory, string> = {
19
+ ore: 'Ore',
20
+ crystal: 'Crystal',
21
+ gas: 'Gas',
22
+ regolith: 'Regolith',
23
+ biomass: 'Biomass',
24
+ }
25
+
26
+ function tierNumber(tier: string): number {
27
+ return Number(String(tier).replace(/^t/i, ''))
28
+ }
29
+
30
+ export function displayName(resolved: ResolvedItem): string {
31
+ if (resolved.itemType === 'resource') {
32
+ const tierNum = tierNumber(resolved.tier)
33
+ const adj = TIER_ADJECTIVES[tierNum] ?? 'Unknown'
34
+ const cat = resolved.category ? CATEGORY_LABELS[resolved.category] : 'Resource'
35
+ return `${adj} ${cat}`
36
+ }
37
+ return resolved.name
38
+ }
39
+
40
+ export interface DescribeOptions {
41
+ translate?: (key: string) => string
42
+ formatNumber?: (n: number) => string
43
+ formatMass?: (kg: number) => string
44
+ }
45
+
46
+ export function describeItem(resolved: ResolvedItem, opts?: DescribeOptions): string {
47
+ const massFmt = opts?.formatMass ?? defaultFormatMass
48
+ const mass = massFmt(resolved.mass)
49
+ const tier = `T${tierNumber(resolved.tier)}`
50
+ if (resolved.itemType === 'resource') {
51
+ const cat = resolved.category ? CATEGORY_LABELS[resolved.category] : 'Resource'
52
+ const header = `${tier} ${cat}`
53
+ const stats = resolved.stats?.map((s) => `${s.label} ${s.value}`).join(', ')
54
+ return [header, stats, mass].filter(Boolean).join(' · ')
55
+ }
56
+ return `${tier} ${resolved.name} · ${mass}`
57
+ }
@@ -117,14 +117,14 @@ function resolveComponent(id: number, stats?: UInt64Type): ResolvedItem {
117
117
  if (stats !== undefined) {
118
118
  const decoded = decodeCraftedItemStats(id, toBigStats(stats))
119
119
  resolvedStats = Object.entries(decoded).map(([key, value]) => {
120
- const allDefs = getStatDefinitions('metal')
121
- .concat(getStatDefinitions('precious'))
120
+ const allDefs = getStatDefinitions('ore')
121
+ .concat(getStatDefinitions('crystal'))
122
122
  .concat(getStatDefinitions('gas'))
123
- .concat(getStatDefinitions('mineral'))
124
- .concat(getStatDefinitions('organic'))
123
+ .concat(getStatDefinitions('regolith'))
124
+ .concat(getStatDefinitions('biomass'))
125
125
  const def = allDefs.find((d) => d.key === key)
126
126
  const statDef = comp.stats.find((s) => s.key === key)
127
- const cat = (statDef?.source ?? 'metal') as ResourceCategory
127
+ const cat = (statDef?.source ?? 'ore') as ResourceCategory
128
128
  return {
129
129
  key,
130
130
  label: def?.label ?? key,
@@ -219,9 +219,9 @@ function computeCapabilityGroup(
219
219
  }
220
220
  case MODULE_STORAGE: {
221
221
  const str = stats.strength ?? 500
222
- const duc = stats.ductility ?? 500
223
- const pur = stats.purity ?? 500
224
- const statSum = str + duc + pur
222
+ const fin = stats.fineness ?? 500
223
+ const sat = stats.saturation ?? 500
224
+ const statSum = str + fin + sat
225
225
  const pct = 10 + Math.floor((statSum * 10) / 2997)
226
226
  return {capability: 'Storage', attributes: [{label: 'Capacity Bonus', value: pct}]}
227
227
  }
package/src/types.ts CHANGED
@@ -113,7 +113,7 @@ export interface Distance {
113
113
  distance: UInt16
114
114
  }
115
115
 
116
- export type ResourceCategory = 'metal' | 'precious' | 'gas' | 'mineral' | 'organic'
116
+ export type ResourceCategory = 'ore' | 'crystal' | 'gas' | 'regolith' | 'biomass'
117
117
  export type ResourceTier = 't1' | 't2' | 't3' | 't4' | 't5'
118
118
 
119
119
  @Struct.type('item')