@shipload/sdk 1.0.0-next.2 → 1.0.0-next.21

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 (85) hide show
  1. package/lib/shipload.d.ts +1731 -1044
  2. package/lib/shipload.js +6758 -4523
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +6649 -4479
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +833 -0
  7. package/lib/testing.js +3647 -0
  8. package/lib/testing.js.map +1 -0
  9. package/lib/testing.m.js +3641 -0
  10. package/lib/testing.m.js.map +1 -0
  11. package/package.json +15 -2
  12. package/src/capabilities/gathering.ts +17 -7
  13. package/src/capabilities/modules.ts +9 -0
  14. package/src/capabilities/storage.ts +1 -1
  15. package/src/contracts/platform.ts +211 -3
  16. package/src/contracts/server.ts +723 -438
  17. package/src/data/capabilities.ts +9 -329
  18. package/src/data/capability-formulas.ts +76 -0
  19. package/src/data/catalog.ts +0 -5
  20. package/src/data/colors.ts +14 -28
  21. package/src/data/entities.json +46 -10
  22. package/src/data/item-ids.ts +17 -13
  23. package/src/data/items.json +308 -37
  24. package/src/data/kind-registry.json +85 -0
  25. package/src/data/kind-registry.ts +150 -0
  26. package/src/data/metadata.ts +99 -24
  27. package/src/data/recipes-runtime.ts +3 -23
  28. package/src/data/recipes.json +265 -96
  29. package/src/derivation/build-methods.ts +45 -0
  30. package/src/derivation/capabilities.ts +414 -0
  31. package/src/derivation/capability-mappings.ts +117 -0
  32. package/src/derivation/crafting.ts +23 -24
  33. package/src/derivation/index.ts +8 -2
  34. package/src/derivation/reserve-regen.ts +34 -0
  35. package/src/derivation/resources.ts +125 -38
  36. package/src/derivation/stats.ts +1 -2
  37. package/src/derivation/stratum.ts +15 -19
  38. package/src/derivation/tiers.ts +28 -7
  39. package/src/entities/entity.ts +98 -0
  40. package/src/entities/gamestate.ts +3 -28
  41. package/src/entities/makers.ts +75 -129
  42. package/src/entities/slot-multiplier.ts +37 -0
  43. package/src/errors.ts +10 -15
  44. package/src/format.ts +26 -4
  45. package/src/index-module.ts +151 -40
  46. package/src/managers/actions.ts +184 -82
  47. package/src/managers/base.ts +2 -2
  48. package/src/managers/construction-types.ts +68 -0
  49. package/src/managers/construction.ts +292 -0
  50. package/src/managers/context.ts +9 -0
  51. package/src/managers/entities.ts +18 -66
  52. package/src/managers/epochs.ts +40 -0
  53. package/src/managers/index.ts +16 -1
  54. package/src/managers/locations.ts +2 -20
  55. package/src/managers/nft.ts +28 -0
  56. package/src/managers/plot.ts +123 -0
  57. package/src/nft/atomicassets.ts +231 -0
  58. package/src/nft/atomicdata.ts +130 -0
  59. package/src/nft/buildImmutableData.ts +319 -0
  60. package/src/nft/description.ts +45 -13
  61. package/src/nft/index.ts +3 -0
  62. package/src/resolution/describe-module.ts +5 -8
  63. package/src/resolution/display-name.ts +38 -10
  64. package/src/resolution/resolve-item.ts +20 -12
  65. package/src/scheduling/accessor.ts +4 -0
  66. package/src/scheduling/projection.ts +79 -27
  67. package/src/scheduling/schedule.ts +15 -1
  68. package/src/scheduling/task-cargo.ts +46 -0
  69. package/src/shipload.ts +5 -0
  70. package/src/subscriptions/manager.ts +40 -6
  71. package/src/subscriptions/mappers.ts +3 -8
  72. package/src/subscriptions/types.ts +3 -2
  73. package/src/testing/catalog-hash.ts +19 -0
  74. package/src/testing/index.ts +2 -0
  75. package/src/testing/projection-parity.ts +143 -0
  76. package/src/travel/travel.ts +61 -2
  77. package/src/types/index.ts +0 -1
  78. package/src/types.ts +17 -12
  79. package/src/utils/cargo.ts +27 -0
  80. package/src/utils/system.ts +25 -24
  81. package/src/entities/container.ts +0 -108
  82. package/src/entities/ship-deploy.ts +0 -258
  83. package/src/entities/ship.ts +0 -204
  84. package/src/entities/warehouse.ts +0 -119
  85. package/src/types/entity-traits.ts +0 -69
package/src/types.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import {
2
2
  type Int64Type,
3
- Name,
4
3
  type UInt16,
5
4
  type UInt16Type,
6
5
  type UInt32,
@@ -12,7 +11,7 @@ import {ServerContract} from './contracts'
12
11
  export const PRECISION = 10000
13
12
  export const CRAFT_ENERGY_DIVISOR = 150000
14
13
 
15
- export const WAREHOUSE_Z = 500
14
+ export const PLANETARY_STRUCTURE_Z = 0
16
15
 
17
16
  export const CONTAINER_Z = 300
18
17
 
@@ -23,6 +22,8 @@ export const MAX_ORBITAL_ALTITUDE = 3000
23
22
 
24
23
  export const BASE_ORBITAL_MASS = 100000
25
24
 
25
+ export const MIN_TRANSFER_DISTANCE = 100
26
+
26
27
  export interface ShipLike {
27
28
  coordinates: ServerContract.Types.coordinates
28
29
  hullmass?: UInt32
@@ -49,8 +50,11 @@ export enum TaskType {
49
50
  WARP = 6,
50
51
  CRAFT = 7,
51
52
  DEPLOY = 8,
52
- WRAP = 9,
53
53
  UNWRAP = 10,
54
+ UNDEPLOY = 11,
55
+ DEMOLISH = 13,
56
+ CLAIMPLOT = 14,
57
+ BUILDPLOT = 15,
54
58
  }
55
59
 
56
60
  export enum LocationType {
@@ -58,6 +62,7 @@ export enum LocationType {
58
62
  PLANET = 1,
59
63
  ASTEROID = 2,
60
64
  NEBULA = 3,
65
+ ICE_FIELD = 4,
61
66
  }
62
67
 
63
68
  export enum TaskCancelable {
@@ -66,14 +71,6 @@ export enum TaskCancelable {
66
71
  ALWAYS = 2,
67
72
  }
68
73
 
69
- export const EntityType = {
70
- SHIP: Name.from('ship'),
71
- WAREHOUSE: Name.from('warehouse'),
72
- CONTAINER: Name.from('container'),
73
- } as const
74
-
75
- export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
76
-
77
74
  export type CoordinatesType =
78
75
  | Coordinates
79
76
  | ServerContract.Types.coordinates
@@ -122,8 +119,9 @@ export type ModuleType =
122
119
  | 'launcher'
123
120
  | 'storage'
124
121
  | 'hauler'
122
+ | 'battery'
125
123
 
126
- export const TIER_ADJECTIVES: Record<number, string> = {
124
+ export const RESOURCE_TIER_ADJECTIVES: Record<number, string> = {
127
125
  1: 'Crude',
128
126
  2: 'Dense',
129
127
  3: 'Pure',
@@ -136,6 +134,9 @@ export const TIER_ADJECTIVES: Record<number, string> = {
136
134
  10: 'Ascendant',
137
135
  }
138
136
 
137
+ export const COMPONENT_TIER_PREFIXES: Record<number, string> = {}
138
+ export const MODULE_TIER_PREFIXES: Record<number, string> = {}
139
+
139
140
  export const CATEGORY_LABELS: Record<ResourceCategory, string> = {
140
141
  ore: 'Ore',
141
142
  crystal: 'Crystal',
@@ -159,3 +160,7 @@ export interface Item {
159
160
  export function formatTier(tier: number): string {
160
161
  return 'T' + tier
161
162
  }
163
+
164
+ export function tierAdjective(tier: number): string {
165
+ return RESOURCE_TIER_ADJECTIVES[tier] ?? `T${tier}`
166
+ }
@@ -0,0 +1,27 @@
1
+ import type {ServerContract} from '../contracts'
2
+
3
+ export function cargoRef(src: {
4
+ item_id: number
5
+ stats: bigint | number
6
+ modules?: ServerContract.Types.module_entry[]
7
+ }): ServerContract.ActionParams.Type.cargo_ref {
8
+ return {
9
+ item_id: src.item_id,
10
+ stats: src.stats,
11
+ modules: src.modules ?? [],
12
+ }
13
+ }
14
+
15
+ export function cargoItem(
16
+ src: {
17
+ item_id: number
18
+ stats: bigint | number
19
+ modules?: ServerContract.Types.module_entry[]
20
+ },
21
+ quantity: bigint | number
22
+ ): ServerContract.ActionParams.Type.cargo_item {
23
+ return {
24
+ ...cargoRef(src),
25
+ quantity,
26
+ }
27
+ }
@@ -8,7 +8,6 @@ import nebulaAdjectives from '../data/nebula-adjectives.json'
8
8
  import nebulaNouns from '../data/nebula-nouns.json'
9
9
 
10
10
  const LOCATION_EXISTS_THRESHOLD = 0x10
11
- const LOCATION_ACTIVE_THRESHOLD = 0x80
12
11
 
13
12
  export function getLocationType(
14
13
  gameSeed: Checksum256Type,
@@ -22,12 +21,10 @@ export function getLocationType(
22
21
  return LocationType.EMPTY
23
22
  }
24
23
 
25
- if (hashResult.array[1] < 96) {
26
- return LocationType.PLANET
27
- } else if (hashResult.array[1] < 176) {
28
- return LocationType.ASTEROID
29
- }
30
- return LocationType.NEBULA
24
+ if (hashResult.array[1] < 96) return LocationType.PLANET
25
+ if (hashResult.array[1] < 149) return LocationType.ASTEROID
26
+ if (hashResult.array[1] < 202) return LocationType.NEBULA
27
+ return LocationType.ICE_FIELD
31
28
  }
32
29
 
33
30
  export function isGatherableLocation(locationType: LocationType): boolean {
@@ -44,6 +41,8 @@ export function getLocationTypeName(type: LocationType): string {
44
41
  return 'Asteroid'
45
42
  case LocationType.NEBULA:
46
43
  return 'Nebula'
44
+ case LocationType.ICE_FIELD:
45
+ return 'Ice Field'
47
46
  }
48
47
  }
49
48
 
@@ -76,6 +75,15 @@ function generateNebulaName(hashResult: Checksum512): string {
76
75
  return `${nebulaAdjectives[adjIdx]} ${nebulaNouns[nounIdx]}`
77
76
  }
78
77
 
78
+ function generateIceFieldName(hashResult: Checksum512): string {
79
+ const A = 65
80
+ const letter1 = String.fromCharCode(A + (hashResult.array[0] % 26))
81
+ const letter2 = String.fromCharCode(A + (hashResult.array[1] % 26))
82
+ const subId = (hashResult.array[2] % 9) + 1
83
+ const num = (uint16(hashResult, 3) % 9000) + 1000
84
+ return `${letter1}${letter2}-${subId}/${num}`
85
+ }
86
+
79
87
  export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
80
88
  const seed = Checksum256.from(gameSeed)
81
89
  const locationType = getLocationType(seed, location)
@@ -91,6 +99,8 @@ export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesTy
91
99
  return generateAsteroidName(hashResult)
92
100
  case LocationType.NEBULA:
93
101
  return generateNebulaName(hashResult)
102
+ case LocationType.ICE_FIELD:
103
+ return generateIceFieldName(hashResult)
94
104
  default:
95
105
  return generatePlanetName(hashResult)
96
106
  }
@@ -123,10 +133,12 @@ export function deriveLocationStatic(
123
133
 
124
134
  if (hashResult.array[1] < 96) {
125
135
  loc.type = UInt8.from(LocationType.PLANET)
126
- } else if (hashResult.array[1] < 176) {
136
+ } else if (hashResult.array[1] < 149) {
127
137
  loc.type = UInt8.from(LocationType.ASTEROID)
128
- } else {
138
+ } else if (hashResult.array[1] < 202) {
129
139
  loc.type = UInt8.from(LocationType.NEBULA)
140
+ } else {
141
+ loc.type = UInt8.from(LocationType.ICE_FIELD)
130
142
  }
131
143
 
132
144
  loc.subtype = UInt8.from(
@@ -138,31 +150,20 @@ export function deriveLocationStatic(
138
150
  return loc
139
151
  }
140
152
 
141
- export function deriveLocationEpoch(
142
- epochSeed: Checksum256Type,
153
+ export function isLocationBuildable(
154
+ gameSeed: Checksum256Type,
143
155
  coordinates: CoordinatesType
144
- ): ServerContract.Types.location_epoch {
145
- const seed = Checksum256.from(epochSeed)
146
- const coords = Coordinates.from(coordinates)
147
- const str = `system-epoch-${coords.x}-${coords.y}`
148
- const hashResult = hash512(seed, str)
149
-
150
- return ServerContract.Types.location_epoch.from({
151
- active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
152
- seed0: hashResult.array[1],
153
- seed1: hashResult.array[2],
154
- })
156
+ ): boolean {
157
+ return getLocationType(gameSeed, coordinates) === LocationType.PLANET
155
158
  }
156
159
 
157
160
  export function deriveLocation(
158
161
  gameSeed: Checksum256Type,
159
- epochSeed: Checksum256Type,
160
162
  coordinates: CoordinatesType
161
163
  ): ServerContract.Types.location_derived {
162
164
  const staticProps = deriveLocationStatic(gameSeed, coordinates)
163
165
  return ServerContract.Types.location_derived.from({
164
166
  static_props: staticProps,
165
- epoch_props: deriveLocationEpoch(epochSeed, coordinates),
166
167
  size: deriveLocationSize(staticProps),
167
168
  })
168
169
  }
@@ -1,108 +0,0 @@
1
- import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
- import {ServerContract} from '../contracts'
3
- import type {CoordinatesType} from '../types'
4
- import {Location} from './location'
5
- import {ScheduleAccessor} from '../scheduling/accessor'
6
- import * as schedule from '../scheduling/schedule'
7
-
8
- export interface ContainerStateInput {
9
- id: UInt64Type
10
- owner: string
11
- name: string
12
- coordinates: CoordinatesType | {x: number; y: number; z?: number}
13
- hullmass: number
14
- capacity: number
15
- cargomass?: number
16
- cargo?: ServerContract.Types.cargo_item[]
17
- schedule?: ServerContract.Types.schedule
18
- }
19
-
20
- export class Container extends ServerContract.Types.entity_info {
21
- private _sched?: ScheduleAccessor
22
-
23
- get name(): string {
24
- return this.entity_name
25
- }
26
-
27
- get sched(): ScheduleAccessor {
28
- this._sched ??= new ScheduleAccessor(this)
29
- return this._sched
30
- }
31
-
32
- get isIdle(): boolean {
33
- return this.is_idle
34
- }
35
-
36
- isLoading(now: Date): boolean {
37
- return schedule.isLoading(this, now)
38
- }
39
-
40
- isUnloading(now: Date): boolean {
41
- return schedule.isUnloading(this, now)
42
- }
43
-
44
- get location(): Location {
45
- return Location.from(this.coordinates)
46
- }
47
-
48
- get totalMass(): UInt64 {
49
- return UInt64.from(this.hullmass ?? 0).adding(this.cargomass)
50
- }
51
-
52
- get maxCapacity(): UInt64 {
53
- return UInt64.from(this.capacity)
54
- }
55
-
56
- get availableCapacity(): UInt64 {
57
- const cargo = UInt64.from(this.cargomass)
58
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
59
- }
60
-
61
- hasSpace(additionalMass: UInt64): boolean {
62
- return UInt64.from(this.cargomass).adding(additionalMass).lte(this.maxCapacity)
63
- }
64
-
65
- get isFull(): boolean {
66
- return UInt64.from(this.cargomass).gte(this.maxCapacity)
67
- }
68
-
69
- get orbitalAltitude(): number {
70
- return this.coordinates.z?.toNumber() || 0
71
- }
72
- }
73
-
74
- export function computeContainerCapabilities(stats: Record<string, number>): {
75
- hullmass: number
76
- capacity: number
77
- } {
78
- const density = stats['density'] ?? 500
79
- const strength = stats['strength'] ?? 500
80
- const hardness = stats['hardness'] ?? 500
81
- const saturation = stats['saturation'] ?? 500
82
-
83
- const hullmass = 25000 + 75 * density
84
-
85
- const statSum = strength + hardness + saturation
86
- const exponent = statSum / 2997
87
- const capacity = Math.floor(1000000 * 10 ** exponent)
88
-
89
- return {hullmass, capacity}
90
- }
91
-
92
- export function computeContainerT2Capabilities(stats: Record<string, number>): {
93
- hullmass: number
94
- capacity: number
95
- } {
96
- const strength = stats['strength'] ?? 0
97
- const density = stats['density'] ?? 0
98
- const hardness = stats['hardness'] ?? 0
99
- const saturation = stats['saturation'] ?? 0
100
-
101
- const hullmass = 20000 + 50 * density
102
-
103
- const statSum = strength + hardness + saturation
104
- const exponent = statSum / 2500
105
- const capacity = Math.floor(1500000 * 10 ** exponent)
106
-
107
- return {hullmass, capacity}
108
- }
@@ -1,258 +0,0 @@
1
- import {decodeCraftedItemStats} from '../derivation/crafting'
2
- import {
3
- getModuleCapabilityType,
4
- MODULE_CRAFTER,
5
- MODULE_ENGINE,
6
- MODULE_GATHERER,
7
- MODULE_GENERATOR,
8
- MODULE_HAULER,
9
- MODULE_LOADER,
10
- } from '../capabilities/modules'
11
-
12
- export function computeShipHullCapabilities(stats: Record<string, number>): {
13
- hullmass: number
14
- capacity: number
15
- } {
16
- const density = stats.density ?? 500
17
- const strength = stats.strength ?? 500
18
- const hardness = stats.hardness ?? 500
19
- const saturation = stats.saturation ?? 500
20
-
21
- const hullmass = 25000 + 75 * density
22
- const statSum = strength + hardness + saturation
23
- const exponent = statSum / 2997.0
24
- const capacity = Math.floor(1000000 * 10 ** exponent)
25
-
26
- return {hullmass, capacity}
27
- }
28
-
29
- export function computeEngineCapabilities(stats: Record<string, number>): {
30
- thrust: number
31
- drain: number
32
- } {
33
- const vol = stats.volatility ?? 500
34
- const thm = stats.thermal ?? 500
35
-
36
- return {
37
- thrust: 400 + Math.floor((vol * 3) / 4),
38
- drain: Math.max(30, 50 - Math.floor(thm / 70)),
39
- }
40
- }
41
-
42
- export function computeGeneratorCapabilities(stats: Record<string, number>): {
43
- capacity: number
44
- recharge: number
45
- } {
46
- const res = stats.resonance ?? 500
47
- const ref = stats.reflectivity ?? 500
48
-
49
- return {
50
- capacity: 300 + Math.floor(res / 6),
51
- recharge: 1 + Math.floor((ref * 3) / 1000),
52
- }
53
- }
54
-
55
- export function computeGathererCapabilities(stats: Record<string, number>): {
56
- yield: number
57
- drain: number
58
- depth: number
59
- speed: number
60
- } {
61
- const str = stats.strength ?? 500
62
- const con = stats.conductivity ?? 500
63
- const ref = stats.reflectivity ?? 500
64
- const tol = stats.tolerance ?? 500
65
-
66
- return {
67
- yield: 200 + str,
68
- drain: Math.max(250, 1250 - Math.floor((con * 25) / 20)),
69
- depth: 200 + Math.floor((tol * 3) / 2),
70
- speed: 100 + Math.floor((ref * 4) / 5),
71
- }
72
- }
73
-
74
- export function computeLoaderCapabilities(stats: Record<string, number>): {
75
- mass: number
76
- thrust: number
77
- quantity: number
78
- } {
79
- const hrd = stats.hardness ?? 500
80
- const pla = stats.plasticity ?? 500
81
-
82
- return {
83
- mass: Math.max(200, 2000 - Math.floor(hrd * 2)),
84
- thrust: 1 + Math.floor(pla / 500),
85
- quantity: 1,
86
- }
87
- }
88
-
89
- export function computeCrafterCapabilities(stats: Record<string, number>): {
90
- speed: number
91
- drain: number
92
- } {
93
- const rea = stats.reactivity ?? 500
94
- const com = stats.composition ?? 500
95
-
96
- return {
97
- speed: 100 + Math.floor((rea * 4) / 5),
98
- drain: Math.max(5, 30 - Math.floor(com / 33)),
99
- }
100
- }
101
-
102
- export function computeHaulerCapabilities(stats: Record<string, number>): {
103
- capacity: number
104
- efficiency: number
105
- drain: number
106
- } {
107
- const res = stats.resonance ?? 500
108
- const con = stats.conductivity ?? 500
109
- const ref = stats.reflectivity ?? 500
110
-
111
- return {
112
- capacity: Math.max(1, 1 + Math.floor(res / 400)),
113
- efficiency: 2000 + con * 6,
114
- drain: Math.max(3, 15 - Math.floor(ref / 80)),
115
- }
116
- }
117
-
118
- export function computeStorageCapabilities(
119
- stats: Record<string, number>,
120
- baseCapacity: number
121
- ): {
122
- capacityBonus: number
123
- } {
124
- const strength = stats.strength ?? 500
125
- const hardness = stats.hardness ?? 500
126
- const saturation = stats.saturation ?? 500
127
-
128
- const statSum = strength + hardness + saturation
129
- const capacityBonus = Math.floor(
130
- (baseCapacity * (10 + Math.floor((statSum * 10) / 2997))) / 100
131
- )
132
-
133
- return {capacityBonus}
134
- }
135
-
136
- export function computeWarehouseHullCapabilities(stats: Record<string, number>): {
137
- hullmass: number
138
- capacity: number
139
- } {
140
- const density = stats.density ?? 500
141
- const strength = stats.strength ?? 500
142
- const hardness = stats.hardness ?? 500
143
- const saturation = stats.saturation ?? 500
144
-
145
- const hullmass = 25000 + 75 * density
146
- const statSum = strength + hardness + saturation
147
- const exponent = statSum / 2997.0
148
- const capacity = Math.floor(20000000 * 10 ** exponent)
149
-
150
- return {hullmass, capacity}
151
- }
152
-
153
- export interface ShipCapabilities {
154
- engines?: {thrust: number; drain: number}
155
- generator?: {capacity: number; recharge: number}
156
- gatherer?: {yield: number; drain: number; depth: number; speed: number}
157
- hauler?: {capacity: number; efficiency: number; drain: number}
158
- loaders?: {mass: number; thrust: number; quantity: number}
159
- crafter?: {speed: number; drain: number}
160
- }
161
-
162
- export function computeShipCapabilities(
163
- modules: {itemId: number; stats: bigint}[]
164
- ): ShipCapabilities {
165
- const ship: ShipCapabilities = {}
166
-
167
- const engineModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_ENGINE)
168
- if (engineModules.length > 0) {
169
- let totalThrust = 0
170
- let totalDrain = 0
171
- for (const m of engineModules) {
172
- const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
173
- totalThrust += caps.thrust
174
- totalDrain += caps.drain
175
- }
176
- ship.engines = {thrust: totalThrust, drain: totalDrain}
177
- }
178
-
179
- const generatorModules = modules.filter(
180
- (m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR
181
- )
182
- if (generatorModules.length > 0) {
183
- let totalCapacity = 0
184
- let totalRecharge = 0
185
- for (const m of generatorModules) {
186
- const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
187
- totalCapacity += caps.capacity
188
- totalRecharge += caps.recharge
189
- }
190
- ship.generator = {capacity: totalCapacity, recharge: totalRecharge}
191
- }
192
-
193
- const gathererModules = modules.filter(
194
- (m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER
195
- )
196
- if (gathererModules.length > 0) {
197
- let totalYield = 0
198
- let totalDrain = 0
199
- let totalDepth = 0
200
- let totalSpeed = 0
201
- for (const m of gathererModules) {
202
- const caps = computeGathererCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
203
- totalYield += caps.yield
204
- totalDrain += caps.drain
205
- totalDepth += caps.depth
206
- totalSpeed += caps.speed
207
- }
208
- ship.gatherer = {yield: totalYield, drain: totalDrain, depth: totalDepth, speed: totalSpeed}
209
- }
210
-
211
- const haulerModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_HAULER)
212
- if (haulerModules.length > 0) {
213
- let totalCapacity = 0
214
- let weightedEffNum = 0
215
- let totalDrain = 0
216
- for (const m of haulerModules) {
217
- const caps = computeHaulerCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
218
- totalCapacity += caps.capacity
219
- weightedEffNum += caps.efficiency * caps.capacity
220
- totalDrain += caps.drain
221
- }
222
- ship.hauler = {
223
- capacity: totalCapacity,
224
- efficiency: totalCapacity > 0 ? Math.floor(weightedEffNum / totalCapacity) : 0,
225
- drain: totalDrain,
226
- }
227
- }
228
-
229
- const loaderModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_LOADER)
230
- if (loaderModules.length > 0) {
231
- let totalMass = 0
232
- let totalThrust = 0
233
- let totalQuantity = 0
234
- for (const m of loaderModules) {
235
- const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
236
- totalMass += caps.mass
237
- totalThrust += caps.thrust
238
- totalQuantity += caps.quantity
239
- }
240
- ship.loaders = {mass: totalMass, thrust: totalThrust, quantity: totalQuantity}
241
- }
242
-
243
- const crafterModules = modules.filter(
244
- (m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
245
- )
246
- if (crafterModules.length > 0) {
247
- let totalSpeed = 0
248
- let totalDrain = 0
249
- for (const m of crafterModules) {
250
- const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
251
- totalSpeed += caps.speed
252
- totalDrain += caps.drain
253
- }
254
- ship.crafter = {speed: totalSpeed, drain: totalDrain}
255
- }
256
-
257
- return ship
258
- }