@shipload/sdk 1.0.0-next.54 → 1.0.0-next.55
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 +7 -2
- package/lib/shipload.js +95 -15
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +93 -16
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.js +11 -0
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +11 -0
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/data/entities.json +16 -0
- package/src/data/item-ids.ts +1 -0
- package/src/data/items.json +6 -0
- package/src/data/kind-registry.json +12 -0
- package/src/data/kind-registry.ts +5 -0
- package/src/data/metadata.ts +7 -0
- package/src/data/recipes.json +39 -0
- package/src/derivation/capabilities.ts +2 -0
- package/src/derivation/recipe-usage.test.ts +7 -1
- package/src/index-module.ts +2 -0
- package/src/nft/description.ts +4 -0
- package/src/scheduling/projection.ts +1 -14
- package/src/scheduling/schedule.test.ts +12 -9
- package/src/scheduling/schedule.ts +2 -6
package/package.json
CHANGED
package/src/data/entities.json
CHANGED
|
@@ -171,6 +171,22 @@
|
|
|
171
171
|
],
|
|
172
172
|
"baseHullmass": 100000
|
|
173
173
|
},
|
|
174
|
+
{
|
|
175
|
+
"entityItemId": 10209,
|
|
176
|
+
"slots": [
|
|
177
|
+
{
|
|
178
|
+
"type": "generator",
|
|
179
|
+
"outputPct": 200,
|
|
180
|
+
"maxTier": 1
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
"type": "builder",
|
|
184
|
+
"outputPct": 200,
|
|
185
|
+
"maxTier": 1
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"baseHullmass": 100000
|
|
189
|
+
},
|
|
174
190
|
{
|
|
175
191
|
"entityItemId": 10210,
|
|
176
192
|
"slots": [
|
package/src/data/item-ids.ts
CHANGED
|
@@ -80,6 +80,7 @@ export const ITEM_MASS_DRIVER_T1_PACKED = 10205
|
|
|
80
80
|
export const ITEM_MASS_CATCHER_T1_PACKED = 10206
|
|
81
81
|
export const ITEM_HUB_T1_PACKED = 10207
|
|
82
82
|
export const ITEM_WORKSHOP_T1_PACKED = 10208
|
|
83
|
+
export const ITEM_CONSTRUCTION_DOCK_T1_PACKED = 10209
|
|
83
84
|
export const ITEM_ROUSTABOUT_T1_PACKED = 10210
|
|
84
85
|
export const ITEM_PROSPECTOR_T1_PACKED = 10211
|
|
85
86
|
export const ITEM_TENDER_T1_PACKED = 10212
|
package/src/data/items.json
CHANGED
|
@@ -76,6 +76,13 @@
|
|
|
76
76
|
"capabilityFlags": 20,
|
|
77
77
|
"zCoord": 0,
|
|
78
78
|
"defaultLabel": "Workshop"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"kind": "builddock",
|
|
82
|
+
"classification": "OrbitalStructure",
|
|
83
|
+
"capabilityFlags": 20,
|
|
84
|
+
"zCoord": 0,
|
|
85
|
+
"defaultLabel": "Construction Dock"
|
|
79
86
|
}
|
|
80
87
|
],
|
|
81
88
|
"templates": [
|
|
@@ -169,6 +176,11 @@
|
|
|
169
176
|
"kind": "workshop",
|
|
170
177
|
"displayLabel": ""
|
|
171
178
|
},
|
|
179
|
+
{
|
|
180
|
+
"itemId": 10209,
|
|
181
|
+
"kind": "builddock",
|
|
182
|
+
"displayLabel": ""
|
|
183
|
+
},
|
|
172
184
|
{
|
|
173
185
|
"itemId": 20210,
|
|
174
186
|
"kind": "ship",
|
|
@@ -26,6 +26,7 @@ export type EntityTypeName =
|
|
|
26
26
|
| 'warehouse'
|
|
27
27
|
| 'extractor'
|
|
28
28
|
| 'factory'
|
|
29
|
+
| 'builddock'
|
|
29
30
|
| 'workshop'
|
|
30
31
|
| 'container'
|
|
31
32
|
| 'nexus'
|
|
@@ -134,6 +135,7 @@ export const ENTITY_SHIP = Name.from('ship')
|
|
|
134
135
|
export const ENTITY_WAREHOUSE = Name.from('warehouse')
|
|
135
136
|
export const ENTITY_EXTRACTOR = Name.from('extractor')
|
|
136
137
|
export const ENTITY_FACTORY = Name.from('factory')
|
|
138
|
+
export const ENTITY_CONSTRUCTION_DOCK = Name.from('builddock')
|
|
137
139
|
export const ENTITY_WORKSHOP = Name.from('workshop')
|
|
138
140
|
export const ENTITY_CONTAINER = Name.from('container')
|
|
139
141
|
export const ENTITY_NEXUS = Name.from('nexus')
|
|
@@ -154,6 +156,9 @@ export function isExtractor(entity: {type?: Name}): boolean {
|
|
|
154
156
|
export function isFactory(entity: {type?: Name}): boolean {
|
|
155
157
|
return entity.type?.equals(ENTITY_FACTORY) ?? false
|
|
156
158
|
}
|
|
159
|
+
export function isConstructionDock(entity: {type?: Name}): boolean {
|
|
160
|
+
return entity.type?.equals(ENTITY_CONSTRUCTION_DOCK) ?? false
|
|
161
|
+
}
|
|
157
162
|
export function isWorkshop(entity: {type?: Name}): boolean {
|
|
158
163
|
return entity.type?.equals(ENTITY_WORKSHOP) ?? false
|
|
159
164
|
}
|
package/src/data/metadata.ts
CHANGED
|
@@ -279,6 +279,12 @@ export const itemMetadata: Record<number, ItemMetadata> = {
|
|
|
279
279
|
'A station workshop with five independent workers. Visiting ships bring materials and power, and the workshop does the crafting.',
|
|
280
280
|
color: '#B877FF',
|
|
281
281
|
},
|
|
282
|
+
10209: {
|
|
283
|
+
name: 'Construction Dock',
|
|
284
|
+
description:
|
|
285
|
+
'An immobile station construction facility with amplified power core and assembly arm slots.',
|
|
286
|
+
color: '#FFB347',
|
|
287
|
+
},
|
|
282
288
|
10210: {
|
|
283
289
|
name: 'Roustabout',
|
|
284
290
|
description:
|
|
@@ -433,6 +439,7 @@ export const entityMetadata: Record<number, EntityMetadata> = {
|
|
|
433
439
|
10208: {
|
|
434
440
|
moduleSlotLabels: ['Fabricator', 'Fabricator', 'Fabricator', 'Fabricator', 'Fabricator'],
|
|
435
441
|
},
|
|
442
|
+
10209: {moduleSlotLabels: ['Power Core', 'Assembly Arm']},
|
|
436
443
|
20210: {moduleSlotLabels: ['Power Core', 'Power Core', 'Engine', 'Limpet Bay']},
|
|
437
444
|
20211: {moduleSlotLabels: ['Power Core', 'Engine', 'Tractor Beam', 'Tractor Beam']},
|
|
438
445
|
}
|
package/src/data/recipes.json
CHANGED
|
@@ -1016,6 +1016,45 @@
|
|
|
1016
1016
|
],
|
|
1017
1017
|
"blendWeights": []
|
|
1018
1018
|
},
|
|
1019
|
+
{
|
|
1020
|
+
"outputItemId": 10209,
|
|
1021
|
+
"outputMass": 1900000,
|
|
1022
|
+
"inputs": [
|
|
1023
|
+
{
|
|
1024
|
+
"itemId": 10001,
|
|
1025
|
+
"quantity": 600
|
|
1026
|
+
},
|
|
1027
|
+
{
|
|
1028
|
+
"itemId": 10003,
|
|
1029
|
+
"quantity": 600
|
|
1030
|
+
}
|
|
1031
|
+
],
|
|
1032
|
+
"statSlots": [
|
|
1033
|
+
{
|
|
1034
|
+
"sources": [
|
|
1035
|
+
{
|
|
1036
|
+
"inputIndex": 0,
|
|
1037
|
+
"statIndex": 0
|
|
1038
|
+
}
|
|
1039
|
+
]
|
|
1040
|
+
},
|
|
1041
|
+
{
|
|
1042
|
+
"sources": [
|
|
1043
|
+
{
|
|
1044
|
+
"inputIndex": 0,
|
|
1045
|
+
"statIndex": 1
|
|
1046
|
+
}
|
|
1047
|
+
]
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
"sources": []
|
|
1051
|
+
},
|
|
1052
|
+
{
|
|
1053
|
+
"sources": []
|
|
1054
|
+
}
|
|
1055
|
+
],
|
|
1056
|
+
"blendWeights": []
|
|
1057
|
+
},
|
|
1019
1058
|
{
|
|
1020
1059
|
"outputItemId": 10210,
|
|
1021
1060
|
"outputMass": 1600000,
|
|
@@ -218,6 +218,7 @@ export function computeBatteryCapabilities(stats: Record<string, number>): {
|
|
|
218
218
|
import {
|
|
219
219
|
ITEM_CONTAINER_T1_PACKED,
|
|
220
220
|
ITEM_CONTAINER_T2_PACKED,
|
|
221
|
+
ITEM_CONSTRUCTION_DOCK_T1_PACKED,
|
|
221
222
|
ITEM_EXTRACTOR_T1_PACKED,
|
|
222
223
|
ITEM_FACTORY_T1_PACKED,
|
|
223
224
|
ITEM_MASS_CATCHER_T1_PACKED,
|
|
@@ -277,6 +278,7 @@ export function computeBaseCapacity(itemId: number, stats: Record<string, number
|
|
|
277
278
|
switch (itemId) {
|
|
278
279
|
case ITEM_EXTRACTOR_T1_PACKED:
|
|
279
280
|
case ITEM_FACTORY_T1_PACKED:
|
|
281
|
+
case ITEM_CONSTRUCTION_DOCK_T1_PACKED:
|
|
280
282
|
case ITEM_MASS_DRIVER_T1_PACKED:
|
|
281
283
|
case ITEM_MASS_CATCHER_T1_PACKED:
|
|
282
284
|
case ITEM_CONTAINER_T1_PACKED:
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ITEM_BEAM,
|
|
14
14
|
ITEM_GATHERER_T1,
|
|
15
15
|
ITEM_CRAFTER_T1,
|
|
16
|
+
ITEM_BUILDER_T1,
|
|
16
17
|
ITEM_EXTRACTOR_T1_PACKED,
|
|
17
18
|
ITEM_ROUSTABOUT_T1_PACKED,
|
|
18
19
|
ITEM_PROSPECTOR_T1_PACKED,
|
|
@@ -33,7 +34,12 @@ test('getRecipeConsumers lists every recipe that consumes Sensor', () => {
|
|
|
33
34
|
const consumers = getRecipeConsumers(ITEM_SENSOR)
|
|
34
35
|
const ids = consumers.map((c) => c.outputItemId).sort((a, b) => a - b)
|
|
35
36
|
expect(ids).toEqual(
|
|
36
|
-
[
|
|
37
|
+
[
|
|
38
|
+
ITEM_CRAFTER_T1,
|
|
39
|
+
ITEM_BUILDER_T1,
|
|
40
|
+
ITEM_EXTRACTOR_T1_PACKED,
|
|
41
|
+
ITEM_ROUSTABOUT_T1_PACKED,
|
|
42
|
+
].sort((a, b) => a - b)
|
|
37
43
|
)
|
|
38
44
|
})
|
|
39
45
|
|
package/src/index-module.ts
CHANGED
|
@@ -333,6 +333,7 @@ export {
|
|
|
333
333
|
ENTITY_WAREHOUSE,
|
|
334
334
|
ENTITY_EXTRACTOR,
|
|
335
335
|
ENTITY_FACTORY,
|
|
336
|
+
ENTITY_CONSTRUCTION_DOCK,
|
|
336
337
|
ENTITY_WORKSHOP,
|
|
337
338
|
ENTITY_CONTAINER,
|
|
338
339
|
ENTITY_NEXUS,
|
|
@@ -351,6 +352,7 @@ export {
|
|
|
351
352
|
isWarehouse,
|
|
352
353
|
isExtractor,
|
|
353
354
|
isFactory,
|
|
355
|
+
isConstructionDock,
|
|
354
356
|
isWorkshop,
|
|
355
357
|
isContainer,
|
|
356
358
|
isNexus,
|
package/src/nft/description.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
ITEM_CONTAINER_T1_PACKED,
|
|
16
16
|
ITEM_CONTAINER_T2_PACKED,
|
|
17
|
+
ITEM_CONSTRUCTION_DOCK_T1_PACKED,
|
|
17
18
|
ITEM_BUILDER_T1,
|
|
18
19
|
ITEM_CRAFTER_T1,
|
|
19
20
|
ITEM_ENGINE_T1,
|
|
@@ -170,6 +171,8 @@ export function entityDisplayName(itemId: number): string {
|
|
|
170
171
|
return 'Mining Rig'
|
|
171
172
|
case ITEM_FACTORY_T1_PACKED:
|
|
172
173
|
return 'Factory'
|
|
174
|
+
case ITEM_CONSTRUCTION_DOCK_T1_PACKED:
|
|
175
|
+
return 'Construction Dock'
|
|
173
176
|
case ITEM_CONTAINER_T1_PACKED:
|
|
174
177
|
return 'Container'
|
|
175
178
|
case ITEM_CONTAINER_T2_PACKED:
|
|
@@ -317,6 +320,7 @@ export function buildEntityDescription(
|
|
|
317
320
|
} else if (
|
|
318
321
|
itemId === ITEM_EXTRACTOR_T1_PACKED ||
|
|
319
322
|
itemId === ITEM_FACTORY_T1_PACKED ||
|
|
323
|
+
itemId === ITEM_CONSTRUCTION_DOCK_T1_PACKED ||
|
|
320
324
|
itemId === ITEM_CONTAINER_T1_PACKED ||
|
|
321
325
|
itemId === ITEM_CONTAINER_T2_PACKED
|
|
322
326
|
) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Name, type 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
5
|
capsHasMovement,
|
|
6
6
|
capsHasStorage,
|
|
@@ -402,13 +402,6 @@ function applyCraftTask(projected: ProjectedEntity, task: ServerContract.Types.t
|
|
|
402
402
|
}
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
-
// Mirrors calc_task_effect's TASK_REFIT: only ADD has a projectable cargo effect (REMOVE/SWAP return mass the entity row holds, invisible to the task itself).
|
|
406
|
-
function applyRefitTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
407
|
-
if (task.refit?.op.toNumber() === RefitOp.ADD) {
|
|
408
|
-
removeCargoItem(projected, task.cargo[0])
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
405
|
function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task): void {
|
|
413
406
|
switch (task.type.toNumber()) {
|
|
414
407
|
case TaskType.RECHARGE:
|
|
@@ -432,9 +425,6 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
432
425
|
case TaskType.CRAFT:
|
|
433
426
|
applyCraftTask(projected, task)
|
|
434
427
|
break
|
|
435
|
-
case TaskType.REFIT:
|
|
436
|
-
applyRefitTask(projected, task)
|
|
437
|
-
break
|
|
438
428
|
case TaskType.UNDEPLOY:
|
|
439
429
|
case TaskType.DEMOLISH:
|
|
440
430
|
break
|
|
@@ -591,9 +581,6 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
591
581
|
case TaskType.CRAFT:
|
|
592
582
|
if (taskComplete) applyCraftTask(projected, task)
|
|
593
583
|
break
|
|
594
|
-
case TaskType.REFIT:
|
|
595
|
-
if (taskComplete) applyRefitTask(projected, task)
|
|
596
|
-
break
|
|
597
584
|
case TaskType.UNDEPLOY:
|
|
598
585
|
case TaskType.DEMOLISH:
|
|
599
586
|
break
|
|
@@ -50,10 +50,13 @@ function hold(kind: number) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
describe('isCapperTaskType', () => {
|
|
53
|
-
test('UNDEPLOY, DEMOLISH
|
|
53
|
+
test('UNDEPLOY, DEMOLISH are cappers', () => {
|
|
54
54
|
expect(isCapperTaskType(TaskType.UNDEPLOY)).toBe(true)
|
|
55
55
|
expect(isCapperTaskType(TaskType.DEMOLISH)).toBe(true)
|
|
56
|
-
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('REFIT is not a capper', () => {
|
|
59
|
+
expect(isCapperTaskType(TaskType.REFIT)).toBe(false)
|
|
57
60
|
})
|
|
58
61
|
|
|
59
62
|
test('non-capper task types are not cappers', () => {
|
|
@@ -71,8 +74,8 @@ describe('hasPendingCapper', () => {
|
|
|
71
74
|
expect(hasPendingCapper(entity([task({type: TaskType.TRAVEL})]))).toBe(false)
|
|
72
75
|
})
|
|
73
76
|
|
|
74
|
-
test('true when a
|
|
75
|
-
const e = entity([task({type: TaskType.TRAVEL}), task({type: TaskType.
|
|
77
|
+
test('true when a DEMOLISH task is queued anywhere in the lane', () => {
|
|
78
|
+
const e = entity([task({type: TaskType.TRAVEL}), task({type: TaskType.DEMOLISH})])
|
|
76
79
|
expect(hasPendingCapper(e)).toBe(true)
|
|
77
80
|
})
|
|
78
81
|
|
|
@@ -88,18 +91,18 @@ describe('hasResolvable — capper gating', () => {
|
|
|
88
91
|
})
|
|
89
92
|
|
|
90
93
|
test('a completed capper front with no holds is resolvable', () => {
|
|
91
|
-
const e = entity([task({type: TaskType.
|
|
94
|
+
const e = entity([task({type: TaskType.DEMOLISH, duration: 30})])
|
|
92
95
|
expect(hasResolvable(e, NOW)).toBe(true)
|
|
93
96
|
})
|
|
94
97
|
|
|
95
98
|
test('a completed capper front with a live hold is gated', () => {
|
|
96
|
-
const e = entity([task({type: TaskType.
|
|
99
|
+
const e = entity([task({type: TaskType.DEMOLISH, duration: 30})], [hold(2)])
|
|
97
100
|
expect(hasResolvable(e, NOW)).toBe(false)
|
|
98
101
|
})
|
|
99
102
|
|
|
100
103
|
test('a capper front clears once holds empty', () => {
|
|
101
|
-
const withHold = entity([task({type: TaskType.
|
|
102
|
-
const cleared = entity([task({type: TaskType.
|
|
104
|
+
const withHold = entity([task({type: TaskType.DEMOLISH, duration: 30})], [hold(2)])
|
|
105
|
+
const cleared = entity([task({type: TaskType.DEMOLISH, duration: 30})], [])
|
|
103
106
|
expect(hasResolvable(withHold, NOW)).toBe(false)
|
|
104
107
|
expect(hasResolvable(cleared, NOW)).toBe(true)
|
|
105
108
|
})
|
|
@@ -110,7 +113,7 @@ describe('hasResolvable — capper gating', () => {
|
|
|
110
113
|
})
|
|
111
114
|
|
|
112
115
|
test('an in-progress front is not resolvable regardless of holds', () => {
|
|
113
|
-
const e = entity([task({type: TaskType.
|
|
116
|
+
const e = entity([task({type: TaskType.DEMOLISH, duration: 3600})])
|
|
114
117
|
expect(hasResolvable(e, NOW)).toBe(false)
|
|
115
118
|
})
|
|
116
119
|
})
|
|
@@ -63,13 +63,9 @@ export function isIdle(entity: ScheduleData): boolean {
|
|
|
63
63
|
return !hasSchedule(entity) && !hasHolds(entity)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
// Mirrors is_capper_task_type: demolish/undeploy
|
|
66
|
+
// Mirrors is_capper_task_type: demolish/undeploy cap a plan — no further appends once queued.
|
|
67
67
|
export function isCapperTaskType(taskType: number): boolean {
|
|
68
|
-
return
|
|
69
|
-
taskType === TaskType.UNDEPLOY ||
|
|
70
|
-
taskType === TaskType.DEMOLISH ||
|
|
71
|
-
taskType === TaskType.REFIT
|
|
72
|
-
)
|
|
68
|
+
return taskType === TaskType.UNDEPLOY || taskType === TaskType.DEMOLISH
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
export function hasPendingCapper(entity: ScheduleData): boolean {
|