@shipload/sdk 1.0.0-next.5 → 1.0.0-next.50
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/scan.d.ts +52 -0
- package/lib/scan.js +162 -0
- package/lib/scan.js.map +1 -0
- package/lib/scan.m.js +152 -0
- package/lib/scan.m.js.map +1 -0
- package/lib/shipload.d.ts +2881 -1149
- package/lib/shipload.js +13031 -5511
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +12807 -5460
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1028 -0
- package/lib/testing.js +4336 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +4330 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.ts +51 -0
- package/src/capabilities/crafting.test.ts +7 -0
- package/src/capabilities/crafting.ts +6 -7
- package/src/capabilities/gathering.test.ts +29 -0
- package/src/capabilities/gathering.ts +37 -19
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +22 -0
- package/src/capabilities/storage.ts +16 -1
- package/src/contracts/platform.ts +231 -3
- package/src/contracts/server.ts +1160 -520
- package/src/coordinates/address.ts +88 -0
- package/src/coordinates/constants.test.ts +15 -0
- package/src/coordinates/constants.ts +23 -0
- package/src/coordinates/index.ts +15 -0
- package/src/coordinates/memo.test.ts +47 -0
- package/src/coordinates/memo.ts +20 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/data/capabilities.ts +31 -16
- package/src/data/capability-formulas.ts +21 -14
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +13 -47
- package/src/data/entities.json +154 -10
- package/src/data/item-ids.ts +31 -12
- package/src/data/items.json +192 -74
- package/src/data/kind-registry.json +131 -0
- package/src/data/kind-registry.ts +172 -0
- package/src/data/metadata.ts +166 -48
- package/src/data/recipes-runtime.ts +5 -23
- package/src/data/recipes.json +1003 -163
- package/src/derivation/build-methods.test.ts +13 -0
- package/src/derivation/build-methods.ts +48 -0
- package/src/derivation/capabilities.test.ts +151 -0
- package/src/derivation/capabilities.ts +527 -0
- package/src/derivation/capability-mappings.ts +58 -16
- package/src/derivation/crafting.ts +36 -33
- package/src/derivation/index.ts +28 -2
- package/src/derivation/recipe-usage.test.ts +81 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +98 -19
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +56 -0
- package/src/derivation/stars.test.ts +67 -0
- package/src/derivation/stars.ts +25 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/stratum.ts +26 -22
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/upgrades.ts +14 -0
- package/src/derivation/wormhole.ts +141 -0
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +131 -134
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/errors.ts +12 -16
- package/src/format.ts +26 -4
- package/src/index-module.ts +290 -34
- package/src/managers/actions.ts +602 -105
- package/src/managers/base.ts +6 -2
- package/src/managers/cluster.test.ts +39 -0
- package/src/managers/cluster.ts +53 -0
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +412 -0
- package/src/managers/context.ts +29 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +27 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/flatten-gather-plan.test.ts +80 -0
- package/src/managers/index.ts +20 -1
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +14 -0
- package/src/managers/nft.ts +70 -0
- package/src/managers/players.ts +25 -0
- package/src/managers/plot.ts +122 -0
- package/src/nft/atomicassets.abi.json +1342 -0
- package/src/nft/atomicassets.ts +237 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +336 -0
- package/src/nft/description.ts +104 -36
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +242 -0
- package/src/planner/planner.test.ts +325 -0
- package/src/resolution/describe-module.ts +43 -25
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.test.ts +48 -0
- package/src/resolution/resolve-item.ts +74 -47
- package/src/scan/index.ts +244 -0
- package/src/scan/scan-wasm.base64.ts +2 -0
- package/src/scheduling/accessor.ts +65 -23
- package/src/scheduling/availability.ts +108 -0
- package/src/scheduling/cancel.test.ts +348 -0
- package/src/scheduling/cancel.ts +209 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +249 -0
- package/src/scheduling/lanes.ts +198 -0
- package/src/scheduling/projection.ts +210 -107
- package/src/scheduling/schedule.ts +240 -117
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/scheduling/unwrap.test.ts +86 -0
- package/src/scheduling/unwrap.ts +190 -0
- package/src/shipload.ts +26 -1
- package/src/subscriptions/manager.cluster.test.ts +51 -0
- package/src/subscriptions/manager.ts +245 -172
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +28 -3
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +167 -0
- package/src/travel/reach.ts +23 -0
- package/src/travel/route-planner.ts +277 -0
- package/src/travel/travel.ts +148 -117
- package/src/types/capabilities.ts +29 -6
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +36 -14
- package/src/utils/cargo.test.ts +14 -0
- package/src/utils/cargo.ts +29 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/system.ts +36 -24
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -123
- package/src/entities/ship-deploy.ts +0 -295
- package/src/entities/ship.ts +0 -221
- package/src/entities/warehouse.ts +0 -127
- package/src/types/entity-traits.ts +0 -69
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import {Name,
|
|
1
|
+
import {Name, UInt16, UInt32, UInt64} from '@wharfkit/antelope'
|
|
2
2
|
import {ServerContract} from '../contracts'
|
|
3
|
-
import {Coordinates,
|
|
3
|
+
import {Coordinates, TaskType} from '../types'
|
|
4
4
|
import {
|
|
5
|
-
capsHasLoaders,
|
|
6
5
|
capsHasMovement,
|
|
7
6
|
capsHasStorage,
|
|
8
7
|
type EntityCapabilities,
|
|
@@ -14,17 +13,19 @@ import {
|
|
|
14
13
|
RECIPE_INPUTS_INSUFFICIENT,
|
|
15
14
|
RECIPE_INPUTS_INVALID,
|
|
16
15
|
RECIPE_NOT_FOUND,
|
|
17
|
-
|
|
16
|
+
ENTITY_CARGO_NOT_LOADED,
|
|
18
17
|
} from '../errors'
|
|
19
|
-
import {getRecipe, type RecipeInput} from '../data/recipes-runtime'
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
18
|
+
import {getEntityLayout, getRecipe, type RecipeInput} from '../data/recipes-runtime'
|
|
19
|
+
import {computeEntityCapabilities} from '../derivation/capabilities'
|
|
20
|
+
import {decodeCraftedItemStats, decodeStat} from '../derivation/crafting'
|
|
21
|
+
import {packedModulesToInstalled, type InstalledModule} from '../entities/slot-multiplier'
|
|
22
|
+
import {lerp} from '../travel/travel'
|
|
22
23
|
import {
|
|
23
24
|
calcStacksMass,
|
|
24
25
|
cargoItemToStack,
|
|
25
26
|
type CargoStack,
|
|
26
27
|
mergeStacks,
|
|
27
|
-
|
|
28
|
+
subtractFromStacks,
|
|
28
29
|
stackToCargoItem,
|
|
29
30
|
} from '../capabilities/storage'
|
|
30
31
|
import * as schedule from './schedule'
|
|
@@ -37,15 +38,19 @@ export interface ProjectedEntity {
|
|
|
37
38
|
shipMass: UInt32
|
|
38
39
|
capacity?: UInt64
|
|
39
40
|
engines?: ServerContract.Types.movement_stats
|
|
40
|
-
|
|
41
|
+
loaderLanes: ServerContract.Types.loader_lane[]
|
|
41
42
|
generator?: ServerContract.Types.energy_stats
|
|
42
43
|
hauler?: ServerContract.Types.hauler_stats
|
|
44
|
+
launcher?: ServerContract.Types.launcher_stats
|
|
43
45
|
readonly cargoMass: UInt64
|
|
44
46
|
readonly totalMass: UInt64
|
|
47
|
+
readonly gathererLanes: ServerContract.Types.gatherer_lane[]
|
|
48
|
+
readonly crafterLanes: ServerContract.Types.crafter_lane[]
|
|
45
49
|
|
|
46
50
|
hasMovement(): boolean
|
|
47
51
|
hasStorage(): boolean
|
|
48
52
|
hasLoaders(): boolean
|
|
53
|
+
hasLauncher(): boolean
|
|
49
54
|
|
|
50
55
|
capabilities(): EntityCapabilities
|
|
51
56
|
state(): EntityState
|
|
@@ -57,25 +62,155 @@ export interface Projectable extends ScheduleData {
|
|
|
57
62
|
hullmass?: UInt32
|
|
58
63
|
generator?: ServerContract.Types.energy_stats
|
|
59
64
|
engines?: ServerContract.Types.movement_stats
|
|
60
|
-
|
|
65
|
+
loader_lanes?: ServerContract.Types.loader_lane[]
|
|
66
|
+
gatherer_lanes?: ServerContract.Types.gatherer_lane[]
|
|
67
|
+
crafter_lanes?: ServerContract.Types.crafter_lane[]
|
|
61
68
|
hauler?: ServerContract.Types.hauler_stats
|
|
69
|
+
launcher?: ServerContract.Types.launcher_stats
|
|
62
70
|
capacity?: UInt32
|
|
63
71
|
cargo: ServerContract.Types.cargo_item[]
|
|
64
72
|
cargomass: UInt32
|
|
65
73
|
owner?: Name
|
|
74
|
+
stats?: bigint
|
|
75
|
+
item_id?: number | UInt16
|
|
76
|
+
modules?: ServerContract.Types.module_entry[] | InstalledModule[]
|
|
66
77
|
}
|
|
67
78
|
|
|
68
|
-
function
|
|
69
|
-
|
|
79
|
+
function toInstalledModules(
|
|
80
|
+
modules: ServerContract.Types.module_entry[] | InstalledModule[]
|
|
81
|
+
): InstalledModule[] {
|
|
82
|
+
if (modules.length > 0 && 'itemId' in modules[0]) {
|
|
83
|
+
return modules as InstalledModule[]
|
|
84
|
+
}
|
|
85
|
+
return packedModulesToInstalled(modules as ServerContract.Types.module_entry[])
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
interface ProjectedCaps {
|
|
89
|
+
hullmass?: UInt32
|
|
90
|
+
capacity?: UInt32
|
|
91
|
+
engines?: ServerContract.Types.movement_stats
|
|
92
|
+
generator?: ServerContract.Types.energy_stats
|
|
93
|
+
loaderLanes: ServerContract.Types.loader_lane[]
|
|
94
|
+
gathererLanes: ServerContract.Types.gatherer_lane[]
|
|
95
|
+
crafterLanes: ServerContract.Types.crafter_lane[]
|
|
96
|
+
hauler?: ServerContract.Types.hauler_stats
|
|
97
|
+
launcher?: ServerContract.Types.launcher_stats
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function recomputeCaps(entity: Projectable): ProjectedCaps | undefined {
|
|
101
|
+
if (
|
|
102
|
+
entity.item_id === undefined ||
|
|
103
|
+
entity.modules === undefined ||
|
|
104
|
+
entity.stats === undefined
|
|
105
|
+
) {
|
|
106
|
+
return undefined
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const itemId = Number(
|
|
110
|
+
typeof entity.item_id === 'number' ? entity.item_id : entity.item_id.value
|
|
111
|
+
)
|
|
112
|
+
const hullStats = decodeCraftedItemStats(itemId, entity.stats)
|
|
113
|
+
if (hullStats.strength === undefined) hullStats.strength = decodeStat(entity.stats, 0)
|
|
114
|
+
if (hullStats.hardness === undefined) hullStats.hardness = decodeStat(entity.stats, 2)
|
|
115
|
+
const layout = getEntityLayout(itemId)?.slots ?? []
|
|
116
|
+
const installed = toInstalledModules(entity.modules)
|
|
117
|
+
const caps = computeEntityCapabilities(hullStats, itemId, installed, layout)
|
|
118
|
+
|
|
119
|
+
const toLoaderLane = (l: {
|
|
120
|
+
slotIndex: number
|
|
121
|
+
mass: number
|
|
122
|
+
thrust: number
|
|
123
|
+
outputPct: number
|
|
124
|
+
}): ServerContract.Types.loader_lane =>
|
|
125
|
+
ServerContract.Types.loader_lane.from({
|
|
126
|
+
slot_index: l.slotIndex,
|
|
127
|
+
mass: l.mass,
|
|
128
|
+
thrust: l.thrust,
|
|
129
|
+
output_pct: l.outputPct,
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const toGathererLane = (l: {
|
|
133
|
+
slotIndex: number
|
|
134
|
+
yield: number
|
|
135
|
+
drain: number
|
|
136
|
+
depth: number
|
|
137
|
+
outputPct: number
|
|
138
|
+
}): ServerContract.Types.gatherer_lane =>
|
|
139
|
+
ServerContract.Types.gatherer_lane.from({
|
|
140
|
+
slot_index: l.slotIndex,
|
|
141
|
+
yield: l.yield,
|
|
142
|
+
drain: l.drain,
|
|
143
|
+
depth: l.depth,
|
|
144
|
+
output_pct: l.outputPct,
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const toCrafterLane = (l: {
|
|
148
|
+
slotIndex: number
|
|
149
|
+
speed: number
|
|
150
|
+
drain: number
|
|
151
|
+
outputPct: number
|
|
152
|
+
}): ServerContract.Types.crafter_lane =>
|
|
153
|
+
ServerContract.Types.crafter_lane.from({
|
|
154
|
+
slot_index: l.slotIndex,
|
|
155
|
+
speed: l.speed,
|
|
156
|
+
drain: l.drain,
|
|
157
|
+
output_pct: l.outputPct,
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
return {
|
|
161
|
+
hullmass: UInt32.from(caps.hullmass),
|
|
162
|
+
capacity: UInt32.from(caps.capacity),
|
|
163
|
+
engines: caps.engines ? ServerContract.Types.movement_stats.from(caps.engines) : undefined,
|
|
164
|
+
generator: caps.generator
|
|
165
|
+
? ServerContract.Types.energy_stats.from(caps.generator)
|
|
166
|
+
: undefined,
|
|
167
|
+
loaderLanes: (caps.loaderLanes ?? []).map(toLoaderLane),
|
|
168
|
+
gathererLanes: (caps.gathererLanes ?? []).map(toGathererLane),
|
|
169
|
+
crafterLanes: (caps.crafterLanes ?? []).map(toCrafterLane),
|
|
170
|
+
hauler: caps.hauler
|
|
171
|
+
? ServerContract.Types.hauler_stats.from({
|
|
172
|
+
capacity: caps.hauler.capacity,
|
|
173
|
+
efficiency: caps.hauler.efficiency,
|
|
174
|
+
drain: caps.hauler.drain,
|
|
175
|
+
capacity_by_tier: caps.hauler.capacityByTier,
|
|
176
|
+
})
|
|
177
|
+
: undefined,
|
|
178
|
+
launcher: caps.launcher
|
|
179
|
+
? ServerContract.Types.launcher_stats.from({
|
|
180
|
+
charge_rate: caps.launcher.chargeRate,
|
|
181
|
+
velocity: caps.launcher.velocity,
|
|
182
|
+
drain: caps.launcher.drain,
|
|
183
|
+
})
|
|
184
|
+
: undefined,
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function loaderLanesTotalMass(lanes: ServerContract.Types.loader_lane[]): UInt64 {
|
|
189
|
+
let total = 0
|
|
190
|
+
for (const l of lanes) total += Number(l.mass)
|
|
191
|
+
return UInt64.from(total)
|
|
70
192
|
}
|
|
71
193
|
|
|
72
194
|
export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
195
|
+
const needsRecompute =
|
|
196
|
+
entity.hullmass === undefined ||
|
|
197
|
+
entity.loader_lanes === undefined ||
|
|
198
|
+
entity.engines === undefined ||
|
|
199
|
+
entity.generator === undefined ||
|
|
200
|
+
entity.hauler === undefined ||
|
|
201
|
+
entity.launcher === undefined ||
|
|
202
|
+
entity.capacity === undefined
|
|
203
|
+
const caps = needsRecompute ? recomputeCaps(entity) : undefined
|
|
204
|
+
|
|
205
|
+
const shipMass = UInt32.from(entity.hullmass ?? caps?.hullmass ?? 0)
|
|
206
|
+
const loaderLanes = entity.loader_lanes ?? caps?.loaderLanes ?? []
|
|
207
|
+
const gathererLanes = entity.gatherer_lanes ?? caps?.gathererLanes ?? []
|
|
208
|
+
const crafterLanes = entity.crafter_lanes ?? caps?.crafterLanes ?? []
|
|
209
|
+
const engines = entity.engines ?? caps?.engines
|
|
210
|
+
const generator = entity.generator ?? caps?.generator
|
|
211
|
+
const hauler = entity.hauler ?? caps?.hauler
|
|
212
|
+
const launcher = entity.launcher ?? caps?.launcher
|
|
213
|
+
const capacity = entity.capacity ?? caps?.capacity
|
|
79
214
|
|
|
80
215
|
const cargo: CargoStack[] = entity.cargo.map(cargoItemToStack)
|
|
81
216
|
|
|
@@ -88,18 +223,19 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
88
223
|
engines,
|
|
89
224
|
generator,
|
|
90
225
|
hauler,
|
|
91
|
-
|
|
226
|
+
launcher,
|
|
227
|
+
loaderLanes,
|
|
228
|
+
gathererLanes,
|
|
229
|
+
crafterLanes,
|
|
92
230
|
|
|
93
231
|
get cargoMass() {
|
|
94
232
|
return calcStacksMass(this.cargo)
|
|
95
233
|
},
|
|
96
234
|
|
|
97
235
|
get totalMass() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
return mass
|
|
236
|
+
return UInt64.from(this.shipMass)
|
|
237
|
+
.adding(this.cargoMass)
|
|
238
|
+
.adding(loaderLanesTotalMass(this.loaderLanes))
|
|
103
239
|
},
|
|
104
240
|
|
|
105
241
|
hasMovement() {
|
|
@@ -111,7 +247,11 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
111
247
|
},
|
|
112
248
|
|
|
113
249
|
hasLoaders() {
|
|
114
|
-
return
|
|
250
|
+
return this.loaderLanes.length > 0
|
|
251
|
+
},
|
|
252
|
+
|
|
253
|
+
hasLauncher() {
|
|
254
|
+
return this.launcher !== undefined
|
|
115
255
|
},
|
|
116
256
|
|
|
117
257
|
capabilities(): EntityCapabilities {
|
|
@@ -120,7 +260,7 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
120
260
|
capacity: this.capacity ? UInt32.from(this.capacity) : undefined,
|
|
121
261
|
engines: this.engines,
|
|
122
262
|
generator: this.generator,
|
|
123
|
-
|
|
263
|
+
launcher: this.launcher,
|
|
124
264
|
}
|
|
125
265
|
},
|
|
126
266
|
|
|
@@ -160,25 +300,22 @@ function applyFlightTask(
|
|
|
160
300
|
task: ServerContract.Types.task,
|
|
161
301
|
options: {complete: boolean; progress?: number}
|
|
162
302
|
): void {
|
|
163
|
-
if (!task.coordinates
|
|
303
|
+
if (!task.coordinates) return
|
|
164
304
|
|
|
165
|
-
const origin = projected.location
|
|
166
305
|
const destination = Coordinates.from(task.coordinates)
|
|
167
|
-
const distance = distanceBetweenCoordinates(origin, task.coordinates)
|
|
168
|
-
const energyUsage = distance.dividing(PRECISION).multiplying(projected.engines.drain)
|
|
169
306
|
|
|
170
307
|
if (options.complete) {
|
|
171
|
-
projected
|
|
172
|
-
? UInt16.from(projected.energy.subtracting(energyUsage))
|
|
173
|
-
: UInt16.from(0)
|
|
308
|
+
applyEnergyCost(projected, task)
|
|
174
309
|
projected.location = destination
|
|
175
310
|
} else if (options.progress !== undefined) {
|
|
176
|
-
const interpolated = lerp(
|
|
311
|
+
const interpolated = lerp(projected.location, destination, options.progress)
|
|
177
312
|
projected.location = Coordinates.from({
|
|
178
313
|
x: Math.round(interpolated.x),
|
|
179
314
|
y: Math.round(interpolated.y),
|
|
180
315
|
})
|
|
181
|
-
const partialEnergy = UInt64.from(
|
|
316
|
+
const partialEnergy = UInt64.from(
|
|
317
|
+
Math.floor(Number(task.energy_cost ?? 0) * options.progress)
|
|
318
|
+
)
|
|
182
319
|
projected.energy = projected.energy.gt(partialEnergy)
|
|
183
320
|
? UInt16.from(projected.energy.subtracting(partialEnergy))
|
|
184
321
|
: UInt16.from(0)
|
|
@@ -190,7 +327,7 @@ function addCargoItem(projected: ProjectedEntity, item: ServerContract.Types.car
|
|
|
190
327
|
}
|
|
191
328
|
|
|
192
329
|
function removeCargoItem(projected: ProjectedEntity, item: ServerContract.Types.cargo_item): void {
|
|
193
|
-
projected.cargo =
|
|
330
|
+
projected.cargo = subtractFromStacks(projected.cargo, cargoItemToStack(item))
|
|
194
331
|
}
|
|
195
332
|
|
|
196
333
|
function applyAddCargoTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
@@ -248,6 +385,8 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
248
385
|
applyRechargeTask(projected, task, {complete: true})
|
|
249
386
|
break
|
|
250
387
|
case TaskType.TRAVEL:
|
|
388
|
+
case TaskType.WARP:
|
|
389
|
+
case TaskType.TRANSIT:
|
|
251
390
|
applyFlightTask(projected, task, {complete: true})
|
|
252
391
|
break
|
|
253
392
|
case TaskType.LOAD:
|
|
@@ -255,7 +394,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
255
394
|
applyAddCargoTask(projected, task)
|
|
256
395
|
break
|
|
257
396
|
case TaskType.UNLOAD:
|
|
258
|
-
case TaskType.WRAP:
|
|
259
397
|
applyRemoveCargoTask(projected, task)
|
|
260
398
|
break
|
|
261
399
|
case TaskType.GATHER:
|
|
@@ -268,7 +406,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
268
406
|
applyDeployTask(projected, task)
|
|
269
407
|
break
|
|
270
408
|
case TaskType.UNDEPLOY:
|
|
271
|
-
case TaskType.WRAP_ENTITY:
|
|
272
409
|
case TaskType.DEMOLISH:
|
|
273
410
|
break
|
|
274
411
|
}
|
|
@@ -280,50 +417,27 @@ export interface ProjectionOptions {
|
|
|
280
417
|
|
|
281
418
|
export function projectEntity(entity: Projectable, options?: ProjectionOptions): ProjectedEntity {
|
|
282
419
|
const projected = createProjectedEntity(entity)
|
|
283
|
-
|
|
420
|
+
const ordered = schedule.orderedTasks(entity)
|
|
421
|
+
if (ordered.length === 0) return projected
|
|
284
422
|
|
|
285
|
-
const tasks = entity.schedule.tasks
|
|
286
423
|
const taskCount =
|
|
287
424
|
options?.upToTaskIndex !== undefined
|
|
288
|
-
? Math.max(0, Math.min(options.upToTaskIndex,
|
|
289
|
-
:
|
|
425
|
+
? Math.max(0, Math.min(options.upToTaskIndex, ordered.length))
|
|
426
|
+
: ordered.length
|
|
290
427
|
|
|
291
428
|
for (let i = 0; i < taskCount; i++) {
|
|
292
|
-
applyTask(projected,
|
|
429
|
+
applyTask(projected, ordered[i].task)
|
|
293
430
|
}
|
|
294
431
|
return projected
|
|
295
432
|
}
|
|
296
433
|
|
|
297
|
-
export
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function buildRemainingProjectable(snapshot: ProjectableSnapshot): Projectable | null {
|
|
303
|
-
if (!snapshot.schedule) return null
|
|
304
|
-
const remainingTasks: ServerContract.Types.task[] = []
|
|
305
|
-
if (snapshot.current_task) remainingTasks.push(snapshot.current_task)
|
|
306
|
-
if (snapshot.pending_tasks?.length) remainingTasks.push(...snapshot.pending_tasks)
|
|
307
|
-
if (remainingTasks.length === 0) return null
|
|
308
|
-
|
|
309
|
-
const completedCount = snapshot.schedule.tasks.length - remainingTasks.length
|
|
310
|
-
let startedMs = snapshot.schedule.started.toMilliseconds()
|
|
311
|
-
for (let i = 0; i < completedCount; i++) {
|
|
312
|
-
startedMs += snapshot.schedule.tasks[i].duration.toNumber() * 1000
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
return {
|
|
316
|
-
...snapshot,
|
|
317
|
-
schedule: ServerContract.Types.schedule.from({
|
|
318
|
-
started: TimePoint.fromMilliseconds(startedMs),
|
|
319
|
-
tasks: remainingTasks,
|
|
320
|
-
}),
|
|
434
|
+
export function projectRemainingAt(entity: Projectable, _now: Date): ProjectedEntity {
|
|
435
|
+
// Resolve is lazy/entity-global: completed tasks are unsettled until resolve, so replay all.
|
|
436
|
+
const projected = createProjectedEntity(entity)
|
|
437
|
+
for (const {task} of schedule.orderedTasks(entity)) {
|
|
438
|
+
applyTask(projected, task)
|
|
321
439
|
}
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
export function projectFromCurrentState(snapshot: ProjectableSnapshot): ProjectedEntity {
|
|
325
|
-
const projectable = buildRemainingProjectable(snapshot)
|
|
326
|
-
return projectable ? projectEntity(projectable) : createProjectedEntity(snapshot)
|
|
440
|
+
return projected
|
|
327
441
|
}
|
|
328
442
|
|
|
329
443
|
function getRecipeInputsForOutput(outputItemId: number): RecipeInput[] | undefined {
|
|
@@ -346,19 +460,10 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
|
|
|
346
460
|
let matched = false
|
|
347
461
|
for (let ri = 0; ri < recipe.length; ri++) {
|
|
348
462
|
const req = recipe[ri]
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
break
|
|
354
|
-
}
|
|
355
|
-
} else {
|
|
356
|
-
const item = getItem(input.item_id)
|
|
357
|
-
if (item.category === req.category && item.tier === req.tier) {
|
|
358
|
-
groupedInputs[ri].push(input)
|
|
359
|
-
matched = true
|
|
360
|
-
break
|
|
361
|
-
}
|
|
463
|
+
if (input.item_id.toNumber() === req.itemId) {
|
|
464
|
+
groupedInputs[ri].push(input)
|
|
465
|
+
matched = true
|
|
466
|
+
break
|
|
362
467
|
}
|
|
363
468
|
}
|
|
364
469
|
if (!matched) throw new Error(RECIPE_INPUTS_INVALID)
|
|
@@ -389,15 +494,16 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
|
|
|
389
494
|
break
|
|
390
495
|
}
|
|
391
496
|
}
|
|
392
|
-
if (!found) throw new Error(
|
|
497
|
+
if (!found) throw new Error(ENTITY_CARGO_NOT_LOADED)
|
|
393
498
|
}
|
|
394
499
|
}
|
|
395
500
|
|
|
396
501
|
export function validateSchedule(entity: Projectable): void {
|
|
397
|
-
|
|
502
|
+
const ordered = schedule.orderedTasks(entity)
|
|
503
|
+
if (ordered.length === 0) return
|
|
398
504
|
|
|
399
505
|
const projected = createProjectedEntity(entity)
|
|
400
|
-
for (const task of
|
|
506
|
+
for (const {task} of ordered) {
|
|
401
507
|
if (task.type.toNumber() === TaskType.CRAFT) {
|
|
402
508
|
validateCraftTask(task, projected)
|
|
403
509
|
}
|
|
@@ -411,28 +517,35 @@ export function validateSchedule(entity: Projectable): void {
|
|
|
411
517
|
export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity {
|
|
412
518
|
const projected = createProjectedEntity(entity)
|
|
413
519
|
|
|
414
|
-
|
|
520
|
+
const ordered = schedule.orderedTasks(entity)
|
|
521
|
+
if (ordered.length === 0) {
|
|
415
522
|
return projected
|
|
416
523
|
}
|
|
417
524
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
const
|
|
525
|
+
const nowMs = now.getTime()
|
|
526
|
+
|
|
527
|
+
for (const {task, startsAt} of ordered) {
|
|
528
|
+
const duration = task.duration.toNumber()
|
|
529
|
+
const elapsed = Math.min(
|
|
530
|
+
Math.max(0, Math.floor((nowMs - startsAt.getTime()) / 1000)),
|
|
531
|
+
duration
|
|
532
|
+
)
|
|
533
|
+
const taskComplete = elapsed >= duration
|
|
534
|
+
const taskInProgress = elapsed > 0 && elapsed < duration
|
|
422
535
|
|
|
423
536
|
if (!taskComplete && !taskInProgress) {
|
|
424
|
-
|
|
537
|
+
continue
|
|
425
538
|
}
|
|
426
539
|
|
|
427
|
-
const progress = taskInProgress
|
|
428
|
-
? schedule.getTaskElapsed(entity, i, now) / task.duration.toNumber()
|
|
429
|
-
: undefined
|
|
540
|
+
const progress = taskInProgress ? elapsed / duration : undefined
|
|
430
541
|
|
|
431
542
|
switch (task.type.toNumber()) {
|
|
432
543
|
case TaskType.RECHARGE:
|
|
433
544
|
applyRechargeTask(projected, task, {complete: taskComplete, progress})
|
|
434
545
|
break
|
|
435
546
|
case TaskType.TRAVEL:
|
|
547
|
+
case TaskType.WARP:
|
|
548
|
+
case TaskType.TRANSIT:
|
|
436
549
|
applyFlightTask(projected, task, {complete: taskComplete, progress})
|
|
437
550
|
break
|
|
438
551
|
case TaskType.LOAD:
|
|
@@ -440,7 +553,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
440
553
|
if (taskComplete) applyAddCargoTask(projected, task)
|
|
441
554
|
break
|
|
442
555
|
case TaskType.UNLOAD:
|
|
443
|
-
case TaskType.WRAP:
|
|
444
556
|
if (taskComplete) applyRemoveCargoTask(projected, task)
|
|
445
557
|
break
|
|
446
558
|
case TaskType.GATHER:
|
|
@@ -453,7 +565,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
453
565
|
if (taskComplete) applyDeployTask(projected, task)
|
|
454
566
|
break
|
|
455
567
|
case TaskType.UNDEPLOY:
|
|
456
|
-
case TaskType.WRAP_ENTITY:
|
|
457
568
|
case TaskType.DEMOLISH:
|
|
458
569
|
break
|
|
459
570
|
}
|
|
@@ -461,11 +572,3 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
461
572
|
|
|
462
573
|
return projected
|
|
463
574
|
}
|
|
464
|
-
|
|
465
|
-
export function projectFromCurrentStateAt(
|
|
466
|
-
snapshot: ProjectableSnapshot,
|
|
467
|
-
now: Date
|
|
468
|
-
): ProjectedEntity {
|
|
469
|
-
const projectable = buildRemainingProjectable(snapshot)
|
|
470
|
-
return projectable ? projectEntityAt(projectable, now) : createProjectedEntity(snapshot)
|
|
471
|
-
}
|