@shipload/sdk 1.0.0-next.1 → 1.0.0-next.11
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 +618 -353
- package/lib/shipload.js +2250 -1059
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +2193 -1044
- package/lib/shipload.m.js.map +1 -1
- package/package.json +2 -2
- package/src/capabilities/modules.ts +3 -0
- package/src/capabilities/storage.ts +1 -1
- package/src/contracts/platform.ts +13 -1
- package/src/contracts/server.ts +227 -282
- package/src/data/capabilities.ts +5 -330
- package/src/data/capability-formulas.ts +70 -0
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +2 -16
- package/src/data/entities.json +46 -10
- package/src/data/item-ids.ts +4 -1
- package/src/data/items.json +264 -0
- package/src/data/metadata.ts +63 -1
- package/src/data/recipes-runtime.ts +1 -0
- package/src/data/recipes.json +139 -11
- package/src/derivation/capability-mappings.ts +122 -0
- package/src/derivation/index.ts +1 -0
- package/src/derivation/resources.ts +116 -37
- package/src/derivation/stats.ts +1 -2
- package/src/entities/container.ts +25 -10
- package/src/entities/extractor.ts +144 -0
- package/src/entities/factory.ts +135 -0
- package/src/entities/gamestate.ts +0 -9
- package/src/entities/makers.ts +130 -20
- package/src/entities/nexus.ts +29 -0
- package/src/entities/ship-deploy.ts +114 -56
- package/src/entities/ship.ts +17 -0
- package/src/entities/slot-multiplier.ts +21 -0
- package/src/entities/warehouse.ts +20 -3
- package/src/errors.ts +10 -13
- package/src/index-module.ts +81 -26
- package/src/managers/actions.ts +53 -80
- package/src/managers/entities.ts +65 -17
- package/src/managers/locations.ts +2 -20
- package/src/nft/atomicdata.ts +128 -0
- package/src/nft/description.ts +41 -7
- package/src/nft/index.ts +1 -0
- package/src/resolution/resolve-item.ts +17 -9
- package/src/scheduling/accessor.ts +4 -0
- package/src/scheduling/projection.ts +10 -2
- package/src/scheduling/schedule.ts +15 -1
- package/src/scheduling/task-cargo.ts +47 -0
- package/src/subscriptions/connection.ts +50 -2
- package/src/subscriptions/manager.ts +84 -4
- package/src/subscriptions/mappers.ts +5 -1
- package/src/subscriptions/types.ts +2 -2
- package/src/travel/travel.ts +61 -2
- package/src/types/entity-traits.ts +103 -1
- package/src/types.ts +11 -1
- package/src/utils/cargo.ts +27 -0
- package/src/utils/system.ts +25 -24
package/src/managers/entities.ts
CHANGED
|
@@ -3,14 +3,18 @@ import {BaseManager} from './base'
|
|
|
3
3
|
import {Ship} from '../entities/ship'
|
|
4
4
|
import {Warehouse} from '../entities/warehouse'
|
|
5
5
|
import {Container} from '../entities/container'
|
|
6
|
+
import {Extractor} from '../entities/extractor'
|
|
7
|
+
import {Factory} from '../entities/factory'
|
|
8
|
+
import {Nexus} from '../entities/nexus'
|
|
6
9
|
import type {ServerContract} from '../contracts'
|
|
7
10
|
|
|
8
|
-
export type EntityType = 'ship' | 'warehouse' | 'container' | '
|
|
11
|
+
export type EntityType = 'ship' | 'warehouse' | 'extractor' | 'factory' | 'container' | 'nexus'
|
|
9
12
|
|
|
10
13
|
export class EntitiesManager extends BaseManager {
|
|
11
|
-
async getEntity(
|
|
14
|
+
async getEntity(
|
|
15
|
+
id: UInt64Type
|
|
16
|
+
): Promise<Ship | Warehouse | Extractor | Factory | Container | Nexus> {
|
|
12
17
|
const result = await this.server.readonly('getentity', {
|
|
13
|
-
entity_type: Name.from(type),
|
|
14
18
|
entity_id: id,
|
|
15
19
|
})
|
|
16
20
|
const entityInfo = result as ServerContract.Types.entity_info
|
|
@@ -20,11 +24,11 @@ export class EntitiesManager extends BaseManager {
|
|
|
20
24
|
async getEntities(
|
|
21
25
|
owner: NameType | ServerContract.Types.player_row,
|
|
22
26
|
type?: EntityType
|
|
23
|
-
): Promise<(Ship | Warehouse | Container)[]> {
|
|
27
|
+
): Promise<(Ship | Warehouse | Extractor | Factory | Container | Nexus)[]> {
|
|
24
28
|
const ownerName = this.resolveOwner(owner)
|
|
25
29
|
const result = await this.server.readonly('getentities', {
|
|
26
30
|
owner: ownerName,
|
|
27
|
-
entity_type: type
|
|
31
|
+
entity_type: type,
|
|
28
32
|
})
|
|
29
33
|
const entities = result as ServerContract.Types.entity_info[]
|
|
30
34
|
return entities.map((entity) => this.wrapEntity(entity))
|
|
@@ -37,21 +41,29 @@ export class EntitiesManager extends BaseManager {
|
|
|
37
41
|
const ownerName = this.resolveOwner(owner)
|
|
38
42
|
const result = await this.server.readonly('getsummaries', {
|
|
39
43
|
owner: ownerName,
|
|
40
|
-
entity_type: type
|
|
44
|
+
entity_type: type,
|
|
41
45
|
})
|
|
42
46
|
return result as ServerContract.Types.entity_summary[]
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
async getShip(id: UInt64Type): Promise<Ship> {
|
|
46
|
-
return (await this.getEntity(
|
|
50
|
+
return (await this.getEntity(id)) as Ship
|
|
47
51
|
}
|
|
48
52
|
|
|
49
53
|
async getWarehouse(id: UInt64Type): Promise<Warehouse> {
|
|
50
|
-
return (await this.getEntity(
|
|
54
|
+
return (await this.getEntity(id)) as Warehouse
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
async getContainer(id: UInt64Type): Promise<Container> {
|
|
54
|
-
return (await this.getEntity(
|
|
58
|
+
return (await this.getEntity(id)) as Container
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async getExtractor(id: UInt64Type): Promise<Extractor> {
|
|
62
|
+
return (await this.getEntity(id)) as Extractor
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async getFactory(id: UInt64Type): Promise<Factory> {
|
|
66
|
+
return (await this.getEntity(id)) as Factory
|
|
55
67
|
}
|
|
56
68
|
|
|
57
69
|
async getShips(owner: NameType | ServerContract.Types.player_row): Promise<Ship[]> {
|
|
@@ -66,6 +78,14 @@ export class EntitiesManager extends BaseManager {
|
|
|
66
78
|
return (await this.getEntities(owner, 'container')) as Container[]
|
|
67
79
|
}
|
|
68
80
|
|
|
81
|
+
async getExtractors(owner: NameType | ServerContract.Types.player_row): Promise<Extractor[]> {
|
|
82
|
+
return (await this.getEntities(owner, 'extractor')) as Extractor[]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async getFactories(owner: NameType | ServerContract.Types.player_row): Promise<Factory[]> {
|
|
86
|
+
return (await this.getEntities(owner, 'factory')) as Factory[]
|
|
87
|
+
}
|
|
88
|
+
|
|
69
89
|
async getShipSummaries(
|
|
70
90
|
owner: NameType | ServerContract.Types.player_row
|
|
71
91
|
): Promise<ServerContract.Types.entity_summary[]> {
|
|
@@ -84,14 +104,42 @@ export class EntitiesManager extends BaseManager {
|
|
|
84
104
|
return this.getSummaries(owner, 'container')
|
|
85
105
|
}
|
|
86
106
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
107
|
+
async getExtractorSummaries(
|
|
108
|
+
owner: NameType | ServerContract.Types.player_row
|
|
109
|
+
): Promise<ServerContract.Types.entity_summary[]> {
|
|
110
|
+
return this.getSummaries(owner, 'extractor')
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async getFactorySummaries(
|
|
114
|
+
owner: NameType | ServerContract.Types.player_row
|
|
115
|
+
): Promise<ServerContract.Types.entity_summary[]> {
|
|
116
|
+
return this.getSummaries(owner, 'factory')
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async getNexus(id: UInt64Type): Promise<Nexus> {
|
|
120
|
+
return (await this.getEntity(id)) as Nexus
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
async getNexuses(owner: NameType | ServerContract.Types.player_row): Promise<Nexus[]> {
|
|
124
|
+
return (await this.getEntities(owner, 'nexus')) as Nexus[]
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async getNexusSummaries(
|
|
128
|
+
owner: NameType | ServerContract.Types.player_row
|
|
129
|
+
): Promise<ServerContract.Types.entity_summary[]> {
|
|
130
|
+
return this.getSummaries(owner, 'nexus')
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private wrapEntity(
|
|
134
|
+
entity: ServerContract.Types.entity_info
|
|
135
|
+
): Ship | Warehouse | Extractor | Factory | Container | Nexus {
|
|
136
|
+
if (entity.type.equals('ship')) return new Ship(entity)
|
|
137
|
+
if (entity.type.equals('warehouse')) return new Warehouse(entity)
|
|
138
|
+
if (entity.type.equals('extractor')) return new Extractor(entity)
|
|
139
|
+
if (entity.type.equals('factory')) return new Factory(entity)
|
|
140
|
+
if (entity.type.equals('container')) return new Container(entity)
|
|
141
|
+
if (entity.type.equals('nexus')) return new Nexus(entity)
|
|
142
|
+
throw new Error(`unknown entity type: ${entity.type}`)
|
|
95
143
|
}
|
|
96
144
|
|
|
97
145
|
private resolveOwner(owner: NameType | ServerContract.Types.player_row): Name {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type {UInt16Type} from '@wharfkit/antelope'
|
|
2
2
|
import {BaseManager} from './base'
|
|
3
|
-
import
|
|
3
|
+
import type {CoordinatesType, Distance} from '../types'
|
|
4
4
|
import {hasSystem} from '../utils/system'
|
|
5
5
|
import {findNearbyPlanets} from '../travel/travel'
|
|
6
6
|
import type {ServerContract} from '../contracts'
|
|
@@ -47,22 +47,4 @@ export class LocationsManager extends BaseManager {
|
|
|
47
47
|
reserve: overrideMap.get(s.index) ?? s.reserve,
|
|
48
48
|
}))
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
async getLocationEntity(
|
|
52
|
-
id: UInt64Type
|
|
53
|
-
): Promise<ServerContract.Types.location_row | undefined> {
|
|
54
|
-
const row = await this.server.table('location').get(UInt64.from(id))
|
|
55
|
-
return row ?? undefined
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async getLocationEntityAt(
|
|
59
|
-
coords: CoordinatesType
|
|
60
|
-
): Promise<ServerContract.Types.location_row | undefined> {
|
|
61
|
-
const id = coordsToLocationId(coords)
|
|
62
|
-
return this.getLocationEntity(id)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async getAllLocationEntities(): Promise<ServerContract.Types.location_row[]> {
|
|
66
|
-
return this.server.table('location').all()
|
|
67
|
-
}
|
|
68
50
|
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
export interface SchemaField {
|
|
2
|
+
name: string
|
|
3
|
+
type: string
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export type RawData =
|
|
7
|
+
| Uint8Array
|
|
8
|
+
| string
|
|
9
|
+
| number[]
|
|
10
|
+
| {immutable_serialized_data: Uint8Array | string | number[]}
|
|
11
|
+
|
|
12
|
+
export function deserializeAtomicData(
|
|
13
|
+
data: RawData,
|
|
14
|
+
schema: SchemaField[]
|
|
15
|
+
): Record<string, unknown> {
|
|
16
|
+
let rawData: Uint8Array | string | number[]
|
|
17
|
+
if (data && typeof data === 'object' && 'immutable_serialized_data' in (data as object)) {
|
|
18
|
+
rawData = (data as {immutable_serialized_data: Uint8Array | string | number[]})
|
|
19
|
+
.immutable_serialized_data
|
|
20
|
+
} else {
|
|
21
|
+
rawData = data as Uint8Array | string | number[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let bytes: Uint8Array
|
|
25
|
+
if (typeof rawData === 'string') {
|
|
26
|
+
const hex = rawData
|
|
27
|
+
bytes = new Uint8Array(hex.length / 2)
|
|
28
|
+
for (let i = 0; i < hex.length; i += 2) {
|
|
29
|
+
bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16)
|
|
30
|
+
}
|
|
31
|
+
} else if (Array.isArray(rawData)) {
|
|
32
|
+
bytes = new Uint8Array(rawData)
|
|
33
|
+
} else {
|
|
34
|
+
bytes = rawData
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let offset = 0
|
|
38
|
+
|
|
39
|
+
function readVarint(): number {
|
|
40
|
+
let result = 0
|
|
41
|
+
let multiplier = 1
|
|
42
|
+
while (bytes[offset] >= 128) {
|
|
43
|
+
result += (bytes[offset] - 128) * multiplier
|
|
44
|
+
offset++
|
|
45
|
+
multiplier *= 128
|
|
46
|
+
}
|
|
47
|
+
result += bytes[offset] * multiplier
|
|
48
|
+
offset++
|
|
49
|
+
return result
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function readVarint64(): bigint {
|
|
53
|
+
let result = 0n
|
|
54
|
+
let multiplier = 1n
|
|
55
|
+
while (bytes[offset] >= 128) {
|
|
56
|
+
result += BigInt(bytes[offset] - 128) * multiplier
|
|
57
|
+
offset++
|
|
58
|
+
multiplier *= 128n
|
|
59
|
+
}
|
|
60
|
+
result += BigInt(bytes[offset]) * multiplier
|
|
61
|
+
offset++
|
|
62
|
+
return result
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function readZigzagInt64(): bigint {
|
|
66
|
+
const unsigned = readVarint64()
|
|
67
|
+
if (unsigned % 2n === 0n) {
|
|
68
|
+
return unsigned / 2n
|
|
69
|
+
} else {
|
|
70
|
+
return -(unsigned / 2n) - 1n
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readString(): string {
|
|
75
|
+
const length = readVarint()
|
|
76
|
+
const str = new TextDecoder().decode(bytes.slice(offset, offset + length))
|
|
77
|
+
offset += length
|
|
78
|
+
return str
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const RESERVED = 4
|
|
82
|
+
const result: Record<string, unknown> = {}
|
|
83
|
+
|
|
84
|
+
while (offset < bytes.length) {
|
|
85
|
+
const fieldIndex = readVarint() - RESERVED
|
|
86
|
+
const field = schema[fieldIndex]
|
|
87
|
+
if (!field) break
|
|
88
|
+
|
|
89
|
+
switch (field.type) {
|
|
90
|
+
case 'uint16':
|
|
91
|
+
result[field.name] = readVarint()
|
|
92
|
+
break
|
|
93
|
+
case 'uint32':
|
|
94
|
+
result[field.name] = readVarint()
|
|
95
|
+
break
|
|
96
|
+
case 'uint64':
|
|
97
|
+
result[field.name] = readVarint64()
|
|
98
|
+
break
|
|
99
|
+
case 'int32':
|
|
100
|
+
result[field.name] = readZigzagInt64()
|
|
101
|
+
break
|
|
102
|
+
case 'int64':
|
|
103
|
+
result[field.name] = readZigzagInt64()
|
|
104
|
+
break
|
|
105
|
+
case 'string':
|
|
106
|
+
result[field.name] = readString()
|
|
107
|
+
break
|
|
108
|
+
case 'uint16[]': {
|
|
109
|
+
const len = readVarint()
|
|
110
|
+
const arr: number[] = []
|
|
111
|
+
for (let i = 0; i < len; i++) arr.push(readVarint())
|
|
112
|
+
result[field.name] = arr
|
|
113
|
+
break
|
|
114
|
+
}
|
|
115
|
+
case 'uint64[]': {
|
|
116
|
+
const len = readVarint()
|
|
117
|
+
const arr: bigint[] = []
|
|
118
|
+
for (let i = 0; i < len; i++) arr.push(readVarint64())
|
|
119
|
+
result[field.name] = arr
|
|
120
|
+
break
|
|
121
|
+
}
|
|
122
|
+
default:
|
|
123
|
+
throw new Error(`Unknown type: ${field.type}`)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return result
|
|
128
|
+
}
|
package/src/nft/description.ts
CHANGED
|
@@ -4,22 +4,29 @@ import {
|
|
|
4
4
|
MODULE_ENGINE,
|
|
5
5
|
MODULE_GATHERER,
|
|
6
6
|
MODULE_GENERATOR,
|
|
7
|
+
MODULE_HAULER,
|
|
7
8
|
MODULE_LOADER,
|
|
8
9
|
MODULE_STORAGE,
|
|
10
|
+
MODULE_WARP,
|
|
9
11
|
} from '../capabilities/modules'
|
|
10
12
|
import {
|
|
11
13
|
ITEM_CONTAINER_T1_PACKED,
|
|
12
14
|
ITEM_CONTAINER_T2_PACKED,
|
|
13
15
|
ITEM_CRAFTER_T1,
|
|
14
16
|
ITEM_ENGINE_T1,
|
|
17
|
+
ITEM_EXTRACTOR_T1_PACKED,
|
|
15
18
|
ITEM_GATHERER_T1,
|
|
16
19
|
ITEM_GENERATOR_T1,
|
|
20
|
+
ITEM_HAULER_T1,
|
|
17
21
|
ITEM_LOADER_T1,
|
|
18
22
|
ITEM_SHIP_T1_PACKED,
|
|
19
23
|
ITEM_STORAGE_T1,
|
|
20
24
|
ITEM_WAREHOUSE_T1_PACKED,
|
|
25
|
+
ITEM_WARP_T1,
|
|
21
26
|
} from '../data/item-ids'
|
|
22
27
|
import {decodeStat} from '../derivation/crafting'
|
|
28
|
+
import {gathererDepthForTier} from '../entities/ship-deploy'
|
|
29
|
+
import {getItem} from '../data/catalog'
|
|
23
30
|
|
|
24
31
|
function idiv(a: number, b: number): number {
|
|
25
32
|
return Math.floor(a / b)
|
|
@@ -27,7 +34,7 @@ function idiv(a: number, b: number): number {
|
|
|
27
34
|
|
|
28
35
|
export function computeBaseHullmass(stats: bigint): number {
|
|
29
36
|
const density = decodeStat(stats, 1)
|
|
30
|
-
return
|
|
37
|
+
return 100000 - 75 * density
|
|
31
38
|
}
|
|
32
39
|
|
|
33
40
|
export function computeBaseCapacityShip(stats: bigint): number {
|
|
@@ -42,17 +49,22 @@ export function computeBaseCapacityWarehouse(stats: bigint): number {
|
|
|
42
49
|
|
|
43
50
|
export const computeEngineThrust = (vol: number): number => 400 + idiv(vol * 3, 4)
|
|
44
51
|
export const computeEngineDrain = (thm: number): number => Math.max(30, 50 - idiv(thm, 70))
|
|
45
|
-
export const computeGeneratorCap = (
|
|
46
|
-
export const computeGeneratorRech = (
|
|
52
|
+
export const computeGeneratorCap = (com: number): number => 300 + idiv(com, 6)
|
|
53
|
+
export const computeGeneratorRech = (fin: number): number => 1 + idiv(fin * 3, 1000)
|
|
47
54
|
export const computeGathererYield = (str: number): number => 200 + str
|
|
48
55
|
export const computeGathererDrain = (con: number): number =>
|
|
49
56
|
Math.max(250, 1250 - idiv(con * 25, 20))
|
|
50
|
-
export const computeGathererDepth = (tol: number): number =>
|
|
57
|
+
export const computeGathererDepth = (tol: number, tier: number): number =>
|
|
58
|
+
gathererDepthForTier(tol, tier)
|
|
51
59
|
export const computeGathererSpeed = (ref: number): number => 100 + idiv(ref * 4, 5)
|
|
52
|
-
export const computeLoaderMass = (
|
|
60
|
+
export const computeLoaderMass = (ins: number): number => Math.max(200, 2000 - ins * 2)
|
|
53
61
|
export const computeLoaderThrust = (pla: number): number => 1 + idiv(pla, 500)
|
|
54
62
|
export const computeCrafterSpeed = (rea: number): number => 100 + idiv(rea * 4, 5)
|
|
55
|
-
export const computeCrafterDrain = (
|
|
63
|
+
export const computeCrafterDrain = (fin: number): number => Math.max(5, 30 - idiv(fin, 33))
|
|
64
|
+
export const computeHaulerCapacity = (fin: number): number => Math.max(1, 1 + idiv(fin, 400))
|
|
65
|
+
export const computeHaulerEfficiency = (con: number): number => 2000 + con * 6
|
|
66
|
+
export const computeHaulerDrain = (com: number): number => Math.max(3, 15 - idiv(com, 80))
|
|
67
|
+
export const computeWarpRange = (stat: number): number => 100 + stat * 3
|
|
56
68
|
|
|
57
69
|
export function entityDisplayName(itemId: number): string {
|
|
58
70
|
switch (itemId) {
|
|
@@ -60,6 +72,8 @@ export function entityDisplayName(itemId: number): string {
|
|
|
60
72
|
return 'Ship'
|
|
61
73
|
case ITEM_WAREHOUSE_T1_PACKED:
|
|
62
74
|
return 'Warehouse'
|
|
75
|
+
case ITEM_EXTRACTOR_T1_PACKED:
|
|
76
|
+
return 'Extractor'
|
|
63
77
|
case ITEM_CONTAINER_T1_PACKED:
|
|
64
78
|
return 'Container'
|
|
65
79
|
case ITEM_CONTAINER_T2_PACKED:
|
|
@@ -83,6 +97,10 @@ export function moduleDisplayName(itemId: number): string {
|
|
|
83
97
|
return 'Crafter'
|
|
84
98
|
case ITEM_STORAGE_T1:
|
|
85
99
|
return 'Storage'
|
|
100
|
+
case ITEM_HAULER_T1:
|
|
101
|
+
return 'Hauler'
|
|
102
|
+
case ITEM_WARP_T1:
|
|
103
|
+
return 'Warp'
|
|
86
104
|
default:
|
|
87
105
|
return 'Module'
|
|
88
106
|
}
|
|
@@ -116,8 +134,10 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
|
|
|
116
134
|
const tol = decodeStat(stats, 1)
|
|
117
135
|
const con = decodeStat(stats, 3)
|
|
118
136
|
const ref = decodeStat(stats, 4)
|
|
137
|
+
const tier = getItem(itemId).tier
|
|
119
138
|
out += ` Yield ${computeGathererYield(str)} Depth ${computeGathererDepth(
|
|
120
|
-
tol
|
|
139
|
+
tol,
|
|
140
|
+
tier
|
|
121
141
|
)} Speed ${computeGathererSpeed(ref)} Drain ${computeGathererDrain(con)}`
|
|
122
142
|
break
|
|
123
143
|
}
|
|
@@ -142,6 +162,18 @@ export function formatModuleLine(slot: number, itemId: number, stats: bigint): s
|
|
|
142
162
|
out += ` +${pct}% capacity`
|
|
143
163
|
break
|
|
144
164
|
}
|
|
165
|
+
case MODULE_HAULER: {
|
|
166
|
+
const fin = decodeStat(stats, 0)
|
|
167
|
+
const con = decodeStat(stats, 1)
|
|
168
|
+
const com = decodeStat(stats, 2)
|
|
169
|
+
out += ` Capacity ${computeHaulerCapacity(fin)} Efficiency ${computeHaulerEfficiency(con)} Drain ${computeHaulerDrain(com)}`
|
|
170
|
+
break
|
|
171
|
+
}
|
|
172
|
+
case MODULE_WARP: {
|
|
173
|
+
const stat = decodeStat(stats, 0)
|
|
174
|
+
out += ` Range ${computeWarpRange(stat)}`
|
|
175
|
+
break
|
|
176
|
+
}
|
|
145
177
|
}
|
|
146
178
|
return out
|
|
147
179
|
}
|
|
@@ -158,6 +190,8 @@ export function buildEntityDescription(
|
|
|
158
190
|
baseCapacity = computeBaseCapacityShip(hullStats)
|
|
159
191
|
} else if (itemId === ITEM_WAREHOUSE_T1_PACKED) {
|
|
160
192
|
baseCapacity = computeBaseCapacityWarehouse(hullStats)
|
|
193
|
+
} else if (itemId === ITEM_EXTRACTOR_T1_PACKED) {
|
|
194
|
+
baseCapacity = computeBaseCapacityShip(hullStats)
|
|
161
195
|
}
|
|
162
196
|
|
|
163
197
|
let out = entityDisplayName(itemId)
|
package/src/nft/index.ts
CHANGED
|
@@ -39,6 +39,7 @@ import type {ServerContract} from '../contracts'
|
|
|
39
39
|
import {
|
|
40
40
|
ITEM_CONTAINER_T1_PACKED,
|
|
41
41
|
ITEM_CONTAINER_T2_PACKED,
|
|
42
|
+
ITEM_EXTRACTOR_T1_PACKED,
|
|
42
43
|
ITEM_SHIP_T1_PACKED,
|
|
43
44
|
ITEM_WAREHOUSE_T1_PACKED,
|
|
44
45
|
} from '../data/item-ids'
|
|
@@ -155,7 +156,8 @@ function resolveComponent(id: number, stats?: UInt64Type): ResolvedItem {
|
|
|
155
156
|
|
|
156
157
|
function computeCapabilityGroup(
|
|
157
158
|
moduleType: number,
|
|
158
|
-
stats: Record<string, number
|
|
159
|
+
stats: Record<string, number>,
|
|
160
|
+
tier: number
|
|
159
161
|
): ResolvedAttributeGroup | undefined {
|
|
160
162
|
switch (moduleType) {
|
|
161
163
|
case MODULE_ENGINE: {
|
|
@@ -179,7 +181,7 @@ function computeCapabilityGroup(
|
|
|
179
181
|
}
|
|
180
182
|
}
|
|
181
183
|
case MODULE_GATHERER: {
|
|
182
|
-
const caps = computeGathererCapabilities(stats)
|
|
184
|
+
const caps = computeGathererCapabilities(stats, tier)
|
|
183
185
|
return {
|
|
184
186
|
capability: 'Gatherer',
|
|
185
187
|
attributes: [
|
|
@@ -223,10 +225,11 @@ function computeCapabilityGroup(
|
|
|
223
225
|
}
|
|
224
226
|
}
|
|
225
227
|
case MODULE_STORAGE: {
|
|
226
|
-
const str = stats.strength
|
|
227
|
-
const
|
|
228
|
-
const
|
|
229
|
-
const
|
|
228
|
+
const str = stats.strength
|
|
229
|
+
const den = stats.density
|
|
230
|
+
const hrd = stats.hardness
|
|
231
|
+
const sat = stats.saturation
|
|
232
|
+
const statSum = str + den + hrd + sat
|
|
230
233
|
const pct = 10 + Math.floor((statSum * 10) / 2997)
|
|
231
234
|
return {capability: 'Storage', attributes: [{label: 'Capacity Bonus', value: pct}]}
|
|
232
235
|
}
|
|
@@ -241,7 +244,7 @@ function resolveModule(id: number, stats?: UInt64Type): ResolvedItem {
|
|
|
241
244
|
if (stats !== undefined) {
|
|
242
245
|
const decoded = decodeCraftedItemStats(id, toBigStats(stats))
|
|
243
246
|
const modType = getModuleCapabilityType(id)
|
|
244
|
-
const group = computeCapabilityGroup(modType, decoded)
|
|
247
|
+
const group = computeCapabilityGroup(modType, decoded, item.tier)
|
|
245
248
|
if (group) attributes = [group]
|
|
246
249
|
}
|
|
247
250
|
return {
|
|
@@ -268,6 +271,8 @@ function hullCapsForEntity(
|
|
|
268
271
|
return computeShipHullCapabilities(decoded)
|
|
269
272
|
case ITEM_WAREHOUSE_T1_PACKED:
|
|
270
273
|
return computeWarehouseHullCapabilities(decoded)
|
|
274
|
+
case ITEM_EXTRACTOR_T1_PACKED:
|
|
275
|
+
return computeShipHullCapabilities(decoded)
|
|
271
276
|
case ITEM_CONTAINER_T1_PACKED:
|
|
272
277
|
return computeContainerCapabilities(decoded)
|
|
273
278
|
case ITEM_CONTAINER_T2_PACKED:
|
|
@@ -310,13 +315,16 @@ function resolveEntity(
|
|
|
310
315
|
const modStats = BigInt(mod.installed.stats.toString())
|
|
311
316
|
const decodedStats = decodeCraftedItemStats(modItemId, modStats)
|
|
312
317
|
const modType = getModuleCapabilityType(modItemId)
|
|
313
|
-
const group = computeCapabilityGroup(modType, decodedStats)
|
|
314
318
|
let modName = 'Module'
|
|
319
|
+
let modTier = 1
|
|
315
320
|
try {
|
|
316
|
-
|
|
321
|
+
const modItem = getItem(modItemId)
|
|
322
|
+
modName = modItem.name
|
|
323
|
+
modTier = modItem.tier
|
|
317
324
|
} catch {
|
|
318
325
|
modName = itemMetadata[modItemId]?.name ?? 'Module'
|
|
319
326
|
}
|
|
327
|
+
const group = computeCapabilityGroup(modType, decodedStats, modTier)
|
|
320
328
|
return {
|
|
321
329
|
name: modName,
|
|
322
330
|
installed: true,
|
|
@@ -72,6 +72,10 @@ export class ScheduleAccessor {
|
|
|
72
72
|
return schedule.currentTaskProgress(this.entity, now)
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
currentTaskProgressFloat(now: Date): number {
|
|
76
|
+
return schedule.currentTaskProgressFloat(this.entity, now)
|
|
77
|
+
}
|
|
78
|
+
|
|
75
79
|
progress(now: Date): number {
|
|
76
80
|
return schedule.scheduleProgress(this.entity, now)
|
|
77
81
|
}
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
RECIPE_INPUTS_INSUFFICIENT,
|
|
15
15
|
RECIPE_INPUTS_INVALID,
|
|
16
16
|
RECIPE_NOT_FOUND,
|
|
17
|
-
|
|
17
|
+
ENTITY_CARGO_NOT_LOADED,
|
|
18
18
|
} from '../errors'
|
|
19
19
|
import {getRecipe, type RecipeInput} from '../data/recipes-runtime'
|
|
20
20
|
import {getItem} from '../data/catalog'
|
|
@@ -267,6 +267,10 @@ function applyTask(projected: ProjectedEntity, task: ServerContract.Types.task):
|
|
|
267
267
|
case TaskType.DEPLOY:
|
|
268
268
|
applyDeployTask(projected, task)
|
|
269
269
|
break
|
|
270
|
+
case TaskType.UNDEPLOY:
|
|
271
|
+
case TaskType.WRAP_ENTITY:
|
|
272
|
+
case TaskType.DEMOLISH:
|
|
273
|
+
break
|
|
270
274
|
}
|
|
271
275
|
}
|
|
272
276
|
|
|
@@ -385,7 +389,7 @@ function validateCraftTask(task: ServerContract.Types.task, projected: Projected
|
|
|
385
389
|
break
|
|
386
390
|
}
|
|
387
391
|
}
|
|
388
|
-
if (!found) throw new Error(
|
|
392
|
+
if (!found) throw new Error(ENTITY_CARGO_NOT_LOADED)
|
|
389
393
|
}
|
|
390
394
|
}
|
|
391
395
|
|
|
@@ -448,6 +452,10 @@ export function projectEntityAt(entity: Projectable, now: Date): ProjectedEntity
|
|
|
448
452
|
case TaskType.DEPLOY:
|
|
449
453
|
if (taskComplete) applyDeployTask(projected, task)
|
|
450
454
|
break
|
|
455
|
+
case TaskType.UNDEPLOY:
|
|
456
|
+
case TaskType.WRAP_ENTITY:
|
|
457
|
+
case TaskType.DEMOLISH:
|
|
458
|
+
break
|
|
451
459
|
}
|
|
452
460
|
}
|
|
453
461
|
|
|
@@ -77,7 +77,7 @@ export function currentTaskIndex(entity: ScheduleData, now: Date): number {
|
|
|
77
77
|
timeAccum += taskDuration
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
return
|
|
80
|
+
return -1
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
export function currentTask(entity: ScheduleData, now: Date): Task | undefined {
|
|
@@ -147,6 +147,20 @@ export function currentTaskProgress(entity: ScheduleData, now: Date): number {
|
|
|
147
147
|
return Math.min(1, elapsed / duration)
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
export function currentTaskProgressFloat(entity: ScheduleData, now: Date): number {
|
|
151
|
+
if (!entity.schedule || entity.schedule.tasks.length === 0) return 0
|
|
152
|
+
const index = currentTaskIndex(entity, now)
|
|
153
|
+
if (index < 0) return 0
|
|
154
|
+
const task = entity.schedule.tasks[index]
|
|
155
|
+
const durationMs = task.duration.toNumber() * 1000
|
|
156
|
+
if (durationMs === 0) return 1
|
|
157
|
+
const startedMs = entity.schedule.started.toDate().getTime()
|
|
158
|
+
const taskStartMs = startedMs + getTaskStartTime(entity, index) * 1000
|
|
159
|
+
const elapsedMs = now.getTime() - taskStartMs
|
|
160
|
+
if (elapsedMs <= 0) return 0
|
|
161
|
+
return Math.min(1, elapsedMs / durationMs)
|
|
162
|
+
}
|
|
163
|
+
|
|
150
164
|
export function scheduleProgress(entity: ScheduleData, now: Date): number {
|
|
151
165
|
const duration = scheduleDuration(entity)
|
|
152
166
|
if (duration === 0) return hasSchedule(entity) ? 1 : 0
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type {ServerContract} from '../contracts'
|
|
2
|
+
import {TaskType} from '../types'
|
|
3
|
+
|
|
4
|
+
export type TaskCargoDirection = 'in' | 'out'
|
|
5
|
+
|
|
6
|
+
export interface TaskCargoChange {
|
|
7
|
+
direction: TaskCargoDirection
|
|
8
|
+
item_id: number
|
|
9
|
+
stats: bigint
|
|
10
|
+
modules: ServerContract.Types.module_entry[]
|
|
11
|
+
quantity: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function toChange(
|
|
15
|
+
item: ServerContract.Types.cargo_item,
|
|
16
|
+
direction: TaskCargoDirection
|
|
17
|
+
): TaskCargoChange {
|
|
18
|
+
return {
|
|
19
|
+
direction,
|
|
20
|
+
item_id: Number(item.item_id),
|
|
21
|
+
stats: BigInt(item.stats.toString()),
|
|
22
|
+
modules: item.modules ?? [],
|
|
23
|
+
quantity: Number(item.quantity),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function taskCargoChanges(task: ServerContract.Types.task): TaskCargoChange[] {
|
|
28
|
+
const items = task.cargo ?? []
|
|
29
|
+
if (items.length === 0) return []
|
|
30
|
+
switch (Number(task.type)) {
|
|
31
|
+
case TaskType.LOAD:
|
|
32
|
+
case TaskType.UNWRAP:
|
|
33
|
+
return items.map((i) => toChange(i, 'in'))
|
|
34
|
+
case TaskType.GATHER:
|
|
35
|
+
return task.entitytarget ? [] : items.map((i) => toChange(i, 'in'))
|
|
36
|
+
case TaskType.UNLOAD:
|
|
37
|
+
case TaskType.WRAP:
|
|
38
|
+
return items.map((i) => toChange(i, 'out'))
|
|
39
|
+
case TaskType.CRAFT:
|
|
40
|
+
return [
|
|
41
|
+
...items.slice(0, -1).map((i) => toChange(i, 'out')),
|
|
42
|
+
toChange(items[items.length - 1], 'in'),
|
|
43
|
+
]
|
|
44
|
+
default:
|
|
45
|
+
return []
|
|
46
|
+
}
|
|
47
|
+
}
|