@shipload/sdk 1.0.0-next.72 → 1.0.0-next.74
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 +576 -133
- package/lib/shipload.js +6019 -5114
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +6002 -5108
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +194 -52
- package/lib/testing.js +767 -468
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +767 -468
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts/server.ts +523 -143
- package/src/data/catalog.test.ts +81 -1
- package/src/data/catalog.ts +6 -4
- package/src/data/entities.json +2 -2
- package/src/data/metadata.ts +197 -363
- package/src/data/task-types.json +184 -0
- package/src/entities/makers.ts +2 -2
- package/src/index-module.ts +31 -2
- package/src/influence/civic-shuttle.test.ts +58 -0
- package/src/influence/civic-shuttle.ts +52 -6
- package/src/influence/duration.ts +0 -65
- package/src/influence/index.ts +4 -5
- package/src/influence/influence.test.ts +51 -136
- package/src/influence/valuation.ts +75 -0
- package/src/managers/actions.ts +49 -10
- package/src/managers/balances.test.ts +33 -0
- package/src/managers/balances.ts +15 -0
- package/src/managers/context.ts +50 -11
- package/src/managers/index.ts +14 -0
- package/src/managers/jobs.test.ts +82 -1
- package/src/managers/jobs.ts +41 -2
- package/src/managers/nft.test.ts +173 -1
- package/src/managers/nft.ts +35 -2
- package/src/managers/shuttle.test.ts +562 -0
- package/src/managers/shuttle.ts +397 -0
- package/src/resolution/resolve-item.ts +2 -2
- package/src/scheduling/availability.ts +10 -0
- package/src/scheduling/energy.ts +55 -1
- package/src/scheduling/jobs.test.ts +171 -1
- package/src/scheduling/jobs.ts +110 -13
- package/src/scheduling/projection.ts +2 -1
- package/src/scheduling/task-effects.ts +38 -0
- package/src/scheduling/unwrap.test.ts +60 -0
- package/src/scheduling/unwrap.ts +24 -8
- package/src/shipload.ts +23 -4
- package/src/types.ts +1 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
{
|
|
2
|
+
"types": [
|
|
3
|
+
{
|
|
4
|
+
"type": 0,
|
|
5
|
+
"positionBound": false,
|
|
6
|
+
"mobility": false,
|
|
7
|
+
"consumer": false,
|
|
8
|
+
"isTerminal": false,
|
|
9
|
+
"capsPlan": false,
|
|
10
|
+
"cargoEffectResolve": true
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"type": 1,
|
|
14
|
+
"positionBound": false,
|
|
15
|
+
"mobility": true,
|
|
16
|
+
"consumer": false,
|
|
17
|
+
"isTerminal": false,
|
|
18
|
+
"capsPlan": false,
|
|
19
|
+
"cargoEffectResolve": true
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
"type": 2,
|
|
23
|
+
"positionBound": false,
|
|
24
|
+
"mobility": false,
|
|
25
|
+
"consumer": false,
|
|
26
|
+
"isTerminal": false,
|
|
27
|
+
"capsPlan": false,
|
|
28
|
+
"cargoEffectResolve": true
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"type": 3,
|
|
32
|
+
"positionBound": true,
|
|
33
|
+
"mobility": false,
|
|
34
|
+
"consumer": false,
|
|
35
|
+
"isTerminal": false,
|
|
36
|
+
"capsPlan": false,
|
|
37
|
+
"cargoEffectResolve": true
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"type": 4,
|
|
41
|
+
"positionBound": true,
|
|
42
|
+
"mobility": false,
|
|
43
|
+
"consumer": true,
|
|
44
|
+
"isTerminal": false,
|
|
45
|
+
"capsPlan": false,
|
|
46
|
+
"cargoEffectResolve": true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"type": 5,
|
|
50
|
+
"positionBound": true,
|
|
51
|
+
"mobility": false,
|
|
52
|
+
"consumer": false,
|
|
53
|
+
"isTerminal": false,
|
|
54
|
+
"capsPlan": false,
|
|
55
|
+
"cargoEffectResolve": true
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": 6,
|
|
59
|
+
"positionBound": false,
|
|
60
|
+
"mobility": true,
|
|
61
|
+
"consumer": false,
|
|
62
|
+
"isTerminal": false,
|
|
63
|
+
"capsPlan": false,
|
|
64
|
+
"cargoEffectResolve": true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
"type": 7,
|
|
68
|
+
"positionBound": false,
|
|
69
|
+
"mobility": false,
|
|
70
|
+
"consumer": true,
|
|
71
|
+
"isTerminal": false,
|
|
72
|
+
"capsPlan": false,
|
|
73
|
+
"cargoEffectResolve": false
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"type": 9,
|
|
77
|
+
"positionBound": false,
|
|
78
|
+
"mobility": true,
|
|
79
|
+
"consumer": false,
|
|
80
|
+
"isTerminal": false,
|
|
81
|
+
"capsPlan": false,
|
|
82
|
+
"cargoEffectResolve": true
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
"type": 10,
|
|
86
|
+
"positionBound": false,
|
|
87
|
+
"mobility": false,
|
|
88
|
+
"consumer": false,
|
|
89
|
+
"isTerminal": false,
|
|
90
|
+
"capsPlan": false,
|
|
91
|
+
"cargoEffectResolve": false
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"type": 11,
|
|
95
|
+
"positionBound": false,
|
|
96
|
+
"mobility": false,
|
|
97
|
+
"consumer": false,
|
|
98
|
+
"isTerminal": true,
|
|
99
|
+
"capsPlan": true,
|
|
100
|
+
"cargoEffectResolve": false
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": 12,
|
|
104
|
+
"positionBound": false,
|
|
105
|
+
"mobility": false,
|
|
106
|
+
"consumer": false,
|
|
107
|
+
"isTerminal": false,
|
|
108
|
+
"capsPlan": false,
|
|
109
|
+
"cargoEffectResolve": true
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"type": 13,
|
|
113
|
+
"positionBound": false,
|
|
114
|
+
"mobility": false,
|
|
115
|
+
"consumer": false,
|
|
116
|
+
"isTerminal": true,
|
|
117
|
+
"capsPlan": true,
|
|
118
|
+
"cargoEffectResolve": false
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"type": 15,
|
|
122
|
+
"positionBound": true,
|
|
123
|
+
"mobility": false,
|
|
124
|
+
"consumer": false,
|
|
125
|
+
"isTerminal": false,
|
|
126
|
+
"capsPlan": false,
|
|
127
|
+
"cargoEffectResolve": false
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"type": 16,
|
|
131
|
+
"positionBound": false,
|
|
132
|
+
"mobility": false,
|
|
133
|
+
"consumer": false,
|
|
134
|
+
"isTerminal": false,
|
|
135
|
+
"capsPlan": false,
|
|
136
|
+
"cargoEffectResolve": true
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"type": 17,
|
|
140
|
+
"positionBound": true,
|
|
141
|
+
"mobility": false,
|
|
142
|
+
"consumer": true,
|
|
143
|
+
"isTerminal": false,
|
|
144
|
+
"capsPlan": false,
|
|
145
|
+
"cargoEffectResolve": false
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"type": 18,
|
|
149
|
+
"positionBound": true,
|
|
150
|
+
"mobility": false,
|
|
151
|
+
"consumer": false,
|
|
152
|
+
"isTerminal": false,
|
|
153
|
+
"capsPlan": false,
|
|
154
|
+
"cargoEffectResolve": true
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"type": 20,
|
|
158
|
+
"positionBound": false,
|
|
159
|
+
"mobility": false,
|
|
160
|
+
"consumer": true,
|
|
161
|
+
"isTerminal": false,
|
|
162
|
+
"capsPlan": false,
|
|
163
|
+
"cargoEffectResolve": false
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"type": 21,
|
|
167
|
+
"positionBound": true,
|
|
168
|
+
"mobility": false,
|
|
169
|
+
"consumer": true,
|
|
170
|
+
"isTerminal": false,
|
|
171
|
+
"capsPlan": false,
|
|
172
|
+
"cargoEffectResolve": false
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"type": 22,
|
|
176
|
+
"positionBound": true,
|
|
177
|
+
"mobility": false,
|
|
178
|
+
"consumer": false,
|
|
179
|
+
"isTerminal": false,
|
|
180
|
+
"capsPlan": false,
|
|
181
|
+
"cargoEffectResolve": false
|
|
182
|
+
}
|
|
183
|
+
]
|
|
184
|
+
}
|
package/src/entities/makers.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {getKindMeta, getTemplateMeta} from '../data/kind-registry'
|
|
|
6
6
|
import type {EntityTypeName} from '../data/kind-registry'
|
|
7
7
|
import {getEntityLayout} from '../data/recipes-runtime'
|
|
8
8
|
import type {EntitySlot} from '../data/recipes-runtime'
|
|
9
|
-
import {
|
|
9
|
+
import {getItemFamily} from '../data/metadata'
|
|
10
10
|
import {getItem} from '../data/catalog'
|
|
11
11
|
import {getModuleCapabilityType, moduleAccepts, moduleSlotTypeToCode} from '../capabilities/modules'
|
|
12
12
|
import {computeEntityCapabilities} from '../derivation/capabilities'
|
|
@@ -52,7 +52,7 @@ function assignModulesToSlots(
|
|
|
52
52
|
try {
|
|
53
53
|
modName = getItem(mod.itemId).name
|
|
54
54
|
} catch {
|
|
55
|
-
modName =
|
|
55
|
+
modName = getItemFamily(mod.itemId)?.name ?? `item ${mod.itemId}`
|
|
56
56
|
}
|
|
57
57
|
throw new Error(
|
|
58
58
|
`No compatible slot for module ${modName} (type ${modType}) on ${entityLabel}`
|
package/src/index-module.ts
CHANGED
|
@@ -62,6 +62,22 @@ export {
|
|
|
62
62
|
JobsManager,
|
|
63
63
|
InfluenceManager,
|
|
64
64
|
} from './managers'
|
|
65
|
+
export {
|
|
66
|
+
ShuttleManager,
|
|
67
|
+
rankShuttleOptions,
|
|
68
|
+
shuttleReasonCode,
|
|
69
|
+
shuttleCandidates,
|
|
70
|
+
BOOKING_LEVEL_CODES,
|
|
71
|
+
OMITTED_REASONS,
|
|
72
|
+
} from './managers/shuttle'
|
|
73
|
+
export type {
|
|
74
|
+
ShuttleMode,
|
|
75
|
+
ShuttleOption,
|
|
76
|
+
ShuttleOptions,
|
|
77
|
+
ShuttleReason,
|
|
78
|
+
ShuttleReasonCode,
|
|
79
|
+
CandidateEntity,
|
|
80
|
+
} from './managers/shuttle'
|
|
65
81
|
export type {GridCell, ClusterCell, Cluster} from './managers'
|
|
66
82
|
export type {
|
|
67
83
|
CharterProgress,
|
|
@@ -124,6 +140,8 @@ export {
|
|
|
124
140
|
categoryFromIndex,
|
|
125
141
|
categoryLabelFromIndex,
|
|
126
142
|
} from './data/catalog'
|
|
143
|
+
export {getItemFamily, itemFamilies, itemFamilyKey} from './data/metadata'
|
|
144
|
+
export type {ItemFamily} from './data/metadata'
|
|
127
145
|
export {getCurrentEpoch, getEpochInfo} from './scheduling/epoch'
|
|
128
146
|
export type {EpochInfo} from './scheduling/epoch'
|
|
129
147
|
export {
|
|
@@ -339,6 +357,7 @@ export {
|
|
|
339
357
|
jobDropoffTask,
|
|
340
358
|
jobCancelRoute,
|
|
341
359
|
buildJobCancelRoute,
|
|
360
|
+
hostedDropoff,
|
|
342
361
|
jobCancellable,
|
|
343
362
|
jobCancellationBlockReason,
|
|
344
363
|
jobDeposited,
|
|
@@ -354,7 +373,10 @@ export type {
|
|
|
354
373
|
JobStatusInput,
|
|
355
374
|
JobCancelRoute,
|
|
356
375
|
JobCancellationBlockReason,
|
|
376
|
+
JobRouteOptions,
|
|
377
|
+
HostedLeg,
|
|
357
378
|
OwnedJob,
|
|
379
|
+
BuildJob,
|
|
358
380
|
PickupInFlight,
|
|
359
381
|
} from './scheduling/jobs'
|
|
360
382
|
|
|
@@ -374,12 +396,18 @@ export {
|
|
|
374
396
|
derivedLoaders,
|
|
375
397
|
estimateUnwrapDuration,
|
|
376
398
|
incomingHoldMass,
|
|
399
|
+
projectCargomass,
|
|
377
400
|
projectedPeakCargomass,
|
|
378
401
|
receiveFits,
|
|
379
402
|
unwrapLoadDuration,
|
|
380
403
|
unwrapTransitDuration,
|
|
381
404
|
} from './scheduling/unwrap'
|
|
382
|
-
export type {
|
|
405
|
+
export type {
|
|
406
|
+
CargomassProjection,
|
|
407
|
+
DerivedLoaders,
|
|
408
|
+
UnwrapDestination,
|
|
409
|
+
UnwrapItem,
|
|
410
|
+
} from './scheduling/unwrap'
|
|
383
411
|
|
|
384
412
|
export {
|
|
385
413
|
projectedCargoAvailableAt,
|
|
@@ -392,6 +420,7 @@ export {
|
|
|
392
420
|
cargoInputKey,
|
|
393
421
|
hasSourceCoupling,
|
|
394
422
|
hasIncomingCoupling,
|
|
423
|
+
isHostedCivicLeg,
|
|
395
424
|
} from './scheduling/availability'
|
|
396
425
|
export type {CargoInput, IncomingHoldEntity, IncomingSource} from './scheduling/availability'
|
|
397
426
|
|
|
@@ -401,7 +430,7 @@ export {calcClusterIntake, calcClustercraftDuration, INTAKE_RATE} from './capabi
|
|
|
401
430
|
|
|
402
431
|
export {maxCraftable} from './capabilities/craftable'
|
|
403
432
|
|
|
404
|
-
export {energyAtTime} from './scheduling/energy'
|
|
433
|
+
export {energyAtTime, energyDrawsFunded} from './scheduling/energy'
|
|
405
434
|
|
|
406
435
|
export * from './types/capabilities'
|
|
407
436
|
export * from './types/entity'
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
pendingCivicTransfers,
|
|
13
13
|
selectCivicShuttleBay,
|
|
14
14
|
CIVIC_TRANSFER_PER_PLAYER_CAP,
|
|
15
|
+
type CivicShuttleBay,
|
|
15
16
|
} from './civic-shuttle'
|
|
16
17
|
|
|
17
18
|
type Lane = ServerContract.Types.lane
|
|
@@ -63,6 +64,32 @@ function shuttleTask(senderId: number, receiverId: number, group?: number): Task
|
|
|
63
64
|
} as unknown as Task
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
function civicTask(type: number, couplings: unknown[]): Task {
|
|
68
|
+
return {
|
|
69
|
+
type: UInt8.from(type),
|
|
70
|
+
duration: UInt32.from(60),
|
|
71
|
+
cancelable: UInt8.from(2),
|
|
72
|
+
cargo: [],
|
|
73
|
+
couplings,
|
|
74
|
+
} as unknown as Task
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function pullCoupling(id: number) {
|
|
78
|
+
return {
|
|
79
|
+
counterpart: {entity_id: UInt64.from(id), entity_type: UInt8.from(1)},
|
|
80
|
+
hold: UInt64.from(1),
|
|
81
|
+
kind: UInt8.from(HoldKind.PULL),
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function pushCoupling(id: number) {
|
|
86
|
+
return {
|
|
87
|
+
counterpart: {entity_id: UInt64.from(id), entity_type: UInt8.from(1)},
|
|
88
|
+
hold: UInt64.from(1),
|
|
89
|
+
kind: UInt8.from(HoldKind.PUSH),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
66
93
|
function makeLane(laneKey: number, tasks: Task[]): Lane {
|
|
67
94
|
return {
|
|
68
95
|
lane_key: UInt8.from(laneKey),
|
|
@@ -142,6 +169,13 @@ test('selectCivicShuttleBay takes the first free bay, then the lowest occupied o
|
|
|
142
169
|
expect(selectCivicShuttleBay(modules, ITEM_DEPOT_T1_PACKED, bothBusy, T0)?.laneKey).toBe(1)
|
|
143
170
|
})
|
|
144
171
|
|
|
172
|
+
test('selectCivicShuttleBay picks the earliest finish, not the first free bay', () => {
|
|
173
|
+
const modules = depotModules()
|
|
174
|
+
const lanes = [makeLane(1, [shuttleTask(20, 21)])]
|
|
175
|
+
const fast = (bay: CivicShuttleBay) => (bay.slotIndex === 0 ? 10 : 500)
|
|
176
|
+
expect(selectCivicShuttleBay(modules, ITEM_DEPOT_T1_PACKED, lanes, T0, fast)?.slotIndex).toBe(0)
|
|
177
|
+
})
|
|
178
|
+
|
|
145
179
|
test('selectCivicShuttleBay returns nothing when the building has no loaders', () => {
|
|
146
180
|
const modules = [makeModuleEntry(ITEM_STORAGE_T1, storageStats)]
|
|
147
181
|
expect(selectCivicShuttleBay(modules, ITEM_DEPOT_T1_PACKED, [], T0)).toBeUndefined()
|
|
@@ -190,6 +224,30 @@ test('civicTransfersFrom counts only the ships a player sends from', () => {
|
|
|
190
224
|
expect(civicTransfersFrom(entity, [99], T0).length).toBe(0)
|
|
191
225
|
})
|
|
192
226
|
|
|
227
|
+
test('civic legs on bays count toward the player cap', () => {
|
|
228
|
+
const depot = {
|
|
229
|
+
lanes: [makeLane(1, [civicTask(TaskType.CIVIC_WITHDRAW, [pushCoupling(7)])])],
|
|
230
|
+
} as never
|
|
231
|
+
expect(civicTransfersFrom(depot, [7]).length).toBe(1)
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
test('a civic deposit leg reports the same player id as sender and receiver', () => {
|
|
235
|
+
const depot = {
|
|
236
|
+
lanes: [makeLane(1, [civicTask(TaskType.CIVIC_DEPOSIT, [pullCoupling(7)])])],
|
|
237
|
+
} as never
|
|
238
|
+
const [transfer] = pendingCivicTransfers(depot, T0)
|
|
239
|
+
expect(String(transfer.senderId)).toBe('7')
|
|
240
|
+
expect(String(transfer.receiverId)).toBe('7')
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
test('a civic pickup leg is not callable while CANCEL_NEVER', () => {
|
|
244
|
+
const task = civicTask(TaskType.CIVIC_WITHDRAW, [pushCoupling(7)])
|
|
245
|
+
;(task as unknown as {cancelable: unknown}).cancelable = UInt8.from(0)
|
|
246
|
+
const depot = {lanes: [makeLane(1, [task])]} as never
|
|
247
|
+
const [transfer] = pendingCivicTransfers(depot, T0)
|
|
248
|
+
expect(transfer.callable).toBe(false)
|
|
249
|
+
})
|
|
250
|
+
|
|
193
251
|
test('civicTransfersAtCap trips at the per-player cap', () => {
|
|
194
252
|
const mine = Array.from({length: CIVIC_TRANSFER_PER_PLAYER_CAP}, (_, i) =>
|
|
195
253
|
shuttleTask(20 + i, 50)
|
|
@@ -4,7 +4,7 @@ import {getItem} from '../data/catalog'
|
|
|
4
4
|
import {JOB_QUEUE_CAP} from '../scheduling/jobs'
|
|
5
5
|
import {laneKeyForModule, resolveLaneLoader} from '../scheduling/lanes'
|
|
6
6
|
import {orderedTasks, type ScheduleData} from '../scheduling/schedule'
|
|
7
|
-
import {HoldKind, TaskType} from '../types'
|
|
7
|
+
import {HoldKind, TaskCancelable, TaskType} from '../types'
|
|
8
8
|
|
|
9
9
|
type CargoItem = ServerContract.Types.cargo_item
|
|
10
10
|
type Lane = ServerContract.Types.lane
|
|
@@ -22,7 +22,6 @@ export interface CivicShuttleBay {
|
|
|
22
22
|
full: boolean
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
// a landed booking clears during the next civicshuttle, so only unfinished tasks occupy a bay
|
|
26
25
|
function unfinishedTasks(lane: Lane | undefined, now: Date): number {
|
|
27
26
|
if (!lane) return 0
|
|
28
27
|
const startedMs = lane.schedule.started.toDate().getTime()
|
|
@@ -64,15 +63,38 @@ export function civicShuttleBays(
|
|
|
64
63
|
return bays
|
|
65
64
|
}
|
|
66
65
|
|
|
67
|
-
|
|
66
|
+
function laneEndMs(lane: Lane | undefined, nowMs: number): number {
|
|
67
|
+
if (!lane) return nowMs
|
|
68
|
+
let endSec = 0
|
|
69
|
+
for (const task of lane.schedule.tasks) endSec += task.duration.toNumber()
|
|
70
|
+
return Math.max(nowMs, lane.schedule.started.toDate().getTime() + endSec * 1000)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Mirrors cargo.cpp pick_civic_bay: earliest finish among bays below the queue cap.
|
|
68
74
|
export function selectCivicShuttleBay(
|
|
69
75
|
modules: ModuleEntry[],
|
|
70
76
|
entityItemId: number,
|
|
71
77
|
lanes: Lane[],
|
|
72
|
-
now: Date = new Date()
|
|
78
|
+
now: Date = new Date(),
|
|
79
|
+
durationFor: (bay: CivicShuttleBay) => number = () => 0,
|
|
80
|
+
minStart?: Date
|
|
73
81
|
): CivicShuttleBay | undefined {
|
|
74
82
|
const bays = civicShuttleBays(modules, entityItemId, lanes, now)
|
|
75
|
-
|
|
83
|
+
const nowMs = now.getTime()
|
|
84
|
+
const floorMs = Math.max(nowMs, minStart?.getTime() ?? nowMs)
|
|
85
|
+
let best: CivicShuttleBay | undefined
|
|
86
|
+
let bestEnd = Infinity
|
|
87
|
+
for (const bay of bays) {
|
|
88
|
+
if (bay.full) continue
|
|
89
|
+
const lane = lanes.find((l) => l.lane_key.toNumber() === bay.laneKey)
|
|
90
|
+
const start = Math.max(laneEndMs(lane, nowMs), floorMs)
|
|
91
|
+
const end = start + durationFor(bay) * 1000
|
|
92
|
+
if (end < bestEnd) {
|
|
93
|
+
best = bay
|
|
94
|
+
bestEnd = end
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return best ?? bays[0]
|
|
76
98
|
}
|
|
77
99
|
|
|
78
100
|
export interface PendingCivicTransfer {
|
|
@@ -98,7 +120,31 @@ export function pendingCivicTransfers(
|
|
|
98
120
|
}
|
|
99
121
|
const out: PendingCivicTransfer[] = []
|
|
100
122
|
for (const entry of orderedTasks(entity)) {
|
|
101
|
-
|
|
123
|
+
const type = entry.task.type.toNumber()
|
|
124
|
+
if (type === TaskType.CIVIC_DEPOSIT || type === TaskType.CIVIC_WITHDRAW) {
|
|
125
|
+
const side = entry.task.couplings[0]
|
|
126
|
+
if (!side) continue
|
|
127
|
+
const isTail = tailIndex.get(entry.laneKey) === entry.taskIndex
|
|
128
|
+
const complete = entry.completesAt.getTime() <= now.getTime()
|
|
129
|
+
out.push({
|
|
130
|
+
laneKey: entry.laneKey,
|
|
131
|
+
taskIndex: entry.taskIndex,
|
|
132
|
+
senderId: side.counterpart.entity_id,
|
|
133
|
+
receiverId: side.counterpart.entity_id,
|
|
134
|
+
cargo: entry.task.cargo,
|
|
135
|
+
startsAt: entry.startsAt,
|
|
136
|
+
completesAt: entry.completesAt,
|
|
137
|
+
isTail,
|
|
138
|
+
complete,
|
|
139
|
+
callable:
|
|
140
|
+
isTail &&
|
|
141
|
+
!complete &&
|
|
142
|
+
!entry.task.entitygroup &&
|
|
143
|
+
entry.task.cancelable.toNumber() !== TaskCancelable.NEVER,
|
|
144
|
+
})
|
|
145
|
+
continue
|
|
146
|
+
}
|
|
147
|
+
if (type !== TaskType.SHUTTLE) continue
|
|
102
148
|
const pull = entry.task.couplings.find((c) => c.kind.toNumber() === HoldKind.PULL)
|
|
103
149
|
const push = entry.task.couplings.find((c) => c.kind.toNumber() === HoldKind.PUSH)
|
|
104
150
|
if (!pull || !push) continue
|
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type {NameType} from '@wharfkit/antelope'
|
|
2
|
-
import type {ServerContract} from '../contracts'
|
|
3
|
-
import {getEntityClass} from '../data/kind-registry'
|
|
4
1
|
import {computeLoaderMass, computeLoaderThrust} from '../nft/description'
|
|
5
|
-
import {laneKeyForModule, resolveLaneLoader} from '../scheduling/lanes'
|
|
6
|
-
import {calc_onesided_duration} from '../travel/travel'
|
|
7
2
|
import {MASS_STAT_SCALE, MASS_UNITS_PER_TONNE, PRECISION} from '../types'
|
|
8
3
|
import {CIVIC_LOADER_STAT, CIVIC_LOADER_TIER, DEFAULT_ORBITAL_Z} from './constants'
|
|
9
4
|
|
|
@@ -39,63 +34,3 @@ export function contributeDuration(totalMass: number, altitudeZ = 0): number {
|
|
|
39
34
|
export function contributeDurationForTonnes(tonnes: number, altitudeZ = 0): number {
|
|
40
35
|
return contributeDuration(Math.floor(tonnes * MASS_UNITS_PER_TONNE), altitudeZ)
|
|
41
36
|
}
|
|
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
|
-
)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export interface CivicDropoffParams {
|
|
75
|
-
buildingModules: ServerContract.Types.module_entry[]
|
|
76
|
-
buildingItemId: number
|
|
77
|
-
buildingKind: NameType
|
|
78
|
-
buildingZ: number
|
|
79
|
-
shipKind: NameType
|
|
80
|
-
shipZ: number
|
|
81
|
-
cargoMass: number
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Mirrors jobs.cpp craftjob: the building's slot-0 loader when one is installed, the civic loader when none is.
|
|
85
|
-
export function civicDropoffDuration(params: CivicDropoffParams): number {
|
|
86
|
-
const loader = resolveLaneLoader(
|
|
87
|
-
params.buildingModules,
|
|
88
|
-
params.buildingItemId,
|
|
89
|
-
laneKeyForModule(DEPOT_LOADER_SLOT)
|
|
90
|
-
)
|
|
91
|
-
if (!loader.valid) return contributeDuration(params.cargoMass, params.shipZ)
|
|
92
|
-
return calc_onesided_duration(
|
|
93
|
-
loader.thrust,
|
|
94
|
-
loader.mass,
|
|
95
|
-
params.shipZ,
|
|
96
|
-
params.buildingZ,
|
|
97
|
-
getEntityClass(params.shipKind),
|
|
98
|
-
getEntityClass(params.buildingKind),
|
|
99
|
-
params.cargoMass
|
|
100
|
-
)
|
|
101
|
-
}
|
package/src/influence/index.ts
CHANGED
|
@@ -26,24 +26,23 @@ export {
|
|
|
26
26
|
export {
|
|
27
27
|
componentBaseAtomic,
|
|
28
28
|
componentEffortAtomic,
|
|
29
|
+
explainCargoItem,
|
|
29
30
|
pricingFromWeights,
|
|
30
31
|
resourceValueAtomic,
|
|
31
32
|
valueCargoItem,
|
|
32
33
|
valueContribution,
|
|
33
34
|
weightedQualityAtomic,
|
|
35
|
+
type CargoValuation,
|
|
36
|
+
type ComponentValuation,
|
|
34
37
|
type InfluencePricing,
|
|
38
|
+
type ResourceValuation,
|
|
35
39
|
type ValuedItem,
|
|
36
40
|
} from './valuation'
|
|
37
41
|
export {
|
|
38
|
-
civicDropoffDuration,
|
|
39
42
|
civicLoader,
|
|
40
43
|
contributeDuration,
|
|
41
44
|
contributeDurationForTonnes,
|
|
42
|
-
depotTransferDuration,
|
|
43
|
-
DEPOT_LOADER_SLOT,
|
|
44
|
-
type CivicDropoffParams,
|
|
45
45
|
type CivicLoaderStats,
|
|
46
|
-
type DepotTransferParams,
|
|
47
46
|
} from './duration'
|
|
48
47
|
export {
|
|
49
48
|
civicShuttleBays,
|