@shipload/sdk 1.0.0-next.11 → 1.0.0-next.13

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.
@@ -26,8 +26,9 @@ import {
26
26
  computeLoaderCapabilities,
27
27
  computeShipHullCapabilities,
28
28
  computeWarehouseHullCapabilities,
29
- } from '../entities/ship-deploy'
30
- import {computeContainerCapabilities, computeContainerT2Capabilities} from '../entities/container'
29
+ computeContainerCapabilities,
30
+ computeContainerT2Capabilities,
31
+ } from '../derivation/capabilities'
31
32
  import {
32
33
  categoryColors,
33
34
  categoryIcons,
@@ -13,13 +13,10 @@ import type {
13
13
  WireEntity,
14
14
  } from './types'
15
15
  import {mapEntity, parseWireEntity} from './mappers'
16
- import type {Ship} from '../entities/ship'
17
- import type {Warehouse} from '../entities/warehouse'
18
- import type {Container} from '../entities/container'
19
- import type {Nexus} from '../entities/nexus'
16
+ import type {Entity} from '../entities/entity'
20
17
 
21
18
  export type SubscriptionEntityType = 'ship' | 'warehouse' | 'container' | 'nexus'
22
- export type EntityInstance = Ship | Warehouse | Container | Nexus
19
+ export type EntityInstance = Entity
23
20
 
24
21
  export interface SubscriptionsOptions {
25
22
  url: string
@@ -1,18 +1,9 @@
1
1
  import {ServerContract} from '../contracts'
2
- import {Ship} from '../entities/ship'
3
- import {Warehouse} from '../entities/warehouse'
4
- import {Container} from '../entities/container'
5
- import {Nexus} from '../entities/nexus'
2
+ import {Entity} from '../entities/entity'
6
3
  import type {WireEntity} from './types'
7
4
 
8
- export function mapEntity(
9
- ei: ServerContract.Types.entity_info
10
- ): Ship | Warehouse | Container | Nexus {
11
- if (ei.type.equals('ship')) return new Ship(ei)
12
- if (ei.type.equals('warehouse')) return new Warehouse(ei)
13
- if (ei.type.equals('container')) return new Container(ei)
14
- if (ei.type.equals('nexus')) return new Nexus(ei)
15
- throw new Error(`mapEntity: unknown entity type ${ei.type.toString()}`)
5
+ export function mapEntity(ei: ServerContract.Types.entity_info): Entity {
6
+ return new Entity(ei)
16
7
  }
17
8
 
18
9
  export function parseWireEntity(raw: WireEntity): ServerContract.Types.entity_info {
@@ -0,0 +1,19 @@
1
+ import {createHash} from 'node:crypto'
2
+ import {readFileSync} from 'node:fs'
3
+
4
+ export const CATALOG_FILES_REL = [
5
+ 'items.json',
6
+ 'recipes.json',
7
+ 'entities.json',
8
+ 'kind-registry.json',
9
+ 'item-ids.ts',
10
+ ] as const
11
+
12
+ export function computeCatalogHash(filePaths: ReadonlyArray<string>): string {
13
+ const hash = createHash('sha256')
14
+ for (const p of filePaths) {
15
+ hash.update(readFileSync(p))
16
+ hash.update('\0')
17
+ }
18
+ return hash.digest('hex')
19
+ }
@@ -0,0 +1,2 @@
1
+ export * from './catalog-hash'
2
+ export * from './projection-parity'
@@ -0,0 +1,143 @@
1
+ import type {UInt16, UInt32} from '@wharfkit/antelope'
2
+ import type {ServerContract} from '../contracts'
3
+ import type {ProjectedEntity} from '../scheduling/projection'
4
+ import {type CargoStack, cargoItemToStack, mergeStacks} from '../capabilities/storage'
5
+
6
+ export interface ContractProjectedState {
7
+ owner: {toString(): string}
8
+ coordinates: ServerContract.Types.coordinates
9
+ energy?: UInt16
10
+ cargomass: UInt32
11
+ cargo: ServerContract.Types.cargo_view[]
12
+ hullmass?: UInt32
13
+ capacity?: UInt32
14
+ engines?: ServerContract.Types.movement_stats
15
+ loaders?: ServerContract.Types.loader_stats
16
+ generator?: ServerContract.Types.energy_stats
17
+ hauler?: ServerContract.Types.hauler_stats
18
+ }
19
+
20
+ export interface ProjectionComparisonOptions {
21
+ step?: number
22
+ }
23
+
24
+ export function assertProjectionEquals(
25
+ contract: ContractProjectedState,
26
+ sdk: ProjectedEntity,
27
+ options: ProjectionComparisonOptions = {}
28
+ ): void {
29
+ const mismatches: string[] = []
30
+
31
+ const record = (name: string, c: unknown, s: unknown) => {
32
+ if (c !== s) mismatches.push(` ${name}: contract=${fmt(c)} sdk=${fmt(s)}`)
33
+ }
34
+
35
+ const recordStatBlock = (name: string, c: unknown, s: unknown) => {
36
+ const cPresent = c !== undefined && c !== null
37
+ const sPresent = s !== undefined && s !== null
38
+ if (cPresent !== sPresent) {
39
+ mismatches.push(
40
+ ` ${name}: contract=${cPresent ? 'present' : 'absent'} sdk=${sPresent ? 'present' : 'absent'}`
41
+ )
42
+ return
43
+ }
44
+ if (!cPresent) return
45
+ const cn = JSON.stringify(normaliseStatBlock(c))
46
+ const sn = JSON.stringify(normaliseStatBlock(s))
47
+ if (cn !== sn) mismatches.push(` ${name}: contract=${cn} sdk=${sn}`)
48
+ }
49
+
50
+ record('coordinates.x', toNum(contract.coordinates.x), Number(sdk.location.x))
51
+ record('coordinates.y', toNum(contract.coordinates.y), Number(sdk.location.y))
52
+ record('energy', toNum(contract.energy), Number(sdk.energy))
53
+ record('cargomass', toNum(contract.cargomass), Number(sdk.cargoMass))
54
+ record('hullmass', toNum(contract.hullmass), Number(sdk.shipMass))
55
+ record('capacity', toNum(contract.capacity), sdk.capacity ? Number(sdk.capacity) : undefined)
56
+
57
+ recordStatBlock('engines', contract.engines, sdk.engines)
58
+ recordStatBlock('loaders', contract.loaders, sdk.loaders)
59
+ recordStatBlock('generator', contract.generator, sdk.generator)
60
+ recordStatBlock('hauler', contract.hauler, sdk.hauler)
61
+
62
+ if (contract.cargo.length > 0 || sdk.cargo.length > 0) {
63
+ const contractCargo = normaliseCargo(mergeContractCargo(contract.cargo))
64
+ const sdkCargo = normaliseCargo(sdk.cargo)
65
+ if (contractCargo.length !== sdkCargo.length) {
66
+ mismatches.push(
67
+ ` cargo.length: contract=${contractCargo.length} sdk=${sdkCargo.length}`
68
+ )
69
+ } else {
70
+ for (let i = 0; i < contractCargo.length; i++) {
71
+ const c = contractCargo[i]
72
+ const s = sdkCargo[i]
73
+ if (c.itemId !== s.itemId || c.stats !== s.stats || c.quantity !== s.quantity) {
74
+ mismatches.push(
75
+ ` cargo[${i}]: contract={item:${c.itemId},stats:${c.stats},qty:${c.quantity}} sdk={item:${s.itemId},stats:${s.stats},qty:${s.quantity}}`
76
+ )
77
+ }
78
+ }
79
+ }
80
+ }
81
+
82
+ if (mismatches.length > 0) {
83
+ const header =
84
+ options.step !== undefined
85
+ ? `projection divergence at step ${options.step}:`
86
+ : 'projection divergence:'
87
+ throw new Error([header, ...mismatches].join('\n'))
88
+ }
89
+ }
90
+
91
+ interface NormalisedStack {
92
+ itemId: number
93
+ stats: string
94
+ quantity: string
95
+ }
96
+
97
+ function mergeContractCargo(cargo: ServerContract.Types.cargo_view[]): CargoStack[] {
98
+ return cargo.reduce<CargoStack[]>(
99
+ (acc, row) =>
100
+ mergeStacks(acc, cargoItemToStack(row as unknown as ServerContract.Types.cargo_item)),
101
+ []
102
+ )
103
+ }
104
+
105
+ function normaliseCargo(cargo: CargoStack[]): NormalisedStack[] {
106
+ return cargo
107
+ .map((s) => ({
108
+ itemId: Number(s.item_id),
109
+ stats: BigInt(s.stats.toString()).toString(),
110
+ quantity: BigInt(s.quantity.toString()).toString(),
111
+ }))
112
+ .sort(stackSort)
113
+ }
114
+
115
+ function stackSort(a: NormalisedStack, b: NormalisedStack): number {
116
+ if (a.itemId !== b.itemId) return a.itemId - b.itemId
117
+ return a.stats < b.stats ? -1 : a.stats > b.stats ? 1 : 0
118
+ }
119
+
120
+ function toNum(v: unknown): number | undefined {
121
+ if (v === undefined || v === null) return undefined
122
+ if (typeof v === 'number') return v
123
+ if (typeof v === 'bigint') return Number(v)
124
+ if (typeof (v as {toNumber?: unknown}).toNumber === 'function') {
125
+ return (v as {toNumber(): number}).toNumber()
126
+ }
127
+ return Number(v as number)
128
+ }
129
+
130
+ function fmt(v: unknown): string {
131
+ if (v === undefined) return 'undefined'
132
+ if (v === null) return 'null'
133
+ return String(v)
134
+ }
135
+
136
+ function normaliseStatBlock(block: unknown): Record<string, number> {
137
+ const out: Record<string, number> = {}
138
+ const obj = block as Record<string, unknown>
139
+ for (const k of Object.keys(obj).sort()) {
140
+ out[k] = toNum(obj[k]) ?? 0
141
+ }
142
+ return out
143
+ }
@@ -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,6 +1,5 @@
1
1
  import {
2
2
  type Int64Type,
3
- Name,
4
3
  type UInt16,
5
4
  type UInt16Type,
6
5
  type UInt32,
@@ -72,14 +71,6 @@ export enum TaskCancelable {
72
71
  ALWAYS = 2,
73
72
  }
74
73
 
75
- export const EntityType = {
76
- SHIP: Name.from('ship'),
77
- WAREHOUSE: Name.from('warehouse'),
78
- CONTAINER: Name.from('container'),
79
- } as const
80
-
81
- export type EntityTypeName = (typeof EntityType)[keyof typeof EntityType]
82
-
83
74
  export type CoordinatesType =
84
75
  | Coordinates
85
76
  | ServerContract.Types.coordinates
@@ -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(): 'orbital' {
29
- return 'orbital'
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 = 100000 - 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 = 70000 - 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
- }
@@ -1,144 +0,0 @@
1
- import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
- import {ServerContract} from '../contracts'
3
- import type {CoordinatesType} from '../types'
4
- import {Location} from './location'
5
- import {ScheduleAccessor} from '../scheduling/accessor'
6
- import {InventoryAccessor} from './inventory-accessor'
7
- import type {EntityInventory} from './entity-inventory'
8
- import type {PackedModuleInput} from './ship'
9
- import {decodeCraftedItemStats} from '../derivation/crafting'
10
- import {getModuleCapabilityType, MODULE_GATHERER, MODULE_GENERATOR} from '../capabilities/modules'
11
- import {computeGathererCapabilities, computeGeneratorCapabilities} from './ship-deploy'
12
- import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
13
- import type {EntitySlot} from '../data/recipes-runtime'
14
- import {getItem} from '../data/catalog'
15
-
16
- export interface ExtractorStateInput {
17
- id: UInt64Type
18
- owner: string
19
- name: string
20
- coordinates: CoordinatesType | {x: number; y: number; z?: number}
21
- hullmass?: number
22
- capacity?: number
23
- energy?: number
24
- modules?: PackedModuleInput[]
25
- schedule?: ServerContract.Types.schedule
26
- cargo?: ServerContract.Types.cargo_item[]
27
- }
28
-
29
- export class Extractor extends ServerContract.Types.entity_info {
30
- private _sched?: ScheduleAccessor
31
- private _inv?: InventoryAccessor
32
-
33
- get name(): string {
34
- return this.entity_name
35
- }
36
-
37
- get entityClass(): 'planetary' {
38
- return 'planetary'
39
- }
40
-
41
- get canDemolish(): boolean {
42
- return true
43
- }
44
-
45
- get inv(): InventoryAccessor {
46
- this._inv ??= new InventoryAccessor(this)
47
- return this._inv
48
- }
49
-
50
- get inventory(): EntityInventory[] {
51
- return this.inv.items
52
- }
53
-
54
- get sched(): ScheduleAccessor {
55
- this._sched ??= new ScheduleAccessor(this)
56
- return this._sched
57
- }
58
-
59
- get isIdle(): boolean {
60
- return this.is_idle
61
- }
62
-
63
- get location(): Location {
64
- return Location.from(this.coordinates)
65
- }
66
-
67
- get totalCargoMass(): UInt64 {
68
- return this.inv.totalMass
69
- }
70
-
71
- get maxCapacity(): UInt64 {
72
- return UInt64.from(this.capacity)
73
- }
74
-
75
- get availableCapacity(): UInt64 {
76
- const cargo = this.totalCargoMass
77
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
78
- }
79
-
80
- get isFull(): boolean {
81
- return this.totalCargoMass.gte(this.maxCapacity)
82
- }
83
-
84
- get totalMass(): UInt64 {
85
- const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
86
- return hull.adding(this.totalCargoMass)
87
- }
88
- }
89
-
90
- export interface ExtractorCapabilities {
91
- generator?: {capacity: number; recharge: number}
92
- gatherer?: {yield: number; drain: number; depth: number; speed: number}
93
- }
94
-
95
- export function computeExtractorCapabilities(
96
- modules: InstalledModule[],
97
- layout: EntitySlot[]
98
- ): ExtractorCapabilities {
99
- const out: ExtractorCapabilities = {}
100
-
101
- const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
102
- if (genModules.length > 0) {
103
- let totalCapacity = 0
104
- let totalRecharge = 0
105
- for (const m of genModules) {
106
- const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
107
- const amp = getSlotAmp(layout, m.slotIndex)
108
- totalCapacity += applySlotMultiplier(caps.capacity, amp)
109
- totalRecharge += applySlotMultiplier(caps.recharge, amp)
110
- }
111
- out.generator = {
112
- capacity: clampUint16(totalCapacity),
113
- recharge: clampUint16(totalRecharge),
114
- }
115
- }
116
-
117
- const gathModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GATHERER)
118
- if (gathModules.length > 0) {
119
- let totalYield = 0
120
- let totalDrain = 0
121
- let maxDepth = 0
122
- let totalSpeed = 0
123
- for (const m of gathModules) {
124
- const tier = getItem(m.itemId).tier
125
- const caps = computeGathererCapabilities(
126
- decodeCraftedItemStats(m.itemId, m.stats),
127
- tier
128
- )
129
- const amp = getSlotAmp(layout, m.slotIndex)
130
- totalYield += applySlotMultiplier(caps.yield, amp)
131
- totalDrain += caps.drain
132
- if (caps.depth > maxDepth) maxDepth = caps.depth
133
- totalSpeed += applySlotMultiplier(caps.speed, amp)
134
- }
135
- out.gatherer = {
136
- yield: clampUint16(totalYield),
137
- drain: totalDrain,
138
- depth: maxDepth,
139
- speed: clampUint16(totalSpeed),
140
- }
141
- }
142
-
143
- return out
144
- }
@@ -1,135 +0,0 @@
1
- import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
- import {ServerContract} from '../contracts'
3
- import type {CoordinatesType} from '../types'
4
- import {Location} from './location'
5
- import {ScheduleAccessor} from '../scheduling/accessor'
6
- import {InventoryAccessor} from './inventory-accessor'
7
- import type {EntityInventory} from './entity-inventory'
8
- import type {PackedModuleInput} from './ship'
9
- import {decodeCraftedItemStats} from '../derivation/crafting'
10
- import {getModuleCapabilityType, MODULE_CRAFTER, MODULE_GENERATOR} from '../capabilities/modules'
11
- import {computeCrafterCapabilities, computeGeneratorCapabilities} from './ship-deploy'
12
- import {applySlotMultiplier, clampUint16, getSlotAmp, type InstalledModule} from './slot-multiplier'
13
- import type {EntitySlot} from '../data/recipes-runtime'
14
-
15
- export interface FactoryStateInput {
16
- id: UInt64Type
17
- owner: string
18
- name: string
19
- coordinates: CoordinatesType | {x: number; y: number; z?: number}
20
- hullmass?: number
21
- capacity?: number
22
- energy?: number
23
- modules?: PackedModuleInput[]
24
- schedule?: ServerContract.Types.schedule
25
- cargo?: ServerContract.Types.cargo_item[]
26
- }
27
-
28
- export class Factory extends ServerContract.Types.entity_info {
29
- private _sched?: ScheduleAccessor
30
- private _inv?: InventoryAccessor
31
-
32
- get name(): string {
33
- return this.entity_name
34
- }
35
-
36
- get entityClass(): 'planetary' {
37
- return 'planetary'
38
- }
39
-
40
- get canDemolish(): boolean {
41
- return true
42
- }
43
-
44
- get inv(): InventoryAccessor {
45
- this._inv ??= new InventoryAccessor(this)
46
- return this._inv
47
- }
48
-
49
- get inventory(): EntityInventory[] {
50
- return this.inv.items
51
- }
52
-
53
- get sched(): ScheduleAccessor {
54
- this._sched ??= new ScheduleAccessor(this)
55
- return this._sched
56
- }
57
-
58
- get isIdle(): boolean {
59
- return this.is_idle
60
- }
61
-
62
- get location(): Location {
63
- return Location.from(this.coordinates)
64
- }
65
-
66
- get totalCargoMass(): UInt64 {
67
- return this.inv.totalMass
68
- }
69
-
70
- get maxCapacity(): UInt64 {
71
- return UInt64.from(this.capacity)
72
- }
73
-
74
- get availableCapacity(): UInt64 {
75
- const cargo = this.totalCargoMass
76
- return cargo.gte(this.maxCapacity) ? UInt64.from(0) : this.maxCapacity.subtracting(cargo)
77
- }
78
-
79
- get isFull(): boolean {
80
- return this.totalCargoMass.gte(this.maxCapacity)
81
- }
82
-
83
- get totalMass(): UInt64 {
84
- const hull = this.hullmass ? UInt64.from(this.hullmass) : UInt64.from(0)
85
- return hull.adding(this.totalCargoMass)
86
- }
87
- }
88
-
89
- export interface FactoryCapabilities {
90
- generator?: {capacity: number; recharge: number}
91
- crafter?: {speed: number; drain: number}
92
- }
93
-
94
- export function computeFactoryCapabilities(
95
- modules: InstalledModule[],
96
- layout: EntitySlot[]
97
- ): FactoryCapabilities {
98
- const out: FactoryCapabilities = {}
99
-
100
- const genModules = modules.filter((m) => getModuleCapabilityType(m.itemId) === MODULE_GENERATOR)
101
- if (genModules.length > 0) {
102
- let totalCapacity = 0
103
- let totalRecharge = 0
104
- for (const m of genModules) {
105
- const caps = computeGeneratorCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
106
- const amp = getSlotAmp(layout, m.slotIndex)
107
- totalCapacity += applySlotMultiplier(caps.capacity, amp)
108
- totalRecharge += applySlotMultiplier(caps.recharge, amp)
109
- }
110
- out.generator = {
111
- capacity: clampUint16(totalCapacity),
112
- recharge: clampUint16(totalRecharge),
113
- }
114
- }
115
-
116
- const crafterModules = modules.filter(
117
- (m) => getModuleCapabilityType(m.itemId) === MODULE_CRAFTER
118
- )
119
- if (crafterModules.length > 0) {
120
- let totalSpeed = 0
121
- let totalDrain = 0
122
- for (const m of crafterModules) {
123
- const caps = computeCrafterCapabilities(decodeCraftedItemStats(m.itemId, m.stats))
124
- const amp = getSlotAmp(layout, m.slotIndex)
125
- totalSpeed += applySlotMultiplier(caps.speed, amp)
126
- totalDrain += caps.drain
127
- }
128
- out.crafter = {
129
- speed: clampUint16(totalSpeed),
130
- drain: totalDrain,
131
- }
132
- }
133
-
134
- return out
135
- }
@@ -1,29 +0,0 @@
1
- import type {UInt64Type} from '@wharfkit/antelope'
2
- import {ServerContract} from '../contracts'
3
- import type {CoordinatesType} from '../types'
4
- import {Location} from './location'
5
-
6
- export interface NexusStateInput {
7
- id: UInt64Type
8
- owner: string
9
- name: string
10
- coordinates: CoordinatesType | {x: number; y: number; z?: number}
11
- }
12
-
13
- export class Nexus extends ServerContract.Types.entity_info {
14
- get name(): string {
15
- return this.entity_name
16
- }
17
-
18
- get entityClass(): 'orbital' {
19
- return 'orbital'
20
- }
21
-
22
- get location(): Location {
23
- return Location.from(this.coordinates)
24
- }
25
-
26
- get orbitalAltitude(): number {
27
- return this.coordinates.z?.toNumber() || 0
28
- }
29
- }