@shipload/sdk 1.0.0-next.65 → 1.0.0-next.66
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 +698 -316
- package/lib/shipload.js +2473 -1235
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2392 -1216
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +205 -146
- package/lib/testing.js +846 -556
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +846 -556
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/capabilities/crafting.test.ts +51 -6
- package/src/capabilities/crafting.ts +19 -4
- package/src/capabilities/gathering.ts +2 -2
- package/src/capabilities/storage.test.ts +26 -0
- package/src/capabilities/storage.ts +6 -6
- package/src/contracts/fund.ts +79 -2
- package/src/contracts/platform.ts +10 -1
- package/src/contracts/server.ts +467 -331
- package/src/data/charters.json +325 -127
- package/src/data/entities.json +24 -24
- package/src/data/items.json +114 -114
- package/src/data/kind-registry.json +3 -3
- package/src/data/kind-registry.ts +5 -0
- package/src/data/recipes.json +56 -95
- package/src/derivation/build-methods.test.ts +59 -1
- package/src/derivation/build-methods.ts +2 -0
- package/src/derivation/capabilities.ts +7 -7
- package/src/derivation/strata.ts +5 -3
- package/src/derivation/tiers.ts +5 -5
- package/src/entity/hydrate.test.ts +156 -0
- package/src/entity/hydrate.ts +86 -0
- package/src/errors.ts +9 -0
- package/src/format.ts +15 -13
- package/src/index-module.ts +32 -5
- package/src/influence/ballot.test.ts +103 -0
- package/src/influence/ballot.ts +98 -0
- package/src/influence/charter-metadata.test.ts +136 -0
- package/src/influence/charter-metadata.ts +236 -0
- package/src/influence/charters.test.ts +51 -65
- package/src/influence/charters.ts +70 -40
- package/src/influence/civic.test.ts +278 -0
- package/src/influence/civic.ts +269 -0
- package/src/influence/constants.ts +30 -9
- package/src/influence/decomp.ts +15 -15
- package/src/influence/duration.ts +42 -6
- package/src/influence/index.ts +49 -6
- package/src/influence/influence.test.ts +76 -9
- package/src/influence/valuation.ts +17 -17
- package/src/managers/actions.ts +65 -37
- package/src/managers/base.ts +4 -0
- package/src/managers/context.ts +3 -1
- package/src/managers/index.ts +4 -2
- package/src/managers/influence.test.ts +18 -20
- package/src/managers/influence.ts +137 -84
- package/src/managers/jobs.test.ts +2 -2
- package/src/managers/jobs.ts +4 -4
- package/src/nft/description.ts +10 -11
- package/src/planner/index.ts +54 -0
- package/src/planner/planner.test.ts +127 -2
- package/src/resolution/display-name.ts +1 -1
- package/src/scheduling/availability.test.ts +113 -0
- package/src/scheduling/availability.ts +48 -8
- package/src/scheduling/jobs.ts +1 -1
- package/src/scheduling/projection.ts +2 -16
- package/src/scheduling/task-cargo.test.ts +62 -1
- package/src/scheduling/task-cargo.ts +25 -10
- package/src/scheduling/task-effects.test.ts +35 -0
- package/src/scheduling/task-effects.ts +34 -0
- package/src/scheduling/unwrap.test.ts +3 -3
- package/src/scheduling/unwrap.ts +3 -3
- package/src/shipload.ts +22 -3
- package/src/travel/reach.test.ts +86 -0
- package/src/travel/reach.ts +23 -10
- package/src/travel/route-build.test.ts +63 -0
- package/src/travel/route-build.ts +60 -0
- package/src/travel/travel.ts +2 -1
- package/src/types.ts +6 -2
- package/src/utils/hash.ts +18 -2
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import {Name, type NameType, UInt16, UInt64, UInt8} from '@wharfkit/antelope'
|
|
2
|
+
import {
|
|
3
|
+
getModuleCapabilityType,
|
|
4
|
+
MODULE_BUILDER,
|
|
5
|
+
MODULE_CRAFTER,
|
|
6
|
+
MODULE_LOADER,
|
|
7
|
+
MODULE_STORAGE,
|
|
8
|
+
moduleSlotTypeToCode,
|
|
9
|
+
} from '../capabilities/modules'
|
|
10
|
+
import {ServerContract} from '../contracts'
|
|
11
|
+
import {
|
|
12
|
+
ITEM_BUILDER_T1,
|
|
13
|
+
ITEM_CONSTRUCTION_DOCK_T1_PACKED,
|
|
14
|
+
ITEM_CRAFTER_T1,
|
|
15
|
+
ITEM_DEPOT_T1_PACKED,
|
|
16
|
+
ITEM_LOADER_T1,
|
|
17
|
+
ITEM_NEXUS_T1_PACKED,
|
|
18
|
+
ITEM_STORAGE_T1,
|
|
19
|
+
ITEM_WORKSHOP_T1_PACKED,
|
|
20
|
+
} from '../data/item-ids'
|
|
21
|
+
import {
|
|
22
|
+
ENTITY_CONSTRUCTION_DOCK,
|
|
23
|
+
ENTITY_DEPOT,
|
|
24
|
+
ENTITY_NEXUS,
|
|
25
|
+
ENTITY_WORKSHOP,
|
|
26
|
+
} from '../data/kind-registry'
|
|
27
|
+
import {getEntityLayout} from '../data/recipes-runtime'
|
|
28
|
+
import {decodeStat, encodeStats} from '../derivation/crafting'
|
|
29
|
+
import type {CharterGrant, CharterNode} from './charters'
|
|
30
|
+
import {
|
|
31
|
+
CIVIC_DEPOT,
|
|
32
|
+
CIVIC_DOCK,
|
|
33
|
+
CIVIC_GRANT_LEVEL_GATE,
|
|
34
|
+
CIVIC_GRANT_MODULE,
|
|
35
|
+
CIVIC_GRANT_RUNG,
|
|
36
|
+
CIVIC_NEXUS,
|
|
37
|
+
CIVIC_SPEED_CAP,
|
|
38
|
+
CIVIC_STAT_BUILD_SPEED,
|
|
39
|
+
CIVIC_STAT_CRAFT_SPEED,
|
|
40
|
+
CIVIC_STAT_STORAGE_CAPACITY,
|
|
41
|
+
CIVIC_STAT_TRANSFER_SPEED,
|
|
42
|
+
CIVIC_WORKSHOP,
|
|
43
|
+
} from './constants'
|
|
44
|
+
import {getStatCount} from './quality'
|
|
45
|
+
|
|
46
|
+
type ModuleEntry = ServerContract.Types.module_entry
|
|
47
|
+
|
|
48
|
+
export interface CivicStatDef {
|
|
49
|
+
building: number
|
|
50
|
+
stat: number
|
|
51
|
+
base: number
|
|
52
|
+
cap: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const CIVIC_STAT_DEFS: readonly CivicStatDef[] = [
|
|
56
|
+
{building: CIVIC_WORKSHOP, stat: CIVIC_STAT_CRAFT_SPEED, base: 0, cap: CIVIC_SPEED_CAP},
|
|
57
|
+
{building: CIVIC_DOCK, stat: CIVIC_STAT_BUILD_SPEED, base: 0, cap: CIVIC_SPEED_CAP},
|
|
58
|
+
{building: CIVIC_DEPOT, stat: CIVIC_STAT_TRANSFER_SPEED, base: 0, cap: CIVIC_SPEED_CAP},
|
|
59
|
+
{building: CIVIC_DEPOT, stat: CIVIC_STAT_STORAGE_CAPACITY, base: 0, cap: CIVIC_SPEED_CAP},
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
export function findCivicStatDef(building: number, stat: number): CivicStatDef | undefined {
|
|
63
|
+
return CIVIC_STAT_DEFS.find((def) => def.building === building && def.stat === stat)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function civicHullItem(building: number): number {
|
|
67
|
+
switch (building) {
|
|
68
|
+
case CIVIC_WORKSHOP:
|
|
69
|
+
return ITEM_WORKSHOP_T1_PACKED
|
|
70
|
+
case CIVIC_NEXUS:
|
|
71
|
+
return ITEM_NEXUS_T1_PACKED
|
|
72
|
+
case CIVIC_DOCK:
|
|
73
|
+
return ITEM_CONSTRUCTION_DOCK_T1_PACKED
|
|
74
|
+
case CIVIC_DEPOT:
|
|
75
|
+
return ITEM_DEPOT_T1_PACKED
|
|
76
|
+
default:
|
|
77
|
+
return 0
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function civicModuleItemFor(moduleType: number): number {
|
|
82
|
+
switch (moduleType) {
|
|
83
|
+
case MODULE_CRAFTER:
|
|
84
|
+
return ITEM_CRAFTER_T1
|
|
85
|
+
case MODULE_BUILDER:
|
|
86
|
+
return ITEM_BUILDER_T1
|
|
87
|
+
case MODULE_LOADER:
|
|
88
|
+
return ITEM_LOADER_T1
|
|
89
|
+
case MODULE_STORAGE:
|
|
90
|
+
return ITEM_STORAGE_T1
|
|
91
|
+
default:
|
|
92
|
+
return 0
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function civicStatModuleType(stat: number): number {
|
|
97
|
+
switch (stat) {
|
|
98
|
+
case CIVIC_STAT_CRAFT_SPEED:
|
|
99
|
+
return MODULE_CRAFTER
|
|
100
|
+
case CIVIC_STAT_BUILD_SPEED:
|
|
101
|
+
return MODULE_BUILDER
|
|
102
|
+
case CIVIC_STAT_TRANSFER_SPEED:
|
|
103
|
+
return MODULE_LOADER
|
|
104
|
+
case CIVIC_STAT_STORAGE_CAPACITY:
|
|
105
|
+
return MODULE_STORAGE
|
|
106
|
+
default:
|
|
107
|
+
return 0
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function civicBuildingKind(building: number): Name | undefined {
|
|
112
|
+
switch (building) {
|
|
113
|
+
case CIVIC_WORKSHOP:
|
|
114
|
+
return ENTITY_WORKSHOP
|
|
115
|
+
case CIVIC_NEXUS:
|
|
116
|
+
return ENTITY_NEXUS
|
|
117
|
+
case CIVIC_DOCK:
|
|
118
|
+
return ENTITY_CONSTRUCTION_DOCK
|
|
119
|
+
case CIVIC_DEPOT:
|
|
120
|
+
return ENTITY_DEPOT
|
|
121
|
+
default:
|
|
122
|
+
return undefined
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function civicBuildingFor(kind: NameType): number | undefined {
|
|
127
|
+
const name = Name.from(kind)
|
|
128
|
+
if (name.equals(ENTITY_WORKSHOP)) return CIVIC_WORKSHOP
|
|
129
|
+
if (name.equals(ENTITY_NEXUS)) return CIVIC_NEXUS
|
|
130
|
+
if (name.equals(ENTITY_CONSTRUCTION_DOCK)) return CIVIC_DOCK
|
|
131
|
+
if (name.equals(ENTITY_DEPOT)) return CIVIC_DEPOT
|
|
132
|
+
return undefined
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function isCivicKind(kind: NameType): boolean {
|
|
136
|
+
return civicBuildingFor(kind) !== undefined
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function isCivicEntity(entity: {owner: NameType}, civicOwner: NameType): boolean {
|
|
140
|
+
return Name.from(entity.owner).equals(Name.from(civicOwner))
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function moduleItemId(module: ServerContract.Types.packed_module): number {
|
|
144
|
+
return Number(module.item_id.value ?? module.item_id)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function moduleStats(module: ServerContract.Types.packed_module): bigint {
|
|
148
|
+
return BigInt(module.stats.toString())
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function packedModule(itemId: number, stats: bigint): ServerContract.Types.packed_module {
|
|
152
|
+
return ServerContract.Types.packed_module.from({
|
|
153
|
+
item_id: UInt16.from(itemId),
|
|
154
|
+
stats: UInt64.from(stats.toString()),
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function cloneEntry(
|
|
159
|
+
entry: ModuleEntry,
|
|
160
|
+
installed?: ServerContract.Types.packed_module
|
|
161
|
+
): ModuleEntry {
|
|
162
|
+
return ServerContract.Types.module_entry.from({
|
|
163
|
+
type: UInt8.from(Number(entry.type.value ?? entry.type)),
|
|
164
|
+
installed:
|
|
165
|
+
installed ??
|
|
166
|
+
(entry.installed
|
|
167
|
+
? packedModule(moduleItemId(entry.installed), moduleStats(entry.installed))
|
|
168
|
+
: undefined),
|
|
169
|
+
})
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function emptyCivicModules(building: number): ModuleEntry[] {
|
|
173
|
+
const layout = getEntityLayout(civicHullItem(building))?.slots ?? []
|
|
174
|
+
return layout.map((slot) =>
|
|
175
|
+
ServerContract.Types.module_entry.from({type: UInt8.from(moduleSlotTypeToCode(slot.type))})
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function fitCivicModules(modules: ModuleEntry[], count: number): ModuleEntry[] {
|
|
180
|
+
const next = modules.map((entry) => cloneEntry(entry))
|
|
181
|
+
let remaining = count
|
|
182
|
+
for (let i = 0; i < next.length && remaining > 0; i++) {
|
|
183
|
+
if (next[i].installed) continue
|
|
184
|
+
const type = Number(next[i].type.value ?? next[i].type)
|
|
185
|
+
const item = civicModuleItemFor(type)
|
|
186
|
+
if (item === 0) throw new Error('charter grant found no open slot of its module type')
|
|
187
|
+
let stats = encodeStats(new Array(getStatCount(item)).fill(0))
|
|
188
|
+
for (const sibling of next) {
|
|
189
|
+
if (
|
|
190
|
+
sibling.installed &&
|
|
191
|
+
getModuleCapabilityType(moduleItemId(sibling.installed)) === type
|
|
192
|
+
) {
|
|
193
|
+
stats = moduleStats(sibling.installed)
|
|
194
|
+
break
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
next[i] = cloneEntry(next[i], packedModule(item, stats))
|
|
198
|
+
remaining--
|
|
199
|
+
}
|
|
200
|
+
if (remaining > 0) throw new Error('charter grant found no open slot of its module type')
|
|
201
|
+
return next
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export function raiseCivicStat(modules: ModuleEntry[], grant: CharterGrant): ModuleEntry[] {
|
|
205
|
+
const def = findCivicStatDef(grant.building, grant.stat)
|
|
206
|
+
if (!def) throw new Error(`no civic stat ${grant.stat} on building ${grant.building}`)
|
|
207
|
+
const type = civicStatModuleType(grant.stat)
|
|
208
|
+
let raised = 0
|
|
209
|
+
const next = modules.map((entry) => {
|
|
210
|
+
if (!entry.installed || getModuleCapabilityType(moduleItemId(entry.installed)) !== type) {
|
|
211
|
+
return cloneEntry(entry)
|
|
212
|
+
}
|
|
213
|
+
const item = moduleItemId(entry.installed)
|
|
214
|
+
const stats = moduleStats(entry.installed)
|
|
215
|
+
const values: number[] = []
|
|
216
|
+
for (let c = 0; c < getStatCount(item); c++) {
|
|
217
|
+
values.push(Math.min(decodeStat(stats, c) + grant.value, def.cap))
|
|
218
|
+
}
|
|
219
|
+
raised++
|
|
220
|
+
return cloneEntry(entry, packedModule(item, encodeStats(values)))
|
|
221
|
+
})
|
|
222
|
+
if (raised === 0) throw new Error('charter rung found no module carrying its stat')
|
|
223
|
+
return next
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
export interface CivicBuildingPreview {
|
|
227
|
+
building: number
|
|
228
|
+
itemId: number
|
|
229
|
+
spawned: boolean
|
|
230
|
+
modules: ModuleEntry[]
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export type CivicStanding = Partial<Record<number, ModuleEntry[]>>
|
|
234
|
+
|
|
235
|
+
export function previewCharterGrants(
|
|
236
|
+
node: CharterNode,
|
|
237
|
+
standing: CivicStanding = {}
|
|
238
|
+
): CivicBuildingPreview[] {
|
|
239
|
+
const previews = new Map<number, CivicBuildingPreview>()
|
|
240
|
+
const target = (building: number, spawn: boolean): CivicBuildingPreview => {
|
|
241
|
+
let preview = previews.get(building)
|
|
242
|
+
if (preview) return preview
|
|
243
|
+
const current = standing[building]
|
|
244
|
+
if (!current && !spawn)
|
|
245
|
+
throw new Error('charter grant targets a building that is not standing')
|
|
246
|
+
preview = {
|
|
247
|
+
building,
|
|
248
|
+
itemId: civicHullItem(building),
|
|
249
|
+
spawned: !current,
|
|
250
|
+
modules: current
|
|
251
|
+
? current.map((entry) => cloneEntry(entry))
|
|
252
|
+
: emptyCivicModules(building),
|
|
253
|
+
}
|
|
254
|
+
previews.set(building, preview)
|
|
255
|
+
return preview
|
|
256
|
+
}
|
|
257
|
+
for (const grant of node.grants) {
|
|
258
|
+
if (grant.kind === CIVIC_GRANT_LEVEL_GATE) {
|
|
259
|
+
target(grant.building, true)
|
|
260
|
+
} else if (grant.kind === CIVIC_GRANT_MODULE) {
|
|
261
|
+
const preview = target(grant.building, false)
|
|
262
|
+
preview.modules = fitCivicModules(preview.modules, grant.value)
|
|
263
|
+
} else if (grant.kind === CIVIC_GRANT_RUNG) {
|
|
264
|
+
const preview = target(grant.building, false)
|
|
265
|
+
preview.modules = raiseCivicStat(preview.modules, grant)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return [...previews.values()]
|
|
269
|
+
}
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
import {MASS_UNITS_PER_TONNE} from '../types'
|
|
2
|
+
|
|
1
3
|
export const INFLUENCE_ATOMIC_PER_POINT = 10_000
|
|
2
4
|
export const NEED_FP_SCALE = 10_000
|
|
3
5
|
export const WEIGHT_FP_SCALE = 10_000
|
|
4
|
-
export const MASS_KG_PER_TONNE = 1_000
|
|
5
6
|
|
|
6
7
|
export const INFLUENCE_WEIGHT_FP_MAX = 1_000_000n
|
|
7
8
|
export const INFLUENCE_NEED_FP_MAX = 1_000_000n
|
|
8
|
-
export const
|
|
9
|
+
export const INFLUENCE_MASS_MAX = 1n << 48n
|
|
9
10
|
|
|
10
11
|
export const DECAY_RETAIN_NUM = 19n
|
|
11
12
|
export const DECAY_RETAIN_DEN = 20n
|
|
12
13
|
export const DECAY_MAX_ITERATIONS = 1_024
|
|
13
14
|
|
|
14
|
-
export const
|
|
15
|
+
export const W_EFF_ATOMIC_PER_UNIT = BigInt(INFLUENCE_ATOMIC_PER_POINT / MASS_UNITS_PER_TONNE)
|
|
15
16
|
|
|
16
17
|
export const DECOMP_MAX_BUCKETS = 12
|
|
17
18
|
export const DECOMP_MAX_DEPTH = 8
|
|
18
|
-
export const
|
|
19
|
-
export const
|
|
19
|
+
export const DECOMP_RAW_MASS_MAX = 1_000_000
|
|
20
|
+
export const DECOMP_PROCESSED_MASS_MAX = 1_000_000
|
|
20
21
|
|
|
21
22
|
export const RESOURCE_ORE = 0
|
|
22
23
|
export const RESOURCE_GAS = 1
|
|
@@ -39,13 +40,33 @@ export const BAR_STEP_UP = BAR_STEP_UNIT * 9
|
|
|
39
40
|
export const BAR_STEP_DOWN = BAR_STEP_UNIT
|
|
40
41
|
|
|
41
42
|
export const CHARTER_NONE = 0
|
|
42
|
-
export const CHARTER_WORKSHOP =
|
|
43
|
-
export const
|
|
44
|
-
export const
|
|
43
|
+
export const CHARTER_WORKSHOP = 10001
|
|
44
|
+
export const CIVIC_GRANT_NONE = 0
|
|
45
|
+
export const CIVIC_GRANT_MODULE = 1
|
|
46
|
+
export const CIVIC_GRANT_RUNG = 2
|
|
47
|
+
export const CIVIC_GRANT_LEVEL_GATE = 3
|
|
48
|
+
export const CIVIC_GRANT_ADVANCEMENT = 4
|
|
49
|
+
|
|
50
|
+
export const CIVIC_WORLD = 0
|
|
51
|
+
export const CIVIC_WORKSHOP = 1
|
|
52
|
+
export const CIVIC_NEXUS = 2
|
|
53
|
+
export const CIVIC_DOCK = 3
|
|
54
|
+
export const CIVIC_DEPOT = 4
|
|
55
|
+
|
|
56
|
+
export const CIVIC_STAT_NONE = 0
|
|
57
|
+
export const CIVIC_STAT_CRAFT_SPEED = 1
|
|
58
|
+
export const CIVIC_STAT_BUILD_SPEED = 2
|
|
59
|
+
export const CIVIC_STAT_TRANSFER_SPEED = 3
|
|
60
|
+
export const CIVIC_STAT_STORAGE_CAPACITY = 4
|
|
45
61
|
export const VOTE_READY_DEFAULT_MAX = 20
|
|
62
|
+
export const BALLOT_CHARTER = 1
|
|
63
|
+
export const BALLOT_MAX_PICKS = 8
|
|
46
64
|
export const CHARTER_WORKSHOP_COST = 2_000_000_000n
|
|
47
|
-
export const CHARTER_BASELINE_STAT =
|
|
65
|
+
export const CHARTER_BASELINE_STAT = 200
|
|
66
|
+
export const CHARTER_RUNG_STEP = 50
|
|
67
|
+
export const CIVIC_SPEED_CAP = 999
|
|
48
68
|
export const CHARTER_MAX_PREREQS = 4
|
|
69
|
+
export const CHARTER_MAX_GRANTS = 4
|
|
49
70
|
|
|
50
71
|
export const INFLUENCE_D1_SEED = 45_369
|
|
51
72
|
export const DEMAND_TRIPLE_SEED = {peak: 20_000n, base: 10_000n, floor: 1_000n}
|
package/src/influence/decomp.ts
CHANGED
|
@@ -4,40 +4,40 @@ import recipes from '../data/recipes.json'
|
|
|
4
4
|
import {
|
|
5
5
|
DECOMP_MAX_BUCKETS,
|
|
6
6
|
DECOMP_MAX_DEPTH,
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
DECOMP_PROCESSED_MASS_MAX,
|
|
8
|
+
DECOMP_RAW_MASS_MAX,
|
|
9
9
|
} from './constants'
|
|
10
10
|
import {categoryIndex} from './categories'
|
|
11
11
|
|
|
12
12
|
export interface DecompBucket {
|
|
13
13
|
category: number
|
|
14
14
|
tier: number
|
|
15
|
-
|
|
15
|
+
rawMass: number
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export interface DecompEntry {
|
|
19
19
|
itemId: number
|
|
20
|
-
|
|
20
|
+
processedMass: number
|
|
21
21
|
buckets: DecompBucket[]
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
interface Accumulator {
|
|
25
25
|
buckets: DecompBucket[]
|
|
26
|
-
|
|
26
|
+
processedMass: number
|
|
27
27
|
overflow: boolean
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
function add(acc: Accumulator, category: number, tier: number,
|
|
30
|
+
function add(acc: Accumulator, category: number, tier: number, mass: number): void {
|
|
31
31
|
const existing = acc.buckets.find((b) => b.category === category && b.tier === tier)
|
|
32
32
|
if (existing) {
|
|
33
|
-
existing.
|
|
33
|
+
existing.rawMass += mass
|
|
34
34
|
return
|
|
35
35
|
}
|
|
36
36
|
if (acc.buckets.length >= DECOMP_MAX_BUCKETS) {
|
|
37
37
|
acc.overflow = true
|
|
38
38
|
return
|
|
39
39
|
}
|
|
40
|
-
acc.buckets.push({category, tier,
|
|
40
|
+
acc.buckets.push({category, tier, rawMass: mass})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
function walk(itemId: number, multiplier: number, acc: Accumulator, depth: number): void {
|
|
@@ -51,14 +51,14 @@ function walk(itemId: number, multiplier: number, acc: Accumulator, depth: numbe
|
|
|
51
51
|
for (const input of recipe.inputs) {
|
|
52
52
|
const def = tryGetItem(input.itemId)
|
|
53
53
|
const units = multiplier * input.quantity
|
|
54
|
-
const
|
|
55
|
-
acc.
|
|
54
|
+
const mass = units * (def ? def.mass : 0)
|
|
55
|
+
acc.processedMass += mass
|
|
56
56
|
if (getRecipe(input.itemId)) {
|
|
57
57
|
walk(input.itemId, units, acc, depth + 1)
|
|
58
58
|
} else if (def?.type !== 'resource' || def.category === undefined) {
|
|
59
59
|
acc.overflow = true
|
|
60
60
|
} else {
|
|
61
|
-
add(acc, categoryIndex(def.category), def.tier,
|
|
61
|
+
add(acc, categoryIndex(def.category), def.tier, mass)
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -66,18 +66,18 @@ function walk(itemId: number, multiplier: number, acc: Accumulator, depth: numbe
|
|
|
66
66
|
function buildRegistry(): DecompEntry[] {
|
|
67
67
|
const out: DecompEntry[] = []
|
|
68
68
|
for (const recipe of recipes as {outputItemId: number}[]) {
|
|
69
|
-
const acc: Accumulator = {buckets: [],
|
|
69
|
+
const acc: Accumulator = {buckets: [], processedMass: 0, overflow: false}
|
|
70
70
|
walk(recipe.outputItemId, 1, acc, 0)
|
|
71
71
|
acc.buckets.sort((a, b) => a.category - b.category || a.tier - b.tier)
|
|
72
72
|
|
|
73
|
-
const rawTotal = acc.buckets.reduce((sum, b) => sum + b.
|
|
74
|
-
if (rawTotal >
|
|
73
|
+
const rawTotal = acc.buckets.reduce((sum, b) => sum + b.rawMass, 0)
|
|
74
|
+
if (rawTotal > DECOMP_RAW_MASS_MAX || acc.processedMass > DECOMP_PROCESSED_MASS_MAX) {
|
|
75
75
|
acc.overflow = true
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
out.push({
|
|
79
79
|
itemId: recipe.outputItemId,
|
|
80
|
-
|
|
80
|
+
processedMass: acc.overflow ? 0 : acc.processedMass,
|
|
81
81
|
buckets: acc.buckets,
|
|
82
82
|
})
|
|
83
83
|
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import type {NameType} from '@wharfkit/antelope'
|
|
2
|
+
import type {ServerContract} from '../contracts'
|
|
3
|
+
import {getEntityClass} from '../data/kind-registry'
|
|
1
4
|
import {computeLoaderMass, computeLoaderThrust} from '../nft/description'
|
|
2
|
-
import {
|
|
5
|
+
import {laneKeyForModule, resolveLaneLoader} from '../scheduling/lanes'
|
|
6
|
+
import {calc_onesided_duration} from '../travel/travel'
|
|
7
|
+
import {MASS_STAT_SCALE, MASS_UNITS_PER_TONNE, PRECISION} from '../types'
|
|
3
8
|
import {CIVIC_LOADER_STAT, CIVIC_LOADER_TIER, DEFAULT_ORBITAL_Z} from './constants'
|
|
4
9
|
|
|
5
10
|
export interface CivicLoaderStats {
|
|
@@ -16,7 +21,7 @@ export function civicLoader(): CivicLoaderStats {
|
|
|
16
21
|
|
|
17
22
|
function acceleration(thrust: number, mass: number): number {
|
|
18
23
|
if (mass <= 0) return 0
|
|
19
|
-
return (thrust / mass) * PRECISION
|
|
24
|
+
return (thrust / (mass * MASS_STAT_SCALE)) * PRECISION
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
function flightTime(distance: number, accel: number): number {
|
|
@@ -24,13 +29,44 @@ function flightTime(distance: number, accel: number): number {
|
|
|
24
29
|
return Math.floor(2 * Math.sqrt(distance / accel))
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
export function contributeDuration(
|
|
32
|
+
export function contributeDuration(totalMass: number, altitudeZ = 0): number {
|
|
28
33
|
const loader = civicLoader()
|
|
29
|
-
const
|
|
34
|
+
const mass = totalMass + loader.mass
|
|
30
35
|
const z = Math.max(altitudeZ, DEFAULT_ORBITAL_Z)
|
|
31
|
-
return flightTime(z, acceleration(loader.thrust,
|
|
36
|
+
return flightTime(z, acceleration(loader.thrust, mass))
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
export function contributeDurationForTonnes(tonnes: number, altitudeZ = 0): number {
|
|
35
|
-
return contributeDuration(Math.floor(tonnes *
|
|
40
|
+
return contributeDuration(Math.floor(tonnes * MASS_UNITS_PER_TONNE), altitudeZ)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const DEPOT_LOADER_SLOT = 0
|
|
44
|
+
|
|
45
|
+
export interface DepotTransferParams {
|
|
46
|
+
depotModules: ServerContract.Types.module_entry[]
|
|
47
|
+
depotItemId: number
|
|
48
|
+
depotKind: NameType
|
|
49
|
+
depotZ: number
|
|
50
|
+
shipKind: NameType
|
|
51
|
+
shipZ: number
|
|
52
|
+
cargoMass: number
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Mirrors depot.cpp: the depot's slot-0 loader drives the transfer; 0 when no loader is installed.
|
|
56
|
+
export function depotTransferDuration(params: DepotTransferParams): number {
|
|
57
|
+
const loader = resolveLaneLoader(
|
|
58
|
+
params.depotModules,
|
|
59
|
+
params.depotItemId,
|
|
60
|
+
laneKeyForModule(DEPOT_LOADER_SLOT)
|
|
61
|
+
)
|
|
62
|
+
if (!loader.valid) return 0
|
|
63
|
+
return calc_onesided_duration(
|
|
64
|
+
loader.thrust,
|
|
65
|
+
loader.mass,
|
|
66
|
+
params.shipZ,
|
|
67
|
+
params.depotZ,
|
|
68
|
+
getEntityClass(params.shipKind),
|
|
69
|
+
getEntityClass(params.depotKind),
|
|
70
|
+
params.cargoMass
|
|
71
|
+
)
|
|
36
72
|
}
|
package/src/influence/index.ts
CHANGED
|
@@ -38,26 +38,69 @@ export {
|
|
|
38
38
|
civicLoader,
|
|
39
39
|
contributeDuration,
|
|
40
40
|
contributeDurationForTonnes,
|
|
41
|
+
depotTransferDuration,
|
|
42
|
+
DEPOT_LOADER_SLOT,
|
|
41
43
|
type CivicLoaderStats,
|
|
44
|
+
type DepotTransferParams,
|
|
42
45
|
} from './duration'
|
|
43
46
|
export {citizenryName, citizenryPatternCount} from './citizenry'
|
|
44
47
|
export {
|
|
45
|
-
|
|
46
|
-
charterEffectTargetPresent,
|
|
48
|
+
charterBuildingEntity,
|
|
47
49
|
charterEligible,
|
|
50
|
+
charterEligibleChained,
|
|
51
|
+
charterGateNodeFor,
|
|
48
52
|
charterIneligible,
|
|
49
53
|
charterNode,
|
|
50
54
|
charterPrereqsMet,
|
|
55
|
+
charterRungValue,
|
|
51
56
|
charterSingletonMandate,
|
|
52
|
-
|
|
57
|
+
charterModuleCount,
|
|
53
58
|
CHARTER_INELIGIBILITY_MESSAGES,
|
|
54
59
|
CHARTER_REGISTRY,
|
|
55
|
-
effectiveMandate,
|
|
56
60
|
eligibleCharters,
|
|
57
61
|
type BuiltCharter,
|
|
58
|
-
type
|
|
62
|
+
type CharterGrant,
|
|
59
63
|
type CharterIneligibility,
|
|
60
64
|
type CharterNode,
|
|
61
65
|
type CharterWorld,
|
|
62
|
-
type
|
|
66
|
+
type WorldBuilding,
|
|
63
67
|
} from './charters'
|
|
68
|
+
export {
|
|
69
|
+
projectBallot,
|
|
70
|
+
type BallotInput,
|
|
71
|
+
type BallotProjection,
|
|
72
|
+
type BallotVoter,
|
|
73
|
+
type ProjectedOption,
|
|
74
|
+
type ProjectedSeat,
|
|
75
|
+
} from './ballot'
|
|
76
|
+
export {
|
|
77
|
+
charterMetadata,
|
|
78
|
+
charterName,
|
|
79
|
+
charterSignature,
|
|
80
|
+
charterSummary,
|
|
81
|
+
civicBuildingLabel,
|
|
82
|
+
civicStatLabel,
|
|
83
|
+
romanNumeral,
|
|
84
|
+
type CharterGateSignature,
|
|
85
|
+
type CharterMeta,
|
|
86
|
+
type CharterRungSignature,
|
|
87
|
+
type CharterSignature,
|
|
88
|
+
} from './charter-metadata'
|
|
89
|
+
export {
|
|
90
|
+
CIVIC_STAT_DEFS,
|
|
91
|
+
civicBuildingFor,
|
|
92
|
+
civicBuildingKind,
|
|
93
|
+
civicHullItem,
|
|
94
|
+
civicModuleItemFor,
|
|
95
|
+
civicStatModuleType,
|
|
96
|
+
emptyCivicModules,
|
|
97
|
+
findCivicStatDef,
|
|
98
|
+
fitCivicModules,
|
|
99
|
+
isCivicEntity,
|
|
100
|
+
isCivicKind,
|
|
101
|
+
previewCharterGrants,
|
|
102
|
+
raiseCivicStat,
|
|
103
|
+
type CivicBuildingPreview,
|
|
104
|
+
type CivicStanding,
|
|
105
|
+
type CivicStatDef,
|
|
106
|
+
} from './civic'
|