@shipload/sdk 1.0.0-next.67 → 1.0.0-next.69
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 +9 -5
- package/lib/shipload.js +51 -15
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +51 -15
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1 -0
- package/lib/testing.js +4 -1
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +4 -1
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts/server.ts +3 -1
- package/src/entities/makers.ts +3 -1
- package/src/influence/civic-shuttle.test.ts +56 -13
- package/src/influence/civic-shuttle.ts +37 -10
- package/src/scheduling/availability.test.ts +3 -0
- package/src/scheduling/cancel.test.ts +8 -0
- package/src/scheduling/projection.ts +21 -6
- package/src/scheduling/schedule.test.ts +1 -0
|
@@ -18,6 +18,7 @@ function task(over: Partial<{type: number; duration: number; cancelable: number;
|
|
|
18
18
|
|
|
19
19
|
function entity(tasks: ReturnType<typeof task>[], startedISO = T0) {
|
|
20
20
|
return ServerContract.Types.entity_info.from({
|
|
21
|
+
projected_at: 0,
|
|
21
22
|
type: 'ship',
|
|
22
23
|
id: 1,
|
|
23
24
|
owner: 'player.gm',
|
|
@@ -155,6 +156,7 @@ describe('cancelEligibility — effects', () => {
|
|
|
155
156
|
const lt = loadTask('warehouse', 6, 1, 4)
|
|
156
157
|
const upcoming = new Date('2026-06-18T23:59:50.000Z')
|
|
157
158
|
const e = ServerContract.Types.entity_info.from({
|
|
159
|
+
projected_at: 0,
|
|
158
160
|
type: 'ship',
|
|
159
161
|
id: 1,
|
|
160
162
|
owner: 'player.gm',
|
|
@@ -188,6 +190,7 @@ describe('cancelEligibility — effects', () => {
|
|
|
188
190
|
const lt = loadTask('warehouse', 6, 1, 4)
|
|
189
191
|
const upcoming = new Date('2026-06-18T23:59:50.000Z')
|
|
190
192
|
const e = ServerContract.Types.entity_info.from({
|
|
193
|
+
projected_at: 0,
|
|
191
194
|
type: 'ship',
|
|
192
195
|
id: 1,
|
|
193
196
|
owner: 'player.gm',
|
|
@@ -220,6 +223,7 @@ describe('cancelEligibility — effects', () => {
|
|
|
220
223
|
test('uncoupled task emits no releasedHolds entry', () => {
|
|
221
224
|
const upcoming = new Date('2026-06-18T23:59:50.000Z')
|
|
222
225
|
const e = ServerContract.Types.entity_info.from({
|
|
226
|
+
projected_at: 0,
|
|
223
227
|
type: 'ship',
|
|
224
228
|
id: 1,
|
|
225
229
|
owner: 'player.gm',
|
|
@@ -272,6 +276,7 @@ describe('cancelEligibility — feasibility', () => {
|
|
|
272
276
|
couplings: [],
|
|
273
277
|
})
|
|
274
278
|
const e = ServerContract.Types.entity_info.from({
|
|
279
|
+
projected_at: 0,
|
|
275
280
|
type: 'ship',
|
|
276
281
|
id: 1,
|
|
277
282
|
owner: 'player.gm',
|
|
@@ -318,6 +323,7 @@ describe('cancelEligibility — feasibility', () => {
|
|
|
318
323
|
couplings: [],
|
|
319
324
|
})
|
|
320
325
|
const e = ServerContract.Types.entity_info.from({
|
|
326
|
+
projected_at: 0,
|
|
321
327
|
type: 'ship',
|
|
322
328
|
id: 1,
|
|
323
329
|
owner: 'player.gm',
|
|
@@ -357,6 +363,7 @@ describe('cancelEligibility — feasibility', () => {
|
|
|
357
363
|
couplings: [],
|
|
358
364
|
})
|
|
359
365
|
const e = ServerContract.Types.entity_info.from({
|
|
366
|
+
projected_at: 0,
|
|
360
367
|
type: 'ship',
|
|
361
368
|
id: 1,
|
|
362
369
|
owner: 'player.gm',
|
|
@@ -397,6 +404,7 @@ describe('cancelEligibility — cross-entity strand (counterpart queued consumer
|
|
|
397
404
|
}[] = []
|
|
398
405
|
) {
|
|
399
406
|
return ServerContract.Types.entity_info.from({
|
|
407
|
+
projected_at: 0,
|
|
400
408
|
type: 'ship',
|
|
401
409
|
id,
|
|
402
410
|
owner: 'player.gm',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {Name, type UInt16, UInt32, UInt64} from '@wharfkit/antelope'
|
|
1
|
+
import {Name, type TimePoint, type UInt16, UInt32, UInt64} from '@wharfkit/antelope'
|
|
2
2
|
import {ServerContract} from '../contracts'
|
|
3
3
|
import {Coordinates, TaskType} from '../types'
|
|
4
4
|
import {
|
|
@@ -75,6 +75,7 @@ export interface Projectable extends ScheduleData {
|
|
|
75
75
|
capacity?: UInt32
|
|
76
76
|
cargo: ServerContract.Types.cargo_item[]
|
|
77
77
|
cargomass: UInt32
|
|
78
|
+
projected_at?: TimePoint
|
|
78
79
|
owner?: Name
|
|
79
80
|
stats?: bigint
|
|
80
81
|
item_id?: number | UInt16
|
|
@@ -425,6 +426,18 @@ export interface ProjectionOptions {
|
|
|
425
426
|
upToTaskIndex?: number
|
|
426
427
|
}
|
|
427
428
|
|
|
429
|
+
// Mirrors the contract's completed_task_count_at: inclusive at the anchor.
|
|
430
|
+
function anchoredSkipCount(entity: Projectable, ordered: readonly schedule.OrderedTask[]): number {
|
|
431
|
+
const anchor = entity.projected_at
|
|
432
|
+
if (anchor === undefined) return 0
|
|
433
|
+
const anchorMs = Number(anchor.toMilliseconds())
|
|
434
|
+
let count = 0
|
|
435
|
+
for (const {completesAt} of ordered) {
|
|
436
|
+
if (completesAt.getTime() <= anchorMs) count++
|
|
437
|
+
}
|
|
438
|
+
return count
|
|
439
|
+
}
|
|
440
|
+
|
|
428
441
|
export function projectEntity(entity: Projectable, options?: ProjectionOptions): ProjectedEntity {
|
|
429
442
|
const projected = createProjectedEntity(entity)
|
|
430
443
|
const ordered = schedule.orderedTasks(entity)
|
|
@@ -435,17 +448,17 @@ export function projectEntity(entity: Projectable, options?: ProjectionOptions):
|
|
|
435
448
|
? Math.max(0, Math.min(options.upToTaskIndex, ordered.length))
|
|
436
449
|
: ordered.length
|
|
437
450
|
|
|
438
|
-
for (let i =
|
|
451
|
+
for (let i = anchoredSkipCount(entity, ordered); i < taskCount; i++) {
|
|
439
452
|
applyTask(projected, ordered[i].task)
|
|
440
453
|
}
|
|
441
454
|
return projected
|
|
442
455
|
}
|
|
443
456
|
|
|
444
457
|
export function projectRemainingAt(entity: Projectable, _now: Date): ProjectedEntity {
|
|
445
|
-
// Resolve is lazy/entity-global: completed tasks are unsettled until resolve, so replay all.
|
|
446
458
|
const projected = createProjectedEntity(entity)
|
|
447
|
-
|
|
448
|
-
|
|
459
|
+
const ordered = schedule.orderedTasks(entity)
|
|
460
|
+
for (let i = anchoredSkipCount(entity, ordered); i < ordered.length; i++) {
|
|
461
|
+
applyTask(projected, ordered[i].task)
|
|
449
462
|
}
|
|
450
463
|
return projected
|
|
451
464
|
}
|
|
@@ -533,8 +546,10 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
533
546
|
}
|
|
534
547
|
|
|
535
548
|
const nowMs = now.getTime()
|
|
549
|
+
const skip = anchoredSkipCount(entity, ordered)
|
|
536
550
|
|
|
537
|
-
for (
|
|
551
|
+
for (let i = skip; i < ordered.length; i++) {
|
|
552
|
+
const {task, startsAt} = ordered[i]
|
|
538
553
|
const duration = task.duration.toNumber()
|
|
539
554
|
const elapsed = Math.min(
|
|
540
555
|
Math.max(0, Math.floor((nowMs - startsAt.getTime()) / 1000)),
|