@shipload/sdk 2.0.0-rc13 → 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.
- package/lib/shipload.d.ts +148 -60
- package/lib/shipload.js +970 -606
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +956 -605
- package/lib/shipload.m.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/modules.ts +3 -3
- package/src/capabilities/storage.ts +6 -9
- package/src/contracts/server.ts +37 -34
- package/src/data/categories.ts +22 -25
- package/src/data/colors.ts +28 -10
- package/src/data/items.json +15 -15
- package/src/data/recipes.ts +93 -87
- package/src/derivation/crafting.ts +50 -36
- package/src/derivation/resources.ts +23 -23
- package/src/derivation/stats.ts +29 -29
- package/src/derivation/stratum.ts +12 -0
- package/src/entities/container.ts +7 -6
- package/src/entities/makers.ts +126 -11
- package/src/entities/ship-deploy.ts +25 -30
- package/src/entities/ship.ts +16 -4
- package/src/entities/warehouse.ts +36 -1
- package/src/format.ts +12 -0
- package/src/index-module.ts +26 -4
- package/src/managers/actions.ts +48 -8
- package/src/market/items.ts +1 -1
- package/src/nft/description.ts +47 -46
- package/src/nft/deserializers.ts +8 -8
- package/src/resolution/describe-module.ts +165 -0
- package/src/resolution/display-name.ts +57 -0
- package/src/resolution/resolve-item.ts +68 -45
- package/src/scheduling/projection.ts +3 -1
- package/src/types/capabilities.ts +5 -0
- package/src/types.ts +1 -1
package/src/derivation/stats.ts
CHANGED
|
@@ -8,7 +8,7 @@ export interface StatDefinition {
|
|
|
8
8
|
inverted?: boolean
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
const
|
|
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
|
|
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: '
|
|
42
|
-
label: '
|
|
43
|
-
abbreviation: '
|
|
44
|
-
purpose: '
|
|
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: '
|
|
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
|
|
75
|
+
const REGOLITH_STATS: StatDefinition[] = [
|
|
76
76
|
{
|
|
77
|
-
key: '
|
|
78
|
-
label: '
|
|
79
|
-
abbreviation: '
|
|
80
|
-
purpose: '
|
|
77
|
+
key: 'composition',
|
|
78
|
+
label: 'Composition',
|
|
79
|
+
abbreviation: 'COM',
|
|
80
|
+
purpose: 'Mineral/metal mix — drives sensor, chip, and optic crafting quality',
|
|
81
81
|
},
|
|
82
82
|
{
|
|
83
83
|
key: 'hardness',
|
|
84
84
|
label: 'Hardness',
|
|
85
85
|
abbreviation: 'HRD',
|
|
86
|
-
purpose: '
|
|
86
|
+
purpose: 'Particle hardness — cutting surfaces, abrasives, wear resistance',
|
|
87
87
|
},
|
|
88
88
|
{
|
|
89
|
-
key: '
|
|
90
|
-
label: '
|
|
91
|
-
abbreviation: '
|
|
92
|
-
purpose: '
|
|
89
|
+
key: 'fineness',
|
|
90
|
+
label: 'Fineness',
|
|
91
|
+
abbreviation: 'FIN',
|
|
92
|
+
purpose: 'Grain size — fine powder for smooth composites and sintering',
|
|
93
93
|
},
|
|
94
94
|
]
|
|
95
95
|
|
|
96
|
-
const
|
|
96
|
+
const BIOMASS_STATS: StatDefinition[] = [
|
|
97
97
|
{
|
|
98
98
|
key: 'plasticity',
|
|
99
99
|
label: 'Plasticity',
|
|
100
100
|
abbreviation: 'PLA',
|
|
101
|
-
purpose: '
|
|
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: '
|
|
107
|
+
purpose: 'Thermal and electrical blocking capacity',
|
|
108
108
|
},
|
|
109
109
|
{
|
|
110
|
-
key: '
|
|
111
|
-
label: '
|
|
112
|
-
abbreviation: '
|
|
113
|
-
purpose: '
|
|
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
|
-
|
|
119
|
-
|
|
118
|
+
ore: ORE_STATS,
|
|
119
|
+
crystal: CRYSTAL_STATS,
|
|
120
120
|
gas: GAS_STATS,
|
|
121
|
-
|
|
122
|
-
|
|
121
|
+
regolith: REGOLITH_STATS,
|
|
122
|
+
biomass: BIOMASS_STATS,
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
export function getStatDefinitions(category: ResourceCategory): StatDefinition[] {
|
|
@@ -89,6 +89,18 @@ export function deriveStratum(
|
|
|
89
89
|
return {itemId: selectedItemId, seed: seedBigInt, richness, reserve}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/**
|
|
93
|
+
* Derives the three stat values for a raw resource from a deposit's
|
|
94
|
+
* entropy seed (hash-based, weibull-transformed).
|
|
95
|
+
*
|
|
96
|
+
* **Use only on deposit seeds** — the bigint returned by `deriveStratum`
|
|
97
|
+
* or carried on a `MassDeposit`. Do NOT call this on a cargo item's
|
|
98
|
+
* `stats` field; cargo stats are bit-packed and must be read via
|
|
99
|
+
* `decodeStat` (or `decodeStackStats` for category-mapped output).
|
|
100
|
+
*
|
|
101
|
+
* Passing a cargo `stats` value here produces meaningless output
|
|
102
|
+
* (hash of the packed bits, unrelated to the actual stats).
|
|
103
|
+
*/
|
|
92
104
|
export function deriveResourceStats(seed: bigint): ResourceStats {
|
|
93
105
|
const seedBytes = new Uint8Array(8)
|
|
94
106
|
for (let i = 0; i < 8; i++) {
|
|
@@ -13,6 +13,7 @@ export interface ContainerStateInput {
|
|
|
13
13
|
hullmass: number
|
|
14
14
|
capacity: number
|
|
15
15
|
cargomass?: number
|
|
16
|
+
cargo?: ServerContract.Types.cargo_item[]
|
|
16
17
|
schedule?: ServerContract.Types.schedule
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -75,12 +76,12 @@ export function computeContainerCapabilities(stats: Record<string, number>): {
|
|
|
75
76
|
} {
|
|
76
77
|
const density = stats['density'] ?? 500
|
|
77
78
|
const strength = stats['strength'] ?? 500
|
|
78
|
-
const
|
|
79
|
-
const
|
|
79
|
+
const fineness = stats['fineness'] ?? 500
|
|
80
|
+
const saturation = stats['saturation'] ?? 500
|
|
80
81
|
|
|
81
82
|
const hullmass = 25000 + 75 * density
|
|
82
83
|
|
|
83
|
-
const statSum = strength +
|
|
84
|
+
const statSum = strength + fineness + saturation
|
|
84
85
|
const exponent = statSum / 2997
|
|
85
86
|
const capacity = Math.floor(1000000 * Math.pow(10, exponent))
|
|
86
87
|
|
|
@@ -93,12 +94,12 @@ export function computeContainerT2Capabilities(stats: Record<string, number>): {
|
|
|
93
94
|
} {
|
|
94
95
|
const strength = stats['strength'] ?? 0
|
|
95
96
|
const density = stats['density'] ?? 0
|
|
96
|
-
const
|
|
97
|
-
const
|
|
97
|
+
const fineness = stats['fineness'] ?? 0
|
|
98
|
+
const saturation = stats['saturation'] ?? 0
|
|
98
99
|
|
|
99
100
|
const hullmass = 20000 + 50 * density
|
|
100
101
|
|
|
101
|
-
const statSum = strength +
|
|
102
|
+
const statSum = strength + fineness + saturation
|
|
102
103
|
const exponent = statSum / 2500
|
|
103
104
|
const capacity = Math.floor(1500000 * Math.pow(10, exponent))
|
|
104
105
|
|
package/src/entities/makers.ts
CHANGED
|
@@ -1,8 +1,86 @@
|
|
|
1
|
-
import {Name, UInt16, UInt32, UInt64} from '@wharfkit/antelope'
|
|
1
|
+
import {Name, UInt16, UInt32, UInt64, UInt8} from '@wharfkit/antelope'
|
|
2
2
|
import {ServerContract} from '../contracts'
|
|
3
|
-
import {Ship, ShipStateInput} from './ship'
|
|
4
|
-
import {Warehouse, WarehouseStateInput} from './warehouse'
|
|
3
|
+
import {PackedModuleInput, Ship, ShipStateInput} from './ship'
|
|
4
|
+
import {computeWarehouseCapabilities, Warehouse, WarehouseStateInput} from './warehouse'
|
|
5
5
|
import {Container, ContainerStateInput} from './container'
|
|
6
|
+
import {
|
|
7
|
+
getEntitySlotLayout,
|
|
8
|
+
getModuleRecipeByItemId,
|
|
9
|
+
ITEM_SHIP_T1_PACKED,
|
|
10
|
+
ITEM_WAREHOUSE_T1_PACKED,
|
|
11
|
+
} from '../data/recipes'
|
|
12
|
+
import {getModuleCapabilityType, MODULE_STORAGE, moduleAccepts} from '../capabilities/modules'
|
|
13
|
+
import {computeShipCapabilities, computeStorageCapabilities} from './ship-deploy'
|
|
14
|
+
import {decodeCraftedItemStats} from '../derivation/crafting'
|
|
15
|
+
|
|
16
|
+
function assignModulesToSlots(
|
|
17
|
+
packedEntityItemId: number,
|
|
18
|
+
modules: PackedModuleInput[],
|
|
19
|
+
entityLabel: string
|
|
20
|
+
): ServerContract.Types.module_entry[] {
|
|
21
|
+
const slots = getEntitySlotLayout(packedEntityItemId)
|
|
22
|
+
const result: Array<{type: number; installed?: ServerContract.Types.packed_module}> = slots.map(
|
|
23
|
+
(s) => ({type: s.type, installed: undefined})
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
for (const mod of modules) {
|
|
27
|
+
const itemId = Number(UInt16.from(mod.itemId).value.toString())
|
|
28
|
+
const modType = getModuleCapabilityType(itemId)
|
|
29
|
+
const slotIdx = result.findIndex((r) => !r.installed && moduleAccepts(r.type, modType))
|
|
30
|
+
if (slotIdx === -1) {
|
|
31
|
+
const recipe = getModuleRecipeByItemId(itemId)
|
|
32
|
+
const modName = recipe?.name ?? `item ${itemId}`
|
|
33
|
+
throw new Error(
|
|
34
|
+
`No compatible slot for module ${modName} (type ${modType}) on ${entityLabel}`
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
result[slotIdx].installed = ServerContract.Types.packed_module.from({
|
|
38
|
+
item_id: UInt16.from(mod.itemId),
|
|
39
|
+
stats: UInt64.from(mod.stats),
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return result.map((r) =>
|
|
44
|
+
ServerContract.Types.module_entry.from({
|
|
45
|
+
type: UInt8.from(r.type),
|
|
46
|
+
installed: r.installed,
|
|
47
|
+
})
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function decodePackedInput(m: PackedModuleInput): {itemId: number; stats: bigint} {
|
|
52
|
+
return {
|
|
53
|
+
itemId: Number(UInt16.from(m.itemId).value.toString()),
|
|
54
|
+
stats: BigInt(UInt64.from(m.stats).toString()),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function computeStorageBonus(
|
|
59
|
+
decoded: {itemId: number; stats: bigint}[],
|
|
60
|
+
baseCapacity: number
|
|
61
|
+
): number {
|
|
62
|
+
let totalBonus = 0
|
|
63
|
+
for (const m of decoded) {
|
|
64
|
+
if (getModuleCapabilityType(m.itemId) !== MODULE_STORAGE) continue
|
|
65
|
+
const stats = decodeCraftedItemStats(m.itemId, m.stats)
|
|
66
|
+
const {capacityBonus} = computeStorageCapabilities(stats, baseCapacity)
|
|
67
|
+
totalBonus += capacityBonus
|
|
68
|
+
}
|
|
69
|
+
return totalBonus
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function deriveShipFromModules(
|
|
73
|
+
modules: PackedModuleInput[],
|
|
74
|
+
baseCapacity: number
|
|
75
|
+
): {
|
|
76
|
+
capabilities: ReturnType<typeof computeShipCapabilities>
|
|
77
|
+
finalCapacity: number
|
|
78
|
+
} {
|
|
79
|
+
const decoded = modules.map(decodePackedInput)
|
|
80
|
+
const capabilities = computeShipCapabilities(decoded)
|
|
81
|
+
const totalBonus = computeStorageBonus(decoded, baseCapacity)
|
|
82
|
+
return {capabilities, finalCapacity: baseCapacity + totalBonus}
|
|
83
|
+
}
|
|
6
84
|
|
|
7
85
|
export function makeShip(state: ShipStateInput): Ship {
|
|
8
86
|
const info: Record<string, unknown> = {
|
|
@@ -19,14 +97,32 @@ export function makeShip(state: ShipStateInput): Ship {
|
|
|
19
97
|
pending_tasks: [],
|
|
20
98
|
}
|
|
21
99
|
if (state.hullmass !== undefined) info.hullmass = UInt32.from(state.hullmass)
|
|
22
|
-
if (state.capacity !== undefined) info.capacity = UInt32.from(state.capacity)
|
|
23
100
|
if (state.energy !== undefined) info.energy = UInt16.from(state.energy)
|
|
24
|
-
if (state.engines) info.engines = state.engines
|
|
25
|
-
if (state.generator) info.generator = state.generator
|
|
26
|
-
if (state.loaders) info.loaders = state.loaders
|
|
27
101
|
if (state.schedule) info.schedule = state.schedule
|
|
102
|
+
|
|
103
|
+
let moduleEntries: ServerContract.Types.module_entry[] = []
|
|
104
|
+
if (state.modules && state.modules.length > 0) {
|
|
105
|
+
moduleEntries = assignModulesToSlots(ITEM_SHIP_T1_PACKED, state.modules, 'Ship T1')
|
|
106
|
+
const {capabilities, finalCapacity} = deriveShipFromModules(
|
|
107
|
+
state.modules,
|
|
108
|
+
state.capacity ?? 0
|
|
109
|
+
)
|
|
110
|
+
if (capabilities.engines) info.engines = capabilities.engines
|
|
111
|
+
if (capabilities.generator) info.generator = capabilities.generator
|
|
112
|
+
if (capabilities.gatherer) info.gatherer = capabilities.gatherer
|
|
113
|
+
if (capabilities.hauler) info.hauler = capabilities.hauler
|
|
114
|
+
if (capabilities.loaders) info.loaders = capabilities.loaders
|
|
115
|
+
if (capabilities.crafter) info.crafter = capabilities.crafter
|
|
116
|
+
if (state.capacity !== undefined) info.capacity = UInt32.from(finalCapacity)
|
|
117
|
+
} else {
|
|
118
|
+
moduleEntries = assignModulesToSlots(ITEM_SHIP_T1_PACKED, [], 'Ship T1')
|
|
119
|
+
if (state.capacity !== undefined) info.capacity = UInt32.from(state.capacity)
|
|
120
|
+
}
|
|
121
|
+
|
|
28
122
|
const entityInfo = ServerContract.Types.entity_info.from(info)
|
|
29
|
-
|
|
123
|
+
const ship = new Ship(entityInfo)
|
|
124
|
+
ship.setModules(moduleEntries)
|
|
125
|
+
return ship
|
|
30
126
|
}
|
|
31
127
|
|
|
32
128
|
export function makeWarehouse(state: WarehouseStateInput): Warehouse {
|
|
@@ -45,10 +141,29 @@ export function makeWarehouse(state: WarehouseStateInput): Warehouse {
|
|
|
45
141
|
pending_tasks: [],
|
|
46
142
|
}
|
|
47
143
|
if (state.hullmass !== undefined) info.hullmass = UInt32.from(state.hullmass)
|
|
48
|
-
if (state.loaders) info.loaders = state.loaders
|
|
49
144
|
if (state.schedule) info.schedule = state.schedule
|
|
145
|
+
|
|
146
|
+
let moduleEntries: ServerContract.Types.module_entry[] = []
|
|
147
|
+
if (state.modules && state.modules.length > 0) {
|
|
148
|
+
moduleEntries = assignModulesToSlots(
|
|
149
|
+
ITEM_WAREHOUSE_T1_PACKED,
|
|
150
|
+
state.modules,
|
|
151
|
+
'Warehouse T1'
|
|
152
|
+
)
|
|
153
|
+
const decoded = state.modules.map(decodePackedInput)
|
|
154
|
+
const capabilities = computeWarehouseCapabilities(decoded)
|
|
155
|
+
if (capabilities.loaders) info.loaders = capabilities.loaders
|
|
156
|
+
|
|
157
|
+
const totalBonus = computeStorageBonus(decoded, state.capacity)
|
|
158
|
+
info.capacity = UInt32.from(state.capacity + totalBonus)
|
|
159
|
+
} else {
|
|
160
|
+
moduleEntries = assignModulesToSlots(ITEM_WAREHOUSE_T1_PACKED, [], 'Warehouse T1')
|
|
161
|
+
}
|
|
162
|
+
|
|
50
163
|
const entityInfo = ServerContract.Types.entity_info.from(info)
|
|
51
|
-
|
|
164
|
+
const warehouse = new Warehouse(entityInfo)
|
|
165
|
+
warehouse.setModules(moduleEntries)
|
|
166
|
+
return warehouse
|
|
52
167
|
}
|
|
53
168
|
|
|
54
169
|
export function makeContainer(state: ContainerStateInput): Container {
|
|
@@ -61,7 +176,7 @@ export function makeContainer(state: ContainerStateInput): Container {
|
|
|
61
176
|
hullmass: UInt32.from(state.hullmass),
|
|
62
177
|
capacity: UInt32.from(state.capacity),
|
|
63
178
|
cargomass: UInt32.from(state.cargomass || 0),
|
|
64
|
-
cargo: [],
|
|
179
|
+
cargo: state.cargo || [],
|
|
65
180
|
is_idle: !state.schedule,
|
|
66
181
|
current_task_elapsed: UInt32.from(0),
|
|
67
182
|
current_task_remaining: UInt32.from(0),
|
|
@@ -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
|
|
19
|
-
const
|
|
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 +
|
|
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
|
|
47
|
+
const ref = stats.reflectivity ?? 500
|
|
48
48
|
|
|
49
49
|
return {
|
|
50
50
|
capacity: 300 + Math.floor(res / 6),
|
|
51
|
-
recharge:
|
|
51
|
+
recharge: 1 + Math.floor((ref * 3) / 1000),
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
@@ -65,7 +65,7 @@ export function computeGathererCapabilities(stats: Record<string, number>): {
|
|
|
65
65
|
|
|
66
66
|
return {
|
|
67
67
|
yield: 200 + str,
|
|
68
|
-
drain: Math.max(
|
|
68
|
+
drain: Math.max(250, 1250 - Math.floor((con * 25) / 20)),
|
|
69
69
|
depth: 200 + Math.floor((tol * 3) / 2),
|
|
70
70
|
speed: 100 + Math.floor((ref * 4) / 5),
|
|
71
71
|
}
|
|
@@ -76,11 +76,11 @@ export function computeLoaderCapabilities(stats: Record<string, number>): {
|
|
|
76
76
|
thrust: number
|
|
77
77
|
quantity: number
|
|
78
78
|
} {
|
|
79
|
-
const
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
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(
|
|
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
|
|
126
|
-
const
|
|
125
|
+
const fineness = stats.fineness ?? 500
|
|
126
|
+
const saturation = stats.saturation ?? 500
|
|
127
127
|
|
|
128
|
-
const statSum = strength +
|
|
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
|
|
143
|
-
const
|
|
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 +
|
|
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
|
|
|
@@ -160,7 +160,7 @@ export interface ShipCapabilities {
|
|
|
160
160
|
}
|
|
161
161
|
|
|
162
162
|
export function computeShipCapabilities(
|
|
163
|
-
modules: {itemId: number;
|
|
163
|
+
modules: {itemId: number; stats: bigint}[]
|
|
164
164
|
): ShipCapabilities {
|
|
165
165
|
const ship: ShipCapabilities = {}
|
|
166
166
|
|
|
@@ -169,7 +169,7 @@ export function computeShipCapabilities(
|
|
|
169
169
|
let totalThrust = 0
|
|
170
170
|
let totalDrain = 0
|
|
171
171
|
for (const m of engineModules) {
|
|
172
|
-
const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.
|
|
172
|
+
const caps = computeEngineCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
173
173
|
totalThrust += caps.thrust
|
|
174
174
|
totalDrain += caps.drain
|
|
175
175
|
}
|
|
@@ -183,7 +183,7 @@ export function computeShipCapabilities(
|
|
|
183
183
|
let totalCapacity = 0
|
|
184
184
|
let totalRecharge = 0
|
|
185
185
|
for (const m of generatorModules) {
|
|
186
|
-
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.
|
|
186
|
+
const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
187
187
|
totalCapacity += caps.capacity
|
|
188
188
|
totalRecharge += caps.recharge
|
|
189
189
|
}
|
|
@@ -199,7 +199,7 @@ export function computeShipCapabilities(
|
|
|
199
199
|
let totalDepth = 0
|
|
200
200
|
let totalSpeed = 0
|
|
201
201
|
for (const m of gathererModules) {
|
|
202
|
-
const caps = computeGathererCapabilities(decodeCraftedItemStats(m.itemId, m.
|
|
202
|
+
const caps = computeGathererCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
203
203
|
totalYield += caps.yield
|
|
204
204
|
totalDrain += caps.drain
|
|
205
205
|
totalDepth += caps.depth
|
|
@@ -214,12 +214,7 @@ export function computeShipCapabilities(
|
|
|
214
214
|
let weightedEffNum = 0
|
|
215
215
|
let totalDrain = 0
|
|
216
216
|
for (const m of haulerModules) {
|
|
217
|
-
const
|
|
218
|
-
const caps = computeHaulerCapabilities({
|
|
219
|
-
resonance: decoded.capacity,
|
|
220
|
-
conductivity: decoded.efficiency,
|
|
221
|
-
clarity: decoded.drain,
|
|
222
|
-
})
|
|
217
|
+
const caps = computeHaulerCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
223
218
|
totalCapacity += caps.capacity
|
|
224
219
|
weightedEffNum += caps.efficiency * caps.capacity
|
|
225
220
|
totalDrain += caps.drain
|
|
@@ -237,7 +232,7 @@ export function computeShipCapabilities(
|
|
|
237
232
|
let totalThrust = 0
|
|
238
233
|
let totalQuantity = 0
|
|
239
234
|
for (const m of loaderModules) {
|
|
240
|
-
const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.
|
|
235
|
+
const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
241
236
|
totalMass += caps.mass
|
|
242
237
|
totalThrust += caps.thrust
|
|
243
238
|
totalQuantity += caps.quantity
|
|
@@ -252,7 +247,7 @@ export function computeShipCapabilities(
|
|
|
252
247
|
let totalSpeed = 0
|
|
253
248
|
let totalDrain = 0
|
|
254
249
|
for (const m of crafterModules) {
|
|
255
|
-
const caps = computeManufacturingCapabilities(decodeCraftedItemStats(m.itemId, m.
|
|
250
|
+
const caps = computeManufacturingCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
256
251
|
totalSpeed += caps.speed
|
|
257
252
|
totalDrain += caps.drain
|
|
258
253
|
}
|
package/src/entities/ship.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {UInt16, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
|
|
1
|
+
import {UInt16, UInt16Type, UInt32, UInt64, UInt64Type} from '@wharfkit/antelope'
|
|
2
2
|
import {ServerContract} from '../contracts'
|
|
3
3
|
import {Coordinates, CoordinatesType} from '../types'
|
|
4
4
|
import {
|
|
@@ -23,6 +23,11 @@ import {
|
|
|
23
23
|
} from '../capabilities/movement'
|
|
24
24
|
import * as schedule from '../scheduling/schedule'
|
|
25
25
|
|
|
26
|
+
export interface PackedModuleInput {
|
|
27
|
+
itemId: UInt16Type
|
|
28
|
+
stats: UInt64Type
|
|
29
|
+
}
|
|
30
|
+
|
|
26
31
|
export interface ShipStateInput {
|
|
27
32
|
id: UInt64Type
|
|
28
33
|
owner: string
|
|
@@ -31,9 +36,7 @@ export interface ShipStateInput {
|
|
|
31
36
|
hullmass?: number
|
|
32
37
|
capacity?: number
|
|
33
38
|
energy?: number
|
|
34
|
-
|
|
35
|
-
generator?: ServerContract.Types.energy_stats
|
|
36
|
-
loaders?: ServerContract.Types.loader_stats
|
|
39
|
+
modules?: PackedModuleInput[]
|
|
37
40
|
schedule?: ServerContract.Types.schedule
|
|
38
41
|
cargo?: ServerContract.Types.cargo_item[]
|
|
39
42
|
}
|
|
@@ -47,11 +50,20 @@ type MovementEntity = {
|
|
|
47
50
|
export class Ship extends ServerContract.Types.entity_info {
|
|
48
51
|
private _sched?: ScheduleAccessor
|
|
49
52
|
private _inv?: InventoryAccessor
|
|
53
|
+
private _modules: ServerContract.Types.module_entry[] = []
|
|
50
54
|
|
|
51
55
|
get name(): string {
|
|
52
56
|
return this.entity_name
|
|
53
57
|
}
|
|
54
58
|
|
|
59
|
+
get modules(): ServerContract.Types.module_entry[] {
|
|
60
|
+
return this._modules
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setModules(modules: ServerContract.Types.module_entry[]): void {
|
|
64
|
+
this._modules = modules
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
get inv(): InventoryAccessor {
|
|
56
68
|
return (this._inv ??= new InventoryAccessor(this))
|
|
57
69
|
}
|
|
@@ -6,6 +6,10 @@ import {ScheduleAccessor} from '../scheduling/accessor'
|
|
|
6
6
|
import {InventoryAccessor} from './inventory-accessor'
|
|
7
7
|
import {EntityInventory} from './entity-inventory'
|
|
8
8
|
import * as schedule from '../scheduling/schedule'
|
|
9
|
+
import type {PackedModuleInput} from './ship'
|
|
10
|
+
import {decodeCraftedItemStats} from '../derivation/crafting'
|
|
11
|
+
import {getModuleCapabilityType, MODULE_LOADER} from '../capabilities/modules'
|
|
12
|
+
import {computeLoaderCapabilities} from './ship-deploy'
|
|
9
13
|
|
|
10
14
|
export interface WarehouseStateInput {
|
|
11
15
|
id: UInt64Type
|
|
@@ -14,7 +18,7 @@ export interface WarehouseStateInput {
|
|
|
14
18
|
coordinates: CoordinatesType | {x: number; y: number; z?: number}
|
|
15
19
|
hullmass?: number
|
|
16
20
|
capacity: number
|
|
17
|
-
|
|
21
|
+
modules?: PackedModuleInput[]
|
|
18
22
|
schedule?: ServerContract.Types.schedule
|
|
19
23
|
cargo?: ServerContract.Types.cargo_item[]
|
|
20
24
|
}
|
|
@@ -22,11 +26,20 @@ export interface WarehouseStateInput {
|
|
|
22
26
|
export class Warehouse extends ServerContract.Types.entity_info {
|
|
23
27
|
private _sched?: ScheduleAccessor
|
|
24
28
|
private _inv?: InventoryAccessor
|
|
29
|
+
private _modules: ServerContract.Types.module_entry[] = []
|
|
25
30
|
|
|
26
31
|
get name(): string {
|
|
27
32
|
return this.entity_name
|
|
28
33
|
}
|
|
29
34
|
|
|
35
|
+
get modules(): ServerContract.Types.module_entry[] {
|
|
36
|
+
return this._modules
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setModules(modules: ServerContract.Types.module_entry[]): void {
|
|
40
|
+
this._modules = modules
|
|
41
|
+
}
|
|
42
|
+
|
|
30
43
|
get inv(): InventoryAccessor {
|
|
31
44
|
return (this._inv ??= new InventoryAccessor(this))
|
|
32
45
|
}
|
|
@@ -89,3 +102,25 @@ export class Warehouse extends ServerContract.Types.entity_info {
|
|
|
89
102
|
return hull.adding(this.totalCargoMass)
|
|
90
103
|
}
|
|
91
104
|
}
|
|
105
|
+
|
|
106
|
+
export function computeWarehouseCapabilities(modules: {itemId: number; stats: bigint}[]): {
|
|
107
|
+
loaders?: {mass: number; thrust: number; quantity: number}
|
|
108
|
+
} {
|
|
109
|
+
const warehouse: {loaders?: {mass: number; thrust: number; quantity: number}} = {}
|
|
110
|
+
|
|
111
|
+
const loaderModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_LOADER)
|
|
112
|
+
if (loaderModules.length > 0) {
|
|
113
|
+
let totalMass = 0
|
|
114
|
+
let totalThrust = 0
|
|
115
|
+
let totalQuantity = 0
|
|
116
|
+
for (const m of loaderModules) {
|
|
117
|
+
const caps = computeLoaderCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
|
|
118
|
+
totalMass += caps.mass
|
|
119
|
+
totalThrust += caps.thrust
|
|
120
|
+
totalQuantity += caps.quantity
|
|
121
|
+
}
|
|
122
|
+
warehouse.loaders = {mass: totalMass, thrust: totalThrust, quantity: totalQuantity}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return warehouse
|
|
126
|
+
}
|
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
|
+
}
|