@shipload/sdk 1.0.0-next.7 → 1.0.0-next.71

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 (203) hide show
  1. package/lib/scan.d.ts +52 -0
  2. package/lib/scan.js +162 -0
  3. package/lib/scan.js.map +1 -0
  4. package/lib/scan.m.js +152 -0
  5. package/lib/scan.m.js.map +1 -0
  6. package/lib/shipload.d.ts +5822 -1484
  7. package/lib/shipload.js +20838 -5419
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +20674 -5669
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +1691 -0
  12. package/lib/testing.js +7109 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +7103 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.test.ts +82 -0
  18. package/src/capabilities/craftable.ts +82 -0
  19. package/src/capabilities/crafting.test.ts +80 -0
  20. package/src/capabilities/crafting.ts +50 -8
  21. package/src/capabilities/gathering.test.ts +29 -0
  22. package/src/capabilities/gathering.ts +38 -20
  23. package/src/capabilities/hauling.ts +0 -5
  24. package/src/capabilities/index.ts +0 -1
  25. package/src/capabilities/modules.ts +27 -30
  26. package/src/capabilities/movement.ts +1 -1
  27. package/src/capabilities/storage.test.ts +26 -0
  28. package/src/capabilities/storage.ts +22 -7
  29. package/src/contracts/fund.ts +306 -0
  30. package/src/contracts/platform.ts +312 -3
  31. package/src/contracts/server.ts +2793 -478
  32. package/src/contracts/token.ts +170 -0
  33. package/src/contracts.ts +2 -0
  34. package/src/coordinates/address.ts +88 -0
  35. package/src/coordinates/constants.test.ts +15 -0
  36. package/src/coordinates/constants.ts +23 -0
  37. package/src/coordinates/index.ts +15 -0
  38. package/src/coordinates/memo.test.ts +47 -0
  39. package/src/coordinates/memo.ts +20 -0
  40. package/src/coordinates/permutation.ts +77 -0
  41. package/src/coordinates/regions.ts +48 -0
  42. package/src/coordinates/sectors.ts +115 -0
  43. package/src/data/capabilities.ts +49 -18
  44. package/src/data/capability-formulas.ts +26 -14
  45. package/src/data/catalog.test.ts +19 -0
  46. package/src/data/catalog.ts +13 -3
  47. package/src/data/charters.json +396 -0
  48. package/src/data/citizenry-adjectives.json +42 -0
  49. package/src/data/citizenry-nouns.json +50 -0
  50. package/src/data/colors.ts +14 -32
  51. package/src/data/entities.json +421 -15
  52. package/src/data/item-ids.ts +53 -13
  53. package/src/data/items.json +330 -77
  54. package/src/data/kind-registry.json +212 -0
  55. package/src/data/kind-registry.ts +192 -0
  56. package/src/data/metadata.ts +312 -51
  57. package/src/data/recipes-runtime.ts +6 -23
  58. package/src/data/recipes.json +2173 -173
  59. package/src/data/tiers.ts +9 -6
  60. package/src/derivation/build-methods.test.ts +71 -0
  61. package/src/derivation/build-methods.ts +50 -0
  62. package/src/derivation/capabilities.test.ts +348 -0
  63. package/src/derivation/capabilities.ts +707 -0
  64. package/src/derivation/capability-mappings.ts +60 -16
  65. package/src/derivation/crafting.test.ts +17 -0
  66. package/src/derivation/crafting.ts +57 -34
  67. package/src/derivation/index.ts +27 -2
  68. package/src/derivation/recipe-usage.test.ts +88 -0
  69. package/src/derivation/recipe-usage.ts +141 -0
  70. package/src/derivation/reserve-regen.ts +34 -0
  71. package/src/derivation/resources.ts +9 -1
  72. package/src/derivation/rollups.test.ts +55 -0
  73. package/src/derivation/rollups.ts +72 -0
  74. package/src/derivation/stars.test.ts +67 -0
  75. package/src/derivation/stars.ts +25 -0
  76. package/src/derivation/stat-scaling.ts +12 -0
  77. package/src/derivation/stats.ts +6 -6
  78. package/src/derivation/strata.ts +5 -3
  79. package/src/derivation/stratum.ts +26 -22
  80. package/src/derivation/tiers.ts +40 -7
  81. package/src/derivation/upgrades.ts +14 -0
  82. package/src/derivation/wormhole.ts +154 -0
  83. package/src/entities/entity.ts +102 -0
  84. package/src/entities/gamestate.ts +3 -28
  85. package/src/entities/makers.ts +144 -136
  86. package/src/entities/slot-multiplier.ts +43 -0
  87. package/src/entity/hydrate.test.ts +156 -0
  88. package/src/entity/hydrate.ts +86 -0
  89. package/src/errors.ts +21 -16
  90. package/src/format.ts +42 -9
  91. package/src/index-module.ts +425 -32
  92. package/src/influence/ballot.test.ts +103 -0
  93. package/src/influence/ballot.ts +98 -0
  94. package/src/influence/categories.ts +32 -0
  95. package/src/influence/charter-metadata.test.ts +136 -0
  96. package/src/influence/charter-metadata.ts +236 -0
  97. package/src/influence/charters.test.ts +112 -0
  98. package/src/influence/charters.ts +150 -0
  99. package/src/influence/citizenry.ts +38 -0
  100. package/src/influence/civic-shuttle.test.ts +202 -0
  101. package/src/influence/civic-shuttle.ts +142 -0
  102. package/src/influence/civic.test.ts +287 -0
  103. package/src/influence/civic.ts +269 -0
  104. package/src/influence/constants.ts +84 -0
  105. package/src/influence/decay.ts +20 -0
  106. package/src/influence/decomp.ts +95 -0
  107. package/src/influence/demand.ts +106 -0
  108. package/src/influence/duration.ts +101 -0
  109. package/src/influence/index.ts +118 -0
  110. package/src/influence/influence.test.ts +450 -0
  111. package/src/influence/quality.ts +25 -0
  112. package/src/influence/valuation.ts +154 -0
  113. package/src/managers/actions.ts +950 -93
  114. package/src/managers/balances.test.ts +161 -0
  115. package/src/managers/balances.ts +93 -0
  116. package/src/managers/base.ts +10 -2
  117. package/src/managers/cluster.test.ts +39 -0
  118. package/src/managers/cluster.ts +53 -0
  119. package/src/managers/construction-types.ts +80 -0
  120. package/src/managers/construction.ts +453 -0
  121. package/src/managers/context.ts +58 -1
  122. package/src/managers/coordinates.ts +14 -0
  123. package/src/managers/entities.ts +35 -63
  124. package/src/managers/epochs.ts +72 -1
  125. package/src/managers/index.ts +38 -1
  126. package/src/managers/influence.test.ts +56 -0
  127. package/src/managers/influence.ts +425 -0
  128. package/src/managers/jobs.test.ts +96 -0
  129. package/src/managers/jobs.ts +58 -0
  130. package/src/managers/locations.ts +25 -29
  131. package/src/managers/nft.test.ts +21 -0
  132. package/src/managers/nft.ts +110 -0
  133. package/src/managers/players.ts +25 -0
  134. package/src/managers/plot.ts +122 -0
  135. package/src/nft/atomicassets.abi.json +1342 -0
  136. package/src/nft/atomicassets.ts +237 -0
  137. package/src/nft/atomicdata.ts +130 -0
  138. package/src/nft/buildImmutableData.ts +388 -0
  139. package/src/nft/description.ts +222 -100
  140. package/src/nft/index.ts +3 -0
  141. package/src/planner/index.ts +296 -0
  142. package/src/planner/planner.test.ts +459 -0
  143. package/src/receipts.ts +22 -0
  144. package/src/resolution/describe-module.ts +43 -25
  145. package/src/resolution/display-name.ts +39 -11
  146. package/src/resolution/resolve-item.test.ts +48 -0
  147. package/src/resolution/resolve-item.ts +112 -58
  148. package/src/scan/index.ts +244 -0
  149. package/src/scan/scan-wasm.base64.ts +2 -0
  150. package/src/scheduling/accessor.ts +65 -23
  151. package/src/scheduling/availability.test.ts +320 -0
  152. package/src/scheduling/availability.ts +251 -0
  153. package/src/scheduling/cancel.test.ts +550 -0
  154. package/src/scheduling/cancel.ts +254 -0
  155. package/src/scheduling/cluster-stock.test.ts +31 -0
  156. package/src/scheduling/cluster-stock.ts +15 -0
  157. package/src/scheduling/energy.ts +47 -0
  158. package/src/scheduling/epoch.ts +1 -0
  159. package/src/scheduling/idle-resolve.ts +45 -0
  160. package/src/scheduling/jobs.test.ts +448 -0
  161. package/src/scheduling/jobs.ts +343 -0
  162. package/src/scheduling/lane-core.ts +128 -0
  163. package/src/scheduling/lanes.test.ts +250 -0
  164. package/src/scheduling/lanes.ts +279 -0
  165. package/src/scheduling/projection.ts +265 -149
  166. package/src/scheduling/schedule.test.ts +163 -0
  167. package/src/scheduling/schedule.ts +282 -116
  168. package/src/scheduling/task-cargo.test.ts +110 -0
  169. package/src/scheduling/task-cargo.ts +62 -0
  170. package/src/scheduling/task-effects.test.ts +35 -0
  171. package/src/scheduling/task-effects.ts +34 -0
  172. package/src/scheduling/unwrap.test.ts +86 -0
  173. package/src/scheduling/unwrap.ts +190 -0
  174. package/src/shipload.ts +63 -4
  175. package/src/subscriptions/manager.cluster.test.ts +51 -0
  176. package/src/subscriptions/manager.ts +245 -172
  177. package/src/subscriptions/mappers.ts +5 -8
  178. package/src/subscriptions/types.ts +28 -3
  179. package/src/testing/catalog-hash.ts +19 -0
  180. package/src/testing/index.ts +2 -0
  181. package/src/testing/projection-parity.ts +167 -0
  182. package/src/travel/reach.test.ts +86 -0
  183. package/src/travel/reach.ts +34 -0
  184. package/src/travel/route-build.test.ts +63 -0
  185. package/src/travel/route-build.ts +60 -0
  186. package/src/travel/route-planner.ts +288 -0
  187. package/src/travel/route-simulator.ts +170 -0
  188. package/src/travel/travel.ts +190 -123
  189. package/src/types/capabilities.ts +37 -8
  190. package/src/types/entity.ts +3 -3
  191. package/src/types/index.ts +0 -1
  192. package/src/types.ts +81 -23
  193. package/src/utils/cargo.test.ts +14 -0
  194. package/src/utils/cargo.ts +2 -0
  195. package/src/utils/display-name.ts +70 -0
  196. package/src/utils/hash.ts +22 -2
  197. package/src/utils/system.ts +24 -5
  198. package/src/capabilities/loading.ts +0 -8
  199. package/src/entities/container.ts +0 -123
  200. package/src/entities/ship-deploy.ts +0 -295
  201. package/src/entities/ship.ts +0 -221
  202. package/src/entities/warehouse.ts +0 -127
  203. package/src/types/entity-traits.ts +0 -69
@@ -1,13 +1,35 @@
1
- import type {Name, UInt16, UInt32} from '@wharfkit/antelope'
1
+ import type {Name, UInt32, UInt8} from '@wharfkit/antelope'
2
2
  import type {ServerContract} from '../contracts'
3
3
 
4
+ export interface LoaderStats {
5
+ mass: {toNumber(): number; multiplying(v: unknown): {toNumber(): number}}
6
+ thrust: {toNumber(): number}
7
+ quantity: {toNumber(): number; gt(v: unknown): boolean}
8
+ }
9
+
10
+ export interface GathererStats {
11
+ yield: {toNumber(): number}
12
+ drain: {toNumber(): number}
13
+ depth: {toNumber(): number; toString(): string}
14
+ }
15
+
16
+ export interface CrafterStats {
17
+ speed: {toNumber(): number}
18
+ drain: {toNumber(): number}
19
+ }
20
+
21
+ export interface BuilderStats {
22
+ speed: {toNumber(): number}
23
+ drain: {toNumber(): number}
24
+ }
25
+
4
26
  export interface MovementCapability {
5
27
  engines: ServerContract.Types.movement_stats
6
28
  generator: ServerContract.Types.energy_stats
7
29
  }
8
30
 
9
31
  export interface EnergyCapability {
10
- energy: UInt16
32
+ energy: UInt32
11
33
  }
12
34
 
13
35
  export interface StorageCapability {
@@ -17,11 +39,11 @@ export interface StorageCapability {
17
39
  }
18
40
 
19
41
  export interface LoaderCapability {
20
- loaders: ServerContract.Types.loader_stats
42
+ loaders: LoaderStats
21
43
  }
22
44
 
23
45
  export interface GathererCapability {
24
- gatherer: ServerContract.Types.gatherer_stats
46
+ gatherer: GathererStats
25
47
  }
26
48
 
27
49
  export interface MassCapability {
@@ -29,6 +51,7 @@ export interface MassCapability {
29
51
  }
30
52
 
31
53
  export interface ScheduleCapability {
54
+ lanes?: ServerContract.Types.lane[]
32
55
  schedule?: ServerContract.Types.schedule
33
56
  }
34
57
 
@@ -37,16 +60,18 @@ export interface EntityCapabilities {
37
60
  capacity?: UInt32
38
61
  engines?: ServerContract.Types.movement_stats
39
62
  generator?: ServerContract.Types.energy_stats
40
- loaders?: ServerContract.Types.loader_stats
41
- gatherer?: ServerContract.Types.gatherer_stats
42
- crafter?: ServerContract.Types.crafter_stats
63
+ loaders?: LoaderStats
64
+ gatherer?: GathererStats
65
+ crafter?: CrafterStats
66
+ builder?: BuilderStats
43
67
  hauler?: ServerContract.Types.hauler_stats
68
+ launcher?: ServerContract.Types.launcher_stats
44
69
  }
45
70
 
46
71
  export interface EntityState {
47
72
  owner: Name
48
73
  location: ServerContract.Types.coordinates
49
- energy?: UInt16
74
+ energy?: UInt32
50
75
  cargomass: UInt32
51
76
  cargo: ServerContract.Types.cargo_item[]
52
77
  }
@@ -74,3 +99,7 @@ export function capsHasMass(caps: EntityCapabilities): boolean {
74
99
  export function capsHasHauler(caps: EntityCapabilities): boolean {
75
100
  return caps.hauler !== undefined
76
101
  }
102
+
103
+ export function capsHasLauncher(caps: EntityCapabilities): boolean {
104
+ return caps.launcher !== undefined
105
+ }
@@ -3,6 +3,7 @@ import type {ServerContract} from '../contracts'
3
3
  import type {Coordinates} from '../types'
4
4
  import type {
5
5
  EnergyCapability,
6
+ GathererCapability,
6
7
  LoaderCapability,
7
8
  MassCapability,
8
9
  MovementCapability,
@@ -24,9 +25,8 @@ export type ShipEntity = Entity &
24
25
  StorageCapability &
25
26
  Partial<LoaderCapability> &
26
27
  MassCapability &
27
- ScheduleCapability & {
28
- gatherer?: ServerContract.Types.gatherer_stats
29
- }
28
+ ScheduleCapability &
29
+ Partial<GathererCapability>
30
30
 
31
31
  export type WarehouseEntity = Entity &
32
32
  StorageCapability &
@@ -1,3 +1,2 @@
1
1
  export * from './capabilities'
2
2
  export * from './entity'
3
- export * from './entity-traits'
package/src/types.ts CHANGED
@@ -1,35 +1,50 @@
1
1
  import {
2
2
  type Int64Type,
3
- Name,
4
3
  type UInt16,
5
4
  type UInt16Type,
6
5
  type UInt32,
7
6
  type UInt32Type,
8
7
  UInt64,
8
+ type UInt64Type,
9
9
  } from '@wharfkit/antelope'
10
10
  import {ServerContract} from './contracts'
11
+ import {COORD_MAX, COORD_MIN} from './coordinates/constants'
11
12
 
12
13
  export const PRECISION = 10000
13
- export const CRAFT_ENERGY_DIVISOR = 150000
14
+ export const MASS_UNITS_PER_TONNE = 10
15
+ export const MASS_STAT_SCALE = 100
16
+ export const CRAFT_ENERGY_DIVISOR = 1500
14
17
 
15
- export const WAREHOUSE_Z = 500
18
+ export const PLANETARY_STRUCTURE_Z = 0
16
19
 
17
20
  export const CONTAINER_Z = 300
18
21
 
19
22
  export const TRAVEL_MAX_DURATION = 86400
20
23
 
24
+ export const BASE_HAUL_PENALTY_MILLI = 300
25
+ export const HAULER_EFFICIENCY_DENOM = 10000
26
+
21
27
  export const MIN_ORBITAL_ALTITUDE = 800
22
28
  export const MAX_ORBITAL_ALTITUDE = 3000
23
29
 
24
- export const BASE_ORBITAL_MASS = 100000
30
+ export const BASE_ORBITAL_MASS = 1000
31
+
32
+ export const MIN_TRANSFER_DISTANCE_PLANETARY_STRUCTURE = 100
33
+ export const MIN_TRANSFER_DISTANCE_ORBITAL_VESSEL = 200
34
+
35
+ export interface ClusterSlotType {
36
+ hub: UInt64Type
37
+ gx: number
38
+ gy: number
39
+ }
25
40
 
26
41
  export interface ShipLike {
27
42
  coordinates: ServerContract.Types.coordinates
28
43
  hullmass?: UInt32
29
- energy?: UInt16
44
+ energy?: UInt32
30
45
  engines?: ServerContract.Types.movement_stats
31
46
  generator?: ServerContract.Types.energy_stats
32
- loaders?: ServerContract.Types.loader_stats
47
+ loader_lanes?: ServerContract.Types.loader_lane[]
33
48
  hauler?: ServerContract.Types.hauler_stats
34
49
  capacity?: UInt32
35
50
  }
@@ -48,12 +63,39 @@ export enum TaskType {
48
63
  GATHER = 5,
49
64
  WARP = 6,
50
65
  CRAFT = 7,
51
- DEPLOY = 8,
52
- WRAP = 9,
66
+ TRANSIT = 9,
53
67
  UNWRAP = 10,
54
68
  UNDEPLOY = 11,
55
- WRAP_ENTITY = 12,
69
+ LAUNCH = 12,
56
70
  DEMOLISH = 13,
71
+ BUILDPLOT = 15,
72
+ CHARGE = 16,
73
+ UPGRADE = 17,
74
+ SHUTTLE = 18,
75
+ REFIT = 19,
76
+ CONTRIBUTE = 20,
77
+ /** @deprecated Renamed to CIVIC_DEPOSIT. */
78
+ DEPOT_STORE = 21,
79
+ /** @deprecated Renamed to CIVIC_WITHDRAW. */
80
+ DEPOT_TAKE = 22,
81
+ CIVIC_DEPOSIT = 21,
82
+ CIVIC_WITHDRAW = 22,
83
+ }
84
+
85
+ export enum RefitOp {
86
+ ADD = 0,
87
+ REMOVE = 1,
88
+ SWAP = 2,
89
+ }
90
+
91
+ export enum HoldKind {
92
+ PULL = 1,
93
+ PUSH = 2,
94
+ GATHER = 3,
95
+ BUILD = 4,
96
+ FLIGHT = 5,
97
+ UPGRADE = 6,
98
+ SOURCE = 7,
57
99
  }
58
100
 
59
101
  export enum LocationType {
@@ -70,14 +112,6 @@ export enum TaskCancelable {
70
112
  ALWAYS = 2,
71
113
  }
72
114
 
73
- export const EntityType = {
74
- SHIP: Name.from('ship'),
75
- WAREHOUSE: Name.from('warehouse'),
76
- CONTAINER: Name.from('container'),
77
- } as const
78
-
79
- export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
80
-
81
115
  export type CoordinatesType =
82
116
  | Coordinates
83
117
  | ServerContract.Types.coordinates
@@ -100,13 +134,30 @@ export class Coordinates extends ServerContract.Types.coordinates {
100
134
 
101
135
  export function coordsToLocationId(coords: CoordinatesType): UInt64 {
102
136
  const c = Coordinates.from(coords)
103
- const mask = BigInt(0xffffffff)
104
- const x = BigInt(c.x.toNumber()) & mask
105
- const y = BigInt(c.y.toNumber()) & mask
106
- const id = (x << BigInt(32)) | y
137
+ const x = BigInt(c.x.toString())
138
+ const y = BigInt(c.y.toString())
139
+ if (
140
+ x < BigInt(COORD_MIN) ||
141
+ x > BigInt(COORD_MAX) ||
142
+ y < BigInt(COORD_MIN) ||
143
+ y > BigInt(COORD_MAX)
144
+ ) {
145
+ throw new Error('coordinate out of int32 bounds')
146
+ }
147
+ const offset = BigInt(2147483648)
148
+ const id = ((x + offset) << BigInt(32)) | (y + offset)
107
149
  return UInt64.from(id)
108
150
  }
109
151
 
152
+ export function locationIdToCoords(id: UInt64Type): {x: number; y: number} {
153
+ const value = BigInt(UInt64.from(id).toString())
154
+ const offset = BigInt(2147483648)
155
+ return {
156
+ x: Number((value >> BigInt(32)) - offset),
157
+ y: Number((value & BigInt('0xffffffff')) - offset),
158
+ }
159
+ }
160
+
110
161
  export interface Distance {
111
162
  origin: ServerContract.ActionParams.Type.coordinates
112
163
  destination: ServerContract.ActionParams.Type.coordinates
@@ -123,11 +174,15 @@ export type ModuleType =
123
174
  | 'loader'
124
175
  | 'warp'
125
176
  | 'crafter'
177
+ | 'builder'
126
178
  | 'launcher'
127
179
  | 'storage'
128
180
  | 'hauler'
181
+ | 'battery'
182
+ | 'catcher'
183
+ | 'aux'
129
184
 
130
- export const TIER_ADJECTIVES: Record<number, string> = {
185
+ export const RESOURCE_TIER_ADJECTIVES: Record<number, string> = {
131
186
  1: 'Crude',
132
187
  2: 'Dense',
133
188
  3: 'Pure',
@@ -140,6 +195,9 @@ export const TIER_ADJECTIVES: Record<number, string> = {
140
195
  10: 'Ascendant',
141
196
  }
142
197
 
198
+ export const COMPONENT_TIER_PREFIXES: Record<number, string> = {}
199
+ export const MODULE_TIER_PREFIXES: Record<number, string> = {}
200
+
143
201
  export const CATEGORY_LABELS: Record<ResourceCategory, string> = {
144
202
  ore: 'Ore',
145
203
  crystal: 'Crystal',
@@ -165,5 +223,5 @@ export function formatTier(tier: number): string {
165
223
  }
166
224
 
167
225
  export function tierAdjective(tier: number): string {
168
- return TIER_ADJECTIVES[tier] ?? `T${tier}`
226
+ return RESOURCE_TIER_ADJECTIVES[tier] ?? `T${tier}`
169
227
  }
@@ -0,0 +1,14 @@
1
+ import {describe, expect, test} from 'bun:test'
2
+ import {cargoRef} from './cargo'
3
+
4
+ describe('cargoRef', () => {
5
+ test('forwards entity_id when provided', () => {
6
+ const ref = cargoRef({item_id: 10201, stats: 196849n, modules: [], entity_id: 42n})
7
+ expect(ref.entity_id).toBe(42n)
8
+ })
9
+
10
+ test('omits entity_id when absent', () => {
11
+ const ref = cargoRef({item_id: 10201, stats: 196849n})
12
+ expect(ref.entity_id).toBeUndefined()
13
+ })
14
+ })
@@ -4,11 +4,13 @@ export function cargoRef(src: {
4
4
  item_id: number
5
5
  stats: bigint | number
6
6
  modules?: ServerContract.Types.module_entry[]
7
+ entity_id?: bigint | number
7
8
  }): ServerContract.ActionParams.Type.cargo_ref {
8
9
  return {
9
10
  item_id: src.item_id,
10
11
  stats: src.stats,
11
12
  modules: src.modules ?? [],
13
+ entity_id: src.entity_id,
12
14
  }
13
15
  }
14
16
 
@@ -0,0 +1,70 @@
1
+ export interface DisplayNameResult {
2
+ valid: boolean
3
+ reason?: string
4
+ name: string
5
+ }
6
+
7
+ const MAX_DISPLAY_NAME_BYTES = 32
8
+ const ASCII_SPACE = 0x20
9
+ const ZERO_WIDTH_CODE_POINTS = new Set([0x200b, 0x200c, 0x200d, 0x2060, 0xfeff])
10
+ const textEncoder = new TextEncoder()
11
+
12
+ function isControlCharacter(codePoint: number): boolean {
13
+ return codePoint <= 0x1f || codePoint === 0x7f || (codePoint >= 0x80 && codePoint <= 0x9f)
14
+ }
15
+
16
+ function isLoneSurrogate(codePoint: number): boolean {
17
+ return codePoint >= 0xd800 && codePoint <= 0xdfff
18
+ }
19
+
20
+ function isBidiControl(codePoint: number): boolean {
21
+ return (
22
+ (codePoint >= 0x202a && codePoint <= 0x202e) || (codePoint >= 0x2066 && codePoint <= 0x2069)
23
+ )
24
+ }
25
+
26
+ function isInvalidDisplayNameCodePoint(codePoint: number): boolean {
27
+ return (
28
+ isControlCharacter(codePoint) ||
29
+ isLoneSurrogate(codePoint) ||
30
+ ZERO_WIDTH_CODE_POINTS.has(codePoint) ||
31
+ isBidiControl(codePoint)
32
+ )
33
+ }
34
+
35
+ export function normalizeDisplayName(input: string): string {
36
+ let start = 0
37
+ let end = input.length
38
+
39
+ while (start < end && input.charCodeAt(start) === ASCII_SPACE) start++
40
+ while (end > start && input.charCodeAt(end - 1) === ASCII_SPACE) end--
41
+
42
+ return input.slice(start, end)
43
+ }
44
+
45
+ export interface ValidateDisplayNameOptions {
46
+ allowEmpty?: boolean
47
+ }
48
+
49
+ export function validateDisplayName(
50
+ input: string,
51
+ opts: ValidateDisplayNameOptions = {}
52
+ ): DisplayNameResult {
53
+ const name = normalizeDisplayName(input)
54
+
55
+ if (name.length === 0) {
56
+ return opts.allowEmpty ? {valid: true, name} : {valid: false, reason: 'empty', name}
57
+ }
58
+ if (textEncoder.encode(name).length > MAX_DISPLAY_NAME_BYTES) {
59
+ return {valid: false, reason: 'too_long', name}
60
+ }
61
+
62
+ for (const character of name) {
63
+ const codePoint = character.codePointAt(0)!
64
+ if (isInvalidDisplayNameCodePoint(codePoint)) {
65
+ return {valid: false, reason: 'invalid_char', name}
66
+ }
67
+ }
68
+
69
+ return {valid: true, name}
70
+ }
package/src/utils/hash.ts CHANGED
@@ -1,11 +1,31 @@
1
1
  import {Bytes, Checksum256, type Checksum256Type, Checksum512} from '@wharfkit/antelope'
2
2
 
3
+ type NativeHasher = new (
4
+ algorithm: 'sha256' | 'sha512'
5
+ ) => {
6
+ update(data: Uint8Array): {digest(): Uint8Array}
7
+ }
8
+
9
+ // antelope hashes through pure-JS hash.js; bun's native hasher is ~30x faster and byte-identical.
10
+ const nativeHasher: NativeHasher | undefined = (globalThis as {Bun?: {CryptoHasher?: NativeHasher}})
11
+ .Bun?.CryptoHasher
12
+
13
+ function digest(algorithm: 'sha256' | 'sha512', bytes: Bytes): Uint8Array | undefined {
14
+ return nativeHasher ? new nativeHasher(algorithm).update(bytes.array).digest() : undefined
15
+ }
16
+
3
17
  export function hash(seed: Checksum256Type, string: string): Checksum256 {
4
18
  const bytes = Bytes.from(`${seed}${string}`, 'utf8')
5
- return Checksum256.hash(bytes)
19
+ const native = digest('sha256', bytes)
20
+ return native ? new Checksum256(native) : Checksum256.hash(bytes)
6
21
  }
7
22
 
8
23
  export function hash512(seed: Checksum256Type, string: string): Checksum512 {
9
24
  const bytes = Bytes.from(`${seed}${string}`, 'utf8')
10
- return Checksum512.hash(bytes)
25
+ const native = digest('sha512', bytes)
26
+ return native ? new Checksum512(native) : Checksum512.hash(bytes)
27
+ }
28
+
29
+ export function uint16(hash: Checksum512, offset: number): number {
30
+ return (hash.array[offset] << 8) | hash.array[offset + 1]
11
31
  }
@@ -1,8 +1,9 @@
1
1
  import {Checksum256, type Checksum256Type, type Checksum512, UInt8} from '@wharfkit/antelope'
2
- import {hash512} from './hash'
2
+ import {hash512, uint16} from './hash'
3
3
  import {Coordinates, type CoordinatesType, LocationType} from '../types'
4
4
  import {ServerContract} from '../contracts'
5
5
  import {deriveLocationSize} from '../derivation/location-size'
6
+ import {wormholeAt} from '../derivation/wormhole'
6
7
  import syllables from '../data/syllables.json'
7
8
  import nebulaAdjectives from '../data/nebula-adjectives.json'
8
9
  import nebulaNouns from '../data/nebula-nouns.json'
@@ -46,10 +47,6 @@ export function getLocationTypeName(type: LocationType): string {
46
47
  }
47
48
  }
48
49
 
49
- function uint16(hash: Checksum512, offset: number): number {
50
- return (hash.array[offset] << 8) | hash.array[offset + 1]
51
- }
52
-
53
50
  function generatePlanetName(hashResult: Checksum512): string {
54
51
  const syllableCount = 2 + (hashResult.array[0] % 2)
55
52
  const name: string[] = []
@@ -110,6 +107,16 @@ export function hasSystem(gameSeed: Checksum256Type, coordinates: CoordinatesTyp
110
107
  return getLocationType(gameSeed, coordinates) !== LocationType.EMPTY
111
108
  }
112
109
 
110
+ export function getLocationKind(
111
+ gameSeed: Checksum256Type,
112
+ x: number,
113
+ y: number
114
+ ): 'wormhole' | 'system' | 'empty' {
115
+ if (wormholeAt(gameSeed, x, y)) return 'wormhole'
116
+ if (hasSystem(gameSeed, {x, y})) return 'system'
117
+ return 'empty'
118
+ }
119
+
113
120
  export function deriveLocationStatic(
114
121
  gameSeed: Checksum256Type,
115
122
  coordinates: CoordinatesType
@@ -150,6 +157,18 @@ export function deriveLocationStatic(
150
157
  return loc
151
158
  }
152
159
 
160
+ export function isLocationBuildable(
161
+ gameSeed: Checksum256Type,
162
+ coordinates: CoordinatesType
163
+ ): boolean {
164
+ const type = getLocationType(gameSeed, coordinates)
165
+ return (
166
+ type === LocationType.ASTEROID ||
167
+ type === LocationType.NEBULA ||
168
+ type === LocationType.ICE_FIELD
169
+ )
170
+ }
171
+
153
172
  export function deriveLocation(
154
173
  gameSeed: Checksum256Type,
155
174
  coordinates: CoordinatesType
@@ -1,8 +0,0 @@
1
- import {UInt32, type UInt64} from '@wharfkit/antelope'
2
- import type {LoaderCapability} from '../types/capabilities'
3
-
4
- export function calcLoadDuration(entity: LoaderCapability, cargoMass: UInt64): UInt32 {
5
- const totalThrust = entity.loaders.thrust.toNumber() * entity.loaders.quantity.toNumber()
6
- if (totalThrust === 0) return UInt32.from(0)
7
- return UInt32.from(Math.ceil(Number(cargoMass) / totalThrust))
8
- }
@@ -1,123 +0,0 @@
1
- import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
- import {ServerContract} from '../contracts'
3
- import type {CoordinatesType} from '../types'
4
- import {type FloatPosition, getInterpolatedPosition} from '../travel/travel'
5
- import {Location} from './location'
6
- import {ScheduleAccessor} from '../scheduling/accessor'
7
- import * as schedule from '../scheduling/schedule'
8
-
9
- export interface ContainerStateInput {
10
- id: UInt64Type
11
- owner: string
12
- name: string
13
- coordinates: CoordinatesType | {x: number; y: number; z?: number}
14
- hullmass: number
15
- capacity: number
16
- cargomass?: number
17
- cargo?: ServerContract.Types.cargo_item[]
18
- schedule?: ServerContract.Types.schedule
19
- }
20
-
21
- export class Container extends ServerContract.Types.entity_info {
22
- private _sched?: ScheduleAccessor
23
-
24
- get name(): string {
25
- return this.entity_name
26
- }
27
-
28
- get entityClass(): 'mobile' {
29
- return 'mobile'
30
- }
31
-
32
- get canUndeploy(): boolean {
33
- return true
34
- }
35
-
36
- get sched(): ScheduleAccessor {
37
- this._sched ??= new ScheduleAccessor(this)
38
- return this._sched
39
- }
40
-
41
- get isIdle(): boolean {
42
- return this.is_idle
43
- }
44
-
45
- interpolatedPositionAt(now: Date): FloatPosition {
46
- const taskIndex = this.sched.currentTaskIndex(now)
47
- const progress = this.sched.currentTaskProgressFloat(now)
48
- return getInterpolatedPosition(this, taskIndex, progress)
49
- }
50
-
51
- isLoading(now: Date): boolean {
52
- return schedule.isLoading(this, now)
53
- }
54
-
55
- isUnloading(now: Date): boolean {
56
- return schedule.isUnloading(this, now)
57
- }
58
-
59
- get location(): Location {
60
- return Location.from(this.coordinates)
61
- }
62
-
63
- get totalMass(): UInt64 {
64
- return UInt64.from(this.hullmass ?? 0).adding(this.cargomass)
65
- }
66
-
67
- get maxCapacity(): UInt64 {
68
- return UInt64.from(this.capacity)
69
- }
70
-
71
- get availableCapacity(): UInt64 {
72
- const cargo = UInt64.from(this.cargomass)
73
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
74
- }
75
-
76
- hasSpace(additionalMass: UInt64): boolean {
77
- return UInt64.from(this.cargomass).adding(additionalMass).lte(this.maxCapacity)
78
- }
79
-
80
- get isFull(): boolean {
81
- return UInt64.from(this.cargomass).gte(this.maxCapacity)
82
- }
83
-
84
- get orbitalAltitude(): number {
85
- return this.coordinates.z?.toNumber() || 0
86
- }
87
- }
88
-
89
- export function computeContainerCapabilities(stats: Record<string, number>): {
90
- hullmass: number
91
- capacity: number
92
- } {
93
- const density = stats.density
94
- const strength = stats.strength
95
- const hardness = stats.hardness
96
- const saturation = stats.saturation
97
-
98
- const hullmass = 25000 + 75 * density
99
-
100
- const statSum = strength + hardness + saturation
101
- const exponent = statSum / 2997
102
- const capacity = Math.floor(1000000 * 10 ** exponent)
103
-
104
- return {hullmass, capacity}
105
- }
106
-
107
- export function computeContainerT2Capabilities(stats: Record<string, number>): {
108
- hullmass: number
109
- capacity: number
110
- } {
111
- const strength = stats.strength
112
- const density = stats.density
113
- const hardness = stats.hardness
114
- const saturation = stats.saturation
115
-
116
- const hullmass = 20000 + 50 * density
117
-
118
- const statSum = strength + hardness + saturation
119
- const exponent = statSum / 2500
120
- const capacity = Math.floor(1500000 * 10 ** exponent)
121
-
122
- return {hullmass, capacity}
123
- }