Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PrismarineJS
GitHub Repository: PrismarineJS/mineflayer
Path: blob/master/test/externalTests/sound.js
2155 views
1
const assert = require('assert')
2
const { once } = require('../../lib/promise_utils')
3
4
module.exports = () => async (bot) => {
5
// Helper function to check if positions are close enough
6
const positionsAreClose = (pos1, pos2, tolerance = 1.0) => {
7
return Math.abs(pos1.x - pos2.x) <= tolerance &&
8
Math.abs(pos1.y - pos2.y) <= tolerance &&
9
Math.abs(pos1.z - pos2.z) <= tolerance
10
}
11
12
// Helper function to retry an operation
13
const retry = async (operation, maxAttempts = 1, delay = 2000) => {
14
let lastError
15
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
16
try {
17
return await operation()
18
} catch (error) {
19
lastError = error
20
if (attempt < maxAttempts) {
21
await new Promise(resolve => setTimeout(resolve, delay))
22
}
23
}
24
}
25
throw lastError
26
}
27
28
// Test sound effect events
29
const soundTest = async () => {
30
await new Promise(resolve => setTimeout(resolve, 2000))
31
32
return retry(async () => {
33
const soundPromise = once(bot, 'soundEffectHeard', 5000)
34
35
if (bot.supportFeature('playsoundUsesResourceLocation')) {
36
// 1.9+ syntax
37
let soundName
38
if (bot.supportFeature('noteBlockNameIsNoteBlock')) {
39
soundName = 'minecraft:block.note_block.harp'
40
} else {
41
soundName = 'block.note.harp'
42
}
43
bot.chat(`/playsound ${soundName} master ${bot.username} ~ ~ ~ 1 1`)
44
} else {
45
// 1.8.8 syntax
46
bot.chat(`/playsound note.harp ${bot.username} ~ ~ ~ 1 1`)
47
}
48
49
const [soundName, position, volume, pitch] = await soundPromise
50
51
assert.ok(typeof soundName === 'string' || typeof soundName === 'number',
52
`Invalid soundName type: ${typeof soundName}`)
53
assert.strictEqual(typeof position, 'object', 'Position should be an object')
54
assert.strictEqual(typeof volume, 'number', 'Volume should be a number')
55
assert.strictEqual(typeof pitch, 'number', 'Pitch should be a number')
56
57
const isClose = positionsAreClose(position, bot.entity.position)
58
assert.ok(isClose,
59
`Position mismatch: expected ${JSON.stringify(bot.entity.position)}, got ${JSON.stringify(position)}`)
60
})
61
}
62
63
// Test note block sounds
64
const noteTest = async () => {
65
const pos = bot.entity.position.offset(1, 0, 0).floored()
66
const noteBlockName = bot.supportFeature('noteBlockNameIsNoteBlock') ? 'note_block' : 'noteblock'
67
68
return retry(async () => {
69
await bot.test.setBlock({ x: pos.x, y: pos.y, z: pos.z, blockName: noteBlockName, relative: false })
70
await new Promise(resolve => setTimeout(resolve, 250))
71
72
const noteHeardPromise = once(bot, 'noteHeard', 5000)
73
await bot.test.setBlock({ x: pos.x, y: pos.y - 1, z: pos.z, blockName: 'redstone_block', relative: false })
74
75
const [block, instrument, pitch] = await noteHeardPromise
76
77
assert.strictEqual(block.name, noteBlockName, 'Wrong block name')
78
79
if (typeof instrument === 'string') {
80
assert.ok(typeof instrument === 'string', 'Instrument should be a string')
81
} else if (typeof instrument === 'object' && instrument !== null) {
82
assert.ok(typeof instrument.name === 'string', 'Instrument name should be a string')
83
assert.ok(typeof instrument.id === 'number', 'Instrument id should be a number')
84
} else {
85
throw new Error(`Unexpected instrument type: ${typeof instrument}`)
86
}
87
88
assert.strictEqual(typeof pitch, 'number', 'Pitch should be a number')
89
assert.ok(pitch >= 0 && pitch <= 24, `Pitch out of range: ${pitch}`)
90
})
91
}
92
93
// Test hardcoded sound effects
94
const hardcodedTest = async () => {
95
return retry(async () => {
96
const soundPromise = Promise.race([
97
once(bot, 'hardcodedSoundEffectHeard', 5000),
98
once(bot, 'soundEffectHeard', 5000).then(([soundName, position, volume, pitch]) => {
99
return [0, 'master', position, volume, pitch]
100
})
101
])
102
103
if (bot.supportFeature('playsoundUsesResourceLocation')) {
104
bot.chat(`/playsound minecraft:ui.button.click master ${bot.username} ~ ~ ~ 1 1`)
105
} else {
106
bot.chat(`/playsound gui.button.press ${bot.username} ~ ~ ~ 1 1`)
107
}
108
109
const [soundId, soundCategory, position, volume, pitch] = await soundPromise
110
111
assert.strictEqual(typeof soundId, 'number', 'SoundId should be a number')
112
assert.ok(typeof soundCategory === 'string' || typeof soundCategory === 'number',
113
`Invalid soundCategory type: ${typeof soundCategory}`)
114
assert.strictEqual(typeof position, 'object', 'Position should be an object')
115
assert.strictEqual(typeof volume, 'number', 'Volume should be a number')
116
assert.strictEqual(typeof pitch, 'number', 'Pitch should be a number')
117
})
118
}
119
120
try {
121
bot.chat('### Starting sound')
122
123
// Run all tests
124
await soundTest()
125
await noteTest()
126
await hardcodedTest()
127
} finally {
128
// Cleanup: remove the note block and redstone block
129
const pos = bot.entity.position.offset(1, 0, 0).floored()
130
await bot.test.setBlock({ x: pos.x, y: pos.y, z: pos.z, blockName: 'air' })
131
await bot.test.setBlock({ x: pos.x, y: pos.y - 1, z: pos.z, blockName: 'air' })
132
}
133
}
134
135