@shipload/sdk 1.0.0-next.4 → 1.0.0-next.40
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 +2473 -973
- package/lib/shipload.js +11529 -5211
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +11338 -5162
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +970 -0
- package/lib/testing.js +4013 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +4007 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +15 -2
- package/src/capabilities/craftable.ts +51 -0
- package/src/capabilities/crafting.test.ts +7 -0
- package/src/capabilities/crafting.ts +5 -6
- package/src/capabilities/gathering.test.ts +16 -0
- package/src/capabilities/gathering.ts +35 -18
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +9 -0
- package/src/capabilities/storage.ts +16 -1
- package/src/contracts/platform.ts +231 -3
- package/src/contracts/server.ts +1021 -481
- 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 +12 -5
- package/src/data/capability-formulas.ts +14 -7
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +14 -47
- package/src/data/entities.json +76 -10
- package/src/data/item-ids.ts +18 -12
- package/src/data/items.json +321 -38
- package/src/data/kind-registry.json +109 -0
- package/src/data/kind-registry.ts +165 -0
- package/src/data/metadata.ts +119 -33
- package/src/data/recipes-runtime.ts +3 -23
- package/src/data/recipes.json +238 -117
- package/src/derivation/build-methods.ts +45 -0
- package/src/derivation/capabilities.test.ts +151 -0
- package/src/derivation/capabilities.ts +512 -0
- package/src/derivation/capability-mappings.ts +9 -12
- package/src/derivation/crafting.ts +23 -24
- package/src/derivation/index.ts +25 -2
- package/src/derivation/recipe-usage.test.ts +78 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +125 -38
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +56 -0
- package/src/derivation/stars.test.ts +51 -0
- package/src/derivation/stars.ts +15 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/stratum.ts +17 -20
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/wormhole.ts +136 -0
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +124 -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 +267 -47
- package/src/managers/actions.ts +528 -95
- package/src/managers/base.ts +6 -2
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +412 -0
- package/src/managers/context.ts +20 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +18 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/index.ts +17 -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/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 +338 -0
- package/src/nft/description.ts +98 -24
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +127 -0
- package/src/planner/planner.test.ts +319 -0
- package/src/resolution/describe-module.ts +18 -13
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.test.ts +37 -0
- package/src/resolution/resolve-item.ts +55 -24
- package/src/scheduling/accessor.ts +68 -22
- 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 +209 -105
- package/src/scheduling/schedule.ts +241 -104
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/shipload.ts +21 -1
- package/src/subscriptions/manager.ts +229 -142
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +11 -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 +196 -0
- package/src/travel/travel.ts +200 -112
- 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 +28 -13
- package/src/utils/cargo.ts +27 -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 -108
- package/src/entities/ship-deploy.ts +0 -259
- package/src/entities/ship.ts +0 -204
- package/src/entities/warehouse.ts +0 -119
- 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,148 @@ 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 ? ServerContract.Types.hauler_stats.from(caps.hauler) : undefined,
|
|
171
|
+
launcher: caps.launcher
|
|
172
|
+
? ServerContract.Types.launcher_stats.from({
|
|
173
|
+
charge_rate: caps.launcher.chargeRate,
|
|
174
|
+
velocity: caps.launcher.velocity,
|
|
175
|
+
drain: caps.launcher.drain,
|
|
176
|
+
})
|
|
177
|
+
: undefined,
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function loaderLanesTotalMass(lanes: ServerContract.Types.loader_lane[]): UInt64 {
|
|
182
|
+
let total = 0
|
|
183
|
+
for (const l of lanes) total += Number(l.mass)
|
|
184
|
+
return UInt64.from(total)
|
|
70
185
|
}
|
|
71
186
|
|
|
72
187
|
export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
188
|
+
const needsRecompute =
|
|
189
|
+
entity.hullmass === undefined ||
|
|
190
|
+
entity.loader_lanes === undefined ||
|
|
191
|
+
entity.engines === undefined ||
|
|
192
|
+
entity.generator === undefined ||
|
|
193
|
+
entity.hauler === undefined ||
|
|
194
|
+
entity.launcher === undefined ||
|
|
195
|
+
entity.capacity === undefined
|
|
196
|
+
const caps = needsRecompute ? recomputeCaps(entity) : undefined
|
|
197
|
+
|
|
198
|
+
const shipMass = UInt32.from(entity.hullmass ?? caps?.hullmass ?? 0)
|
|
199
|
+
const loaderLanes = entity.loader_lanes ?? caps?.loaderLanes ?? []
|
|
200
|
+
const gathererLanes = entity.gatherer_lanes ?? caps?.gathererLanes ?? []
|
|
201
|
+
const crafterLanes = entity.crafter_lanes ?? caps?.crafterLanes ?? []
|
|
202
|
+
const engines = entity.engines ?? caps?.engines
|
|
203
|
+
const generator = entity.generator ?? caps?.generator
|
|
204
|
+
const hauler = entity.hauler ?? caps?.hauler
|
|
205
|
+
const launcher = entity.launcher ?? caps?.launcher
|
|
206
|
+
const capacity = entity.capacity ?? caps?.capacity
|
|
79
207
|
|
|
80
208
|
const cargo: CargoStack[] = entity.cargo.map(cargoItemToStack)
|
|
81
209
|
|
|
@@ -88,18 +216,19 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
88
216
|
engines,
|
|
89
217
|
generator,
|
|
90
218
|
hauler,
|
|
91
|
-
|
|
219
|
+
launcher,
|
|
220
|
+
loaderLanes,
|
|
221
|
+
gathererLanes,
|
|
222
|
+
crafterLanes,
|
|
92
223
|
|
|
93
224
|
get cargoMass() {
|
|
94
225
|
return calcStacksMass(this.cargo)
|
|
95
226
|
},
|
|
96
227
|
|
|
97
228
|
get totalMass() {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
return mass
|
|
229
|
+
return UInt64.from(this.shipMass)
|
|
230
|
+
.adding(this.cargoMass)
|
|
231
|
+
.adding(loaderLanesTotalMass(this.loaderLanes))
|
|
103
232
|
},
|
|
104
233
|
|
|
105
234
|
hasMovement() {
|
|
@@ -111,7 +240,11 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
111
240
|
},
|
|
112
241
|
|
|
113
242
|
hasLoaders() {
|
|
114
|
-
return
|
|
243
|
+
return this.loaderLanes.length > 0
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
hasLauncher() {
|
|
247
|
+
return this.launcher !== undefined
|
|
115
248
|
},
|
|
116
249
|
|
|
117
250
|
capabilities(): EntityCapabilities {
|
|
@@ -120,7 +253,7 @@ export function createProjectedEntity(entity: Projectable): ProjectedEntity {
|
|
|
120
253
|
capacity: this.capacity ? UInt32.from(this.capacity) : undefined,
|
|
121
254
|
engines: this.engines,
|
|
122
255
|
generator: this.generator,
|
|
123
|
-
|
|
256
|
+
launcher: this.launcher,
|
|
124
257
|
}
|
|
125
258
|
},
|
|
126
259
|
|
|
@@ -160,25 +293,22 @@ function applyFlightTask(
|
|
|
160
293
|
task: ServerContract.Types.task,
|
|
161
294
|
options: {complete: boolean; progress?: number}
|
|
162
295
|
): void {
|
|
163
|
-
if (!task.coordinates
|
|
296
|
+
if (!task.coordinates) return
|
|
164
297
|
|
|
165
|
-
const origin = projected.location
|
|
166
298
|
const destination = Coordinates.from(task.coordinates)
|
|
167
|
-
const distance = distanceBetweenCoordinates(origin, task.coordinates)
|
|
168
|
-
const energyUsage = distance.dividing(PRECISION).multiplying(projected.engines.drain)
|
|
169
299
|
|
|
170
300
|
if (options.complete) {
|
|
171
|
-
projected
|
|
172
|
-
? UInt16.from(projected.energy.subtracting(energyUsage))
|
|
173
|
-
: UInt16.from(0)
|
|
301
|
+
applyEnergyCost(projected, task)
|
|
174
302
|
projected.location = destination
|
|
175
303
|
} else if (options.progress !== undefined) {
|
|
176
|
-
const interpolated = lerp(
|
|
304
|
+
const interpolated = lerp(projected.location, destination, options.progress)
|
|
177
305
|
projected.location = Coordinates.from({
|
|
178
306
|
x: Math.round(interpolated.x),
|
|
179
307
|
y: Math.round(interpolated.y),
|
|
180
308
|
})
|
|
181
|
-
const partialEnergy = UInt64.from(
|
|
309
|
+
const partialEnergy = UInt64.from(
|
|
310
|
+
Math.floor(Number(task.energy_cost ?? 0) * options.progress)
|
|
311
|
+
)
|
|
182
312
|
projected.energy = projected.energy.gt(partialEnergy)
|
|
183
313
|
? UInt16.from(projected.energy.subtracting(partialEnergy))
|
|
184
314
|
: UInt16.from(0)
|
|
@@ -190,7 +320,7 @@ function addCargoItem(projected: ProjectedEntity, item: ServerContract.Types.car
|
|
|
190
320
|
}
|
|
191
321
|
|
|
192
322
|
function removeCargoItem(projected: ProjectedEntity, item: ServerContract.Types.cargo_item): void {
|
|
193
|
-
projected.cargo =
|
|
323
|
+
projected.cargo = subtractFromStacks(projected.cargo, cargoItemToStack(item))
|
|
194
324
|
}
|
|
195
325
|
|
|
196
326
|
function applyAddCargoTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
@@ -248,6 +378,8 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
248
378
|
applyRechargeTask(projected, task, {complete: true})
|
|
249
379
|
break
|
|
250
380
|
case TaskType.TRAVEL:
|
|
381
|
+
case TaskType.WARP:
|
|
382
|
+
case TaskType.TRANSIT:
|
|
251
383
|
applyFlightTask(projected, task, {complete: true})
|
|
252
384
|
break
|
|
253
385
|
case TaskType.LOAD:
|
|
@@ -255,7 +387,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
255
387
|
applyAddCargoTask(projected, task)
|
|
256
388
|
break
|
|
257
389
|
case TaskType.UNLOAD:
|
|
258
|
-
case TaskType.WRAP:
|
|
259
390
|
applyRemoveCargoTask(projected, task)
|
|
260
391
|
break
|
|
261
392
|
case TaskType.GATHER:
|
|
@@ -267,6 +398,9 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
267
398
|
case TaskType.DEPLOY:
|
|
268
399
|
applyDeployTask(projected, task)
|
|
269
400
|
break
|
|
401
|
+
case TaskType.UNDEPLOY:
|
|
402
|
+
case TaskType.DEMOLISH:
|
|
403
|
+
break
|
|
270
404
|
}
|
|
271
405
|
}
|
|
272
406
|
|
|
@@ -276,50 +410,27 @@ export interface ProjectionOptions {
|
|
|
276
410
|
|
|
277
411
|
export function projectEntity(entity: Projectable, options?: ProjectionOptions): ProjectedEntity {
|
|
278
412
|
const projected = createProjectedEntity(entity)
|
|
279
|
-
|
|
413
|
+
const ordered = schedule.orderedTasks(entity)
|
|
414
|
+
if (ordered.length === 0) return projected
|
|
280
415
|
|
|
281
|
-
const tasks = entity.schedule.tasks
|
|
282
416
|
const taskCount =
|
|
283
417
|
options?.upToTaskIndex !== undefined
|
|
284
|
-
? Math.max(0, Math.min(options.upToTaskIndex,
|
|
285
|
-
:
|
|
418
|
+
? Math.max(0, Math.min(options.upToTaskIndex, ordered.length))
|
|
419
|
+
: ordered.length
|
|
286
420
|
|
|
287
421
|
for (let i = 0; i < taskCount; i++) {
|
|
288
|
-
applyTask(projected,
|
|
422
|
+
applyTask(projected, ordered[i].task)
|
|
289
423
|
}
|
|
290
424
|
return projected
|
|
291
425
|
}
|
|
292
426
|
|
|
293
|
-
export
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function buildRemainingProjectable(snapshot: ProjectableSnapshot): Projectable | null {
|
|
299
|
-
if (!snapshot.schedule) return null
|
|
300
|
-
const remainingTasks: ServerContract.Types.task[] = []
|
|
301
|
-
if (snapshot.current_task) remainingTasks.push(snapshot.current_task)
|
|
302
|
-
if (snapshot.pending_tasks?.length) remainingTasks.push(...snapshot.pending_tasks)
|
|
303
|
-
if (remainingTasks.length === 0) return null
|
|
304
|
-
|
|
305
|
-
const completedCount = snapshot.schedule.tasks.length - remainingTasks.length
|
|
306
|
-
let startedMs = snapshot.schedule.started.toMilliseconds()
|
|
307
|
-
for (let i = 0; i < completedCount; i++) {
|
|
308
|
-
startedMs += snapshot.schedule.tasks[i].duration.toNumber() * 1000
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
return {
|
|
312
|
-
...snapshot,
|
|
313
|
-
schedule: ServerContract.Types.schedule.from({
|
|
314
|
-
started: TimePoint.fromMilliseconds(startedMs),
|
|
315
|
-
tasks: remainingTasks,
|
|
316
|
-
}),
|
|
427
|
+
export function projectRemainingAt(entity: Projectable, _now: Date): ProjectedEntity {
|
|
428
|
+
// Resolve is lazy/entity-global: completed tasks are unsettled until resolve, so replay all.
|
|
429
|
+
const projected = createProjectedEntity(entity)
|
|
430
|
+
for (const {task} of schedule.orderedTasks(entity)) {
|
|
431
|
+
applyTask(projected, task)
|
|
317
432
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
export function projectFromCurrentState(snapshot: ProjectableSnapshot): ProjectedEntity {
|
|
321
|
-
const projectable = buildRemainingProjectable(snapshot)
|
|
322
|
-
return projectable ? projectEntity(projectable) : createProjectedEntity(snapshot)
|
|
433
|
+
return projected
|
|
323
434
|
}
|
|
324
435
|
|
|
325
436
|
function getRecipeInputsForOutput(outputItemId: number): RecipeInput[] | undefined {
|
|
@@ -342,19 +453,10 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
|
|
|
342
453
|
let matched = false
|
|
343
454
|
for (let ri = 0; ri < recipe.length; ri++) {
|
|
344
455
|
const req = recipe[ri]
|
|
345
|
-
if (
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
break
|
|
350
|
-
}
|
|
351
|
-
} else {
|
|
352
|
-
const item = getItem(input.item_id)
|
|
353
|
-
if (item.category === req.category && item.tier === req.tier) {
|
|
354
|
-
groupedInputs[ri].push(input)
|
|
355
|
-
matched = true
|
|
356
|
-
break
|
|
357
|
-
}
|
|
456
|
+
if (input.item_id.toNumber() === req.itemId) {
|
|
457
|
+
groupedInputs[ri].push(input)
|
|
458
|
+
matched = true
|
|
459
|
+
break
|
|
358
460
|
}
|
|
359
461
|
}
|
|
360
462
|
if (!matched) throw new Error(RECIPE_INPUTS_INVALID)
|
|
@@ -385,15 +487,16 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
|
|
|
385
487
|
break
|
|
386
488
|
}
|
|
387
489
|
}
|
|
388
|
-
if (!found) throw new Error(
|
|
490
|
+
if (!found) throw new Error(ENTITY_CARGO_NOT_LOADED)
|
|
389
491
|
}
|
|
390
492
|
}
|
|
391
493
|
|
|
392
494
|
export function validateSchedule(entity: Projectable): void {
|
|
393
|
-
|
|
495
|
+
const ordered = schedule.orderedTasks(entity)
|
|
496
|
+
if (ordered.length === 0) return
|
|
394
497
|
|
|
395
498
|
const projected = createProjectedEntity(entity)
|
|
396
|
-
for (const task of
|
|
499
|
+
for (const {task} of ordered) {
|
|
397
500
|
if (task.type.toNumber() === TaskType.CRAFT) {
|
|
398
501
|
validateCraftTask(task, projected)
|
|
399
502
|
}
|
|
@@ -407,28 +510,35 @@ export function validateSchedule(entity: Projectable): void {
|
|
|
407
510
|
export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity {
|
|
408
511
|
const projected = createProjectedEntity(entity)
|
|
409
512
|
|
|
410
|
-
|
|
513
|
+
const ordered = schedule.orderedTasks(entity)
|
|
514
|
+
if (ordered.length === 0) {
|
|
411
515
|
return projected
|
|
412
516
|
}
|
|
413
517
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
const
|
|
518
|
+
const nowMs = now.getTime()
|
|
519
|
+
|
|
520
|
+
for (const {task, startsAt} of ordered) {
|
|
521
|
+
const duration = task.duration.toNumber()
|
|
522
|
+
const elapsed = Math.min(
|
|
523
|
+
Math.max(0, Math.floor((nowMs - startsAt.getTime()) / 1000)),
|
|
524
|
+
duration
|
|
525
|
+
)
|
|
526
|
+
const taskComplete = elapsed >= duration
|
|
527
|
+
const taskInProgress = elapsed > 0 && elapsed < duration
|
|
418
528
|
|
|
419
529
|
if (!taskComplete && !taskInProgress) {
|
|
420
|
-
|
|
530
|
+
continue
|
|
421
531
|
}
|
|
422
532
|
|
|
423
|
-
const progress = taskInProgress
|
|
424
|
-
? schedule.getTaskElapsed(entity, i, now) / task.duration.toNumber()
|
|
425
|
-
: undefined
|
|
533
|
+
const progress = taskInProgress ? elapsed / duration : undefined
|
|
426
534
|
|
|
427
535
|
switch (task.type.toNumber()) {
|
|
428
536
|
case TaskType.RECHARGE:
|
|
429
537
|
applyRechargeTask(projected, task, {complete: taskComplete, progress})
|
|
430
538
|
break
|
|
431
539
|
case TaskType.TRAVEL:
|
|
540
|
+
case TaskType.WARP:
|
|
541
|
+
case TaskType.TRANSIT:
|
|
432
542
|
applyFlightTask(projected, task, {complete: taskComplete, progress})
|
|
433
543
|
break
|
|
434
544
|
case TaskType.LOAD:
|
|
@@ -436,7 +546,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
436
546
|
if (taskComplete) applyAddCargoTask(projected, task)
|
|
437
547
|
break
|
|
438
548
|
case TaskType.UNLOAD:
|
|
439
|
-
case TaskType.WRAP:
|
|
440
549
|
if (taskComplete) applyRemoveCargoTask(projected, task)
|
|
441
550
|
break
|
|
442
551
|
case TaskType.GATHER:
|
|
@@ -448,16 +557,11 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
448
557
|
case TaskType.DEPLOY:
|
|
449
558
|
if (taskComplete) applyDeployTask(projected, task)
|
|
450
559
|
break
|
|
560
|
+
case TaskType.UNDEPLOY:
|
|
561
|
+
case TaskType.DEMOLISH:
|
|
562
|
+
break
|
|
451
563
|
}
|
|
452
564
|
}
|
|
453
565
|
|
|
454
566
|
return projected
|
|
455
567
|
}
|
|
456
|
-
|
|
457
|
-
export function projectFromCurrentStateAt(
|
|
458
|
-
snapshot: ProjectableSnapshot,
|
|
459
|
-
now: Date
|
|
460
|
-
): ProjectedEntity {
|
|
461
|
-
const projectable = buildRemainingProjectable(snapshot)
|
|
462
|
-
return projectable ? projectEntityAt(projectable, now) : createProjectedEntity(snapshot)
|
|
463
|
-
}
|