@shipload/sdk 0.7.1 → 2.0.0-rc2

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.
Files changed (62) hide show
  1. package/README.md +349 -1
  2. package/lib/shipload.d.ts +2016 -230
  3. package/lib/shipload.js +5733 -2094
  4. package/lib/shipload.js.map +1 -1
  5. package/lib/shipload.m.js +5425 -2012
  6. package/lib/shipload.m.js.map +1 -1
  7. package/package.json +5 -5
  8. package/src/capabilities/extraction.ts +37 -0
  9. package/src/capabilities/guards.ts +43 -0
  10. package/src/capabilities/index.ts +5 -0
  11. package/src/capabilities/loading.ts +8 -0
  12. package/src/capabilities/movement.ts +29 -0
  13. package/src/capabilities/storage.ts +67 -0
  14. package/src/contracts/server.ts +788 -202
  15. package/src/data/goods.json +23 -0
  16. package/src/data/syllables.json +1184 -0
  17. package/src/entities/cargo-utils.ts +142 -0
  18. package/src/entities/container.ts +70 -0
  19. package/src/entities/entity-inventory.ts +39 -0
  20. package/src/entities/gamestate.ts +152 -0
  21. package/src/entities/inventory-accessor.ts +46 -0
  22. package/src/entities/location.ts +255 -0
  23. package/src/entities/makers.ts +69 -0
  24. package/src/entities/player.ts +288 -0
  25. package/src/entities/ship.ts +208 -0
  26. package/src/entities/warehouse.ts +89 -0
  27. package/src/errors.ts +46 -9
  28. package/src/index-module.ts +152 -7
  29. package/src/managers/actions.ts +200 -0
  30. package/src/managers/base.ts +25 -0
  31. package/src/managers/context.ts +104 -0
  32. package/src/managers/entities.ts +103 -0
  33. package/src/managers/epochs.ts +47 -0
  34. package/src/managers/index.ts +9 -0
  35. package/src/managers/locations.ts +122 -0
  36. package/src/managers/players.ts +13 -0
  37. package/src/managers/trades.ts +119 -0
  38. package/src/market/goods.ts +31 -0
  39. package/src/{market.ts → market/market.ts} +31 -37
  40. package/src/{rolls.ts → market/rolls.ts} +3 -3
  41. package/src/scheduling/accessor.ts +82 -0
  42. package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
  43. package/src/scheduling/projection.ts +290 -0
  44. package/src/scheduling/schedule.ts +179 -0
  45. package/src/shipload.ts +39 -157
  46. package/src/trading/collect.ts +938 -0
  47. package/src/trading/deal.ts +207 -0
  48. package/src/trading/trade.ts +203 -0
  49. package/src/travel/travel.ts +486 -0
  50. package/src/types/capabilities.ts +79 -0
  51. package/src/types/entity-traits.ts +70 -0
  52. package/src/types/entity.ts +36 -0
  53. package/src/types/index.ts +3 -0
  54. package/src/types.ts +127 -25
  55. package/src/{hash.ts → utils/hash.ts} +1 -1
  56. package/src/utils/system.ts +155 -0
  57. package/src/goods.ts +0 -124
  58. package/src/ship.ts +0 -36
  59. package/src/state.ts +0 -0
  60. package/src/syllables.ts +0 -1184
  61. package/src/system.ts +0 -37
  62. package/src/travel.ts +0 -259
package/src/types.ts CHANGED
@@ -1,16 +1,128 @@
1
- import {Struct, UInt16, UInt16Type, UInt64, UInt64Type} from '@wharfkit/antelope'
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 TRAVEL_MAXMASS_PENALTY = 5 // Penalty (in seconds) for exceeding the maximum mass per 1000 unit
6
14
 
7
- export interface CameraPosition extends ServerContract.ActionParams.Type.coordinates {
8
- z: number
15
+ // Ship constants
16
+ export const INITIAL_SHIP_GENERATOR_CAPACITY = 350
17
+ export const INITIAL_SHIP_DRAIN = 25
18
+ export const INITIAL_SHIP_ENERGY = 350
19
+ export const INITIAL_SHIP_HULLMASS = 100000
20
+ export const INITIAL_SHIP_CAPACITY = 500000
21
+ export const INITIAL_SHIP_Z = 800
22
+ export const INITIAL_SHIP_RECHARGE = 10
23
+ export const INITIAL_SHIP_THRUST = 250
24
+
25
+ // Loader constants
26
+ export const INITIAL_LOADER_MASS = 1000
27
+ export const INITIAL_LOADER_QUANTITY = 1
28
+ export const INITIAL_LOADER_THRUST = 1
29
+
30
+ // Warehouse constants
31
+ export const WAREHOUSE_Z = 500
32
+ export const INITIAL_WAREHOUSE_CAPACITY = 10000000
33
+
34
+ // Container constants
35
+ export const CONTAINER_Z = 300
36
+ export const INITIAL_CONTAINER_HULLMASS = 50000
37
+ export const INITIAL_CONTAINER_CAPACITY = 2000000
38
+
39
+ // Mechanics
40
+ export const TRAVEL_MAX_DURATION = 86400
41
+
42
+ // Altitude limits (for UI/calculations)
43
+ export const MIN_ORBITAL_ALTITUDE = 800
44
+ export const MAX_ORBITAL_ALTITUDE = 3000
45
+
46
+ // Legacy alias (deprecated, use INITIAL_SHIP_CAPACITY)
47
+ export const INITIAL_SHIP_MASS = 500000
48
+
49
+ // Extractor constants
50
+ export const INITIAL_EXTRACTOR_RATE = 700
51
+ export const INITIAL_EXTRACTOR_DRAIN = 2500
52
+ export const INITIAL_EXTRACTOR_EFFICIENCY = 5000
53
+
54
+ export interface ShipLike {
55
+ coordinates: ServerContract.Types.coordinates
56
+ hullmass: UInt32
57
+ energy: UInt16
58
+ engines: ServerContract.Types.movement_stats
59
+ generator: ServerContract.Types.energy_stats
60
+ loaders: ServerContract.Types.loader_stats
61
+ capacity: UInt32
62
+ }
63
+
64
+ export interface CargoMassInfo {
65
+ good_id: UInt16Type
66
+ quantity: UInt32Type
67
+ }
68
+
69
+ export enum TaskType {
70
+ IDLE = 0,
71
+ TRAVEL = 1,
72
+ RECHARGE = 2,
73
+ LOAD = 3,
74
+ UNLOAD = 4,
75
+ EXTRACT = 5,
76
+ }
77
+
78
+ export enum LocationType {
79
+ EMPTY = 0,
80
+ PLANET = 1,
81
+ ASTEROID = 2,
82
+ NEBULA = 3,
9
83
  }
10
84
 
11
- export interface Dimensions {
12
- width: number
13
- height: number
85
+ export enum TaskCancelable {
86
+ NEVER = 0, // Task cannot be cancelled
87
+ BEFORE_START = 1, // Task can only be cancelled before it starts
88
+ ALWAYS = 2, // Task can always be cancelled
89
+ }
90
+
91
+ export const EntityType = {
92
+ SHIP: Name.from('ship'),
93
+ WAREHOUSE: Name.from('warehouse'),
94
+ CONTAINER: Name.from('container'),
95
+ } as const
96
+
97
+ export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
98
+
99
+ export type CoordinatesType =
100
+ | Coordinates
101
+ | ServerContract.Types.coordinates
102
+ | {x: Int64Type; y: Int64Type}
103
+
104
+ export class Coordinates extends ServerContract.Types.coordinates {
105
+ static from(value: CoordinatesType): Coordinates {
106
+ return super.from(value) as Coordinates
107
+ }
108
+
109
+ equals(other: CoordinatesType): boolean {
110
+ const coords = Coordinates.from(other)
111
+ return this.x.equals(coords.x) && this.y.equals(coords.y)
112
+ }
113
+
114
+ toLocationId(): UInt64 {
115
+ return coordsToLocationId(this)
116
+ }
117
+ }
118
+
119
+ export function coordsToLocationId(coords: CoordinatesType): UInt64 {
120
+ const c = Coordinates.from(coords)
121
+ const mask = BigInt(0xffffffff)
122
+ const x = BigInt(c.x.toNumber()) & mask
123
+ const y = BigInt(c.y.toNumber()) & mask
124
+ const id = (x << BigInt(32)) | y
125
+ return UInt64.from(id)
14
126
  }
15
127
 
16
128
  export interface Distance {
@@ -27,18 +139,10 @@ export class Good extends Struct {
27
139
  name!: string
28
140
  @Struct.field('string')
29
141
  description!: string
30
- @Struct.field(UInt64)
31
- base_price!: UInt64
32
- @Struct.field(UInt64)
33
- mass!: UInt64
34
- }
35
-
36
- export interface GoodType {
37
- id: UInt16Type
38
- name: string
39
- description: string
40
- base_price: UInt64Type
41
- mass: UInt64Type
142
+ @Struct.field(UInt32)
143
+ base_price!: UInt32
144
+ @Struct.field(UInt32)
145
+ mass!: UInt32
42
146
  }
43
147
 
44
148
  @Struct.type('GoodPrice')
@@ -47,10 +151,8 @@ export class GoodPrice extends Struct {
47
151
  id!: UInt16
48
152
  @Struct.field(Good)
49
153
  good!: Good
50
- @Struct.field(UInt64)
51
- price!: UInt64
52
- @Struct.field(UInt64)
53
- supply!: UInt64
154
+ @Struct.field(UInt32)
155
+ price!: UInt32
156
+ @Struct.field(UInt16)
157
+ supply!: UInt16
54
158
  }
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): Checksum512 {
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, UInt8} from '@wharfkit/antelope'
2
+ import {hash512} from './hash'
3
+ import {Coordinates, CoordinatesType, LocationType, PRECISION} from '../types'
4
+ import {ServerContract} from '../contracts'
5
+ import syllables from '../data/syllables.json'
6
+
7
+ const LOCATION_EXISTS_THRESHOLD = 0x10
8
+ const LOCATION_ACTIVE_THRESHOLD = 0x80
9
+
10
+ export function getLocationType(
11
+ gameSeed: Checksum256Type,
12
+ coordinates: CoordinatesType
13
+ ): LocationType {
14
+ const seed = Checksum256.from(gameSeed)
15
+ const str = ['system', coordinates.x, coordinates.y].join('-')
16
+ const hashResult = hash512(seed, str)
17
+
18
+ if (hashResult.array[0] >= LOCATION_EXISTS_THRESHOLD) {
19
+ return LocationType.EMPTY
20
+ }
21
+
22
+ if (hashResult.array[1] < 96) {
23
+ return LocationType.PLANET
24
+ } else if (hashResult.array[1] < 176) {
25
+ return LocationType.ASTEROID
26
+ }
27
+ return LocationType.NEBULA
28
+ }
29
+
30
+ export function isExtractableLocation(locationType: LocationType): boolean {
31
+ return locationType === LocationType.ASTEROID || locationType === LocationType.NEBULA
32
+ }
33
+
34
+ export function getSystemName(gameSeed: Checksum256Type, location: CoordinatesType): string {
35
+ const seed = Checksum256.from(gameSeed)
36
+ if (!hasSystem(seed, location)) {
37
+ throw new Error("System doesn't exist at location")
38
+ }
39
+ const seedStr = `${location.x}${location.y}systemName`
40
+ const hashResult = hash512(seed, seedStr)
41
+ const syllableCount = 1 + (hashResult.array[0] % 3)
42
+ const name: string[] = []
43
+ for (let i = 0; i < syllableCount; i++) {
44
+ const index = hashResult.array[i] % syllables.length
45
+ const syllable = syllables[index]
46
+ name.push(i > 0 ? syllable.toLowerCase() : syllable)
47
+ }
48
+ return name.join('')
49
+ }
50
+
51
+ export function hasSystem(gameSeed: Checksum256Type, coordinates: CoordinatesType): boolean {
52
+ return getLocationType(gameSeed, coordinates) !== LocationType.EMPTY
53
+ }
54
+
55
+ export function deriveLocationStatic(
56
+ gameSeed: Checksum256Type,
57
+ coordinates: CoordinatesType
58
+ ): ServerContract.Types.location_static {
59
+ const seed = Checksum256.from(gameSeed)
60
+ const coords = Coordinates.from(coordinates)
61
+ const str = `system-${coords.x}-${coords.y}`
62
+ const hashResult = hash512(seed, str)
63
+
64
+ const loc = ServerContract.Types.location_static.from({
65
+ coords: coords,
66
+ type: LocationType.EMPTY,
67
+ subtype: 0,
68
+ seed0: 0,
69
+ seed1: 0,
70
+ })
71
+
72
+ if (hashResult.array[0] >= LOCATION_EXISTS_THRESHOLD) {
73
+ return loc
74
+ }
75
+
76
+ if (hashResult.array[1] < 96) {
77
+ loc.type = UInt8.from(LocationType.PLANET)
78
+ } else if (hashResult.array[1] < 176) {
79
+ loc.type = UInt8.from(LocationType.ASTEROID)
80
+ } else {
81
+ loc.type = UInt8.from(LocationType.NEBULA)
82
+ }
83
+
84
+ loc.subtype = UInt8.from(hashResult.array[2])
85
+ loc.seed0 = UInt8.from(hashResult.array[3])
86
+ loc.seed1 = UInt8.from(hashResult.array[4])
87
+
88
+ return loc
89
+ }
90
+
91
+ export function deriveLocationEpoch(
92
+ epochSeed: Checksum256Type,
93
+ coordinates: CoordinatesType
94
+ ): ServerContract.Types.location_epoch {
95
+ const seed = Checksum256.from(epochSeed)
96
+ const coords = Coordinates.from(coordinates)
97
+ const str = `system-epoch-${coords.x}-${coords.y}`
98
+ const hashResult = hash512(seed, str)
99
+
100
+ return ServerContract.Types.location_epoch.from({
101
+ active: hashResult.array[0] < LOCATION_ACTIVE_THRESHOLD,
102
+ seed0: hashResult.array[1],
103
+ seed1: hashResult.array[2],
104
+ })
105
+ }
106
+
107
+ export function deriveLocation(
108
+ gameSeed: Checksum256Type,
109
+ epochSeed: Checksum256Type,
110
+ coordinates: CoordinatesType
111
+ ): ServerContract.Types.location_derived {
112
+ return ServerContract.Types.location_derived.from({
113
+ static_props: deriveLocationStatic(gameSeed, coordinates),
114
+ epoch_props: deriveLocationEpoch(epochSeed, coordinates),
115
+ })
116
+ }
117
+
118
+ export function deriveLocationMixture(
119
+ location: ServerContract.Types.location_derived,
120
+ epochSeed: Checksum256Type
121
+ ): ServerContract.Types.mixture_info {
122
+ const locationType = location.static_props.type.toNumber()
123
+
124
+ if (locationType === LocationType.NEBULA) {
125
+ return ServerContract.Types.mixture_info.from({
126
+ components: [{good_id: 1, purity: PRECISION}],
127
+ })
128
+ }
129
+
130
+ if (locationType === LocationType.ASTEROID) {
131
+ const seed = Checksum256.from(epochSeed)
132
+ const coords = location.static_props.coords
133
+ const str = `mixture-${coords.x}-${coords.y}`
134
+ const hashResult = hash512(seed, str)
135
+
136
+ const ironPrimary = location.static_props.subtype.toNumber() % 2 === 0
137
+ const purityRange = 0.3
138
+ const purityRoll = hashResult.array[0] / 255
139
+ const primaryPurity = 0.5 + purityRoll * purityRange
140
+
141
+ const primaryId = ironPrimary ? 26 : 29
142
+ const secondaryId = ironPrimary ? 29 : 26
143
+ const primaryAmt = Math.floor(primaryPurity * PRECISION)
144
+ const secondaryAmt = PRECISION - primaryAmt
145
+
146
+ return ServerContract.Types.mixture_info.from({
147
+ components: [
148
+ {good_id: primaryId, purity: primaryAmt},
149
+ {good_id: secondaryId, purity: secondaryAmt},
150
+ ],
151
+ })
152
+ }
153
+
154
+ return ServerContract.Types.mixture_info.from({components: []})
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/ship.ts DELETED
@@ -1,36 +0,0 @@
1
- import {UInt32} from '@wharfkit/antelope'
2
- import {ServerContract} from './contracts'
3
- import {PRECISION} from './types'
4
- import {travelplanDuration} from './travel'
5
-
6
- export class Ship extends ServerContract.Types.ship_row {
7
- get maxDistance(): UInt32 {
8
- return this.stats.capacity.dividing(this.stats.drain).multiplying(PRECISION)
9
- }
10
-
11
- get traveling(): boolean {
12
- return !!this.travelplan
13
- }
14
-
15
- get arrived(): boolean {
16
- if (!this.travelplan) {
17
- throw new Error('Ship is not traveling')
18
- }
19
- const depart = this.travelplan.departure.toDate()
20
- const arrive = new Date(
21
- depart.getTime() + Number(travelplanDuration(this.travelplan)) * 1000
22
- )
23
- return new Date() >= arrive
24
- }
25
-
26
- get eta(): number {
27
- if (!this.travelplan) {
28
- throw new Error('Ship is not traveling')
29
- }
30
- const depart = this.travelplan.departure.toDate()
31
- const arrive = new Date(
32
- depart.getTime() + Number(travelplanDuration(this.travelplan)) * 1000
33
- )
34
- return arrive.getTime() - new Date().getTime()
35
- }
36
- }
package/src/state.ts DELETED
File without changes