@shipload/sdk 2.0.0-rc1 → 2.0.0-rc11
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 +1701 -1183
- package/lib/shipload.js +6746 -3447
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +6429 -3229
- package/lib/shipload.m.js.map +1 -1
- package/package.json +6 -6
- package/src/capabilities/crafting.ts +26 -0
- package/src/capabilities/gathering.ts +36 -0
- package/src/capabilities/guards.ts +38 -0
- package/src/capabilities/hauling.ts +22 -0
- package/src/capabilities/index.ts +8 -0
- package/src/capabilities/loading.ts +8 -0
- package/src/capabilities/modules.ts +57 -0
- package/src/capabilities/movement.ts +29 -0
- package/src/capabilities/storage.ts +72 -0
- package/src/contracts/server.ts +932 -314
- package/src/data/capabilities.ts +408 -0
- package/src/data/categories.ts +58 -0
- package/src/data/colors.ts +53 -0
- package/src/data/items.json +17 -0
- package/src/data/locations.ts +53 -0
- package/src/data/nebula-adjectives.json +211 -0
- package/src/data/nebula-nouns.json +151 -0
- package/src/data/recipes.ts +571 -0
- package/src/data/syllables.json +1386 -780
- package/src/data/tiers.ts +45 -0
- package/src/derivation/crafting.ts +197 -0
- package/src/derivation/index.ts +28 -0
- package/src/derivation/location-size.ts +15 -0
- package/src/derivation/resources.ts +142 -0
- package/src/derivation/stats.ts +146 -0
- package/src/derivation/stratum.ts +124 -0
- package/src/entities/cargo-utils.ts +46 -9
- package/src/entities/container.ts +106 -0
- package/src/entities/entity-inventory.ts +13 -13
- package/src/entities/inventory-accessor.ts +42 -0
- package/src/entities/location.ts +7 -188
- package/src/entities/makers.ts +72 -0
- package/src/entities/player.ts +1 -273
- package/src/entities/ship-deploy.ts +263 -0
- package/src/entities/ship.ts +93 -453
- package/src/entities/warehouse.ts +34 -148
- package/src/errors.ts +4 -4
- package/src/index-module.ts +226 -42
- package/src/managers/actions.ts +111 -79
- package/src/managers/context.ts +0 -9
- package/src/managers/entities.ts +22 -5
- package/src/managers/index.ts +0 -1
- package/src/managers/locations.ts +15 -79
- package/src/market/items.ts +30 -0
- package/src/nft/description.ts +175 -0
- package/src/nft/deserializers.ts +81 -0
- package/src/nft/index.ts +2 -0
- package/src/resolution/resolve-item.ts +313 -0
- package/src/scheduling/accessor.ts +82 -0
- package/src/scheduling/projection.ts +158 -54
- package/src/scheduling/schedule.ts +24 -0
- package/src/shipload.ts +0 -5
- package/src/travel/travel.ts +93 -19
- package/src/types/capabilities.ts +71 -0
- package/src/types/entity-traits.ts +69 -0
- package/src/types/entity.ts +39 -0
- package/src/types/index.ts +3 -0
- package/src/types.ts +76 -33
- package/src/utils/hash.ts +1 -1
- package/src/utils/system.ts +148 -11
- package/src/data/goods.json +0 -23
- package/src/managers/trades.ts +0 -119
- package/src/market/goods.ts +0 -31
- package/src/market/market.ts +0 -209
- package/src/market/rolls.ts +0 -8
- package/src/trading/collect.ts +0 -939
- package/src/trading/deal.ts +0 -208
- package/src/trading/trade.ts +0 -203
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import {Name} from '@wharfkit/antelope'
|
|
2
|
+
|
|
3
|
+
export const ENTITY_SHIP = Name.from('ship')
|
|
4
|
+
export const ENTITY_WAREHOUSE = Name.from('warehouse')
|
|
5
|
+
export const ENTITY_CONTAINER = Name.from('container')
|
|
6
|
+
|
|
7
|
+
export type EntityTypeName = 'ship' | 'warehouse' | 'container'
|
|
8
|
+
|
|
9
|
+
export interface EntityTraits {
|
|
10
|
+
typeName: Name
|
|
11
|
+
isMovable: boolean
|
|
12
|
+
hasEnergy: boolean
|
|
13
|
+
hasLoaders: boolean
|
|
14
|
+
notFoundError: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const shipTraits: EntityTraits = {
|
|
18
|
+
typeName: ENTITY_SHIP,
|
|
19
|
+
isMovable: true,
|
|
20
|
+
hasEnergy: true,
|
|
21
|
+
hasLoaders: true,
|
|
22
|
+
|
|
23
|
+
notFoundError: 'ship not found',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const warehouseTraits: EntityTraits = {
|
|
27
|
+
typeName: ENTITY_WAREHOUSE,
|
|
28
|
+
isMovable: false,
|
|
29
|
+
hasEnergy: false,
|
|
30
|
+
hasLoaders: true,
|
|
31
|
+
|
|
32
|
+
notFoundError: 'warehouse not found',
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const containerTraits: EntityTraits = {
|
|
36
|
+
typeName: ENTITY_CONTAINER,
|
|
37
|
+
isMovable: true,
|
|
38
|
+
hasEnergy: false,
|
|
39
|
+
hasLoaders: false,
|
|
40
|
+
|
|
41
|
+
notFoundError: 'container not found',
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function getEntityTraits(entityType: Name | EntityTypeName): EntityTraits {
|
|
45
|
+
const typeName = typeof entityType === 'string' ? entityType : entityType.toString()
|
|
46
|
+
|
|
47
|
+
switch (typeName) {
|
|
48
|
+
case 'ship':
|
|
49
|
+
return shipTraits
|
|
50
|
+
case 'warehouse':
|
|
51
|
+
return warehouseTraits
|
|
52
|
+
case 'container':
|
|
53
|
+
return containerTraits
|
|
54
|
+
default:
|
|
55
|
+
throw new Error(`Unknown entity type: ${typeName}`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function isShip(entity: {type?: Name}): boolean {
|
|
60
|
+
return entity.type?.equals(ENTITY_SHIP) ?? false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isWarehouse(entity: {type?: Name}): boolean {
|
|
64
|
+
return entity.type?.equals(ENTITY_WAREHOUSE) ?? false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function isContainer(entity: {type?: Name}): boolean {
|
|
68
|
+
return entity.type?.equals(ENTITY_CONTAINER) ?? false
|
|
69
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {Name, UInt64} from '@wharfkit/antelope'
|
|
2
|
+
import {ServerContract} from '../contracts'
|
|
3
|
+
import {Coordinates} from '../types'
|
|
4
|
+
import {
|
|
5
|
+
EnergyCapability,
|
|
6
|
+
LoaderCapability,
|
|
7
|
+
MassCapability,
|
|
8
|
+
MovementCapability,
|
|
9
|
+
ScheduleCapability,
|
|
10
|
+
StorageCapability,
|
|
11
|
+
} from './capabilities'
|
|
12
|
+
|
|
13
|
+
export interface Entity {
|
|
14
|
+
id: UInt64
|
|
15
|
+
type: Name
|
|
16
|
+
owner: Name
|
|
17
|
+
entity_name: string
|
|
18
|
+
location: Coordinates | ServerContract.Types.coordinates
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type ShipEntity = Entity &
|
|
22
|
+
Partial<MovementCapability> &
|
|
23
|
+
Partial<EnergyCapability> &
|
|
24
|
+
StorageCapability &
|
|
25
|
+
Partial<LoaderCapability> &
|
|
26
|
+
MassCapability &
|
|
27
|
+
ScheduleCapability & {
|
|
28
|
+
gatherer?: ServerContract.Types.gatherer_stats
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type WarehouseEntity = Entity &
|
|
32
|
+
StorageCapability &
|
|
33
|
+
Partial<LoaderCapability> &
|
|
34
|
+
MassCapability &
|
|
35
|
+
ScheduleCapability
|
|
36
|
+
|
|
37
|
+
export type ContainerEntity = Entity & StorageCapability & MassCapability & ScheduleCapability
|
|
38
|
+
|
|
39
|
+
export type AnyEntity = ShipEntity | WarehouseEntity | ContainerEntity
|
package/src/types.ts
CHANGED
|
@@ -1,43 +1,78 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Int64Type,
|
|
3
|
+
Name,
|
|
4
|
+
Struct,
|
|
5
|
+
UInt16,
|
|
6
|
+
UInt16Type,
|
|
7
|
+
UInt32,
|
|
8
|
+
UInt32Type,
|
|
9
|
+
UInt64,
|
|
10
|
+
} from '@wharfkit/antelope'
|
|
2
11
|
import {ServerContract} from './contracts'
|
|
3
12
|
|
|
4
13
|
export const PRECISION = 10000
|
|
14
|
+
export const CRAFT_ENERGY_DIVISOR = 150000
|
|
15
|
+
|
|
16
|
+
export const WAREHOUSE_Z = 500
|
|
17
|
+
export const INITIAL_WAREHOUSE_CAPACITY = 10000000
|
|
18
|
+
|
|
19
|
+
export const CONTAINER_Z = 300
|
|
20
|
+
export const INITIAL_CONTAINER_HULLMASS = 50000
|
|
21
|
+
export const INITIAL_CONTAINER_CAPACITY = 2000000
|
|
22
|
+
|
|
23
|
+
export const TRAVEL_MAX_DURATION = 86400
|
|
5
24
|
|
|
6
|
-
export const INITIAL_SHIP_MASS = 500000
|
|
7
25
|
export const MIN_ORBITAL_ALTITUDE = 800
|
|
8
26
|
export const MAX_ORBITAL_ALTITUDE = 3000
|
|
9
27
|
|
|
28
|
+
export const BASE_ORBITAL_MASS = 100000
|
|
29
|
+
|
|
10
30
|
export interface ShipLike {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
energy
|
|
14
|
-
engines
|
|
15
|
-
generator
|
|
16
|
-
loaders
|
|
17
|
-
|
|
31
|
+
coordinates: ServerContract.Types.coordinates
|
|
32
|
+
hullmass?: UInt32
|
|
33
|
+
energy?: UInt16
|
|
34
|
+
engines?: ServerContract.Types.movement_stats
|
|
35
|
+
generator?: ServerContract.Types.energy_stats
|
|
36
|
+
loaders?: ServerContract.Types.loader_stats
|
|
37
|
+
hauler?: ServerContract.Types.hauler_stats
|
|
38
|
+
capacity?: UInt32
|
|
18
39
|
}
|
|
19
40
|
|
|
20
41
|
export interface CargoMassInfo {
|
|
21
|
-
|
|
42
|
+
item_id: UInt16Type
|
|
22
43
|
quantity: UInt32Type
|
|
23
44
|
}
|
|
24
45
|
|
|
25
46
|
export enum TaskType {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
47
|
+
IDLE = 0,
|
|
48
|
+
TRAVEL = 1,
|
|
49
|
+
RECHARGE = 2,
|
|
50
|
+
LOAD = 3,
|
|
51
|
+
UNLOAD = 4,
|
|
52
|
+
GATHER = 5,
|
|
53
|
+
WARP = 6,
|
|
54
|
+
CRAFT = 7,
|
|
55
|
+
DEPLOY = 8,
|
|
56
|
+
DEPLOY_SHIP = 9,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export enum LocationType {
|
|
60
|
+
EMPTY = 0,
|
|
61
|
+
PLANET = 1,
|
|
62
|
+
ASTEROID = 2,
|
|
63
|
+
NEBULA = 3,
|
|
30
64
|
}
|
|
31
65
|
|
|
32
66
|
export enum TaskCancelable {
|
|
33
|
-
NEVER = 0,
|
|
34
|
-
BEFORE_START = 1,
|
|
35
|
-
ALWAYS = 2,
|
|
67
|
+
NEVER = 0,
|
|
68
|
+
BEFORE_START = 1,
|
|
69
|
+
ALWAYS = 2,
|
|
36
70
|
}
|
|
37
71
|
|
|
38
72
|
export const EntityType = {
|
|
39
73
|
SHIP: Name.from('ship'),
|
|
40
74
|
WAREHOUSE: Name.from('warehouse'),
|
|
75
|
+
CONTAINER: Name.from('container'),
|
|
41
76
|
} as const
|
|
42
77
|
|
|
43
78
|
export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
|
|
@@ -56,6 +91,19 @@ export class Coordinates extends ServerContract.Types.coordinates {
|
|
|
56
91
|
const coords = Coordinates.from(other)
|
|
57
92
|
return this.x.equals(coords.x) && this.y.equals(coords.y)
|
|
58
93
|
}
|
|
94
|
+
|
|
95
|
+
toLocationId(): UInt64 {
|
|
96
|
+
return coordsToLocationId(this)
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function coordsToLocationId(coords: CoordinatesType): UInt64 {
|
|
101
|
+
const c = Coordinates.from(coords)
|
|
102
|
+
const mask = BigInt(0xffffffff)
|
|
103
|
+
const x = BigInt(c.x.toNumber()) & mask
|
|
104
|
+
const y = BigInt(c.y.toNumber()) & mask
|
|
105
|
+
const id = (x << BigInt(32)) | y
|
|
106
|
+
return UInt64.from(id)
|
|
59
107
|
}
|
|
60
108
|
|
|
61
109
|
export interface Distance {
|
|
@@ -64,8 +112,11 @@ export interface Distance {
|
|
|
64
112
|
distance: UInt16
|
|
65
113
|
}
|
|
66
114
|
|
|
67
|
-
|
|
68
|
-
export
|
|
115
|
+
export type ResourceCategory = 'metal' | 'precious' | 'gas' | 'mineral' | 'organic'
|
|
116
|
+
export type ResourceTier = 't1' | 't2' | 't3' | 't4' | 't5'
|
|
117
|
+
|
|
118
|
+
@Struct.type('item')
|
|
119
|
+
export class Item extends Struct {
|
|
69
120
|
@Struct.field(UInt16)
|
|
70
121
|
id!: UInt16
|
|
71
122
|
@Struct.field('string')
|
|
@@ -73,19 +124,11 @@ export class Good extends Struct {
|
|
|
73
124
|
@Struct.field('string')
|
|
74
125
|
description!: string
|
|
75
126
|
@Struct.field(UInt32)
|
|
76
|
-
base_price!: UInt32
|
|
77
|
-
@Struct.field(UInt32)
|
|
78
127
|
mass!: UInt32
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@Struct.
|
|
82
|
-
|
|
83
|
-
@Struct.field(
|
|
84
|
-
|
|
85
|
-
@Struct.field(Good)
|
|
86
|
-
good!: Good
|
|
87
|
-
@Struct.field(UInt32)
|
|
88
|
-
price!: UInt32
|
|
89
|
-
@Struct.field(UInt16)
|
|
90
|
-
supply!: UInt16
|
|
128
|
+
@Struct.field('string')
|
|
129
|
+
category!: ResourceCategory
|
|
130
|
+
@Struct.field('string')
|
|
131
|
+
tier!: ResourceTier
|
|
132
|
+
@Struct.field('string')
|
|
133
|
+
color!: string
|
|
91
134
|
}
|
package/src/utils/hash.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {Bytes, Checksum256, Checksum256Type, Checksum512} from '@wharfkit/antelope'
|
|
2
2
|
|
|
3
|
-
export function hash(seed: Checksum256Type, string: string):
|
|
3
|
+
export function hash(seed: Checksum256Type, string: string): Checksum256 {
|
|
4
4
|
const bytes = Bytes.from(`${seed}${string}`, 'utf8')
|
|
5
5
|
return Checksum256.hash(bytes)
|
|
6
6
|
}
|
package/src/utils/system.ts
CHANGED
|
@@ -1,27 +1,164 @@
|
|
|
1
|
-
import {Checksum256, Checksum256Type} from '@wharfkit/antelope'
|
|
1
|
+
import {Checksum256, Checksum256Type, Checksum512, UInt8} from '@wharfkit/antelope'
|
|
2
2
|
import {hash512} from './hash'
|
|
3
|
-
import {CoordinatesType} from '../types'
|
|
3
|
+
import {Coordinates, CoordinatesType, LocationType} from '../types'
|
|
4
|
+
import {ServerContract} from '../contracts'
|
|
5
|
+
import {deriveLocationSize} from '../derivation/location-size'
|
|
4
6
|
import syllables from '../data/syllables.json'
|
|
7
|
+
import nebulaAdjectives from '../data/nebula-adjectives.json'
|
|
8
|
+
import nebulaNouns from '../data/nebula-nouns.json'
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
const LOCATION_EXISTS_THRESHOLD = 0x10
|
|
11
|
+
const LOCATION_ACTIVE_THRESHOLD = 0x80
|
|
12
|
+
|
|
13
|
+
export function getLocationType(
|
|
14
|
+
gameSeed: Checksum256Type,
|
|
15
|
+
coordinates: CoordinatesType
|
|
16
|
+
): LocationType {
|
|
7
17
|
const seed = Checksum256.from(gameSeed)
|
|
8
|
-
|
|
9
|
-
|
|
18
|
+
const str = ['system', coordinates.x, coordinates.y].join('-')
|
|
19
|
+
const hashResult = hash512(seed, str)
|
|
20
|
+
|
|
21
|
+
if (hashResult.array[0] >= LOCATION_EXISTS_THRESHOLD) {
|
|
22
|
+
return LocationType.EMPTY
|
|
10
23
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
|
|
25
|
+
if (hashResult.array[1] < 96) {
|
|
26
|
+
return LocationType.PLANET
|
|
27
|
+
} else if (hashResult.array[1] < 176) {
|
|
28
|
+
return LocationType.ASTEROID
|
|
29
|
+
}
|
|
30
|
+
return LocationType.NEBULA
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isGatherableLocation(locationType: LocationType): boolean {
|
|
34
|
+
return locationType !== LocationType.EMPTY
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function getLocationTypeName(type: LocationType): string {
|
|
38
|
+
switch (type) {
|
|
39
|
+
case LocationType.EMPTY: return 'Empty'
|
|
40
|
+
case LocationType.PLANET: return 'Planet'
|
|
41
|
+
case LocationType.ASTEROID: return 'Asteroid'
|
|
42
|
+
case LocationType.NEBULA: return 'Nebula'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function uint16(hash: Checksum512, offset: number): number {
|
|
47
|
+
return (hash.array[offset] << 8) | hash.array[offset + 1]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function generatePlanetName(hashResult: Checksum512): string {
|
|
51
|
+
const syllableCount = 2 + (hashResult.array[0] % 2)
|
|
14
52
|
const name: string[] = []
|
|
15
53
|
for (let i = 0; i < syllableCount; i++) {
|
|
16
|
-
const index = hashResult
|
|
54
|
+
const index = uint16(hashResult, 1 + i * 2) % syllables.length
|
|
17
55
|
const syllable = syllables[index]
|
|
18
56
|
name.push(i > 0 ? syllable.toLowerCase() : syllable)
|
|
19
57
|
}
|
|
20
58
|
return name.join('')
|
|
21
59
|
}
|
|
22
60
|
|
|
61
|
+
function generateAsteroidName(hashResult: Checksum512): string {
|
|
62
|
+
const A = 65
|
|
63
|
+
const letter1 = String.fromCharCode(A + (hashResult.array[0] % 26))
|
|
64
|
+
const letter2 = String.fromCharCode(A + (hashResult.array[1] % 26))
|
|
65
|
+
const num = (uint16(hashResult, 2) % 9000) + 1000
|
|
66
|
+
return `${letter1}${letter2}-${num}`
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function generateNebulaName(hashResult: Checksum512): string {
|
|
70
|
+
const adjIdx = uint16(hashResult, 0) % nebulaAdjectives.length
|
|
71
|
+
const nounIdx = uint16(hashResult, 2) % nebulaNouns.length
|
|
72
|
+
return `${nebulaAdjectives[adjIdx]} ${nebulaNouns[nounIdx]}`
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
|
|
76
|
+
const seed = Checksum256.from(gameSeed)
|
|
77
|
+
const locationType = getLocationType(seed, location)
|
|
78
|
+
if (locationType === LocationType.EMPTY) {
|
|
79
|
+
throw new Error("System doesn't exist at location")
|
|
80
|
+
}
|
|
81
|
+
const seedStr = `${location.x}-${location.y}-${locationType}-name`
|
|
82
|
+
const hashResult = hash512(seed, seedStr)
|
|
83
|
+
switch (locationType) {
|
|
84
|
+
case LocationType.PLANET:
|
|
85
|
+
return generatePlanetName(hashResult)
|
|
86
|
+
case LocationType.ASTEROID:
|
|
87
|
+
return generateAsteroidName(hashResult)
|
|
88
|
+
case LocationType.NEBULA:
|
|
89
|
+
return generateNebulaName(hashResult)
|
|
90
|
+
default:
|
|
91
|
+
return generatePlanetName(hashResult)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
23
95
|
export function hasSystem(gameSeed: Checksum256Type, coordinates: CoordinatesType): boolean {
|
|
96
|
+
return getLocationType(gameSeed, coordinates) !== LocationType.EMPTY
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function deriveLocationStatic(
|
|
100
|
+
gameSeed: Checksum256Type,
|
|
101
|
+
coordinates: CoordinatesType
|
|
102
|
+
): ServerContract.Types.location_static {
|
|
24
103
|
const seed = Checksum256.from(gameSeed)
|
|
25
|
-
const
|
|
26
|
-
|
|
104
|
+
const coords = Coordinates.from(coordinates)
|
|
105
|
+
const str = `system-${coords.x}-${coords.y}`
|
|
106
|
+
const hashResult = hash512(seed, str)
|
|
107
|
+
|
|
108
|
+
const loc = ServerContract.Types.location_static.from({
|
|
109
|
+
coords: coords,
|
|
110
|
+
type: LocationType.EMPTY,
|
|
111
|
+
subtype: 0,
|
|
112
|
+
seed0: 0,
|
|
113
|
+
seed1: 0,
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
if (hashResult.array[0] >= LOCATION_EXISTS_THRESHOLD) {
|
|
117
|
+
return loc
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (hashResult.array[1] < 96) {
|
|
121
|
+
loc.type = UInt8.from(LocationType.PLANET)
|
|
122
|
+
} else if (hashResult.array[1] < 176) {
|
|
123
|
+
loc.type = UInt8.from(LocationType.ASTEROID)
|
|
124
|
+
} else {
|
|
125
|
+
loc.type = UInt8.from(LocationType.NEBULA)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
loc.subtype = UInt8.from(
|
|
129
|
+
Number(loc.type) === LocationType.PLANET ? hashResult.array[2] % 6 : hashResult.array[2]
|
|
130
|
+
)
|
|
131
|
+
loc.seed0 = UInt8.from(hashResult.array[3])
|
|
132
|
+
loc.seed1 = UInt8.from(hashResult.array[4])
|
|
133
|
+
|
|
134
|
+
return loc
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export function deriveLocationEpoch(
|
|
138
|
+
epochSeed: Checksum256Type,
|
|
139
|
+
coordinates: CoordinatesType
|
|
140
|
+
): ServerContract.Types.location_epoch {
|
|
141
|
+
const seed = Checksum256.from(epochSeed)
|
|
142
|
+
const coords = Coordinates.from(coordinates)
|
|
143
|
+
const str = `system-epoch-${coords.x}-${coords.y}`
|
|
144
|
+
const hashResult = hash512(seed, str)
|
|
145
|
+
|
|
146
|
+
return ServerContract.Types.location_epoch.from({
|
|
147
|
+
active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
|
|
148
|
+
seed0: hashResult.array[1],
|
|
149
|
+
seed1: hashResult.array[2],
|
|
150
|
+
})
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export function deriveLocation(
|
|
154
|
+
gameSeed: Checksum256Type,
|
|
155
|
+
epochSeed: Checksum256Type,
|
|
156
|
+
coordinates: CoordinatesType
|
|
157
|
+
): ServerContract.Types.location_derived {
|
|
158
|
+
const staticProps = deriveLocationStatic(gameSeed, coordinates)
|
|
159
|
+
return ServerContract.Types.location_derived.from({
|
|
160
|
+
static_props: staticProps,
|
|
161
|
+
epoch_props: deriveLocationEpoch(epochSeed, coordinates),
|
|
162
|
+
size: deriveLocationSize(staticProps),
|
|
163
|
+
})
|
|
27
164
|
}
|
package/src/data/goods.json
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": 1,
|
|
4
|
-
"name": "Hydrogen",
|
|
5
|
-
"description": "A lightweight fuel source essential for interstellar travel.",
|
|
6
|
-
"base_price": 50,
|
|
7
|
-
"mass": 15000
|
|
8
|
-
},
|
|
9
|
-
{
|
|
10
|
-
"id": 2,
|
|
11
|
-
"name": "Iron",
|
|
12
|
-
"description": "A versatile metal used in construction and manufacturing.",
|
|
13
|
-
"base_price": 125,
|
|
14
|
-
"mass": 40000
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"id": 3,
|
|
18
|
-
"name": "Copper",
|
|
19
|
-
"description": "A conductive metal vital for electronics and wiring.",
|
|
20
|
-
"base_price": 200,
|
|
21
|
-
"mass": 60000
|
|
22
|
-
}
|
|
23
|
-
]
|
package/src/managers/trades.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import {UInt64} from '@wharfkit/antelope'
|
|
2
|
-
import {BaseManager} from './base'
|
|
3
|
-
import {Ship} from '../entities/ship'
|
|
4
|
-
import {Deal, findDealsForShip, FindDealsOptions} from '../trading/deal'
|
|
5
|
-
import {
|
|
6
|
-
analyzeCollectOptions,
|
|
7
|
-
CollectAnalysis,
|
|
8
|
-
CollectAnalysisCallbacks,
|
|
9
|
-
CollectAnalysisOptions,
|
|
10
|
-
} from '../trading/collect'
|
|
11
|
-
import {Coordinates, GoodPrice} from '../types'
|
|
12
|
-
import {Location, toLocation} from '../entities/location'
|
|
13
|
-
import {findNearbyPlanets} from '../travel/travel'
|
|
14
|
-
import {getCurrentEpoch} from '../scheduling/epoch'
|
|
15
|
-
|
|
16
|
-
export class TradesManager extends BaseManager {
|
|
17
|
-
private priceCache = new Map<string, GoodPrice[]>()
|
|
18
|
-
private priceCacheEpoch: UInt64 | undefined
|
|
19
|
-
|
|
20
|
-
private makePriceCacheKey(location: Coordinates): string {
|
|
21
|
-
return `${location.x},${location.y}`
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
private async createCallbacks(): Promise<CollectAnalysisCallbacks> {
|
|
25
|
-
const game = await this.getGame()
|
|
26
|
-
const serverState = await this.getState()
|
|
27
|
-
const currentEpoch = getCurrentEpoch(game)
|
|
28
|
-
|
|
29
|
-
if (!this.priceCacheEpoch || !this.priceCacheEpoch.equals(currentEpoch)) {
|
|
30
|
-
this.priceCache.clear()
|
|
31
|
-
this.priceCacheEpoch = currentEpoch
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const getNearbyLocations = async (
|
|
35
|
-
origin: Coordinates,
|
|
36
|
-
maxDistance: number
|
|
37
|
-
): Promise<Location[]> => {
|
|
38
|
-
const nearby = findNearbyPlanets(game.config.seed, origin, maxDistance)
|
|
39
|
-
return nearby.map((d) => toLocation(d.destination))
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const getMarketPrices = async (location: Coordinates): Promise<GoodPrice[]> => {
|
|
43
|
-
const cacheKey = this.makePriceCacheKey(location)
|
|
44
|
-
const cached = this.priceCache.get(cacheKey)
|
|
45
|
-
if (cached) {
|
|
46
|
-
return cached
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const locationWithSupply = await this.context.locations.getLocationComplete(location)
|
|
50
|
-
const prices = locationWithSupply.marketPrices || []
|
|
51
|
-
|
|
52
|
-
const result = prices.map((price) => {
|
|
53
|
-
const actualSupply = locationWithSupply.getSupply(price.id)
|
|
54
|
-
|
|
55
|
-
if (actualSupply !== undefined) {
|
|
56
|
-
return GoodPrice.from({
|
|
57
|
-
id: price.id,
|
|
58
|
-
good: price.good,
|
|
59
|
-
price: price.price,
|
|
60
|
-
supply: actualSupply,
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
return price
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
this.priceCache.set(cacheKey, result)
|
|
67
|
-
return result
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const getGameSeed = () => game.config.seed
|
|
71
|
-
const getState = () => serverState
|
|
72
|
-
|
|
73
|
-
return {getNearbyLocations, getMarketPrices, getGameSeed, getState}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
clearPriceCache(): void {
|
|
77
|
-
this.priceCache.clear()
|
|
78
|
-
this.priceCacheEpoch = undefined
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async findDeals(
|
|
82
|
-
ship: Ship,
|
|
83
|
-
originLocation?: Coordinates,
|
|
84
|
-
options: FindDealsOptions = {}
|
|
85
|
-
): Promise<Deal[]> {
|
|
86
|
-
const origin = originLocation || ship.currentLocation
|
|
87
|
-
const callbacks = await this.createCallbacks()
|
|
88
|
-
|
|
89
|
-
const deals = await findDealsForShip(
|
|
90
|
-
ship,
|
|
91
|
-
origin,
|
|
92
|
-
callbacks.getNearbyLocations,
|
|
93
|
-
callbacks.getMarketPrices,
|
|
94
|
-
options
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
return deals
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async findBestDeal(
|
|
101
|
-
ship: Ship,
|
|
102
|
-
originLocation?: Coordinates,
|
|
103
|
-
options: FindDealsOptions = {}
|
|
104
|
-
): Promise<Deal | undefined> {
|
|
105
|
-
const deals = await this.findDeals(ship, originLocation, {...options, maxDeals: 1})
|
|
106
|
-
return deals[0]
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async getCollectOptions(
|
|
110
|
-
ship: Ship,
|
|
111
|
-
arrivedAt?: Coordinates,
|
|
112
|
-
options: CollectAnalysisOptions = {}
|
|
113
|
-
): Promise<CollectAnalysis> {
|
|
114
|
-
const location = arrivedAt || ship.currentLocation
|
|
115
|
-
const callbacks = await this.createCallbacks()
|
|
116
|
-
|
|
117
|
-
return analyzeCollectOptions(ship, location, callbacks, options)
|
|
118
|
-
}
|
|
119
|
-
}
|
package/src/market/goods.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import {UInt16, UInt16Type, UInt32} from '@wharfkit/antelope'
|
|
2
|
-
import {Good} from '../types'
|
|
3
|
-
import goodsData from '../data/goods.json'
|
|
4
|
-
|
|
5
|
-
const goods = goodsData as Array<{
|
|
6
|
-
id: number
|
|
7
|
-
name: string
|
|
8
|
-
description: string
|
|
9
|
-
base_price: number
|
|
10
|
-
mass: number
|
|
11
|
-
}>
|
|
12
|
-
|
|
13
|
-
export const goodIds = goods.map((g) => g.id)
|
|
14
|
-
|
|
15
|
-
export function getGood(goodId: UInt16Type): Good {
|
|
16
|
-
const good = goods.find((g) => UInt16.from(goodId).equals(g.id))
|
|
17
|
-
if (!good) {
|
|
18
|
-
throw new Error('Good does not exist')
|
|
19
|
-
}
|
|
20
|
-
return Good.from({
|
|
21
|
-
id: UInt16.from(good.id),
|
|
22
|
-
name: good.name,
|
|
23
|
-
description: good.description,
|
|
24
|
-
base_price: UInt32.from(good.base_price),
|
|
25
|
-
mass: UInt32.from(good.mass),
|
|
26
|
-
})
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getGoods(): Good[] {
|
|
30
|
-
return goods.map((g) => getGood(g.id))
|
|
31
|
-
}
|