@shipload/sdk 0.7.1 → 2.0.0-rc10
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 +2203 -288
- package/lib/shipload.js +8441 -2210
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +8160 -2167
- package/lib/shipload.m.js.map +1 -1
- package/package.json +7 -6
- package/src/capabilities/crafting.ts +26 -0
- package/src/capabilities/extraction.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 +1217 -254
- package/src/data/capabilities.ts +408 -0
- package/src/data/categories.ts +58 -0
- package/src/data/colors.ts +52 -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 +1790 -0
- 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 +118 -0
- package/src/entities/cargo-utils.ts +84 -0
- package/src/entities/container.ts +106 -0
- package/src/entities/entity-inventory.ts +39 -0
- package/src/entities/gamestate.ts +152 -0
- package/src/entities/inventory-accessor.ts +42 -0
- package/src/entities/location.ts +60 -0
- package/src/entities/makers.ts +72 -0
- package/src/entities/player.ts +15 -0
- package/src/entities/ship-deploy.ts +263 -0
- package/src/entities/ship.ts +199 -0
- package/src/entities/warehouse.ts +91 -0
- package/src/errors.ts +46 -9
- package/src/index-module.ts +302 -7
- package/src/managers/actions.ts +197 -0
- package/src/managers/base.ts +25 -0
- package/src/managers/context.ts +95 -0
- package/src/managers/entities.ts +103 -0
- package/src/managers/epochs.ts +47 -0
- package/src/managers/index.ts +8 -0
- package/src/managers/locations.ts +39 -0
- package/src/managers/players.ts +13 -0
- 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/{epoch.ts → scheduling/epoch.ts} +1 -1
- package/src/scheduling/projection.ts +322 -0
- package/src/scheduling/schedule.ts +179 -0
- package/src/shipload.ts +36 -159
- package/src/travel/travel.ts +499 -0
- 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 +113 -35
- package/src/{hash.ts → utils/hash.ts} +1 -1
- package/src/utils/system.ts +155 -0
- package/src/goods.ts +0 -124
- package/src/market.ts +0 -214
- package/src/rolls.ts +0 -8
- package/src/ship.ts +0 -36
- package/src/state.ts +0 -0
- package/src/syllables.ts +0 -1184
- package/src/system.ts +0 -37
- package/src/travel.ts +0 -259
package/src/types.ts
CHANGED
|
@@ -1,16 +1,109 @@
|
|
|
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
|
|
5
|
-
export const
|
|
14
|
+
export const CRAFT_ENERGY_DIVISOR = 150000
|
|
6
15
|
|
|
7
|
-
export
|
|
8
|
-
|
|
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
|
|
24
|
+
|
|
25
|
+
export const MIN_ORBITAL_ALTITUDE = 800
|
|
26
|
+
export const MAX_ORBITAL_ALTITUDE = 3000
|
|
27
|
+
|
|
28
|
+
export const BASE_ORBITAL_MASS = 100000
|
|
29
|
+
|
|
30
|
+
export interface ShipLike {
|
|
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
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface CargoMassInfo {
|
|
42
|
+
item_id: UInt16Type
|
|
43
|
+
quantity: UInt32Type
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export enum TaskType {
|
|
47
|
+
IDLE = 0,
|
|
48
|
+
TRAVEL = 1,
|
|
49
|
+
RECHARGE = 2,
|
|
50
|
+
LOAD = 3,
|
|
51
|
+
UNLOAD = 4,
|
|
52
|
+
EXTRACT = 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,
|
|
9
64
|
}
|
|
10
65
|
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
|
|
66
|
+
export enum TaskCancelable {
|
|
67
|
+
NEVER = 0,
|
|
68
|
+
BEFORE_START = 1,
|
|
69
|
+
ALWAYS = 2,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export const EntityType = {
|
|
73
|
+
SHIP: Name.from('ship'),
|
|
74
|
+
WAREHOUSE: Name.from('warehouse'),
|
|
75
|
+
CONTAINER: Name.from('container'),
|
|
76
|
+
} as const
|
|
77
|
+
|
|
78
|
+
export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
|
|
79
|
+
|
|
80
|
+
export type CoordinatesType =
|
|
81
|
+
| Coordinates
|
|
82
|
+
| ServerContract.Types.coordinates
|
|
83
|
+
| {x: Int64Type; y: Int64Type}
|
|
84
|
+
|
|
85
|
+
export class Coordinates extends ServerContract.Types.coordinates {
|
|
86
|
+
static from(value: CoordinatesType): Coordinates {
|
|
87
|
+
return super.from(value) as Coordinates
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
equals(other: CoordinatesType): boolean {
|
|
91
|
+
const coords = Coordinates.from(other)
|
|
92
|
+
return this.x.equals(coords.x) && this.y.equals(coords.y)
|
|
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)
|
|
14
107
|
}
|
|
15
108
|
|
|
16
109
|
export interface Distance {
|
|
@@ -19,38 +112,23 @@ export interface Distance {
|
|
|
19
112
|
distance: UInt16
|
|
20
113
|
}
|
|
21
114
|
|
|
22
|
-
|
|
23
|
-
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 {
|
|
24
120
|
@Struct.field(UInt16)
|
|
25
121
|
id!: UInt16
|
|
26
122
|
@Struct.field('string')
|
|
27
123
|
name!: string
|
|
28
124
|
@Struct.field('string')
|
|
29
125
|
description!: string
|
|
30
|
-
@Struct.field(
|
|
31
|
-
|
|
32
|
-
@Struct.field(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
name: string
|
|
39
|
-
description: string
|
|
40
|
-
base_price: UInt64Type
|
|
41
|
-
mass: UInt64Type
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
@Struct.type('GoodPrice')
|
|
45
|
-
export class GoodPrice extends Struct {
|
|
46
|
-
@Struct.field(UInt16)
|
|
47
|
-
id!: UInt16
|
|
48
|
-
@Struct.field(Good)
|
|
49
|
-
good!: Good
|
|
50
|
-
@Struct.field(UInt64)
|
|
51
|
-
price!: UInt64
|
|
52
|
-
@Struct.field(UInt64)
|
|
53
|
-
supply!: UInt64
|
|
126
|
+
@Struct.field(UInt32)
|
|
127
|
+
mass!: UInt32
|
|
128
|
+
@Struct.field('string')
|
|
129
|
+
category!: ResourceCategory
|
|
130
|
+
@Struct.field('string')
|
|
131
|
+
tier!: ResourceTier
|
|
132
|
+
@Struct.field('string')
|
|
133
|
+
color!: string
|
|
54
134
|
}
|
|
55
|
-
|
|
56
|
-
export interface Coordinates extends ServerContract.ActionParams.Type.coordinates {}
|
|
@@ -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
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import {Checksum256, Checksum256Type, Checksum512, UInt8} from '@wharfkit/antelope'
|
|
2
|
+
import {hash512} from './hash'
|
|
3
|
+
import {Coordinates, CoordinatesType, LocationType} from '../types'
|
|
4
|
+
import {ServerContract} from '../contracts'
|
|
5
|
+
import {deriveLocationSize} from '../derivation/location-size'
|
|
6
|
+
import syllables from '../data/syllables.json'
|
|
7
|
+
import nebulaAdjectives from '../data/nebula-adjectives.json'
|
|
8
|
+
import nebulaNouns from '../data/nebula-nouns.json'
|
|
9
|
+
|
|
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 {
|
|
17
|
+
const seed = Checksum256.from(gameSeed)
|
|
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
|
|
23
|
+
}
|
|
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 isExtractableLocation(locationType: LocationType): boolean {
|
|
34
|
+
return locationType !== LocationType.EMPTY
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function uint16(hash: Checksum512, offset: number): number {
|
|
38
|
+
return (hash.array[offset] << 8) | hash.array[offset + 1]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function generatePlanetName(hashResult: Checksum512): string {
|
|
42
|
+
const syllableCount = 2 + (hashResult.array[0] % 2)
|
|
43
|
+
const name: string[] = []
|
|
44
|
+
for (let i = 0; i < syllableCount; i++) {
|
|
45
|
+
const index = uint16(hashResult, 1 + i * 2) % syllables.length
|
|
46
|
+
const syllable = syllables[index]
|
|
47
|
+
name.push(i > 0 ? syllable.toLowerCase() : syllable)
|
|
48
|
+
}
|
|
49
|
+
return name.join('')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function generateAsteroidName(hashResult: Checksum512): string {
|
|
53
|
+
const A = 65
|
|
54
|
+
const letter1 = String.fromCharCode(A + (hashResult.array[0] % 26))
|
|
55
|
+
const letter2 = String.fromCharCode(A + (hashResult.array[1] % 26))
|
|
56
|
+
const num = (uint16(hashResult, 2) % 9000) + 1000
|
|
57
|
+
return `${letter1}${letter2}-${num}`
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function generateNebulaName(hashResult: Checksum512): string {
|
|
61
|
+
const adjIdx = uint16(hashResult, 0) % nebulaAdjectives.length
|
|
62
|
+
const nounIdx = uint16(hashResult, 2) % nebulaNouns.length
|
|
63
|
+
return `${nebulaAdjectives[adjIdx]} ${nebulaNouns[nounIdx]}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
|
|
67
|
+
const seed = Checksum256.from(gameSeed)
|
|
68
|
+
const locationType = getLocationType(seed, location)
|
|
69
|
+
if (locationType === LocationType.EMPTY) {
|
|
70
|
+
throw new Error("System doesn't exist at location")
|
|
71
|
+
}
|
|
72
|
+
const seedStr = `${location.x}-${location.y}-${locationType}-name`
|
|
73
|
+
const hashResult = hash512(seed, seedStr)
|
|
74
|
+
switch (locationType) {
|
|
75
|
+
case LocationType.PLANET:
|
|
76
|
+
return generatePlanetName(hashResult)
|
|
77
|
+
case LocationType.ASTEROID:
|
|
78
|
+
return generateAsteroidName(hashResult)
|
|
79
|
+
case LocationType.NEBULA:
|
|
80
|
+
return generateNebulaName(hashResult)
|
|
81
|
+
default:
|
|
82
|
+
return generatePlanetName(hashResult)
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function hasSystem(gameSeed: Checksum256Type, coordinates: CoordinatesType): boolean {
|
|
87
|
+
return getLocationType(gameSeed, coordinates) !== LocationType.EMPTY
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function deriveLocationStatic(
|
|
91
|
+
gameSeed: Checksum256Type,
|
|
92
|
+
coordinates: CoordinatesType
|
|
93
|
+
): ServerContract.Types.location_static {
|
|
94
|
+
const seed = Checksum256.from(gameSeed)
|
|
95
|
+
const coords = Coordinates.from(coordinates)
|
|
96
|
+
const str = `system-${coords.x}-${coords.y}`
|
|
97
|
+
const hashResult = hash512(seed, str)
|
|
98
|
+
|
|
99
|
+
const loc = ServerContract.Types.location_static.from({
|
|
100
|
+
coords: coords,
|
|
101
|
+
type: LocationType.EMPTY,
|
|
102
|
+
subtype: 0,
|
|
103
|
+
seed0: 0,
|
|
104
|
+
seed1: 0,
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
if (hashResult.array[0] >= LOCATION_EXISTS_THRESHOLD) {
|
|
108
|
+
return loc
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (hashResult.array[1] < 96) {
|
|
112
|
+
loc.type = UInt8.from(LocationType.PLANET)
|
|
113
|
+
} else if (hashResult.array[1] < 176) {
|
|
114
|
+
loc.type = UInt8.from(LocationType.ASTEROID)
|
|
115
|
+
} else {
|
|
116
|
+
loc.type = UInt8.from(LocationType.NEBULA)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
loc.subtype = UInt8.from(
|
|
120
|
+
Number(loc.type) === LocationType.PLANET ? hashResult.array[2] % 6 : hashResult.array[2]
|
|
121
|
+
)
|
|
122
|
+
loc.seed0 = UInt8.from(hashResult.array[3])
|
|
123
|
+
loc.seed1 = UInt8.from(hashResult.array[4])
|
|
124
|
+
|
|
125
|
+
return loc
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function deriveLocationEpoch(
|
|
129
|
+
epochSeed: Checksum256Type,
|
|
130
|
+
coordinates: CoordinatesType
|
|
131
|
+
): ServerContract.Types.location_epoch {
|
|
132
|
+
const seed = Checksum256.from(epochSeed)
|
|
133
|
+
const coords = Coordinates.from(coordinates)
|
|
134
|
+
const str = `system-epoch-${coords.x}-${coords.y}`
|
|
135
|
+
const hashResult = hash512(seed, str)
|
|
136
|
+
|
|
137
|
+
return ServerContract.Types.location_epoch.from({
|
|
138
|
+
active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
|
|
139
|
+
seed0: hashResult.array[1],
|
|
140
|
+
seed1: hashResult.array[2],
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function deriveLocation(
|
|
145
|
+
gameSeed: Checksum256Type,
|
|
146
|
+
epochSeed: Checksum256Type,
|
|
147
|
+
coordinates: CoordinatesType
|
|
148
|
+
): ServerContract.Types.location_derived {
|
|
149
|
+
const staticProps = deriveLocationStatic(gameSeed, coordinates)
|
|
150
|
+
return ServerContract.Types.location_derived.from({
|
|
151
|
+
static_props: staticProps,
|
|
152
|
+
epoch_props: deriveLocationEpoch(epochSeed, coordinates),
|
|
153
|
+
size: deriveLocationSize(staticProps),
|
|
154
|
+
})
|
|
155
|
+
}
|
package/src/goods.ts
DELETED
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import {UInt16, UInt16Type, UInt64} from '@wharfkit/antelope'
|
|
2
|
-
import {Coordinates, Good, GoodType, PRECISION} from './types'
|
|
3
|
-
|
|
4
|
-
// List of goods with titles and descriptions
|
|
5
|
-
const goods: GoodType[] = [
|
|
6
|
-
{
|
|
7
|
-
id: 1,
|
|
8
|
-
name: 'FizzGlo',
|
|
9
|
-
description: 'Pops with flavor! A neon drink that makes your burps glow.',
|
|
10
|
-
base_price: 50,
|
|
11
|
-
mass: 35_000,
|
|
12
|
-
},
|
|
13
|
-
// {
|
|
14
|
-
// id: 2,
|
|
15
|
-
// name: 'ZapSnacks',
|
|
16
|
-
// description: 'Electric taste! Spicy edible energy sparks for a tongue-tingling experience.',
|
|
17
|
-
// base_price: 0,
|
|
18
|
-
// mass: 0,
|
|
19
|
-
// },
|
|
20
|
-
{
|
|
21
|
-
id: 3,
|
|
22
|
-
name: 'Blob Buddies',
|
|
23
|
-
description: 'Squishy friends! Clingy, cute and mood-matching pet blobs for every home!',
|
|
24
|
-
base_price: 95,
|
|
25
|
-
mass: 60_000,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
id: 4,
|
|
29
|
-
name: 'TuneTooth',
|
|
30
|
-
description: 'Whistle while you eat! Edible instrument treats that play tunes when chewed.',
|
|
31
|
-
base_price: 145,
|
|
32
|
-
mass: 75_000,
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: 5,
|
|
36
|
-
name: 'SunPods',
|
|
37
|
-
description: 'Miniature suns in your pocket providing on-demand light & warmth.',
|
|
38
|
-
base_price: 295,
|
|
39
|
-
mass: 135_000,
|
|
40
|
-
},
|
|
41
|
-
// {
|
|
42
|
-
// id: 6,
|
|
43
|
-
// name: 'Fuzzix',
|
|
44
|
-
// description: 'Pocket-sized quantum fluff generator for instant comfy.',
|
|
45
|
-
// base_price: 0,
|
|
46
|
-
// mass: 0,
|
|
47
|
-
// },
|
|
48
|
-
{
|
|
49
|
-
id: 7,
|
|
50
|
-
name: 'GlowGo',
|
|
51
|
-
description: 'Ingestible bioluminescent jelly, your inside glows in the dark!',
|
|
52
|
-
base_price: 650,
|
|
53
|
-
mass: 255_000,
|
|
54
|
-
},
|
|
55
|
-
// {
|
|
56
|
-
// id: 8,
|
|
57
|
-
// name: 'KrackleKaps',
|
|
58
|
-
// description: 'Capsules packed with tiny firecrackers, spice up meals and parties.',
|
|
59
|
-
// base_price: 0,
|
|
60
|
-
// mass: 0,
|
|
61
|
-
// },
|
|
62
|
-
{
|
|
63
|
-
id: 9,
|
|
64
|
-
name: 'PlasmaMints',
|
|
65
|
-
description: 'Hypercharged candy giving plasma breath capable of cutting through steel.',
|
|
66
|
-
base_price: 3450,
|
|
67
|
-
mass: 1_100_000,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 10,
|
|
71
|
-
name: 'TimeTreats',
|
|
72
|
-
description: 'Confectionery morsels releasing slow-mo effect over a limited period.',
|
|
73
|
-
base_price: 8500,
|
|
74
|
-
mass: 2_100_000,
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
id: 11,
|
|
78
|
-
name: 'QuantumQuencher',
|
|
79
|
-
description:
|
|
80
|
-
'Bottled hyper-fluid quenching thirst across multiple parallel realities simultaneously.',
|
|
81
|
-
base_price: 20_500,
|
|
82
|
-
mass: 4_100_000,
|
|
83
|
-
},
|
|
84
|
-
// {
|
|
85
|
-
// id: 12,
|
|
86
|
-
// name: 'TransmatterTruffles',
|
|
87
|
-
// description: 'Delectable chocolates instantly teleporting consumers short distances.',
|
|
88
|
-
// base_price: 0,
|
|
89
|
-
// mass: 0,
|
|
90
|
-
// },
|
|
91
|
-
{
|
|
92
|
-
id: 13,
|
|
93
|
-
name: 'MemoryGum',
|
|
94
|
-
description: 'Chewable gum storing or replaying memories while being chewed.',
|
|
95
|
-
base_price: 52_500,
|
|
96
|
-
mass: 9_500_000,
|
|
97
|
-
},
|
|
98
|
-
{
|
|
99
|
-
id: 14,
|
|
100
|
-
name: 'SymbioSnack',
|
|
101
|
-
description: 'Edible alien larvae adopting owner’s taste preference upon consumption.',
|
|
102
|
-
base_price: 115_000,
|
|
103
|
-
mass: 16_000_000,
|
|
104
|
-
},
|
|
105
|
-
]
|
|
106
|
-
|
|
107
|
-
export const goodIds = goods.map((g) => g.id)
|
|
108
|
-
|
|
109
|
-
export function getGood(good_id: UInt16Type): Good {
|
|
110
|
-
const good = goods.find((g) => UInt16.from(good_id).equals(g.id))
|
|
111
|
-
if (!good) {
|
|
112
|
-
throw new Error('Good does not exist')
|
|
113
|
-
}
|
|
114
|
-
return Good.from({
|
|
115
|
-
...good,
|
|
116
|
-
id: UInt16.from(good.id),
|
|
117
|
-
base_price: UInt64.from(good.base_price),
|
|
118
|
-
mass: UInt64.from(good.mass).multiplying(PRECISION),
|
|
119
|
-
})
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export function getGoods(): Good[] {
|
|
123
|
-
return goods.map((g) => getGood(g.id))
|
|
124
|
-
}
|
package/src/market.ts
DELETED
|
@@ -1,214 +0,0 @@
|
|
|
1
|
-
import {Coordinates, GoodPrice} from './types'
|
|
2
|
-
import {getGood, getGoods} from './goods'
|
|
3
|
-
import {Checksum256Type, UInt16Type, UInt64} from '@wharfkit/antelope'
|
|
4
|
-
import {roll} from './rolls'
|
|
5
|
-
import {ServerContract} from './contracts'
|
|
6
|
-
|
|
7
|
-
export enum Rarities {
|
|
8
|
-
legendary = 'LEGENDARY',
|
|
9
|
-
epic = 'EPIC',
|
|
10
|
-
rare = 'RARE',
|
|
11
|
-
uncommon = 'UNCOMMON',
|
|
12
|
-
common = 'COMMON',
|
|
13
|
-
trash = 'TRASH',
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface Rarity {
|
|
17
|
-
rarity: Rarities // The rarity description of this price
|
|
18
|
-
minMultiplier: number // The minimum multiplier for this rarity
|
|
19
|
-
maxMultiplier: number // The maximum multiplier for this rarity
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function generateLocationSeed(
|
|
23
|
-
epochSeed: Checksum256Type,
|
|
24
|
-
location: Coordinates,
|
|
25
|
-
entitySalt: string
|
|
26
|
-
) {
|
|
27
|
-
return `${epochSeed}${location.x}${location.y}${entitySalt}`
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function getRarity(
|
|
31
|
-
gameSeed: Checksum256Type,
|
|
32
|
-
epochSeed: Checksum256Type,
|
|
33
|
-
location: Coordinates,
|
|
34
|
-
good_id: UInt16Type
|
|
35
|
-
): Rarity {
|
|
36
|
-
const seed = `${epochSeed}${location.x}${location.y}${good_id}rarity`
|
|
37
|
-
const rarityRoll = roll(gameSeed, seed)
|
|
38
|
-
|
|
39
|
-
if (rarityRoll < 13) {
|
|
40
|
-
// (Orange) ~0.02% chance = incredibly high value
|
|
41
|
-
return {
|
|
42
|
-
rarity: Rarities.legendary,
|
|
43
|
-
minMultiplier: 2.25,
|
|
44
|
-
maxMultiplier: 3.0,
|
|
45
|
-
}
|
|
46
|
-
} else if (rarityRoll < 176) {
|
|
47
|
-
// (Purple) ~0.25% chance = super high value
|
|
48
|
-
return {
|
|
49
|
-
rarity: Rarities.epic,
|
|
50
|
-
minMultiplier: 1.75,
|
|
51
|
-
maxMultiplier: 2.25,
|
|
52
|
-
}
|
|
53
|
-
} else if (rarityRoll < 996) {
|
|
54
|
-
// (Blue) ~1.25% chance = very high value
|
|
55
|
-
return {
|
|
56
|
-
rarity: Rarities.rare,
|
|
57
|
-
minMultiplier: 1.4,
|
|
58
|
-
maxMultiplier: 1.75,
|
|
59
|
-
}
|
|
60
|
-
} else if (rarityRoll < 2966) {
|
|
61
|
-
// (Green) ~3.00% chance = high value
|
|
62
|
-
return {
|
|
63
|
-
rarity: Rarities.uncommon,
|
|
64
|
-
minMultiplier: 1.225,
|
|
65
|
-
maxMultiplier: 1.4,
|
|
66
|
-
}
|
|
67
|
-
} else if (rarityRoll < 19568) {
|
|
68
|
-
// (White) ~25.33% chance = slightly higher value
|
|
69
|
-
return {
|
|
70
|
-
rarity: Rarities.common,
|
|
71
|
-
minMultiplier: 1.07,
|
|
72
|
-
maxMultiplier: 1.225,
|
|
73
|
-
}
|
|
74
|
-
} else if (rarityRoll < 45988) {
|
|
75
|
-
// ~40.30% chance = no value change
|
|
76
|
-
return {
|
|
77
|
-
rarity: Rarities.trash,
|
|
78
|
-
minMultiplier: 1,
|
|
79
|
-
maxMultiplier: 1.07,
|
|
80
|
-
} // Product is not available
|
|
81
|
-
} else if (rarityRoll < 62508) {
|
|
82
|
-
// (White) ~25.33% chance = slightly lower value
|
|
83
|
-
return {
|
|
84
|
-
rarity: Rarities.common,
|
|
85
|
-
minMultiplier: 0.925,
|
|
86
|
-
maxMultiplier: 1,
|
|
87
|
-
}
|
|
88
|
-
} else if (rarityRoll < 64518) {
|
|
89
|
-
// (Green) ~3.00% chance = low value
|
|
90
|
-
return {
|
|
91
|
-
rarity: Rarities.uncommon,
|
|
92
|
-
minMultiplier: 0.77,
|
|
93
|
-
maxMultiplier: 0.925,
|
|
94
|
-
}
|
|
95
|
-
} else if (rarityRoll < 65437) {
|
|
96
|
-
// (Blue) ~1.25% chance = very low value
|
|
97
|
-
return {
|
|
98
|
-
rarity: Rarities.rare,
|
|
99
|
-
minMultiplier: 0.595,
|
|
100
|
-
maxMultiplier: 0.77,
|
|
101
|
-
}
|
|
102
|
-
} else if (rarityRoll < 65523) {
|
|
103
|
-
// (Purple) ~0.25% chance = super low value
|
|
104
|
-
return {
|
|
105
|
-
rarity: Rarities.epic,
|
|
106
|
-
minMultiplier: 0.41,
|
|
107
|
-
maxMultiplier: 0.595,
|
|
108
|
-
}
|
|
109
|
-
} else {
|
|
110
|
-
// (Orange) ~0.02% chance = incredibly low value
|
|
111
|
-
return {
|
|
112
|
-
rarity: Rarities.legendary,
|
|
113
|
-
minMultiplier: 0.285,
|
|
114
|
-
maxMultiplier: 0.41,
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function getRarityMultiplier(
|
|
120
|
-
gameSeed: Checksum256Type,
|
|
121
|
-
epochSeed: Checksum256Type,
|
|
122
|
-
location: Coordinates,
|
|
123
|
-
good_id: UInt16Type
|
|
124
|
-
): number {
|
|
125
|
-
const rarity = getRarity(gameSeed, epochSeed, location, good_id)
|
|
126
|
-
const range = rarity.maxMultiplier - rarity.minMultiplier
|
|
127
|
-
const seed = `${epochSeed}${location.x}${location.y}${good_id}raritymultiplier`
|
|
128
|
-
const r = roll(gameSeed, seed)
|
|
129
|
-
return rarity.minMultiplier + (r / 65535) * range
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export function getLocationMultiplier(
|
|
133
|
-
gameSeed: Checksum256Type,
|
|
134
|
-
location: Coordinates,
|
|
135
|
-
good_id: UInt16Type
|
|
136
|
-
): number {
|
|
137
|
-
const seed = `${location.x}${location.y}${good_id}locationmultiplier`
|
|
138
|
-
const r = roll(gameSeed, seed)
|
|
139
|
-
if (r < 13) {
|
|
140
|
-
return 0.75
|
|
141
|
-
} else if (r < 176) {
|
|
142
|
-
return 0.8
|
|
143
|
-
} else if (r < 996) {
|
|
144
|
-
return 0.85
|
|
145
|
-
} else if (r < 2966) {
|
|
146
|
-
return 0.9
|
|
147
|
-
} else if (r < 19568) {
|
|
148
|
-
return 0.95
|
|
149
|
-
} else if (r < 45988) {
|
|
150
|
-
return 1
|
|
151
|
-
} else if (r < 62508) {
|
|
152
|
-
return 1.05
|
|
153
|
-
} else if (r < 64518) {
|
|
154
|
-
return 1.1
|
|
155
|
-
} else if (r < 65437) {
|
|
156
|
-
return 1.15
|
|
157
|
-
} else if (r < 65523) {
|
|
158
|
-
return 1.2
|
|
159
|
-
} else {
|
|
160
|
-
return 1.25
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export function getSupply(
|
|
165
|
-
gameSeed: Checksum256Type,
|
|
166
|
-
state: ServerContract.Types.state_row,
|
|
167
|
-
location: Coordinates,
|
|
168
|
-
good_id: UInt16Type
|
|
169
|
-
): number {
|
|
170
|
-
const seed = `${state.seed}${location.x}${location.y}${good_id}supply`
|
|
171
|
-
const r = roll(gameSeed, seed)
|
|
172
|
-
const percent = r / 65535
|
|
173
|
-
const epoch = 1 + Number(state.epoch) / 90
|
|
174
|
-
const ship = Math.pow(Number(state.ships), 1 / 3)
|
|
175
|
-
return UInt64.from((128 / good_id) * percent * ship * epoch).toNumber()
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
export function marketprice(
|
|
179
|
-
location: ServerContract.ActionParams.Type.coordinates,
|
|
180
|
-
good_id: UInt16Type,
|
|
181
|
-
gameSeed: Checksum256Type,
|
|
182
|
-
state: ServerContract.Types.state_row
|
|
183
|
-
): GoodPrice {
|
|
184
|
-
const good = getGood(good_id)
|
|
185
|
-
let price = Number(good.base_price)
|
|
186
|
-
|
|
187
|
-
// Rarity multiplier of the deal (changes with epoch)
|
|
188
|
-
// Large impact range on price, from 0.285x to 3.0x
|
|
189
|
-
const rarityMultiplier = getRarityMultiplier(gameSeed, state.seed, location, good_id)
|
|
190
|
-
price *= rarityMultiplier
|
|
191
|
-
|
|
192
|
-
// Location multiplier of the deal (static, based on game seed)
|
|
193
|
-
// Small impact range on price, from 1.0x to 1.5x
|
|
194
|
-
const locationMultiplier = getLocationMultiplier(gameSeed, location, good_id)
|
|
195
|
-
price *= locationMultiplier
|
|
196
|
-
|
|
197
|
-
// Determine the current supply of the good at the location
|
|
198
|
-
const supply = getSupply(gameSeed, state, location, good_id)
|
|
199
|
-
|
|
200
|
-
return GoodPrice.from({
|
|
201
|
-
id: good_id,
|
|
202
|
-
good,
|
|
203
|
-
price: UInt64.from(price),
|
|
204
|
-
supply: UInt64.from(supply),
|
|
205
|
-
})
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export function marketprices(
|
|
209
|
-
location: ServerContract.ActionParams.Type.coordinates,
|
|
210
|
-
gameSeed: Checksum256Type,
|
|
211
|
-
state: ServerContract.Types.state_row
|
|
212
|
-
): GoodPrice[] {
|
|
213
|
-
return getGoods().map((good) => marketprice(location, good.id, gameSeed, state))
|
|
214
|
-
}
|
package/src/rolls.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import {Checksum256Type} from '@wharfkit/antelope'
|
|
2
|
-
import {hash512} from './hash'
|
|
3
|
-
|
|
4
|
-
export function roll(game_seed: Checksum256Type, roll_seed: string): number {
|
|
5
|
-
const hash = hash512(game_seed, roll_seed)
|
|
6
|
-
// Combine the first two bytes to form a uint16_t value
|
|
7
|
-
return (hash.array[0] << 8) | hash.array[1]
|
|
8
|
-
}
|