@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.
- package/lib/scan.d.ts +52 -0
- package/lib/scan.js +162 -0
- package/lib/scan.js.map +1 -0
- package/lib/scan.m.js +152 -0
- package/lib/scan.m.js.map +1 -0
- package/lib/shipload.d.ts +5822 -1484
- package/lib/shipload.js +20838 -5419
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +20674 -5669
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1691 -0
- package/lib/testing.js +7109 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +7103 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.test.ts +82 -0
- package/src/capabilities/craftable.ts +82 -0
- package/src/capabilities/crafting.test.ts +80 -0
- package/src/capabilities/crafting.ts +50 -8
- package/src/capabilities/gathering.test.ts +29 -0
- package/src/capabilities/gathering.ts +38 -20
- package/src/capabilities/hauling.ts +0 -5
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +27 -30
- package/src/capabilities/movement.ts +1 -1
- package/src/capabilities/storage.test.ts +26 -0
- package/src/capabilities/storage.ts +22 -7
- package/src/contracts/fund.ts +306 -0
- package/src/contracts/platform.ts +312 -3
- package/src/contracts/server.ts +2793 -478
- package/src/contracts/token.ts +170 -0
- package/src/contracts.ts +2 -0
- 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 +49 -18
- package/src/data/capability-formulas.ts +26 -14
- package/src/data/catalog.test.ts +19 -0
- package/src/data/catalog.ts +13 -3
- package/src/data/charters.json +396 -0
- package/src/data/citizenry-adjectives.json +42 -0
- package/src/data/citizenry-nouns.json +50 -0
- package/src/data/colors.ts +14 -32
- package/src/data/entities.json +421 -15
- package/src/data/item-ids.ts +53 -13
- package/src/data/items.json +330 -77
- package/src/data/kind-registry.json +212 -0
- package/src/data/kind-registry.ts +192 -0
- package/src/data/metadata.ts +312 -51
- package/src/data/recipes-runtime.ts +6 -23
- package/src/data/recipes.json +2173 -173
- package/src/data/tiers.ts +9 -6
- package/src/derivation/build-methods.test.ts +71 -0
- package/src/derivation/build-methods.ts +50 -0
- package/src/derivation/capabilities.test.ts +348 -0
- package/src/derivation/capabilities.ts +707 -0
- package/src/derivation/capability-mappings.ts +60 -16
- package/src/derivation/crafting.test.ts +17 -0
- package/src/derivation/crafting.ts +57 -34
- package/src/derivation/index.ts +27 -2
- package/src/derivation/recipe-usage.test.ts +88 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +9 -1
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +72 -0
- package/src/derivation/stars.test.ts +67 -0
- package/src/derivation/stars.ts +25 -0
- package/src/derivation/stat-scaling.ts +12 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/strata.ts +5 -3
- package/src/derivation/stratum.ts +26 -22
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/upgrades.ts +14 -0
- package/src/derivation/wormhole.ts +154 -0
- package/src/entities/entity.ts +102 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +144 -136
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/entity/hydrate.test.ts +156 -0
- package/src/entity/hydrate.ts +86 -0
- package/src/errors.ts +21 -16
- package/src/format.ts +42 -9
- package/src/index-module.ts +425 -32
- package/src/influence/ballot.test.ts +103 -0
- package/src/influence/ballot.ts +98 -0
- package/src/influence/categories.ts +32 -0
- package/src/influence/charter-metadata.test.ts +136 -0
- package/src/influence/charter-metadata.ts +236 -0
- package/src/influence/charters.test.ts +112 -0
- package/src/influence/charters.ts +150 -0
- package/src/influence/citizenry.ts +38 -0
- package/src/influence/civic-shuttle.test.ts +202 -0
- package/src/influence/civic-shuttle.ts +142 -0
- package/src/influence/civic.test.ts +287 -0
- package/src/influence/civic.ts +269 -0
- package/src/influence/constants.ts +84 -0
- package/src/influence/decay.ts +20 -0
- package/src/influence/decomp.ts +95 -0
- package/src/influence/demand.ts +106 -0
- package/src/influence/duration.ts +101 -0
- package/src/influence/index.ts +118 -0
- package/src/influence/influence.test.ts +450 -0
- package/src/influence/quality.ts +25 -0
- package/src/influence/valuation.ts +154 -0
- package/src/managers/actions.ts +950 -93
- package/src/managers/balances.test.ts +161 -0
- package/src/managers/balances.ts +93 -0
- package/src/managers/base.ts +10 -2
- package/src/managers/cluster.test.ts +39 -0
- package/src/managers/cluster.ts +53 -0
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +453 -0
- package/src/managers/context.ts +58 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +35 -63
- package/src/managers/epochs.ts +72 -1
- package/src/managers/index.ts +38 -1
- package/src/managers/influence.test.ts +56 -0
- package/src/managers/influence.ts +425 -0
- package/src/managers/jobs.test.ts +96 -0
- package/src/managers/jobs.ts +58 -0
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +21 -0
- package/src/managers/nft.ts +110 -0
- package/src/managers/players.ts +25 -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 +388 -0
- package/src/nft/description.ts +222 -100
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +296 -0
- package/src/planner/planner.test.ts +459 -0
- package/src/receipts.ts +22 -0
- package/src/resolution/describe-module.ts +43 -25
- package/src/resolution/display-name.ts +39 -11
- package/src/resolution/resolve-item.test.ts +48 -0
- package/src/resolution/resolve-item.ts +112 -58
- package/src/scan/index.ts +244 -0
- package/src/scan/scan-wasm.base64.ts +2 -0
- package/src/scheduling/accessor.ts +65 -23
- package/src/scheduling/availability.test.ts +320 -0
- package/src/scheduling/availability.ts +251 -0
- package/src/scheduling/cancel.test.ts +550 -0
- package/src/scheduling/cancel.ts +254 -0
- package/src/scheduling/cluster-stock.test.ts +31 -0
- package/src/scheduling/cluster-stock.ts +15 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/epoch.ts +1 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/jobs.test.ts +448 -0
- package/src/scheduling/jobs.ts +343 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +250 -0
- package/src/scheduling/lanes.ts +279 -0
- package/src/scheduling/projection.ts +265 -149
- package/src/scheduling/schedule.test.ts +163 -0
- package/src/scheduling/schedule.ts +282 -116
- package/src/scheduling/task-cargo.test.ts +110 -0
- package/src/scheduling/task-cargo.ts +62 -0
- package/src/scheduling/task-effects.test.ts +35 -0
- package/src/scheduling/task-effects.ts +34 -0
- package/src/scheduling/unwrap.test.ts +86 -0
- package/src/scheduling/unwrap.ts +190 -0
- package/src/shipload.ts +63 -4
- package/src/subscriptions/manager.cluster.test.ts +51 -0
- package/src/subscriptions/manager.ts +245 -172
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +28 -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.test.ts +86 -0
- package/src/travel/reach.ts +34 -0
- package/src/travel/route-build.test.ts +63 -0
- package/src/travel/route-build.ts +60 -0
- package/src/travel/route-planner.ts +288 -0
- package/src/travel/route-simulator.ts +170 -0
- package/src/travel/travel.ts +190 -123
- package/src/types/capabilities.ts +37 -8
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +81 -23
- package/src/utils/cargo.test.ts +14 -0
- package/src/utils/cargo.ts +2 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/hash.ts +22 -2
- package/src/utils/system.ts +24 -5
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -123
- package/src/entities/ship-deploy.ts +0 -295
- package/src/entities/ship.ts +0 -221
- package/src/entities/warehouse.ts +0 -127
- package/src/types/entity-traits.ts +0 -69
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {Name, UInt64, type NameType, type UInt64Type} from '@wharfkit/antelope'
|
|
2
|
+
import {BaseManager} from './base'
|
|
3
|
+
import type {PlatformContract, ServerContract} from '../contracts'
|
|
4
|
+
|
|
5
|
+
export interface NftConfigForItem {
|
|
6
|
+
templateId: number
|
|
7
|
+
schemaName: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface WrapConfig {
|
|
11
|
+
feePctBasisPoints: number
|
|
12
|
+
feeAccount: Name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface WrapGate {
|
|
16
|
+
owner: Name
|
|
17
|
+
game: Name
|
|
18
|
+
lastAssetId: UInt64
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface WrapDeposit {
|
|
22
|
+
cost: bigint
|
|
23
|
+
refund: bigint
|
|
24
|
+
feePct: number
|
|
25
|
+
symbol: string
|
|
26
|
+
precision: number
|
|
27
|
+
tokenContract: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function resolveLockedAmount(cost: bigint, feePctBasisPoints: number): bigint {
|
|
31
|
+
const fee = (cost * BigInt(feePctBasisPoints)) / 10_000n
|
|
32
|
+
return cost - fee
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function wrapCostKey(itemType: number, tier: number): UInt64 {
|
|
36
|
+
return UInt64.from((BigInt(itemType) << 8n) | BigInt(tier))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export class NftManager extends BaseManager {
|
|
40
|
+
private cache = new Map<string, NftConfigForItem | null>()
|
|
41
|
+
private wrapConfig?: WrapConfig | null
|
|
42
|
+
|
|
43
|
+
async getNftConfigForItem(itemId: UInt64Type): Promise<NftConfigForItem | undefined> {
|
|
44
|
+
const id = UInt64.from(itemId)
|
|
45
|
+
const key = id.toString()
|
|
46
|
+
if (this.cache.has(key)) {
|
|
47
|
+
return this.cache.get(key) ?? undefined
|
|
48
|
+
}
|
|
49
|
+
const row = (await this.server.table('nftconfig').get(id)) as
|
|
50
|
+
| ServerContract.Types.nftconfig_row
|
|
51
|
+
| undefined
|
|
52
|
+
const result: NftConfigForItem | null = row
|
|
53
|
+
? {templateId: Number(row.template_id), schemaName: String(row.schema_name)}
|
|
54
|
+
: null
|
|
55
|
+
this.cache.set(key, result)
|
|
56
|
+
return result ?? undefined
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async getWrapConfig(reload = false): Promise<WrapConfig | null> {
|
|
60
|
+
if (!reload && this.wrapConfig !== undefined) {
|
|
61
|
+
return this.wrapConfig
|
|
62
|
+
}
|
|
63
|
+
const row = (await this.server.table('wrapconfig').get()) as
|
|
64
|
+
| ServerContract.Types.wrapconfig_row
|
|
65
|
+
| undefined
|
|
66
|
+
this.wrapConfig = row
|
|
67
|
+
? {feePctBasisPoints: Number(row.fee_pct), feeAccount: row.fee_account}
|
|
68
|
+
: null
|
|
69
|
+
return this.wrapConfig
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async getWrapCost(itemType: number, tier: number): Promise<bigint> {
|
|
73
|
+
const row = (await this.server.table('wrapcost').get(wrapCostKey(itemType, tier))) as
|
|
74
|
+
| ServerContract.Types.wrapcost_row
|
|
75
|
+
| undefined
|
|
76
|
+
return row ? BigInt(row.amount.toString()) : 0n
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async getWrapDeposit(
|
|
80
|
+
itemType: number,
|
|
81
|
+
tier: number,
|
|
82
|
+
opts: {reload?: boolean} = {}
|
|
83
|
+
): Promise<WrapDeposit | null> {
|
|
84
|
+
const cost = await this.getWrapCost(itemType, tier)
|
|
85
|
+
if (cost === 0n) return null
|
|
86
|
+
|
|
87
|
+
const wrapConfig = await this.getWrapConfig(opts.reload)
|
|
88
|
+
const feePctBasisPoints = wrapConfig ? wrapConfig.feePctBasisPoints : 0
|
|
89
|
+
|
|
90
|
+
const depositConfig = await this.context.balances.getDepositConfig(opts.reload)
|
|
91
|
+
if (!depositConfig) return null
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
cost,
|
|
95
|
+
refund: resolveLockedAmount(cost, feePctBasisPoints),
|
|
96
|
+
feePct: feePctBasisPoints / 100,
|
|
97
|
+
symbol: depositConfig.symbol.code.toString(),
|
|
98
|
+
precision: depositConfig.symbol.precision,
|
|
99
|
+
tokenContract: depositConfig.tokenContract.toString(),
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async getWrapGate(owner: NameType): Promise<WrapGate | null> {
|
|
104
|
+
const row = (await this.platform.table('wrapgate').get(Name.from(owner))) as
|
|
105
|
+
| PlatformContract.Types.wrapgate_row
|
|
106
|
+
| undefined
|
|
107
|
+
if (!row) return null
|
|
108
|
+
return {owner: row.owner, game: row.game, lastAssetId: row.last_asset_id}
|
|
109
|
+
}
|
|
110
|
+
}
|
package/src/managers/players.ts
CHANGED
|
@@ -2,6 +2,11 @@ import {Name, type NameType} from '@wharfkit/antelope'
|
|
|
2
2
|
import {BaseManager} from './base'
|
|
3
3
|
import {Player} from '../entities/player'
|
|
4
4
|
|
|
5
|
+
export interface PlayerRosterEntry {
|
|
6
|
+
owner: Name
|
|
7
|
+
company?: string
|
|
8
|
+
}
|
|
9
|
+
|
|
5
10
|
export class PlayersManager extends BaseManager {
|
|
6
11
|
async getPlayer(account: NameType): Promise<Player | undefined> {
|
|
7
12
|
const playerRow = await this.server.table('player').get(Name.from(account))
|
|
@@ -10,4 +15,24 @@ export class PlayersManager extends BaseManager {
|
|
|
10
15
|
}
|
|
11
16
|
return new Player(playerRow)
|
|
12
17
|
}
|
|
18
|
+
|
|
19
|
+
async getPlayers(): Promise<Player[]> {
|
|
20
|
+
const rows = await this.server.table('player').all()
|
|
21
|
+
return rows.map((row) => new Player(row))
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async getRoster(): Promise<PlayerRosterEntry[]> {
|
|
25
|
+
const [players, companies] = await Promise.all([
|
|
26
|
+
this.server.table('player').all(),
|
|
27
|
+
this.platform.table('company').all(),
|
|
28
|
+
])
|
|
29
|
+
const companyNames = new Map<string, string>()
|
|
30
|
+
for (const company of companies) {
|
|
31
|
+
companyNames.set(company.account.toString(), company.name)
|
|
32
|
+
}
|
|
33
|
+
return players.map((player) => ({
|
|
34
|
+
owner: player.owner,
|
|
35
|
+
company: companyNames.get(player.owner.toString()),
|
|
36
|
+
}))
|
|
37
|
+
}
|
|
13
38
|
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {Name} from '@wharfkit/antelope'
|
|
2
|
+
import {getItem} from '../data/catalog'
|
|
3
|
+
import {getRecipe} from '../data/recipes-runtime'
|
|
4
|
+
import {computeInputMass} from '../derivation/crafting'
|
|
5
|
+
import {calc_craft_duration} from '../capabilities/crafting'
|
|
6
|
+
import {TaskType} from '../types'
|
|
7
|
+
import {BaseManager} from './base'
|
|
8
|
+
import type {CrafterStats} from '../types/capabilities'
|
|
9
|
+
import type {ServerContract} from '../contracts'
|
|
10
|
+
import type {BuildableTarget, ScheduledBuild} from './construction-types'
|
|
11
|
+
|
|
12
|
+
export interface PlotProgressInputRow {
|
|
13
|
+
itemId: number
|
|
14
|
+
required: number
|
|
15
|
+
provided: number
|
|
16
|
+
missing: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface PlotProgress {
|
|
20
|
+
targetItemId: number
|
|
21
|
+
rows: PlotProgressInputRow[]
|
|
22
|
+
massProvided: number
|
|
23
|
+
massRequired: number
|
|
24
|
+
isComplete: boolean
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export class PlotManager extends BaseManager {
|
|
28
|
+
progress(
|
|
29
|
+
plot: ServerContract.Types.entity_row,
|
|
30
|
+
cargo: ServerContract.Types.cargo_row[]
|
|
31
|
+
): PlotProgress {
|
|
32
|
+
const targetItemId = Number(plot.item_id.toString())
|
|
33
|
+
const recipe = getRecipe(targetItemId)
|
|
34
|
+
if (!recipe) {
|
|
35
|
+
throw new Error(`No recipe found for item ${targetItemId}`)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const plotId = plot.id.toString()
|
|
39
|
+
const plotCargo = cargo.filter((c) => c.entity_id.toString() === plotId)
|
|
40
|
+
|
|
41
|
+
const quantityByItemId = new Map<number, number>()
|
|
42
|
+
for (const c of plotCargo) {
|
|
43
|
+
const id = c.item_id.toNumber()
|
|
44
|
+
quantityByItemId.set(
|
|
45
|
+
id,
|
|
46
|
+
(quantityByItemId.get(id) ?? 0) + Number(c.quantity.toString())
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const rows: PlotProgressInputRow[] = recipe.inputs.map((input) => {
|
|
51
|
+
const itemId = input.itemId
|
|
52
|
+
const required = input.quantity
|
|
53
|
+
const provided = quantityByItemId.get(itemId) ?? 0
|
|
54
|
+
const missing = Math.max(0, required - provided)
|
|
55
|
+
return {itemId, required, provided, missing}
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const massRequired = computeInputMass(targetItemId)
|
|
59
|
+
const massProvided = rows.reduce((sum, r) => {
|
|
60
|
+
const item = getItem(r.itemId)
|
|
61
|
+
return sum + item.mass * r.provided
|
|
62
|
+
}, 0)
|
|
63
|
+
const isComplete = rows.every((r) => r.missing === 0)
|
|
64
|
+
|
|
65
|
+
return {targetItemId, rows, massProvided, massRequired, isComplete}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
buildableTarget(
|
|
69
|
+
plot: ServerContract.Types.entity_row,
|
|
70
|
+
cargo: ServerContract.Types.cargo_row[],
|
|
71
|
+
activeTask?: ServerContract.Types.task,
|
|
72
|
+
scheduledBuild?: ScheduledBuild
|
|
73
|
+
): BuildableTarget {
|
|
74
|
+
const progress = this.progress(plot, cargo)
|
|
75
|
+
const targetItemId = Number(plot.item_id.toString())
|
|
76
|
+
const targetItem = getItem(targetItemId)
|
|
77
|
+
const recipe = getRecipe(targetItemId)
|
|
78
|
+
if (!recipe) {
|
|
79
|
+
throw new Error(`Plot target item ${targetItemId} has no recipe`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
let state: BuildableTarget['state']
|
|
83
|
+
if (scheduledBuild?.hasStarted) {
|
|
84
|
+
state = 'finalizing'
|
|
85
|
+
} else if (scheduledBuild) {
|
|
86
|
+
state = 'scheduled'
|
|
87
|
+
} else if (progress.isComplete) {
|
|
88
|
+
state = 'ready'
|
|
89
|
+
} else {
|
|
90
|
+
state = 'accepting'
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
entityId: plot.id,
|
|
95
|
+
ownerName: plot.owner,
|
|
96
|
+
coordinates: plot.coordinates,
|
|
97
|
+
targetItemId,
|
|
98
|
+
targetItem,
|
|
99
|
+
state,
|
|
100
|
+
recipe,
|
|
101
|
+
progress,
|
|
102
|
+
finalizeAction: Name.from('buildplot'),
|
|
103
|
+
finalizerCapability: 'builder',
|
|
104
|
+
activeTask,
|
|
105
|
+
scheduledBuild,
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
canBuild(
|
|
110
|
+
plot: ServerContract.Types.entity_row,
|
|
111
|
+
cargo: ServerContract.Types.cargo_row[]
|
|
112
|
+
): boolean {
|
|
113
|
+
return this.progress(plot, cargo).isComplete
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
timeToComplete(plot: ServerContract.Types.entity_info, crafter: CrafterStats): number {
|
|
117
|
+
const capacity = Number(plot.capacity?.toString() ?? '0')
|
|
118
|
+
const speed = Number(crafter.speed.toString())
|
|
119
|
+
if (speed === 0) return 0
|
|
120
|
+
return calc_craft_duration(speed, capacity).toNumber()
|
|
121
|
+
}
|
|
122
|
+
}
|