@shipload/sdk 1.0.0-next.34 → 1.0.0-next.35
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 +194 -4
- package/lib/shipload.js +708 -8
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +689 -9
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +35 -0
- package/lib/testing.js +107 -1
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +107 -1
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts/server.ts +103 -1
- package/src/coordinates/address.ts +84 -0
- package/src/coordinates/constants.ts +21 -0
- package/src/coordinates/index.ts +4 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/derivation/wormhole.ts +115 -0
- package/src/errors.ts +2 -0
- package/src/index-module.ts +23 -0
- package/src/managers/actions.ts +45 -2
- package/src/scheduling/availability.ts +1 -1
- package/src/scheduling/cancel.test.ts +327 -0
- package/src/scheduling/cancel.ts +209 -0
- package/src/scheduling/projection.ts +2 -0
- package/src/scheduling/schedule.ts +3 -1
- package/src/travel/travel.ts +14 -4
- package/src/types.ts +1 -0
- package/src/utils/system.ts +11 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type {Checksum256Type} from '@wharfkit/antelope'
|
|
2
|
+
import {hash512} from '../utils/hash'
|
|
3
|
+
|
|
4
|
+
// FROZEN INTERFACE — round count, key-derivation strings, and mixing constants must never change; per-game variation comes from the seed.
|
|
5
|
+
const ROUNDS = 4
|
|
6
|
+
|
|
7
|
+
export interface FeistelConfig {
|
|
8
|
+
n: number
|
|
9
|
+
halfBits: number
|
|
10
|
+
label: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const keyCache = new Map<string, number[]>()
|
|
14
|
+
|
|
15
|
+
function deriveRoundKeys(seed: Checksum256Type, label: string): number[] {
|
|
16
|
+
const cacheKey = `${seed}:${label}`
|
|
17
|
+
const cached = keyCache.get(cacheKey)
|
|
18
|
+
if (cached) return cached
|
|
19
|
+
const h = hash512(seed, `coord-keys-${label}`).array
|
|
20
|
+
const keys: number[] = []
|
|
21
|
+
for (let i = 0; i < ROUNDS; i++) {
|
|
22
|
+
const o = i * 4
|
|
23
|
+
keys.push(((h[o] << 24) | (h[o + 1] << 16) | (h[o + 2] << 8) | h[o + 3]) >>> 0)
|
|
24
|
+
}
|
|
25
|
+
keyCache.set(cacheKey, keys)
|
|
26
|
+
return keys
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function roundFn(r: number, key: number, halfBits: number): number {
|
|
30
|
+
let x = (r ^ key) >>> 0
|
|
31
|
+
x = Math.imul(x ^ (x >>> 16), 0x9e3779b1) >>> 0
|
|
32
|
+
x = Math.imul(x ^ (x >>> 13), 0x7feb352d) >>> 0
|
|
33
|
+
x = (x ^ (x >>> 16)) >>> 0
|
|
34
|
+
return x & ((1 << halfBits) - 1)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function encryptBlock(x: number, halfBits: number, keys: number[]): number {
|
|
38
|
+
const mask = (1 << halfBits) - 1
|
|
39
|
+
let L = (x >>> halfBits) & mask
|
|
40
|
+
let R = x & mask
|
|
41
|
+
for (let i = 0; i < ROUNDS; i++) {
|
|
42
|
+
const F = roundFn(R, keys[i], halfBits)
|
|
43
|
+
const nL = R
|
|
44
|
+
const nR = (L ^ F) & mask
|
|
45
|
+
L = nL
|
|
46
|
+
R = nR
|
|
47
|
+
}
|
|
48
|
+
return ((L << halfBits) | R) >>> 0
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function decryptBlock(y: number, halfBits: number, keys: number[]): number {
|
|
52
|
+
const mask = (1 << halfBits) - 1
|
|
53
|
+
let L = (y >>> halfBits) & mask
|
|
54
|
+
let R = y & mask
|
|
55
|
+
for (let i = ROUNDS - 1; i >= 0; i--) {
|
|
56
|
+
const F = roundFn(L, keys[i], halfBits)
|
|
57
|
+
const nR = L
|
|
58
|
+
const nL = (R ^ F) & mask
|
|
59
|
+
L = nL
|
|
60
|
+
R = nR
|
|
61
|
+
}
|
|
62
|
+
return ((L << halfBits) | R) >>> 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function permute(seed: Checksum256Type, x: number, cfg: FeistelConfig): number {
|
|
66
|
+
const keys = deriveRoundKeys(seed, cfg.label)
|
|
67
|
+
let v = encryptBlock(x, cfg.halfBits, keys)
|
|
68
|
+
while (v >= cfg.n) v = encryptBlock(v, cfg.halfBits, keys)
|
|
69
|
+
return v
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function unpermute(seed: Checksum256Type, y: number, cfg: FeistelConfig): number {
|
|
73
|
+
const keys = deriveRoundKeys(seed, cfg.label)
|
|
74
|
+
let v = decryptBlock(y, cfg.halfBits, keys)
|
|
75
|
+
while (v >= cfg.n) v = decryptBlock(v, cfg.halfBits, keys)
|
|
76
|
+
return v
|
|
77
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type {Checksum256Type} from '@wharfkit/antelope'
|
|
2
|
+
import {REGION_FEISTEL, REGION_PER_AXIS} from './constants'
|
|
3
|
+
import {permute, unpermute} from './permutation'
|
|
4
|
+
|
|
5
|
+
// FROZEN INTERFACE — phoneme tables; tune aesthetics before launch, then never reorder.
|
|
6
|
+
const ONSETS = ['b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't'] // 12
|
|
7
|
+
const VOWELS = ['a', 'e', 'i', 'o', 'u'] // 5
|
|
8
|
+
const CODAS = ['n', 'r', 'l', 's', 'k', 'm', 't', 'x'] // 8
|
|
9
|
+
const SYL_BASE = ONSETS.length * VOWELS.length * CODAS.length // 480
|
|
10
|
+
|
|
11
|
+
function syllable(digit: number): string {
|
|
12
|
+
const onset = Math.floor(digit / (VOWELS.length * CODAS.length))
|
|
13
|
+
const rem = digit % (VOWELS.length * CODAS.length)
|
|
14
|
+
const vowel = Math.floor(rem / CODAS.length)
|
|
15
|
+
const coda = rem % CODAS.length
|
|
16
|
+
return ONSETS[onset] + VOWELS[vowel] + CODAS[coda]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function unsyllable(chunk: string): number {
|
|
20
|
+
const onset = ONSETS.indexOf(chunk[0])
|
|
21
|
+
const vowel = VOWELS.indexOf(chunk[1])
|
|
22
|
+
const coda = CODAS.indexOf(chunk[2])
|
|
23
|
+
if (onset < 0 || vowel < 0 || coda < 0) throw new Error(`invalid region token chunk: ${chunk}`)
|
|
24
|
+
return onset * (VOWELS.length * CODAS.length) + vowel * CODAS.length + coda
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function encodeRegion(seed: Checksum256Type, rx: number, ry: number): string {
|
|
28
|
+
const index = rx * REGION_PER_AXIS + ry
|
|
29
|
+
let n = permute(seed, index, REGION_FEISTEL)
|
|
30
|
+
const d0 = n % SYL_BASE
|
|
31
|
+
n = Math.floor(n / SYL_BASE)
|
|
32
|
+
const d1 = n % SYL_BASE
|
|
33
|
+
const d2 = Math.floor(n / SYL_BASE)
|
|
34
|
+
const token = syllable(d2) + syllable(d1) + syllable(d0)
|
|
35
|
+
return token.charAt(0).toUpperCase() + token.slice(1)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function decodeRegion(seed: Checksum256Type, token: string): {rx: number; ry: number} {
|
|
39
|
+
if (token.length !== 9) throw new Error(`invalid region token length: ${token}`)
|
|
40
|
+
const lower = token.toLowerCase()
|
|
41
|
+
const d2 = unsyllable(lower.slice(0, 3))
|
|
42
|
+
const d1 = unsyllable(lower.slice(3, 6))
|
|
43
|
+
const d0 = unsyllable(lower.slice(6, 9))
|
|
44
|
+
const scrambled = (d2 * SYL_BASE + d1) * SYL_BASE + d0
|
|
45
|
+
if (scrambled >= REGION_FEISTEL.n) throw new Error(`invalid region token: ${token}`)
|
|
46
|
+
const index = unpermute(seed, scrambled, REGION_FEISTEL)
|
|
47
|
+
return {rx: Math.floor(index / REGION_PER_AXIS), ry: index % REGION_PER_AXIS}
|
|
48
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type {Checksum256Type} from '@wharfkit/antelope'
|
|
2
|
+
import {SECTOR_FEISTEL, SECTORS_PER_AXIS} from './constants'
|
|
3
|
+
import {permute, unpermute} from './permutation'
|
|
4
|
+
|
|
5
|
+
// FROZEN INTERFACE — curation seed; review before launch, then never reorder.
|
|
6
|
+
export const SECTOR_ADJECTIVES: readonly string[] = [
|
|
7
|
+
'Amber',
|
|
8
|
+
'Azure',
|
|
9
|
+
'Brass',
|
|
10
|
+
'Cinder',
|
|
11
|
+
'Cobalt',
|
|
12
|
+
'Copper',
|
|
13
|
+
'Coral',
|
|
14
|
+
'Crimson',
|
|
15
|
+
'Crystal',
|
|
16
|
+
'Dusk',
|
|
17
|
+
'Ember',
|
|
18
|
+
'Emerald',
|
|
19
|
+
'Frost',
|
|
20
|
+
'Glimmer',
|
|
21
|
+
'Golden',
|
|
22
|
+
'Hazy',
|
|
23
|
+
'Indigo',
|
|
24
|
+
'Iron',
|
|
25
|
+
'Ivory',
|
|
26
|
+
'Jade',
|
|
27
|
+
'Lunar',
|
|
28
|
+
'Misty',
|
|
29
|
+
'Neon',
|
|
30
|
+
'Onyx',
|
|
31
|
+
'Opal',
|
|
32
|
+
'Pearl',
|
|
33
|
+
'Plasma',
|
|
34
|
+
'Quartz',
|
|
35
|
+
'Rusty',
|
|
36
|
+
'Saffron',
|
|
37
|
+
'Scarlet',
|
|
38
|
+
'Silver',
|
|
39
|
+
'Solar',
|
|
40
|
+
'Static',
|
|
41
|
+
'Stormy',
|
|
42
|
+
'Sunny',
|
|
43
|
+
'Teal',
|
|
44
|
+
'Umber',
|
|
45
|
+
'Velvet',
|
|
46
|
+
'Verdant',
|
|
47
|
+
'Vermilion',
|
|
48
|
+
'Violet',
|
|
49
|
+
'Wispy',
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
export const SECTOR_NOUNS: readonly string[] = [
|
|
53
|
+
'Belt',
|
|
54
|
+
'Bluff',
|
|
55
|
+
'Cluster',
|
|
56
|
+
'Coil',
|
|
57
|
+
'Crest',
|
|
58
|
+
'Drift',
|
|
59
|
+
'Expanse',
|
|
60
|
+
'Fathom',
|
|
61
|
+
'Flare',
|
|
62
|
+
'Gulf',
|
|
63
|
+
'Halo',
|
|
64
|
+
'Haven',
|
|
65
|
+
'Hollow',
|
|
66
|
+
'Maw',
|
|
67
|
+
'Mesa',
|
|
68
|
+
'Mire',
|
|
69
|
+
'Notch',
|
|
70
|
+
'Nook',
|
|
71
|
+
'Oasis',
|
|
72
|
+
'Lagoon',
|
|
73
|
+
'Peak',
|
|
74
|
+
'Pocket',
|
|
75
|
+
'Reach',
|
|
76
|
+
'Reef',
|
|
77
|
+
'Ridge',
|
|
78
|
+
'Rift',
|
|
79
|
+
'Run',
|
|
80
|
+
'Shoal',
|
|
81
|
+
'Shroud',
|
|
82
|
+
'Span',
|
|
83
|
+
'Spire',
|
|
84
|
+
'Spur',
|
|
85
|
+
'Stretch',
|
|
86
|
+
'Sprawl',
|
|
87
|
+
'Tangle',
|
|
88
|
+
'Trace',
|
|
89
|
+
'Trench',
|
|
90
|
+
'Vale',
|
|
91
|
+
'Vault',
|
|
92
|
+
'Verge',
|
|
93
|
+
'Vortex',
|
|
94
|
+
'Ward',
|
|
95
|
+
'Wisp',
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
export function encodeSector(seed: Checksum256Type, sx: number, sy: number): string {
|
|
99
|
+
const index = sx * SECTORS_PER_AXIS + sy
|
|
100
|
+
const scrambled = permute(seed, index, SECTOR_FEISTEL)
|
|
101
|
+
const adj = Math.floor(scrambled / SECTORS_PER_AXIS)
|
|
102
|
+
const noun = scrambled % SECTORS_PER_AXIS
|
|
103
|
+
return `${SECTOR_ADJECTIVES[adj]} ${SECTOR_NOUNS[noun]}`
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function decodeSector(seed: Checksum256Type, name: string): {sx: number; sy: number} {
|
|
107
|
+
const parts = name.trim().split(/\s+/)
|
|
108
|
+
if (parts.length !== 2) throw new Error(`invalid sector name: ${name}`)
|
|
109
|
+
const adj = SECTOR_ADJECTIVES.indexOf(parts[0])
|
|
110
|
+
const noun = SECTOR_NOUNS.indexOf(parts[1])
|
|
111
|
+
if (adj < 0 || noun < 0) throw new Error(`unknown sector name: ${name}`)
|
|
112
|
+
const scrambled = adj * SECTORS_PER_AXIS + noun
|
|
113
|
+
const index = unpermute(seed, scrambled, SECTOR_FEISTEL)
|
|
114
|
+
return {sx: Math.floor(index / SECTORS_PER_AXIS), sy: index % SECTORS_PER_AXIS}
|
|
115
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type {Checksum256Type} from '@wharfkit/antelope'
|
|
2
|
+
import {hash512} from '../utils/hash'
|
|
3
|
+
|
|
4
|
+
export const WH = {
|
|
5
|
+
RSIZE: 75,
|
|
6
|
+
ZONE: 16384,
|
|
7
|
+
THRESHOLD: 8192,
|
|
8
|
+
MIN_REACH: 50000,
|
|
9
|
+
TRANSIT_SPEED: 500,
|
|
10
|
+
} as const
|
|
11
|
+
|
|
12
|
+
const HALF = Math.round(Math.log2(WH.ZONE))
|
|
13
|
+
const MASK = WH.ZONE - 1
|
|
14
|
+
|
|
15
|
+
function roll16(seed: Checksum256Type, str: string): number {
|
|
16
|
+
const h = hash512(seed, str).array
|
|
17
|
+
return (h[0] << 8) | h[1]
|
|
18
|
+
}
|
|
19
|
+
function feistelF(seed: Checksum256Type, x: number, round: number, key: string): number {
|
|
20
|
+
return roll16(seed, `feistel-${key}-${round}-${x}`) & MASK
|
|
21
|
+
}
|
|
22
|
+
export function feistel(seed: Checksum256Type, idx: number, key: string): number {
|
|
23
|
+
let L = (idx >>> HALF) & MASK
|
|
24
|
+
let R = idx & MASK
|
|
25
|
+
for (let r = 0; r < 4; r++) {
|
|
26
|
+
const nR = L ^ feistelF(seed, R, r, key)
|
|
27
|
+
L = R
|
|
28
|
+
R = nR
|
|
29
|
+
}
|
|
30
|
+
return (L << HALF) | R
|
|
31
|
+
}
|
|
32
|
+
export function feistelInv(seed: Checksum256Type, idx: number, key: string): number {
|
|
33
|
+
let L = (idx >>> HALF) & MASK
|
|
34
|
+
let R = idx & MASK
|
|
35
|
+
for (let r = 3; r >= 0; r--) {
|
|
36
|
+
const nL = R ^ feistelF(seed, L, r, key)
|
|
37
|
+
R = L
|
|
38
|
+
L = nL
|
|
39
|
+
}
|
|
40
|
+
return (L << HALF) | R
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
type Region = {rx: number; ry: number}
|
|
44
|
+
|
|
45
|
+
export function regionOf(x: number, y: number): Region {
|
|
46
|
+
return {rx: Math.floor(x / WH.RSIZE), ry: Math.floor(y / WH.RSIZE)}
|
|
47
|
+
}
|
|
48
|
+
export function partnerRegion(seed: Checksum256Type, R: Region): Region {
|
|
49
|
+
const qx = Math.floor(R.rx / WH.ZONE)
|
|
50
|
+
const qy = Math.floor(R.ry / WH.ZONE)
|
|
51
|
+
const zx = qx * WH.ZONE
|
|
52
|
+
const zy = qy * WH.ZONE
|
|
53
|
+
const key = `${qx}:${qy}`
|
|
54
|
+
const idx = (R.ry - zy) * WH.ZONE + (R.rx - zx)
|
|
55
|
+
const p = feistelInv(seed, feistel(seed, idx, key) ^ 1, key)
|
|
56
|
+
return {rx: zx + (p % WH.ZONE), ry: zy + Math.floor(p / WH.ZONE)}
|
|
57
|
+
}
|
|
58
|
+
function regKey(R: Region): string {
|
|
59
|
+
return `${R.rx}:${R.ry}`
|
|
60
|
+
}
|
|
61
|
+
function pairKey(a: Region, b: Region): string {
|
|
62
|
+
const ka = regKey(a)
|
|
63
|
+
const kb = regKey(b)
|
|
64
|
+
return ka < kb ? `${ka}|${kb}` : `${kb}|${ka}`
|
|
65
|
+
}
|
|
66
|
+
function endpointInRegion(seed: Checksum256Type, R: Region, key: string): {x: number; y: number} {
|
|
67
|
+
const h = hash512(seed, `wh-endpoint-${key}-${regKey(R)}`).array
|
|
68
|
+
const ox = ((h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3]) >>> 0
|
|
69
|
+
const oy = ((h[4] << 24) | (h[5] << 16) | (h[6] << 8) | h[7]) >>> 0
|
|
70
|
+
return {x: R.rx * WH.RSIZE + (ox % WH.RSIZE), y: R.ry * WH.RSIZE + (oy % WH.RSIZE)}
|
|
71
|
+
}
|
|
72
|
+
function dist(a: {x: number; y: number}, b: {x: number; y: number}): number {
|
|
73
|
+
return Math.sqrt((a.x - b.x) ** 2 + (a.y - b.y) ** 2)
|
|
74
|
+
}
|
|
75
|
+
function wormholeOfRegion(
|
|
76
|
+
seed: Checksum256Type,
|
|
77
|
+
R: Region
|
|
78
|
+
): {A: {x: number; y: number}; B: {x: number; y: number}} | null {
|
|
79
|
+
const P = partnerRegion(seed, R)
|
|
80
|
+
if (P.rx === R.rx && P.ry === R.ry) return null
|
|
81
|
+
const key = pairKey(R, P)
|
|
82
|
+
if (roll16(seed, `wh-exists-${key}`) >= WH.THRESHOLD) return null
|
|
83
|
+
const A = endpointInRegion(seed, R, key)
|
|
84
|
+
const B = endpointInRegion(seed, P, key)
|
|
85
|
+
if (dist(A, B) < WH.MIN_REACH) return null
|
|
86
|
+
return {A, B}
|
|
87
|
+
}
|
|
88
|
+
export function wormholeAtRegionEndpoint(
|
|
89
|
+
seed: Checksum256Type,
|
|
90
|
+
rx: number,
|
|
91
|
+
ry: number
|
|
92
|
+
): {from: {x: number; y: number}; to: {x: number; y: number}} | null {
|
|
93
|
+
const w = wormholeOfRegion(seed, {rx, ry})
|
|
94
|
+
if (!w) return null
|
|
95
|
+
return {from: w.A, to: w.B}
|
|
96
|
+
}
|
|
97
|
+
export function wormholeAt(
|
|
98
|
+
seed: Checksum256Type,
|
|
99
|
+
x: number,
|
|
100
|
+
y: number
|
|
101
|
+
): {x: number; y: number} | null {
|
|
102
|
+
const w = wormholeOfRegion(seed, regionOf(x, y))
|
|
103
|
+
if (!w || w.A.x !== x || w.A.y !== y) return null
|
|
104
|
+
return w.B
|
|
105
|
+
}
|
|
106
|
+
export function isValidWormholePair(
|
|
107
|
+
seed: Checksum256Type,
|
|
108
|
+
ax: number,
|
|
109
|
+
ay: number,
|
|
110
|
+
bx: number,
|
|
111
|
+
by: number
|
|
112
|
+
): boolean {
|
|
113
|
+
const to = wormholeAt(seed, ax, ay)
|
|
114
|
+
return to !== null && to.x === bx && to.y === by
|
|
115
|
+
}
|
package/src/errors.ts
CHANGED
|
@@ -56,6 +56,8 @@ export const GROUP_HAUL_CAPACITY_EXCEEDED =
|
|
|
56
56
|
'Group travel requires sufficient hauler capacity for all non-self-propelled entities.'
|
|
57
57
|
export const CANCEL_CONTAINS_GROUPED_TASK =
|
|
58
58
|
'Cannot cancel range containing grouped task - cancel non-grouped tasks first.'
|
|
59
|
+
export const WOULD_STRAND = 'Cancelling this would leave a later task without the cargo it needs.'
|
|
60
|
+
export const WOULD_OVERFILL = 'Cancelling this would overfill the other entity with returned cargo.'
|
|
59
61
|
export const WARP_NO_CAPABILITY = 'Entity does not have warp capability.'
|
|
60
62
|
export const WARP_HAS_SCHEDULE = 'Entity must be idle to warp.'
|
|
61
63
|
export const WARP_HAS_CARGO = 'Entity must have no cargo to warp.'
|
package/src/index-module.ts
CHANGED
|
@@ -87,6 +87,7 @@ export type {EpochInfo} from './scheduling/epoch'
|
|
|
87
87
|
export {
|
|
88
88
|
getSystemName,
|
|
89
89
|
hasSystem,
|
|
90
|
+
getLocationKind,
|
|
90
91
|
getLocationType,
|
|
91
92
|
getLocationTypeName,
|
|
92
93
|
isGatherableLocation,
|
|
@@ -164,6 +165,7 @@ export {
|
|
|
164
165
|
calc_ship_mass,
|
|
165
166
|
calc_ship_rechargetime,
|
|
166
167
|
calc_transfer_duration,
|
|
168
|
+
calc_transit_duration,
|
|
167
169
|
calculateFlightTime,
|
|
168
170
|
calculateLoadTimeBreakdown,
|
|
169
171
|
calculateRefuelingTime,
|
|
@@ -232,6 +234,15 @@ export type {TaskCargoChange, TaskCargoDirection} from './scheduling/task-cargo'
|
|
|
232
234
|
export {composeIdleResolve} from './scheduling/idle-resolve'
|
|
233
235
|
export type {CounterpartLookup, IdleResolveTarget} from './scheduling/idle-resolve'
|
|
234
236
|
|
|
237
|
+
export {cancelEligibility, CancelBlockReason} from './scheduling/cancel'
|
|
238
|
+
export type {
|
|
239
|
+
CancelPlan,
|
|
240
|
+
CancelEffects,
|
|
241
|
+
CancelRefund,
|
|
242
|
+
CancelReleasedHold,
|
|
243
|
+
CancelEligibilityInput,
|
|
244
|
+
} from './scheduling/cancel'
|
|
245
|
+
|
|
235
246
|
export {
|
|
236
247
|
projectedCargoAvailableAt,
|
|
237
248
|
availableForItem,
|
|
@@ -356,6 +367,17 @@ export {
|
|
|
356
367
|
} from './derivation/capabilities'
|
|
357
368
|
export type {GathererDepthParams, ComputedCapabilities} from './derivation/capabilities'
|
|
358
369
|
|
|
370
|
+
export {
|
|
371
|
+
WH,
|
|
372
|
+
feistel,
|
|
373
|
+
feistelInv,
|
|
374
|
+
regionOf,
|
|
375
|
+
partnerRegion,
|
|
376
|
+
wormholeAt,
|
|
377
|
+
wormholeAtRegionEndpoint,
|
|
378
|
+
isValidWormholePair,
|
|
379
|
+
} from './derivation/wormhole'
|
|
380
|
+
|
|
359
381
|
export {resolveItem} from './resolution/resolve-item'
|
|
360
382
|
export type {
|
|
361
383
|
ResolvedItem,
|
|
@@ -460,6 +482,7 @@ export {
|
|
|
460
482
|
} from './data/tiers'
|
|
461
483
|
|
|
462
484
|
export {formatMass, formatMassDelta, formatMassScaled, formatLocation} from './format'
|
|
485
|
+
export * from './coordinates'
|
|
463
486
|
|
|
464
487
|
export {displayName, baseName, describeItem} from './resolution/display-name'
|
|
465
488
|
export type {DescribeOptions} from './resolution/display-name'
|
package/src/managers/actions.ts
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
Checksum256,
|
|
4
4
|
type Checksum256Type,
|
|
5
5
|
Int64,
|
|
6
|
+
type Int64Type,
|
|
6
7
|
Name,
|
|
7
8
|
type NameType,
|
|
8
9
|
UInt8,
|
|
@@ -37,13 +38,17 @@ export class ActionsManager extends BaseManager {
|
|
|
37
38
|
})
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
private entityRefs(entities: EntityRefInput[]) {
|
|
42
|
+
return entities.map((e) =>
|
|
42
43
|
ServerContract.Types.entity_ref.from({
|
|
43
44
|
entity_type: e.entityType,
|
|
44
45
|
entity_id: UInt64.from(e.entityId),
|
|
45
46
|
})
|
|
46
47
|
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
grouptravel(entities: EntityRefInput[], destination: CoordinatesType, recharge = true): Action {
|
|
51
|
+
const entityRefs = this.entityRefs(entities)
|
|
47
52
|
const x = Int64.from(destination.x)
|
|
48
53
|
const y = Int64.from(destination.y)
|
|
49
54
|
|
|
@@ -55,6 +60,44 @@ export class ActionsManager extends BaseManager {
|
|
|
55
60
|
})
|
|
56
61
|
}
|
|
57
62
|
|
|
63
|
+
transit(shipId: UInt64Type, entrance: CoordinatesType, exit: CoordinatesType): Action {
|
|
64
|
+
return this.server.action('transit', {
|
|
65
|
+
id: UInt64.from(shipId),
|
|
66
|
+
ax: Int64.from(entrance.x),
|
|
67
|
+
ay: Int64.from(entrance.y),
|
|
68
|
+
bx: Int64.from(exit.x),
|
|
69
|
+
by: Int64.from(exit.y),
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
grouptransit(
|
|
74
|
+
entities: EntityRefInput[],
|
|
75
|
+
entrance: CoordinatesType,
|
|
76
|
+
exit: CoordinatesType
|
|
77
|
+
): Action {
|
|
78
|
+
const entityRefs = this.entityRefs(entities)
|
|
79
|
+
return this.server.action('grouptransit', {
|
|
80
|
+
entities: entityRefs,
|
|
81
|
+
ax: Int64.from(entrance.x),
|
|
82
|
+
ay: Int64.from(entrance.y),
|
|
83
|
+
bx: Int64.from(exit.x),
|
|
84
|
+
by: Int64.from(exit.y),
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
getwormhole(x: Int64Type, y: Int64Type): Action {
|
|
89
|
+
return this.server.action('getwormhole', {x: Int64.from(x), y: Int64.from(y)})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
getdistance(origin: CoordinatesType, destination: CoordinatesType): Action {
|
|
93
|
+
return this.server.action('getdistance', {
|
|
94
|
+
ax: Int64.from(origin.x),
|
|
95
|
+
ay: Int64.from(origin.y),
|
|
96
|
+
bx: Int64.from(destination.x),
|
|
97
|
+
by: Int64.from(destination.y),
|
|
98
|
+
})
|
|
99
|
+
}
|
|
100
|
+
|
|
58
101
|
resolve(entityId: UInt64Type, count?: UInt64Type): Action {
|
|
59
102
|
const params: ServerContract.ActionParams.resolve = {
|
|
60
103
|
id: UInt64.from(entityId),
|
|
@@ -36,7 +36,7 @@ export function taskCargoEffect(task: Task): CargoEffect {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
function cargoKey(item: CargoItem): string {
|
|
39
|
+
export function cargoKey(item: CargoItem): string {
|
|
40
40
|
const base = `${item.item_id.toNumber()}:${item.stats.toString()}`
|
|
41
41
|
const modules = item.modules ?? []
|
|
42
42
|
const entityId = item.entity_id?.toString()
|