@shipload/sdk 2.0.0-rc5 → 2.0.0-rc6

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 (44) hide show
  1. package/lib/shipload.d.ts +376 -1008
  2. package/lib/shipload.js +712 -1948
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +694 -1924
  5. package/lib/shipload.m.js.map +1 -1
  6. package/package.json +1 -1
  7. package/src/capabilities/crafting.ts +10 -0
  8. package/src/capabilities/guards.ts +0 -5
  9. package/src/capabilities/index.ts +1 -0
  10. package/src/capabilities/storage.ts +0 -8
  11. package/src/contracts/server.ts +103 -220
  12. package/src/data/items.json +15 -15
  13. package/src/data/recipes.ts +129 -0
  14. package/src/derivation/crafting.ts +120 -0
  15. package/src/derivation/index.ts +1 -0
  16. package/src/derivation/stats.ts +91 -15
  17. package/src/derivation/stratum.ts +2 -2
  18. package/src/entities/cargo-utils.ts +6 -64
  19. package/src/entities/container.ts +18 -0
  20. package/src/entities/entity-inventory.ts +0 -4
  21. package/src/entities/inventory-accessor.ts +0 -4
  22. package/src/entities/location.ts +2 -197
  23. package/src/entities/player.ts +1 -274
  24. package/src/entities/ship.ts +0 -21
  25. package/src/entities/warehouse.ts +0 -4
  26. package/src/index-module.ts +34 -41
  27. package/src/managers/actions.ts +38 -90
  28. package/src/managers/context.ts +0 -9
  29. package/src/managers/index.ts +0 -1
  30. package/src/managers/locations.ts +2 -85
  31. package/src/market/items.ts +0 -1
  32. package/src/scheduling/projection.ts +0 -10
  33. package/src/shipload.ts +0 -5
  34. package/src/types/capabilities.ts +1 -9
  35. package/src/types/entity-traits.ts +3 -4
  36. package/src/types/entity.ts +0 -1
  37. package/src/types.ts +5 -25
  38. package/src/utils/system.ts +5 -4
  39. package/src/managers/trades.ts +0 -119
  40. package/src/market/market.ts +0 -195
  41. package/src/market/rolls.ts +0 -8
  42. package/src/trading/collect.ts +0 -938
  43. package/src/trading/deal.ts +0 -207
  44. package/src/trading/trade.ts +0 -203
@@ -1,17 +1,17 @@
1
1
  [
2
- {"id": 26, "name": "Iron", "description": "A versatile metal used in hulls and structures.", "base_price": 125, "mass": 40000, "category": "metal", "tier": "t1", "color": "#B7410E"},
3
- {"id": 13, "name": "Aluminum", "description": "A lightweight metal for structural components.", "base_price": 175, "mass": 27000, "category": "metal", "tier": "t2", "color": "#A8B5C2"},
4
- {"id": 24, "name": "Chromium", "description": "A hard, corrosion-resistant alloy metal.", "base_price": 350, "mass": 52000, "category": "metal", "tier": "t3", "color": "#D4E6F1"},
5
- {"id": 29, "name": "Copper", "description": "A conductive metal for electronics and wiring.", "base_price": 100, "mass": 60000, "category": "precious", "tier": "t1", "color": "#B87333"},
6
- {"id": 47, "name": "Silver", "description": "A high-conductivity metal for precision components.", "base_price": 300, "mass": 55000, "category": "precious", "tier": "t2", "color": "#C0C0C0"},
7
- {"id": 79, "name": "Gold", "description": "A corrosion-proof metal for advanced electronics.", "base_price": 500, "mass": 70000, "category": "precious", "tier": "t3", "color": "#FFD700"},
8
- {"id": 1, "name": "Hydrogen", "description": "A lightweight gas used for fuel cells and propulsion.", "base_price": 50, "mass": 15000, "category": "gas", "tier": "t1", "color": "#7EC8E3"},
9
- {"id": 2, "name": "Helium", "description": "An inert noble gas used in energy systems.", "base_price": 75, "mass": 2000, "category": "gas", "tier": "t2", "color": "#F5E6CC"},
10
- {"id": 18, "name": "Argon", "description": "A noble gas used in industrial and energy applications.", "base_price": 250, "mass": 8000, "category": "gas", "tier": "t3", "color": "#9B59B6"},
11
- {"id": 14, "name": "Silicon", "description": "A semiconductor used in sensors and computing.", "base_price": 150, "mass": 28000, "category": "mineral", "tier": "t1", "color": "#B8A9C9"},
12
- {"id": 1000, "name": "Quartz", "description": "A crystalline mineral for sensors and optics.", "base_price": 200, "mass": 35000, "category": "mineral", "tier": "t2", "color": "#E8D5B7"},
13
- {"id": 1001, "name": "Sapphire", "description": "A precious crystal for precision instruments.", "base_price": 400, "mass": 45000, "category": "mineral", "tier": "t3", "color": "#0F52BA"},
14
- {"id": 6, "name": "Carbon", "description": "A versatile element for life support and coatings.", "base_price": 100, "mass": 12000, "category": "organic", "tier": "t1", "color": "#4A4A4A"},
15
- {"id": 1003, "name": "Biomass", "description": "Organic matter for life support systems.", "base_price": 100, "mass": 30000, "category": "organic", "tier": "t2", "color": "#8B4513"},
16
- {"id": 1002, "name": "Resin", "description": "A fossilized organic compound for coatings and sealants.", "base_price": 300, "mass": 25000, "category": "organic", "tier": "t3", "color": "#DAA520"}
2
+ {"id": 26, "name": "Iron", "description": "A versatile metal used in hulls and structures.", "mass": 40000, "category": "metal", "tier": "t1", "color": "#B7410E"},
3
+ {"id": 13, "name": "Aluminum", "description": "A lightweight metal for structural components.", "mass": 27000, "category": "metal", "tier": "t2", "color": "#A8B5C2"},
4
+ {"id": 24, "name": "Chromium", "description": "A hard, corrosion-resistant alloy metal.", "mass": 52000, "category": "metal", "tier": "t3", "color": "#D4E6F1"},
5
+ {"id": 29, "name": "Copper", "description": "A conductive metal for electronics and wiring.", "mass": 60000, "category": "precious", "tier": "t1", "color": "#B87333"},
6
+ {"id": 47, "name": "Silver", "description": "A high-conductivity metal for precision components.", "mass": 55000, "category": "precious", "tier": "t2", "color": "#C0C0C0"},
7
+ {"id": 79, "name": "Gold", "description": "A corrosion-proof metal for advanced electronics.", "mass": 70000, "category": "precious", "tier": "t3", "color": "#FFD700"},
8
+ {"id": 1, "name": "Hydrogen", "description": "A lightweight gas used for fuel cells and propulsion.", "mass": 15000, "category": "gas", "tier": "t1", "color": "#7EC8E3"},
9
+ {"id": 2, "name": "Helium", "description": "An inert noble gas used in energy systems.", "mass": 2000, "category": "gas", "tier": "t2", "color": "#F5E6CC"},
10
+ {"id": 18, "name": "Argon", "description": "A noble gas used in industrial and energy applications.", "mass": 8000, "category": "gas", "tier": "t3", "color": "#9B59B6"},
11
+ {"id": 14, "name": "Silicon", "description": "A semiconductor used in sensors and computing.", "mass": 28000, "category": "mineral", "tier": "t1", "color": "#B8A9C9"},
12
+ {"id": 1000, "name": "Quartz", "description": "A crystalline mineral for sensors and optics.", "mass": 35000, "category": "mineral", "tier": "t2", "color": "#E8D5B7"},
13
+ {"id": 1001, "name": "Sapphire", "description": "A precious crystal for precision instruments.", "mass": 45000, "category": "mineral", "tier": "t3", "color": "#0F52BA"},
14
+ {"id": 6, "name": "Carbon", "description": "A versatile element for life support and coatings.", "mass": 12000, "category": "organic", "tier": "t1", "color": "#4A4A4A"},
15
+ {"id": 1003, "name": "Biomass", "description": "Organic matter for life support systems.", "mass": 30000, "category": "organic", "tier": "t2", "color": "#8B4513"},
16
+ {"id": 1002, "name": "Resin", "description": "A fossilized organic compound for coatings and sealants.", "mass": 25000, "category": "organic", "tier": "t3", "color": "#DAA520"}
17
17
  ]
@@ -0,0 +1,129 @@
1
+ import type {ResourceCategory} from '../types'
2
+
3
+ export const ITEM_HULL_PLATES = 10001
4
+ export const ITEM_CARGO_LINING = 10002
5
+ export const ITEM_CONTAINER_PACKED = 10003
6
+
7
+ export interface RecipeInput {
8
+ category?: ResourceCategory
9
+ itemId?: number
10
+ quantity: number
11
+ }
12
+
13
+ export interface ComponentStat {
14
+ key: string
15
+ source: ResourceCategory
16
+ }
17
+
18
+ export interface ComponentDefinition {
19
+ id: number
20
+ name: string
21
+ description: string
22
+ color: string
23
+ mass: number
24
+ stats: ComponentStat[]
25
+ recipe: RecipeInput[]
26
+ usedIn: {type: 'entity'; name: string}[]
27
+ }
28
+
29
+ export interface EntityRecipe {
30
+ id: string
31
+ name: string
32
+ description: string
33
+ color: string
34
+ packedItemId: number
35
+ recipe: RecipeInput[]
36
+ stats: {key: string; sourceComponentId: number; sourceStatKey: string}[]
37
+ }
38
+
39
+ export interface CraftableItem {
40
+ type: 'component' | 'entity'
41
+ id: number | string
42
+ name: string
43
+ description: string
44
+ color: string
45
+ }
46
+
47
+ export const components: ComponentDefinition[] = [
48
+ {
49
+ id: ITEM_HULL_PLATES,
50
+ name: 'Hull Plates',
51
+ description: 'Structural plating formed from metal. Used in hulls, containers, and frames.',
52
+ color: '#7B8D9E',
53
+ mass: 50000,
54
+ stats: [
55
+ {key: 'strength', source: 'metal'},
56
+ {key: 'density', source: 'metal'},
57
+ ],
58
+ recipe: [{category: 'metal', quantity: 40}],
59
+ usedIn: [{type: 'entity', name: 'Container'}],
60
+ },
61
+ {
62
+ id: ITEM_CARGO_LINING,
63
+ name: 'Cargo Lining',
64
+ description:
65
+ 'Precision-formed composite lining for cargo storage. Combines precious metal shaping with organic sealing.',
66
+ color: '#D4A843',
67
+ mass: 30000,
68
+ stats: [
69
+ {key: 'ductility', source: 'precious'},
70
+ {key: 'purity', source: 'organic'},
71
+ ],
72
+ recipe: [
73
+ {category: 'precious', quantity: 10},
74
+ {category: 'organic', quantity: 20},
75
+ ],
76
+ usedIn: [{type: 'entity', name: 'Container'}],
77
+ },
78
+ ]
79
+
80
+ export const entityRecipes: EntityRecipe[] = [
81
+ {
82
+ id: 'container',
83
+ name: 'Container',
84
+ description: 'Passive floating cargo storage in space. Towed by ships.',
85
+ color: '#7B8D9E',
86
+ packedItemId: ITEM_CONTAINER_PACKED,
87
+ recipe: [
88
+ {itemId: ITEM_HULL_PLATES, quantity: 6},
89
+ {itemId: ITEM_CARGO_LINING, quantity: 2},
90
+ ],
91
+ stats: [
92
+ {key: 'strength', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'strength'},
93
+ {key: 'density', sourceComponentId: ITEM_HULL_PLATES, sourceStatKey: 'density'},
94
+ {key: 'ductility', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'ductility'},
95
+ {key: 'purity', sourceComponentId: ITEM_CARGO_LINING, sourceStatKey: 'purity'},
96
+ ],
97
+ },
98
+ ]
99
+
100
+ export function getComponentById(id: number): ComponentDefinition | undefined {
101
+ return components.find((c) => c.id === id)
102
+ }
103
+
104
+ export function getEntityRecipe(id: string): EntityRecipe | undefined {
105
+ return entityRecipes.find((r) => r.id === id)
106
+ }
107
+
108
+ export function getEntityRecipeByItemId(itemId: number): EntityRecipe | undefined {
109
+ return entityRecipes.find((r) => r.packedItemId === itemId)
110
+ }
111
+
112
+ export function getAllCraftableItems(): CraftableItem[] {
113
+ const items: CraftableItem[] = []
114
+ for (const comp of components) {
115
+ items.push({type: 'component', id: comp.id, name: comp.name, description: comp.description, color: comp.color})
116
+ }
117
+ for (const entity of entityRecipes) {
118
+ items.push({type: 'entity', id: entity.id, name: entity.name, description: entity.description, color: entity.color})
119
+ }
120
+ return items
121
+ }
122
+
123
+ export function getComponentsForCategory(category: ResourceCategory): ComponentDefinition[] {
124
+ return components.filter((c) => c.recipe.some((r) => r.category === category))
125
+ }
126
+
127
+ export function getComponentsForStat(statKey: string): ComponentDefinition[] {
128
+ return components.filter((c) => c.stats.some((s) => s.key === statKey))
129
+ }
@@ -0,0 +1,120 @@
1
+ import type {ResourceCategory} from '../types'
2
+ import {
3
+ components,
4
+ entityRecipes,
5
+ getComponentById,
6
+ getEntityRecipe,
7
+ } from '../data/recipes'
8
+
9
+ export interface StackInput {
10
+ quantity: number
11
+ stats: Record<string, number>
12
+ }
13
+
14
+ export interface CategoryStacks {
15
+ category: ResourceCategory
16
+ stacks: StackInput[]
17
+ }
18
+
19
+ export function encodeStats(values: number[]): bigint {
20
+ let seed = 0n
21
+ for (let i = 0; i < values.length && i < 6; i++) {
22
+ seed |= BigInt(values[i] & 0x3ff) << BigInt(i * 10)
23
+ }
24
+ return seed
25
+ }
26
+
27
+ export function decodeStats(seed: bigint, count: number): number[] {
28
+ const stats: number[] = []
29
+ for (let i = 0; i < count; i++) {
30
+ stats.push(Number((seed >> BigInt(i * 10)) & 0x3ffn))
31
+ }
32
+ return stats
33
+ }
34
+
35
+ export function decodeCraftedItemStats(itemId: number, seed: bigint): Record<string, number> {
36
+ const comp = getComponentById(itemId)
37
+ if (comp) {
38
+ const values = decodeStats(seed, comp.stats.length)
39
+ const result: Record<string, number> = {}
40
+ for (let i = 0; i < comp.stats.length; i++) {
41
+ result[comp.stats[i].key] = values[i]
42
+ }
43
+ return result
44
+ }
45
+
46
+ const entityRecipe = entityRecipes.find((r) => r.packedItemId === itemId)
47
+ if (entityRecipe) {
48
+ const values = decodeStats(seed, entityRecipe.stats.length)
49
+ const result: Record<string, number> = {}
50
+ for (let i = 0; i < entityRecipe.stats.length; i++) {
51
+ result[entityRecipe.stats[i].key] = values[i]
52
+ }
53
+ return result
54
+ }
55
+
56
+ return {}
57
+ }
58
+
59
+ export function blendStacks(stacks: StackInput[], statKey: string): number {
60
+ let totalQty = 0
61
+ let weightedSum = 0
62
+ for (const stack of stacks) {
63
+ const val = stack.stats[statKey] ?? 0
64
+ weightedSum += val * stack.quantity
65
+ totalQty += stack.quantity
66
+ }
67
+ if (totalQty === 0) return 0
68
+ return Math.round(weightedSum / totalQty)
69
+ }
70
+
71
+ export function computeComponentStats(
72
+ componentId: number,
73
+ categoryStacks: CategoryStacks[]
74
+ ): {key: string; value: number}[] {
75
+ const comp = getComponentById(componentId)
76
+ if (!comp) return []
77
+
78
+ return comp.stats.map((statDef) => {
79
+ const matching = categoryStacks.find((cs) => cs.category === statDef.source)
80
+ const value = matching ? blendStacks(matching.stacks, statDef.key) : 0
81
+ return {key: statDef.key, value: Math.max(1, Math.min(999, value))}
82
+ })
83
+ }
84
+
85
+ export function blendComponentStacks(
86
+ stacks: {quantity: number; stats: Record<string, number>}[]
87
+ ): Record<string, number> {
88
+ if (stacks.length === 0) return {}
89
+ const allKeys = new Set<string>()
90
+ for (const s of stacks) {
91
+ for (const k of Object.keys(s.stats)) allKeys.add(k)
92
+ }
93
+ const result: Record<string, number> = {}
94
+ for (const key of allKeys) {
95
+ result[key] = blendStacks(
96
+ stacks.map((s) => ({quantity: s.quantity, stats: s.stats})),
97
+ key
98
+ )
99
+ }
100
+ return result
101
+ }
102
+
103
+ export function computeEntityStats(
104
+ entityRecipeId: string,
105
+ componentStacks: Record<number, {quantity: number; stats: Record<string, number>}[]>
106
+ ): {key: string; value: number}[] {
107
+ const recipe = getEntityRecipe(entityRecipeId)
108
+ if (!recipe) return []
109
+
110
+ const blendedByComponent: Record<number, Record<string, number>> = {}
111
+ for (const [compId, stacks] of Object.entries(componentStacks)) {
112
+ blendedByComponent[Number(compId)] = blendComponentStacks(stacks)
113
+ }
114
+
115
+ return recipe.stats.map((stat) => {
116
+ const blended = blendedByComponent[stat.sourceComponentId] ?? {}
117
+ const value = blended[stat.sourceStatKey] ?? 0
118
+ return {key: stat.key, value: Math.max(1, Math.min(999, value))}
119
+ })
120
+ }
@@ -25,3 +25,4 @@ export {
25
25
  } from './resources'
26
26
 
27
27
  export * from './stats'
28
+ export * from './crafting'
@@ -9,33 +9,109 @@ export interface StatDefinition {
9
9
  }
10
10
 
11
11
  const METAL_STATS: StatDefinition[] = [
12
- {key: 'strength', label: 'Strength', abbreviation: 'STR', purpose: 'Raw structural/mechanical force'},
13
- {key: 'tolerance', label: 'Tolerance', abbreviation: 'TOL', purpose: 'Ability to withstand heat, pressure, and stress extremes'},
14
- {key: 'density', label: 'Density', abbreviation: 'DEN', purpose: 'Mass per unit', inverted: true},
12
+ {
13
+ key: 'strength',
14
+ label: 'Strength',
15
+ abbreviation: 'STR',
16
+ purpose: 'Raw structural/mechanical force',
17
+ },
18
+ {
19
+ key: 'tolerance',
20
+ label: 'Tolerance',
21
+ abbreviation: 'TOL',
22
+ purpose: 'Ability to withstand heat, pressure, and stress extremes',
23
+ },
24
+ {
25
+ key: 'density',
26
+ label: 'Density',
27
+ abbreviation: 'DEN',
28
+ purpose: 'Mass per unit',
29
+ inverted: true,
30
+ },
15
31
  ]
16
32
 
17
33
  const PRECIOUS_STATS: StatDefinition[] = [
18
- {key: 'conductivity', label: 'Conductivity', abbreviation: 'CON', purpose: 'Efficiency of energy/signal transfer'},
19
- {key: 'ductility', label: 'Ductility', abbreviation: 'DUC', purpose: 'Ability to be worked into fine, precise shapes'},
20
- {key: 'reflectivity', label: 'Reflectivity', abbreviation: 'REF', purpose: 'Surface quality for heat management and precision optics'},
34
+ {
35
+ key: 'conductivity',
36
+ label: 'Conductivity',
37
+ abbreviation: 'CON',
38
+ purpose: 'Efficiency of energy/signal transfer',
39
+ },
40
+ {
41
+ key: 'ductility',
42
+ label: 'Ductility',
43
+ abbreviation: 'DUC',
44
+ purpose: 'Ability to be worked into fine, precise shapes',
45
+ },
46
+ {
47
+ key: 'reflectivity',
48
+ label: 'Reflectivity',
49
+ abbreviation: 'REF',
50
+ purpose: 'Surface quality for heat management and precision optics',
51
+ },
21
52
  ]
22
53
 
23
54
  const GAS_STATS: StatDefinition[] = [
24
- {key: 'volatility', label: 'Volatility', abbreviation: 'VOL', purpose: 'Energy release potential for propulsion and force'},
25
- {key: 'reactivity', label: 'Reactivity', abbreviation: 'REA', purpose: 'Chemical interaction speed for processing and penetration'},
26
- {key: 'thermal', label: 'Thermal', abbreviation: 'THM', purpose: 'Heat capacity for thermal management'},
55
+ {
56
+ key: 'volatility',
57
+ label: 'Volatility',
58
+ abbreviation: 'VOL',
59
+ purpose: 'Energy release potential for propulsion and force',
60
+ },
61
+ {
62
+ key: 'reactivity',
63
+ label: 'Reactivity',
64
+ abbreviation: 'REA',
65
+ purpose: 'Chemical interaction speed for processing and penetration',
66
+ },
67
+ {
68
+ key: 'thermal',
69
+ label: 'Thermal',
70
+ abbreviation: 'THM',
71
+ purpose: 'Heat capacity for thermal management',
72
+ },
27
73
  ]
28
74
 
29
75
  const MINERAL_STATS: StatDefinition[] = [
30
- {key: 'resonance', label: 'Resonance', abbreviation: 'RES', purpose: 'Energy field interaction — storage, focusing, projection'},
31
- {key: 'hardness', label: 'Hardness', abbreviation: 'HRD', purpose: 'Resistance to wear — cutting surfaces, penetration'},
32
- {key: 'clarity', label: 'Clarity', abbreviation: 'CLR', purpose: 'Crystalline perfection — precision optics'},
76
+ {
77
+ key: 'resonance',
78
+ label: 'Resonance',
79
+ abbreviation: 'RES',
80
+ purpose: 'Energy field interaction — storage, focusing, projection',
81
+ },
82
+ {
83
+ key: 'hardness',
84
+ label: 'Hardness',
85
+ abbreviation: 'HRD',
86
+ purpose: 'Resistance to wear — cutting surfaces, penetration',
87
+ },
88
+ {
89
+ key: 'clarity',
90
+ label: 'Clarity',
91
+ abbreviation: 'CLR',
92
+ purpose: 'Crystalline perfection — precision optics',
93
+ },
33
94
  ]
34
95
 
35
96
  const ORGANIC_STATS: StatDefinition[] = [
36
- {key: 'plasticity', label: 'Plasticity', abbreviation: 'PLA', purpose: 'Ease of reshaping — speeds processing'},
37
- {key: 'insulation', label: 'Insulation', abbreviation: 'INS', purpose: 'Energy containment — reduces energy loss'},
38
- {key: 'purity', label: 'Purity', abbreviation: 'PUR', purpose: 'Biological cleanliness — better composites and lubricants'},
97
+ {
98
+ key: 'plasticity',
99
+ label: 'Plasticity',
100
+ abbreviation: 'PLA',
101
+ purpose: 'Ease of reshaping — speeds processing',
102
+ },
103
+ {
104
+ key: 'insulation',
105
+ label: 'Insulation',
106
+ abbreviation: 'INS',
107
+ purpose: 'Energy containment — reduces energy loss',
108
+ },
109
+ {
110
+ key: 'purity',
111
+ label: 'Purity',
112
+ abbreviation: 'PUR',
113
+ purpose: 'Biological cleanliness — better composites and lubricants',
114
+ },
39
115
  ]
40
116
 
41
117
  const STAT_MAP: Record<ResourceCategory, StatDefinition[]> = {
@@ -85,7 +85,7 @@ export function deriveStratum(
85
85
 
86
86
  let depthBonus = 0
87
87
  if (stratum > 1) {
88
- depthBonus = 50 * Math.log(stratum) / Math.log(65535)
88
+ depthBonus = (50 * Math.log(stratum)) / Math.log(65535)
89
89
  }
90
90
  const richness = Math.min(Math.floor(baseRichness + depthBonus), 1000)
91
91
 
@@ -95,7 +95,7 @@ export function deriveStratum(
95
95
  export function deriveResourceStats(seed: bigint): ResourceStats {
96
96
  const seedBytes = new Uint8Array(8)
97
97
  for (let i = 7; i >= 0; i--) {
98
- seedBytes[i] = Number(seed & 0xFFn)
98
+ seedBytes[i] = Number(seed & 0xffn)
99
99
  seed >>= 8n
100
100
  }
101
101
  const hashResult = Checksum256.hash(Bytes.from(seedBytes))
@@ -12,12 +12,6 @@ export function totalCargoMass(cargo: EntityInventory[]): UInt64 {
12
12
  }, UInt64.from(0))
13
13
  }
14
14
 
15
- export function cargoValue(cargo: EntityInventory[]): UInt64 {
16
- return cargo.reduce((sum, c) => {
17
- return sum.adding(c.totalCost)
18
- }, UInt64.from(0))
19
- }
20
-
21
15
  export function getCargoForItem(
22
16
  cargo: EntityInventory[],
23
17
  goodId: UInt64Type
@@ -47,84 +41,33 @@ export function isFull(currentMass: UInt64, maxCapacity: UInt64): boolean {
47
41
  return currentMass.gte(maxCapacity)
48
42
  }
49
43
 
50
- export interface SaleValue {
51
- revenue: UInt64
52
- profit: UInt64
53
- cost: UInt64
54
- }
55
-
56
- export function calculateSaleValue(
57
- cargo: ServerContract.Types.cargo_item[],
58
- prices: Map<number, UInt64>
59
- ): SaleValue {
60
- if (cargo.length === 0) {
61
- return {revenue: UInt64.from(0), profit: UInt64.from(0), cost: UInt64.from(0)}
62
- }
63
-
64
- let revenue = UInt64.from(0)
65
- let cost = UInt64.from(0)
66
-
67
- for (const item of cargo) {
68
- if (UInt32.from(item.quantity).equals(UInt32.from(0))) continue
69
-
70
- const goodId = Number(item.item_id)
71
- const salePrice = prices.get(goodId)
72
-
73
- if (salePrice) {
74
- revenue = revenue.adding(salePrice.multiplying(item.quantity))
75
- }
76
-
77
- cost = cost.adding(item.unit_cost.multiplying(item.quantity))
78
- }
79
-
80
- const profit = revenue.gte(cost) ? revenue.subtracting(cost) : UInt64.from(0)
81
-
82
- return {
83
- revenue,
84
- profit,
85
- cost,
86
- }
87
- }
88
-
89
- export function calculateSaleValueFromArray(
90
- cargo: ServerContract.Types.cargo_item[],
91
- prices: UInt64[]
92
- ): SaleValue {
93
- const priceMap = new Map<number, UInt64>()
94
- prices.forEach((price, index) => {
95
- priceMap.set(index, price)
96
- })
97
- return calculateSaleValue(cargo, priceMap)
98
- }
99
-
100
- export function afterSellItems(
44
+ export function afterRemoveItems(
101
45
  cargo: ServerContract.Types.cargo_item[],
102
- goodsToSell: Array<{goodId: number; quantity: number}>
46
+ goodsToRemove: Array<{goodId: number; quantity: number}>
103
47
  ): EntityInventory[] {
104
48
  if (cargo.length === 0) {
105
49
  return []
106
50
  }
107
51
 
108
52
  return cargo.map((item) => {
109
- const saleItem = goodsToSell.find((s) => Number(item.item_id) === s.goodId)
110
- if (!saleItem) {
53
+ const removeItem = goodsToRemove.find((s) => Number(item.item_id) === s.goodId)
54
+ if (!removeItem) {
111
55
  return new EntityInventory(item)
112
56
  }
113
57
 
114
58
  const currentQty = Number(item.quantity)
115
- const newQty = Math.max(0, currentQty - saleItem.quantity)
59
+ const newQty = Math.max(0, currentQty - removeItem.quantity)
116
60
 
117
61
  return new EntityInventory(
118
62
  ServerContract.Types.cargo_item.from({
119
63
  item_id: item.item_id,
120
64
  quantity: UInt32.from(newQty),
121
- unit_cost: item.unit_cost,
122
65
  })
123
66
  )
124
67
  })
125
68
  }
126
69
 
127
- export function afterSellAllItems(cargo: ServerContract.Types.cargo_item[]): EntityInventory[] {
70
+ export function afterRemoveAllItems(cargo: ServerContract.Types.cargo_item[]): EntityInventory[] {
128
71
  if (cargo.length === 0) {
129
72
  return []
130
73
  }
@@ -135,7 +78,6 @@ export function afterSellAllItems(cargo: ServerContract.Types.cargo_item[]): Ent
135
78
  ServerContract.Types.cargo_item.from({
136
79
  item_id: item.item_id,
137
80
  quantity: UInt32.from(0),
138
- unit_cost: item.unit_cost,
139
81
  })
140
82
  )
141
83
  )
@@ -68,3 +68,21 @@ export class Container extends ServerContract.Types.entity_info {
68
68
  return this.coordinates.z?.toNumber() || 0
69
69
  }
70
70
  }
71
+
72
+ export function computeContainerCapabilities(stats: Record<string, number>): {
73
+ hullmass: number
74
+ capacity: number
75
+ } {
76
+ const density = stats['density'] ?? 500
77
+ const strength = stats['strength'] ?? 500
78
+ const ductility = stats['ductility'] ?? 500
79
+ const purity = stats['purity'] ?? 500
80
+
81
+ const hullmass = 25000 + 75 * density
82
+
83
+ const statSum = strength + ductility + purity
84
+ const exponent = statSum / 2997
85
+ const capacity = Math.floor(1000000 * Math.pow(10, exponent))
86
+
87
+ return {hullmass, capacity}
88
+ }
@@ -29,10 +29,6 @@ export class EntityInventory extends ServerContract.Types.cargo_item {
29
29
  return UInt64.from(this.unitMass).multiplying(this.quantity)
30
30
  }
31
31
 
32
- get totalCost(): UInt64 {
33
- return this.unit_cost.multiplying(this.quantity)
34
- }
35
-
36
32
  get hasCargo(): boolean {
37
33
  return UInt32.from(this.quantity).gt(UInt32.from(0))
38
34
  }
@@ -20,10 +20,6 @@ export class InventoryAccessor {
20
20
  return this.items.reduce((sum, c) => sum.adding(c.totalMass), UInt64.from(0))
21
21
  }
22
22
 
23
- get totalValue(): UInt64 {
24
- return this.items.reduce((sum, c) => sum.adding(c.totalCost), UInt64.from(0))
25
- }
26
-
27
23
  forItem(goodId: UInt64Type): EntityInventory | undefined {
28
24
  return this.items.find((c) => c.item_id.equals(goodId))
29
25
  }