Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PrismarineJS
GitHub Repository: PrismarineJS/mineflayer
Path: blob/master/test/externalTests/trade.js
9427 views
1
const assert = require('assert')
2
const { once } = require('../../lib/promise_utils')
3
4
module.exports = () => async (bot) => {
5
function expectAmount (amount, greaterThan) {
6
// TODO: 1.20.5+ does not seem to respect "Count" NBT anymore in /summon
7
// ...as NBT was removed in favor of components that may have something to do
8
if (bot.registry.version['>=']('1.20.5')) {
9
if (amount < 1) throw new Error(`${amount} < 1`) // accept anything >=1
10
} else {
11
assert.strictEqual(amount, greaterThan)
12
}
13
}
14
15
const Item = require('prismarine-item')(bot.registry)
16
17
const villagerType = bot.registry.entitiesByName.villager ? 'villager' : 'Villager'
18
const testFluctuations = bot.supportFeature('selectingTradeMovesItems')
19
20
const summonCommand = bot.supportFeature('indexesVillagerRecipes')
21
? `/summon ${villagerType} ~ ~1 ~ {NoAI:1, Offers:{Recipes:[0:{maxUses:12,buy:{id:"minecraft:emerald",Count:2},sell:{id:"minecraft:pumpkin_pie",Count:2},uses: 1},1:{maxUses:12,buy:{id:"minecraft:emerald",Count:2},buyB:{id:"minecraft:pumpkin_pie",Count:2},sell:{id:"minecraft:wheat",Count:2}, uses:1},2:{maxUses:12,buy:{id:"minecraft:emerald",Count:1},sell:{id:"minecraft:glass",Count:4},uses: 1},3:{maxUses:12,buy:{id:"minecraft:emerald",Count:36},buyB:{id:"minecraft:book",Count:1},sell:{id:"minecraft:wooden_sword",Count:1},uses: 1}]}}`
22
: `/summon ${villagerType} ~ ~1 ~ {NoAI:1, Offers:{Recipes:[{maxUses:12,buy:{id:"minecraft:emerald",Count:2},sell:{id:"minecraft:pumpkin_pie",Count:2},${testFluctuations ? 'demand:60,priceMultiplier:0.05f,specialPrice:-4,' : ''}uses: 1},{maxUses:12,buy:{id:"minecraft:emerald",Count:2},buyB:{id:"minecraft:pumpkin_pie",Count:2},sell:{id:"minecraft:wheat",Count:2}, uses:1},{maxUses:12,buy:{id:"minecraft:emerald",Count:1},sell:{id:"minecraft:glass",Count:4},uses: 1},{maxUses:12,buy:{id:"minecraft:emerald",Count:36},buyB:{id:"minecraft:book",Count:1},sell:{id:"minecraft:wooden_sword",Count:1},uses: 1}]}}`
23
24
const commandBlockPos = bot.entity.position.offset(0.5, 0, 0.5)
25
const redstoneBlockPos = commandBlockPos.offset(1, 0, 0)
26
27
let shouldHaveEmeralds = 0
28
for (let slot = 9; slot <= 17; slot += 1) {
29
await bot.test.setInventorySlot(slot, new Item(bot.registry.itemsByName.emerald.id, 64, 0))
30
shouldHaveEmeralds += 64
31
}
32
await bot.test.setInventorySlot(18, new Item(bot.registry.itemsByName.book.id, 11, 0))
33
34
// A command block is needed to spawn the villager due to the chat's character limit in some versions
35
bot.test.sayEverywhere(`/setblock ${commandBlockPos.toArray().join(' ')} command_block`)
36
await bot.test.wait(500)
37
bot.setCommandBlock(commandBlockPos, summonCommand)
38
await bot.test.wait(500)
39
bot.test.sayEverywhere(`/setblock ${redstoneBlockPos.toArray().join(' ')} redstone_block`) // Activate the command block
40
41
const [entity] = await once(bot, 'entitySpawn')
42
assert(entity.name === villagerType)
43
44
const villager = await bot.openVillager(entity)
45
console.log('Opened villager')
46
// console.dir(villager, { depth: null })
47
48
// Handle trade #1 -- takes 2x emerald and returns 2x pumpkin_pie
49
{
50
const trade = villager.trades[0]
51
assert.strictEqual(trade.inputs.length, 1, 'Expected single input from villager on first trade')
52
verifyTrade(trade)
53
54
const [input] = trade.inputs
55
assert.strictEqual(input.name, 'emerald')
56
expectAmount(input.count, 2)
57
58
const [output] = trade.outputs
59
assert.strictEqual(output.name, 'pumpkin_pie')
60
expectAmount(output.count, 2)
61
62
await bot.trade(villager, 0, 11)
63
shouldHaveEmeralds -= testFluctuations ? (2 * 2 * 11) : (2 * 11)
64
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.emerald.id), shouldHaveEmeralds)
65
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.pumpkin_pie.id), 22)
66
}
67
68
// Handle trade #2 -- takes [2x emerald, 2x pumpkin_pie] and returns 2x wheat
69
{
70
const trade = villager.trades[1]
71
assert.strictEqual(trade.inputs.length, 2, 'Expected two inputs from villager on second trade')
72
verifyTrade(trade)
73
74
const [input1, input2] = trade.inputs
75
assert.strictEqual(input1.name, 'emerald')
76
expectAmount(input1.count, 2)
77
assert.strictEqual(input2.name, 'pumpkin_pie')
78
expectAmount(input2.count, 2)
79
80
const [output] = trade.outputs
81
assert.strictEqual(output.name, 'wheat')
82
expectAmount(output.count, 2)
83
84
await bot.trade(villager, 1, 11)
85
shouldHaveEmeralds -= 11 * 2
86
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.emerald.id), shouldHaveEmeralds)
87
assert.strictEqual(bot.currentWindow.count(bot.registry.itemsByName.pumpkin_pie.id), 0)
88
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.wheat.id), 22)
89
}
90
91
// Handle trade #3 -- takes 1x emerald and returns 4x glass
92
{
93
const trade = villager.trades[2]
94
assert.strictEqual(trade.inputs.length, 1, 'Expected single input from villager on first trade')
95
verifyTrade(trade)
96
97
const [input] = trade.inputs
98
assert.strictEqual(input.name, 'emerald')
99
expectAmount(input.count, 1)
100
101
const [output] = trade.outputs
102
assert.strictEqual(output.name, 'glass')
103
expectAmount(output.count, 4)
104
105
await bot.trade(villager, 2, 11)
106
shouldHaveEmeralds -= 11
107
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.emerald.id), shouldHaveEmeralds)
108
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.glass.id), 44)
109
}
110
111
// Handle trade #4 -- takes [36x emerald, 1x book] and returns 1x wooden sword
112
{
113
const trade = villager.trades[3]
114
assert.strictEqual(trade.inputs.length, 2, 'Expected two inputs from villager on second trade')
115
verifyTrade(trade)
116
117
const [input1, input2] = trade.inputs
118
assert.strictEqual(input1.name, 'emerald')
119
expectAmount(input1.count, 36)
120
assert.strictEqual(input2.name, 'book')
121
assert.strictEqual(input2.count, 1)
122
123
const [output] = trade.outputs
124
assert.strictEqual(output.name, 'wooden_sword')
125
assert.strictEqual(output.count, 1)
126
127
await bot.trade(villager, 3, 11)
128
shouldHaveEmeralds -= 11 * 36
129
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.emerald.id), shouldHaveEmeralds)
130
assert.strictEqual(bot.currentWindow.count(bot.registry.itemsByName.book.id), 0)
131
expectAmount(bot.currentWindow.count(bot.registry.itemsByName.wooden_sword.id), 11)
132
}
133
134
function verifyTrade (trade) {
135
assert.strictEqual(trade.nbTradeUses, 1)
136
assert.strictEqual(trade.maximumNbTradeUses, 12)
137
assert.strictEqual(trade.tradeDisabled, false)
138
139
const printCountInv = function (item) {
140
return `${bot.currentWindow.count(bot.registry.itemsByName[item.name].id)}x ${item.displayName}`
141
}
142
const printCountTrade = function (item) {
143
return `${item.count}x ${item.displayName}`
144
}
145
146
bot.test.sayEverywhere(`I have ${printCountInv(trade.inputItem1)} ${trade.hasItem2 ? 'and ' + printCountInv(trade.inputItem2) : ''}`)
147
bot.test.sayEverywhere(`I can trade ${printCountTrade(trade.inputItem1)} ${trade.hasItem2 ? 'and ' + printCountTrade(trade.inputItem2) : ''} for ${printCountTrade(trade.outputItem)}`)
148
}
149
150
assert.rejects(bot.trade(villager, 1, 1)) // Shouldn't be able, the trade is blocked!
151
villager.close()
152
bot.test.sayEverywhere(`/kill @e[type=${villagerType}]`)
153
}
154
155