Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PrismarineJS
GitHub Repository: PrismarineJS/mineflayer
Path: blob/master/lib/plugins/anvil.js
1467 views
1
const assert = require('assert')
2
const { sleep } = require('../promise_utils')
3
const { once } = require('../promise_utils')
4
5
module.exports = inject
6
7
function inject (bot) {
8
const Item = require('prismarine-item')(bot.registry)
9
10
const matchWindowType = window => /minecraft:(?:chipped_|damaged_)?anvil/.test(window.type)
11
12
async function openAnvil (anvilBlock) {
13
const anvil = await bot.openBlock(anvilBlock)
14
if (!matchWindowType(anvil)) {
15
throw new Error('Not a anvil-like window: ' + JSON.stringify(anvil))
16
}
17
18
function err (name) {
19
anvil.close()
20
throw new Error(name)
21
}
22
23
function sendItemName (name) {
24
if (bot.supportFeature('useMCItemName')) {
25
bot._client.writeChannel('MC|ItemName', name)
26
} else {
27
bot._client.write('name_item', { name })
28
}
29
}
30
31
async function addCustomName (name) {
32
if (!name) return
33
for (let i = 1; i < name.length + 1; i++) {
34
sendItemName(name.substring(0, i))
35
await sleep(50)
36
}
37
}
38
async function putInAnvil (itemOne, itemTwo) {
39
await putSomething(0, itemOne.type, itemOne.metadata, itemOne.count, itemOne.nbt)
40
sendItemName('') // sent like this by vnailla
41
if (!bot.supportFeature('useMCItemName')) sendItemName('')
42
await putSomething(1, itemTwo.type, itemTwo.metadata, itemTwo.count, itemTwo.nbt)
43
}
44
45
async function combine (itemOne, itemTwo, name) {
46
if (name?.length > 35) err('Name is too long.')
47
if (bot.supportFeature('useMCItemName')) {
48
bot._client.registerChannel('MC|ItemName', 'string')
49
}
50
51
assert.ok(itemOne && itemTwo)
52
const { xpCost: normalCost } = Item.anvil(itemOne, itemTwo, bot.game.gameMode === 'creative', name)
53
const { xpCost: inverseCost } = Item.anvil(itemTwo, itemOne, bot.game.gameMode === 'creative', name)
54
if (normalCost === 0 && inverseCost === 0) err('Not anvil-able (in either direction), cancelling.')
55
56
const smallest = (normalCost < inverseCost ? normalCost : inverseCost) === 0 ? inverseCost : 0
57
if (bot.game.gameMode !== 'creative' && bot.experience.level < smallest) {
58
err('Player does not have enough xp to do action, cancelling.')
59
}
60
61
const xpPromise = bot.game.gameMode === 'creative' ? Promise.resolve() : once(bot, 'experience')
62
if (normalCost === 0) await putInAnvil(itemTwo, itemOne)
63
else if (inverseCost === 0) await putInAnvil(itemOne, itemTwo)
64
else if (normalCost < inverseCost) await putInAnvil(itemOne, itemTwo)
65
else await putInAnvil(itemTwo, itemOne)
66
67
await addCustomName(name)
68
await bot.putAway(2)
69
await xpPromise
70
}
71
72
async function rename (item, name) {
73
if (name?.length > 35) err('Name is too long.')
74
if (bot.supportFeature('useMCItemName')) {
75
bot._client.registerChannel('MC|ItemName', 'string')
76
}
77
assert.ok(item)
78
const { xpCost: normalCost } = Item.anvil(item, null, bot.game.gameMode === 'creative', name)
79
if (normalCost === 0) err('Not valid rename, cancelling.')
80
81
if (bot.game.gameMode !== 'creative' && bot.experience.level < normalCost) {
82
err('Player does not have enough xp to do action, cancelling.')
83
}
84
const xpPromise = once(bot, 'experience')
85
await putSomething(0, item.type, item.metadata, item.count, item.nbt)
86
sendItemName('') // sent like this by vnailla
87
if (!bot.supportFeature('useMCItemName')) sendItemName('')
88
await addCustomName(name)
89
await bot.putAway(2)
90
await xpPromise
91
}
92
93
async function putSomething (destSlot, itemId, metadata, count, nbt) {
94
const options = {
95
window: anvil,
96
itemType: itemId,
97
metadata,
98
count,
99
nbt,
100
sourceStart: anvil.inventoryStart,
101
sourceEnd: anvil.inventoryEnd,
102
destStart: destSlot,
103
destEnd: destSlot + 1
104
}
105
await bot.transfer(options)
106
}
107
108
anvil.combine = combine
109
anvil.rename = rename
110
111
return anvil
112
}
113
114
bot.openAnvil = openAnvil
115
}
116
117