@shipload/sdk 1.0.0-next.4 → 1.0.0-next.41
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/scan.d.ts +34 -0
- package/lib/scan.js +136 -0
- package/lib/scan.js.map +1 -0
- package/lib/scan.m.js +129 -0
- package/lib/scan.m.js.map +1 -0
- package/lib/shipload.d.ts +2473 -973
- package/lib/shipload.js +11529 -5211
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +11338 -5162
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +970 -0
- package/lib/testing.js +4013 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +4007 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.ts +51 -0
- package/src/capabilities/crafting.test.ts +7 -0
- package/src/capabilities/crafting.ts +5 -6
- package/src/capabilities/gathering.test.ts +16 -0
- package/src/capabilities/gathering.ts +35 -18
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +9 -0
- package/src/capabilities/storage.ts +16 -1
- package/src/contracts/platform.ts +231 -3
- package/src/contracts/server.ts +1021 -481
- package/src/coordinates/address.ts +88 -0
- package/src/coordinates/constants.test.ts +15 -0
- package/src/coordinates/constants.ts +23 -0
- package/src/coordinates/index.ts +15 -0
- package/src/coordinates/memo.test.ts +47 -0
- package/src/coordinates/memo.ts +20 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/data/capabilities.ts +12 -5
- package/src/data/capability-formulas.ts +14 -7
- package/src/data/catalog.ts +0 -5
- package/src/data/colors.ts +14 -47
- package/src/data/entities.json +76 -10
- package/src/data/item-ids.ts +18 -12
- package/src/data/items.json +321 -38
- package/src/data/kind-registry.json +109 -0
- package/src/data/kind-registry.ts +165 -0
- package/src/data/metadata.ts +119 -33
- package/src/data/recipes-runtime.ts +3 -23
- package/src/data/recipes.json +238 -117
- package/src/derivation/build-methods.ts +45 -0
- package/src/derivation/capabilities.test.ts +151 -0
- package/src/derivation/capabilities.ts +512 -0
- package/src/derivation/capability-mappings.ts +9 -12
- package/src/derivation/crafting.ts +23 -24
- package/src/derivation/index.ts +25 -2
- package/src/derivation/recipe-usage.test.ts +78 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +125 -38
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +56 -0
- package/src/derivation/stars.test.ts +51 -0
- package/src/derivation/stars.ts +15 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/stratum.ts +17 -20
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/wormhole.ts +136 -0
- package/src/entities/entity.ts +98 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +124 -134
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/errors.ts +12 -16
- package/src/format.ts +26 -4
- package/src/index-module.ts +267 -47
- package/src/managers/actions.ts +528 -95
- package/src/managers/base.ts +6 -2
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +412 -0
- package/src/managers/context.ts +20 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +18 -66
- package/src/managers/epochs.ts +40 -0
- package/src/managers/index.ts +17 -1
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +14 -0
- package/src/managers/nft.ts +70 -0
- package/src/managers/plot.ts +122 -0
- package/src/nft/atomicassets.abi.json +1342 -0
- package/src/nft/atomicassets.ts +237 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +338 -0
- package/src/nft/description.ts +98 -24
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +127 -0
- package/src/planner/planner.test.ts +319 -0
- package/src/resolution/describe-module.ts +18 -13
- package/src/resolution/display-name.ts +38 -10
- package/src/resolution/resolve-item.test.ts +37 -0
- package/src/resolution/resolve-item.ts +55 -24
- package/src/scan/index.ts +180 -0
- package/src/scan/scan-wasm.base64.ts +2 -0
- package/src/scheduling/accessor.ts +68 -22
- package/src/scheduling/availability.ts +108 -0
- package/src/scheduling/cancel.test.ts +348 -0
- package/src/scheduling/cancel.ts +209 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +249 -0
- package/src/scheduling/lanes.ts +198 -0
- package/src/scheduling/projection.ts +209 -105
- package/src/scheduling/schedule.ts +241 -104
- package/src/scheduling/task-cargo.ts +46 -0
- package/src/shipload.ts +21 -1
- package/src/subscriptions/manager.ts +229 -142
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +11 -3
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +167 -0
- package/src/travel/reach.ts +23 -0
- package/src/travel/route-planner.ts +196 -0
- package/src/travel/travel.ts +200 -112
- package/src/types/capabilities.ts +29 -6
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +28 -13
- package/src/utils/cargo.ts +27 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/system.ts +36 -24
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -108
- package/src/entities/ship-deploy.ts +0 -259
- package/src/entities/ship.ts +0 -204
- package/src/entities/warehouse.ts +0 -119
- package/src/types/entity-traits.ts +0 -69
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ABI,
|
|
3
|
+
type ABIDef,
|
|
4
|
+
Action,
|
|
5
|
+
type APIClient,
|
|
6
|
+
type NameType,
|
|
7
|
+
Name,
|
|
8
|
+
PermissionLevel,
|
|
9
|
+
UInt64,
|
|
10
|
+
} from '@wharfkit/antelope'
|
|
11
|
+
import {deserializeAtomicData, type SchemaField} from './atomicdata'
|
|
12
|
+
import {deserializeAsset, type NFTCargoItem, type NFTModuleSlot} from './deserializers'
|
|
13
|
+
import type {ImmutableEntry} from './buildImmutableData'
|
|
14
|
+
import atomicAssetsAbi from './atomicassets.abi.json'
|
|
15
|
+
|
|
16
|
+
const PLACEHOLDER_AUTH = PermissionLevel.from({
|
|
17
|
+
actor: '............1',
|
|
18
|
+
permission: '............2',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
export const ATOMICASSETS_ACCOUNT = 'atomicassets'
|
|
22
|
+
export const SHIPLOAD_COLLECTION = 'shipload'
|
|
23
|
+
|
|
24
|
+
export const ATOMICASSETS_ABI = ABI.from(atomicAssetsAbi as ABIDef)
|
|
25
|
+
|
|
26
|
+
const ATOMIC_ATTRIBUTE_VARIANT_NAME =
|
|
27
|
+
'variant_int8_int16_int32_int64_uint8_uint16_uint32_uint64_float32_float64_string_INT8_VEC_INT16_VEC_INT32_VEC_INT64_VEC_UINT8_VEC_UINT16_VEC_UINT32_VEC_UINT64_VEC_FLOAT_VEC_DOUBLE_VEC_STRING_VEC'
|
|
28
|
+
|
|
29
|
+
const MINTASSET_ABI_DEF: ABIDef = {
|
|
30
|
+
version: 'eosio::abi/1.2',
|
|
31
|
+
types: [
|
|
32
|
+
{new_type_name: 'ATOMIC_ATTRIBUTE', type: ATOMIC_ATTRIBUTE_VARIANT_NAME},
|
|
33
|
+
{new_type_name: 'ATTRIBUTE_MAP', type: 'pair_string_ATOMIC_ATTRIBUTE[]'},
|
|
34
|
+
{new_type_name: 'INT8_VEC', type: 'bytes'},
|
|
35
|
+
{new_type_name: 'INT16_VEC', type: 'int16[]'},
|
|
36
|
+
{new_type_name: 'INT32_VEC', type: 'int32[]'},
|
|
37
|
+
{new_type_name: 'INT64_VEC', type: 'int64[]'},
|
|
38
|
+
{new_type_name: 'UINT8_VEC', type: 'bytes'},
|
|
39
|
+
{new_type_name: 'UINT16_VEC', type: 'uint16[]'},
|
|
40
|
+
{new_type_name: 'UINT32_VEC', type: 'uint32[]'},
|
|
41
|
+
{new_type_name: 'UINT64_VEC', type: 'uint64[]'},
|
|
42
|
+
{new_type_name: 'FLOAT_VEC', type: 'float32[]'},
|
|
43
|
+
{new_type_name: 'DOUBLE_VEC', type: 'float64[]'},
|
|
44
|
+
{new_type_name: 'STRING_VEC', type: 'string[]'},
|
|
45
|
+
],
|
|
46
|
+
structs: [
|
|
47
|
+
{
|
|
48
|
+
name: 'pair_string_ATOMIC_ATTRIBUTE',
|
|
49
|
+
base: '',
|
|
50
|
+
fields: [
|
|
51
|
+
{name: 'first', type: 'string'},
|
|
52
|
+
{name: 'second', type: 'ATOMIC_ATTRIBUTE'},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'mintasset',
|
|
57
|
+
base: '',
|
|
58
|
+
fields: [
|
|
59
|
+
{name: 'authorized_minter', type: 'name'},
|
|
60
|
+
{name: 'collection_name', type: 'name'},
|
|
61
|
+
{name: 'schema_name', type: 'name'},
|
|
62
|
+
{name: 'template_id', type: 'int32'},
|
|
63
|
+
{name: 'new_asset_owner', type: 'name'},
|
|
64
|
+
{name: 'immutable_data', type: 'ATTRIBUTE_MAP'},
|
|
65
|
+
{name: 'mutable_data', type: 'ATTRIBUTE_MAP'},
|
|
66
|
+
{name: 'tokens_to_back', type: 'asset[]'},
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
actions: [{name: 'mintasset', type: 'mintasset', ricardian_contract: ''}],
|
|
71
|
+
variants: [
|
|
72
|
+
{
|
|
73
|
+
name: ATOMIC_ATTRIBUTE_VARIANT_NAME,
|
|
74
|
+
types: [
|
|
75
|
+
'int8',
|
|
76
|
+
'int16',
|
|
77
|
+
'int32',
|
|
78
|
+
'int64',
|
|
79
|
+
'uint8',
|
|
80
|
+
'uint16',
|
|
81
|
+
'uint32',
|
|
82
|
+
'uint64',
|
|
83
|
+
'float32',
|
|
84
|
+
'float64',
|
|
85
|
+
'string',
|
|
86
|
+
'INT8_VEC',
|
|
87
|
+
'INT16_VEC',
|
|
88
|
+
'INT32_VEC',
|
|
89
|
+
'INT64_VEC',
|
|
90
|
+
'UINT8_VEC',
|
|
91
|
+
'UINT16_VEC',
|
|
92
|
+
'UINT32_VEC',
|
|
93
|
+
'UINT64_VEC',
|
|
94
|
+
'FLOAT_VEC',
|
|
95
|
+
'DOUBLE_VEC',
|
|
96
|
+
'STRING_VEC',
|
|
97
|
+
],
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export interface MintAssetParams {
|
|
103
|
+
authorizedMinter: NameType
|
|
104
|
+
collectionName: NameType
|
|
105
|
+
schemaName: NameType
|
|
106
|
+
templateId: number
|
|
107
|
+
newAssetOwner: NameType
|
|
108
|
+
immutableData: ImmutableEntry[]
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const MINTASSET_ABI = ABI.from(MINTASSET_ABI_DEF)
|
|
112
|
+
|
|
113
|
+
export function buildMintAssetAction(params: MintAssetParams): Action {
|
|
114
|
+
return Action.from(
|
|
115
|
+
{
|
|
116
|
+
account: Name.from(ATOMICASSETS_ACCOUNT),
|
|
117
|
+
name: Name.from('mintasset'),
|
|
118
|
+
authorization: [PLACEHOLDER_AUTH],
|
|
119
|
+
data: {
|
|
120
|
+
authorized_minter: Name.from(params.authorizedMinter),
|
|
121
|
+
collection_name: Name.from(params.collectionName),
|
|
122
|
+
schema_name: Name.from(params.schemaName),
|
|
123
|
+
template_id: params.templateId,
|
|
124
|
+
new_asset_owner: Name.from(params.newAssetOwner),
|
|
125
|
+
immutable_data: params.immutableData,
|
|
126
|
+
mutable_data: [],
|
|
127
|
+
tokens_to_back: [],
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
MINTASSET_ABI
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface AtomicAssetRow {
|
|
135
|
+
asset_id: string
|
|
136
|
+
collection_name: string
|
|
137
|
+
schema_name: string
|
|
138
|
+
template_id: number
|
|
139
|
+
ram_payer?: string
|
|
140
|
+
backed_tokens?: string[]
|
|
141
|
+
immutable_serialized_data: string | number[]
|
|
142
|
+
mutable_serialized_data?: string | number[]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface AtomicSchemaRow {
|
|
146
|
+
schema_name: string
|
|
147
|
+
format: SchemaField[]
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export interface FetchAssetsOptions {
|
|
151
|
+
collection?: NameType
|
|
152
|
+
pageSize?: number
|
|
153
|
+
account?: NameType
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function fetchAtomicAssetsForOwner(
|
|
157
|
+
client: APIClient,
|
|
158
|
+
owner: NameType,
|
|
159
|
+
opts: FetchAssetsOptions = {}
|
|
160
|
+
): Promise<AtomicAssetRow[]> {
|
|
161
|
+
const collection = opts.collection ? String(Name.from(opts.collection)) : undefined
|
|
162
|
+
const pageSize = opts.pageSize ?? 1000
|
|
163
|
+
const account = Name.from(opts.account ?? ATOMICASSETS_ACCOUNT)
|
|
164
|
+
const out: AtomicAssetRow[] = []
|
|
165
|
+
let lower: UInt64 | undefined
|
|
166
|
+
while (true) {
|
|
167
|
+
const res = await client.v1.chain.get_table_rows({
|
|
168
|
+
code: account,
|
|
169
|
+
scope: String(Name.from(owner)),
|
|
170
|
+
table: Name.from('assets'),
|
|
171
|
+
limit: pageSize,
|
|
172
|
+
lower_bound: lower,
|
|
173
|
+
json: true,
|
|
174
|
+
})
|
|
175
|
+
for (const row of res.rows as AtomicAssetRow[]) {
|
|
176
|
+
if (!collection || row.collection_name === collection) out.push(row)
|
|
177
|
+
}
|
|
178
|
+
if (!res.more) break
|
|
179
|
+
lower = UInt64.from(String(res.next_key))
|
|
180
|
+
}
|
|
181
|
+
return out
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export async function fetchAtomicSchemas(
|
|
185
|
+
client: APIClient,
|
|
186
|
+
collection: NameType,
|
|
187
|
+
account: NameType = ATOMICASSETS_ACCOUNT
|
|
188
|
+
): Promise<AtomicSchemaRow[]> {
|
|
189
|
+
const out: AtomicSchemaRow[] = []
|
|
190
|
+
let lower: Name | undefined
|
|
191
|
+
while (true) {
|
|
192
|
+
const res = await client.v1.chain.get_table_rows({
|
|
193
|
+
code: Name.from(account),
|
|
194
|
+
scope: String(Name.from(collection)),
|
|
195
|
+
table: Name.from('schemas'),
|
|
196
|
+
limit: 100,
|
|
197
|
+
lower_bound: lower,
|
|
198
|
+
json: true,
|
|
199
|
+
})
|
|
200
|
+
for (const row of res.rows as AtomicSchemaRow[]) out.push(row)
|
|
201
|
+
if (!res.more) break
|
|
202
|
+
lower = Name.from(String(res.next_key))
|
|
203
|
+
}
|
|
204
|
+
return out
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export interface DecodedAtomicAsset {
|
|
208
|
+
asset_id: bigint
|
|
209
|
+
schema_name: string
|
|
210
|
+
template_id: number
|
|
211
|
+
item_id: number
|
|
212
|
+
quantity: number
|
|
213
|
+
stats: string
|
|
214
|
+
origin_x: bigint
|
|
215
|
+
origin_y: bigint
|
|
216
|
+
modules?: NFTModuleSlot[]
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function decodeAtomicAsset(
|
|
220
|
+
asset: AtomicAssetRow,
|
|
221
|
+
schemaFormat: SchemaField[],
|
|
222
|
+
itemId: number
|
|
223
|
+
): DecodedAtomicAsset {
|
|
224
|
+
const data = deserializeAtomicData(asset.immutable_serialized_data, schemaFormat)
|
|
225
|
+
const cargo: NFTCargoItem = deserializeAsset(data, itemId)
|
|
226
|
+
return {
|
|
227
|
+
asset_id: BigInt(String(asset.asset_id)),
|
|
228
|
+
schema_name: String(asset.schema_name),
|
|
229
|
+
template_id: Number(asset.template_id),
|
|
230
|
+
item_id: cargo.item_id,
|
|
231
|
+
quantity: cargo.quantity,
|
|
232
|
+
stats: cargo.stats,
|
|
233
|
+
origin_x: BigInt(String(data.origin_x ?? 0)),
|
|
234
|
+
origin_y: BigInt(String(data.origin_y ?? 0)),
|
|
235
|
+
modules: cargo.modules,
|
|
236
|
+
}
|
|
237
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
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
|
+
case 'image':
|
|
107
|
+
case 'ipfs':
|
|
108
|
+
result[field.name] = readString()
|
|
109
|
+
break
|
|
110
|
+
case 'uint16[]': {
|
|
111
|
+
const len = readVarint()
|
|
112
|
+
const arr: number[] = []
|
|
113
|
+
for (let i = 0; i < len; i++) arr.push(readVarint())
|
|
114
|
+
result[field.name] = arr
|
|
115
|
+
break
|
|
116
|
+
}
|
|
117
|
+
case 'uint64[]': {
|
|
118
|
+
const len = readVarint()
|
|
119
|
+
const arr: bigint[] = []
|
|
120
|
+
for (let i = 0; i < len; i++) arr.push(readVarint64())
|
|
121
|
+
result[field.name] = arr
|
|
122
|
+
break
|
|
123
|
+
}
|
|
124
|
+
default:
|
|
125
|
+
throw new Error(`Unknown type: ${field.type}`)
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result
|
|
130
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import {Serializer} from '@wharfkit/antelope'
|
|
2
|
+
import {getItem} from '../data/catalog'
|
|
3
|
+
import {
|
|
4
|
+
getModuleCapabilityType,
|
|
5
|
+
MODULE_BATTERY,
|
|
6
|
+
MODULE_CRAFTER,
|
|
7
|
+
MODULE_ENGINE,
|
|
8
|
+
MODULE_GATHERER,
|
|
9
|
+
MODULE_GENERATOR,
|
|
10
|
+
MODULE_HAULER,
|
|
11
|
+
MODULE_LOADER,
|
|
12
|
+
MODULE_STORAGE,
|
|
13
|
+
MODULE_WARP,
|
|
14
|
+
} from '../capabilities/modules'
|
|
15
|
+
import {decodeStat, decodeCraftedItemStats} from '../derivation/crafting'
|
|
16
|
+
import {getStatDefinitions} from '../derivation/stats'
|
|
17
|
+
import type {ResourceCategory} from '../types'
|
|
18
|
+
import {Types as ServerTypes} from '../contracts/server'
|
|
19
|
+
import {
|
|
20
|
+
buildEntityDescription,
|
|
21
|
+
computeCrafterDrain,
|
|
22
|
+
computeCrafterSpeed,
|
|
23
|
+
computeEngineDrain,
|
|
24
|
+
computeEngineThrust,
|
|
25
|
+
computeGathererDepth,
|
|
26
|
+
computeGathererDrain,
|
|
27
|
+
computeGathererYield,
|
|
28
|
+
computeGeneratorCap,
|
|
29
|
+
computeGeneratorRech,
|
|
30
|
+
computeCargoBayCapacity,
|
|
31
|
+
computeBatteryBankCapacity,
|
|
32
|
+
computeHaulerCapacity,
|
|
33
|
+
computeHaulerDrain,
|
|
34
|
+
computeHaulerEfficiency,
|
|
35
|
+
computeLoaderMass,
|
|
36
|
+
computeLoaderThrust,
|
|
37
|
+
computeWarpRange,
|
|
38
|
+
} from './description'
|
|
39
|
+
|
|
40
|
+
export type AtomicAttributeType =
|
|
41
|
+
| 'string'
|
|
42
|
+
| 'uint8'
|
|
43
|
+
| 'uint16'
|
|
44
|
+
| 'uint32'
|
|
45
|
+
| 'uint64'
|
|
46
|
+
| 'int32'
|
|
47
|
+
| 'image'
|
|
48
|
+
| 'ipfs'
|
|
49
|
+
| 'UINT16_VEC'
|
|
50
|
+
| 'UINT64_VEC'
|
|
51
|
+
|
|
52
|
+
export interface ImmutableEntry {
|
|
53
|
+
first: string
|
|
54
|
+
second: [AtomicAttributeType, unknown]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ImmutableModuleSlot {
|
|
58
|
+
type?: number | string | bigint
|
|
59
|
+
installed?: {item_id: number | string | bigint; stats: number | string | bigint}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function moduleSlotsForImmutable(
|
|
63
|
+
modules: ServerTypes.module_entry[]
|
|
64
|
+
): ImmutableModuleSlot[] {
|
|
65
|
+
return modules.map((m) => ({
|
|
66
|
+
type: Number(m.type.toString()),
|
|
67
|
+
installed: m.installed
|
|
68
|
+
? {
|
|
69
|
+
item_id: Number(m.installed.item_id.toString()),
|
|
70
|
+
stats: BigInt(m.installed.stats.toString()),
|
|
71
|
+
}
|
|
72
|
+
: undefined,
|
|
73
|
+
}))
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const IMAGE_HOST_URL = 'https://item.shiploadgame.com/item'
|
|
77
|
+
|
|
78
|
+
function bytesToBase64Url(bytes: Uint8Array): string {
|
|
79
|
+
let binary = ''
|
|
80
|
+
for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]!)
|
|
81
|
+
const b64 = btoa(binary)
|
|
82
|
+
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function computeNftImageUrl(
|
|
86
|
+
item: {item_id: number; stats: bigint; modules: ImmutableModuleSlot[]; quantity: number},
|
|
87
|
+
originX: number,
|
|
88
|
+
originY: number
|
|
89
|
+
): string {
|
|
90
|
+
const payload = ServerTypes.nft_item_payload.from({
|
|
91
|
+
item: {
|
|
92
|
+
item_id: item.item_id,
|
|
93
|
+
stats: String(item.stats),
|
|
94
|
+
modules: item.modules,
|
|
95
|
+
quantity: item.quantity,
|
|
96
|
+
},
|
|
97
|
+
location: {x: String(originX), y: String(originY)},
|
|
98
|
+
})
|
|
99
|
+
const bytes = Serializer.encode({object: payload}).array
|
|
100
|
+
return `${IMAGE_HOST_URL}/${bytesToBase64Url(bytes)}.png`
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function commonBaseImmutable(
|
|
104
|
+
quantity: number,
|
|
105
|
+
stats: bigint,
|
|
106
|
+
originX: number,
|
|
107
|
+
originY: number,
|
|
108
|
+
img: string
|
|
109
|
+
): ImmutableEntry[] {
|
|
110
|
+
return [
|
|
111
|
+
{first: 'quantity', second: ['uint32', quantity]},
|
|
112
|
+
{first: 'stats', second: ['uint64', String(stats)]},
|
|
113
|
+
{first: 'origin_x', second: ['int32', originX]},
|
|
114
|
+
{first: 'origin_y', second: ['int32', originY]},
|
|
115
|
+
{first: 'img', second: ['string', img]},
|
|
116
|
+
{first: 'deposit_amount', second: ['uint64', '0']},
|
|
117
|
+
{first: 'deposit_token', second: ['uint64', '0']},
|
|
118
|
+
{first: 'deposit_symbol', second: ['uint64', '0']},
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function buildResourceImmutable(
|
|
123
|
+
itemId: number,
|
|
124
|
+
quantity: number,
|
|
125
|
+
stats: bigint,
|
|
126
|
+
originX: number,
|
|
127
|
+
originY: number
|
|
128
|
+
): ImmutableEntry[] {
|
|
129
|
+
const item = getItem(itemId)
|
|
130
|
+
const cat = item.category
|
|
131
|
+
if (!cat) throw new Error(`Resource item ${itemId} has no category`)
|
|
132
|
+
const definitions = getStatDefinitions(cat as ResourceCategory)
|
|
133
|
+
const img = computeNftImageUrl(
|
|
134
|
+
{item_id: itemId, stats, modules: [], quantity},
|
|
135
|
+
originX,
|
|
136
|
+
originY
|
|
137
|
+
)
|
|
138
|
+
const base = commonBaseImmutable(quantity, stats, originX, originY, img)
|
|
139
|
+
base.push({first: definitions[0].key, second: ['uint16', decodeStat(stats, 0)]})
|
|
140
|
+
base.push({first: definitions[1].key, second: ['uint16', decodeStat(stats, 1)]})
|
|
141
|
+
base.push({first: definitions[2].key, second: ['uint16', decodeStat(stats, 2)]})
|
|
142
|
+
return base
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export function buildComponentImmutable(
|
|
146
|
+
itemId: number,
|
|
147
|
+
quantity: number,
|
|
148
|
+
stats: bigint,
|
|
149
|
+
originX: number,
|
|
150
|
+
originY: number
|
|
151
|
+
): ImmutableEntry[] {
|
|
152
|
+
const img = computeNftImageUrl(
|
|
153
|
+
{item_id: itemId, stats, modules: [], quantity},
|
|
154
|
+
originX,
|
|
155
|
+
originY
|
|
156
|
+
)
|
|
157
|
+
const base = commonBaseImmutable(quantity, stats, originX, originY, img)
|
|
158
|
+
const decoded = decodeCraftedItemStats(itemId, stats)
|
|
159
|
+
for (const [key, value] of Object.entries(decoded)) {
|
|
160
|
+
base.push({first: key, second: ['uint16', value]})
|
|
161
|
+
}
|
|
162
|
+
return base
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function buildModuleImmutable(
|
|
166
|
+
itemId: number,
|
|
167
|
+
quantity: number,
|
|
168
|
+
stats: bigint,
|
|
169
|
+
originX: number,
|
|
170
|
+
originY: number
|
|
171
|
+
): ImmutableEntry[] {
|
|
172
|
+
const img = computeNftImageUrl(
|
|
173
|
+
{item_id: itemId, stats, modules: [], quantity},
|
|
174
|
+
originX,
|
|
175
|
+
originY
|
|
176
|
+
)
|
|
177
|
+
const base = commonBaseImmutable(quantity, stats, originX, originY, img)
|
|
178
|
+
const subtype = getModuleCapabilityType(itemId)
|
|
179
|
+
const item = getItem(itemId)
|
|
180
|
+
switch (subtype) {
|
|
181
|
+
case MODULE_ENGINE: {
|
|
182
|
+
const vol = decodeStat(stats, 0)
|
|
183
|
+
const thm = decodeStat(stats, 1)
|
|
184
|
+
base.push({first: 'volatility', second: ['uint16', vol]})
|
|
185
|
+
base.push({first: 'thermal', second: ['uint16', thm]})
|
|
186
|
+
base.push({first: 'thrust', second: ['uint32', computeEngineThrust(vol)]})
|
|
187
|
+
base.push({first: 'drain', second: ['uint16', computeEngineDrain(thm)]})
|
|
188
|
+
break
|
|
189
|
+
}
|
|
190
|
+
case MODULE_GENERATOR: {
|
|
191
|
+
const res = decodeStat(stats, 0)
|
|
192
|
+
const ref = decodeStat(stats, 1)
|
|
193
|
+
base.push({first: 'resonance', second: ['uint16', res]})
|
|
194
|
+
base.push({first: 'reflectivity', second: ['uint16', ref]})
|
|
195
|
+
base.push({first: 'capacity', second: ['uint16', computeGeneratorCap(res)]})
|
|
196
|
+
base.push({first: 'recharge', second: ['uint16', computeGeneratorRech(ref)]})
|
|
197
|
+
break
|
|
198
|
+
}
|
|
199
|
+
case MODULE_GATHERER: {
|
|
200
|
+
const str = decodeStat(stats, 0)
|
|
201
|
+
const tol = decodeStat(stats, 1)
|
|
202
|
+
const con = decodeStat(stats, 2)
|
|
203
|
+
const ref = decodeStat(stats, 3)
|
|
204
|
+
base.push({first: 'strength', second: ['uint16', str]})
|
|
205
|
+
base.push({first: 'tolerance', second: ['uint16', tol]})
|
|
206
|
+
base.push({first: 'conductivity', second: ['uint16', con]})
|
|
207
|
+
base.push({first: 'reflectivity', second: ['uint16', ref]})
|
|
208
|
+
base.push({first: 'yield', second: ['uint16', computeGathererYield(str)]})
|
|
209
|
+
base.push({first: 'drain', second: ['uint16', computeGathererDrain(con)]})
|
|
210
|
+
base.push({first: 'depth', second: ['uint16', computeGathererDepth(tol, item.tier)]})
|
|
211
|
+
break
|
|
212
|
+
}
|
|
213
|
+
case MODULE_LOADER: {
|
|
214
|
+
const fin = decodeStat(stats, 0)
|
|
215
|
+
const pla = decodeStat(stats, 1)
|
|
216
|
+
base.push({first: 'fineness', second: ['uint16', fin]})
|
|
217
|
+
base.push({first: 'plasticity', second: ['uint16', pla]})
|
|
218
|
+
base.push({first: 'mass', second: ['uint32', computeLoaderMass(fin)]})
|
|
219
|
+
base.push({first: 'thrust', second: ['uint16', computeLoaderThrust(pla)]})
|
|
220
|
+
break
|
|
221
|
+
}
|
|
222
|
+
case MODULE_WARP: {
|
|
223
|
+
const res = decodeStat(stats, 0)
|
|
224
|
+
base.push({first: 'resonance', second: ['uint16', res]})
|
|
225
|
+
base.push({first: 'range', second: ['uint32', computeWarpRange(res)]})
|
|
226
|
+
break
|
|
227
|
+
}
|
|
228
|
+
case MODULE_CRAFTER: {
|
|
229
|
+
const rea = decodeStat(stats, 0)
|
|
230
|
+
const con = decodeStat(stats, 1)
|
|
231
|
+
base.push({first: 'reactivity', second: ['uint16', rea]})
|
|
232
|
+
base.push({first: 'conductivity', second: ['uint16', con]})
|
|
233
|
+
base.push({first: 'speed', second: ['uint16', computeCrafterSpeed(rea)]})
|
|
234
|
+
base.push({first: 'drain', second: ['uint16', computeCrafterDrain(con)]})
|
|
235
|
+
break
|
|
236
|
+
}
|
|
237
|
+
case MODULE_STORAGE: {
|
|
238
|
+
const str = decodeStat(stats, 0)
|
|
239
|
+
const den = decodeStat(stats, 1)
|
|
240
|
+
const hrd = decodeStat(stats, 2)
|
|
241
|
+
const com = decodeStat(stats, 3)
|
|
242
|
+
base.push({first: 'strength', second: ['uint16', str]})
|
|
243
|
+
base.push({first: 'density', second: ['uint16', den]})
|
|
244
|
+
base.push({first: 'hardness', second: ['uint16', hrd]})
|
|
245
|
+
base.push({first: 'cohesion', second: ['uint16', com]})
|
|
246
|
+
base.push({
|
|
247
|
+
first: 'capacity',
|
|
248
|
+
second: ['uint32', computeCargoBayCapacity(str, den, hrd, com)],
|
|
249
|
+
})
|
|
250
|
+
break
|
|
251
|
+
}
|
|
252
|
+
case MODULE_BATTERY: {
|
|
253
|
+
const vol = decodeStat(stats, 0)
|
|
254
|
+
const thm = decodeStat(stats, 1)
|
|
255
|
+
const pla = decodeStat(stats, 2)
|
|
256
|
+
const ins = decodeStat(stats, 3)
|
|
257
|
+
base.push({first: 'volatility', second: ['uint16', vol]})
|
|
258
|
+
base.push({first: 'thermal', second: ['uint16', thm]})
|
|
259
|
+
base.push({first: 'plasticity', second: ['uint16', pla]})
|
|
260
|
+
base.push({first: 'insulation', second: ['uint16', ins]})
|
|
261
|
+
base.push({
|
|
262
|
+
first: 'capacity',
|
|
263
|
+
second: ['uint32', computeBatteryBankCapacity(vol, thm, pla, ins)],
|
|
264
|
+
})
|
|
265
|
+
break
|
|
266
|
+
}
|
|
267
|
+
case MODULE_HAULER: {
|
|
268
|
+
const res = decodeStat(stats, 0)
|
|
269
|
+
const pla = decodeStat(stats, 1)
|
|
270
|
+
const ref = decodeStat(stats, 2)
|
|
271
|
+
base.push({first: 'resonance', second: ['uint16', res]})
|
|
272
|
+
base.push({first: 'plasticity', second: ['uint16', pla]})
|
|
273
|
+
base.push({first: 'reflectivity', second: ['uint16', ref]})
|
|
274
|
+
base.push({first: 'capacity', second: ['uint8', computeHaulerCapacity(res)]})
|
|
275
|
+
base.push({first: 'efficiency', second: ['uint16', computeHaulerEfficiency(pla)]})
|
|
276
|
+
base.push({first: 'drain', second: ['uint16', computeHaulerDrain(ref)]})
|
|
277
|
+
break
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return base
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
export function buildEntityImmutable(
|
|
284
|
+
itemId: number,
|
|
285
|
+
quantity: number,
|
|
286
|
+
stats: bigint,
|
|
287
|
+
originX: number,
|
|
288
|
+
originY: number,
|
|
289
|
+
modules: ImmutableModuleSlot[]
|
|
290
|
+
): ImmutableEntry[] {
|
|
291
|
+
const moduleItems: number[] = []
|
|
292
|
+
const moduleStats: string[] = []
|
|
293
|
+
for (const m of modules) {
|
|
294
|
+
if (m.installed) {
|
|
295
|
+
moduleItems.push(Number(m.installed.item_id))
|
|
296
|
+
moduleStats.push(String(m.installed.stats))
|
|
297
|
+
} else {
|
|
298
|
+
moduleItems.push(0)
|
|
299
|
+
moduleStats.push('0')
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const img = computeNftImageUrl({item_id: itemId, stats, modules, quantity}, originX, originY)
|
|
303
|
+
const base = commonBaseImmutable(quantity, stats, originX, originY, img)
|
|
304
|
+
base.push({first: 'module_items', second: ['UINT16_VEC', moduleItems]})
|
|
305
|
+
base.push({first: 'module_stats', second: ['UINT64_VEC', moduleStats]})
|
|
306
|
+
const description = buildEntityDescription(
|
|
307
|
+
itemId,
|
|
308
|
+
stats,
|
|
309
|
+
moduleItems,
|
|
310
|
+
moduleStats.map((s) => BigInt(s))
|
|
311
|
+
)
|
|
312
|
+
base.push({first: 'description', second: ['string', description]})
|
|
313
|
+
return base
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export function buildImmutableData(
|
|
317
|
+
itemId: number,
|
|
318
|
+
quantity: number,
|
|
319
|
+
stats: bigint,
|
|
320
|
+
originX: number,
|
|
321
|
+
originY: number,
|
|
322
|
+
modules: ImmutableModuleSlot[] = []
|
|
323
|
+
): ImmutableEntry[] {
|
|
324
|
+
const item = getItem(itemId)
|
|
325
|
+
if (item.type === 'resource') {
|
|
326
|
+
return buildResourceImmutable(itemId, quantity, stats, originX, originY)
|
|
327
|
+
}
|
|
328
|
+
if (item.type === 'component') {
|
|
329
|
+
return buildComponentImmutable(itemId, quantity, stats, originX, originY)
|
|
330
|
+
}
|
|
331
|
+
if (item.type === 'module') {
|
|
332
|
+
return buildModuleImmutable(itemId, quantity, stats, originX, originY)
|
|
333
|
+
}
|
|
334
|
+
if (item.type === 'entity') {
|
|
335
|
+
return buildEntityImmutable(itemId, quantity, stats, originX, originY, modules)
|
|
336
|
+
}
|
|
337
|
+
throw new Error(`Unsupported item type for wrap: ${item.type}`)
|
|
338
|
+
}
|