chomens-bot-js/plugins/music.js

160 lines
4.9 KiB
JavaScript
Raw Normal View History

2022-12-30 03:40:17 -05:00
const path = require('path')
2022-11-27 02:35:28 -05:00
const { Midi } = require('@tonejs/midi')
const { convertMidi } = require('../util/midi_converter')
2022-12-30 03:40:17 -05:00
const convertNBS = require('../util/nbs_converter')
const parseTXTSong = require('../util/txt_song_parser')
2022-08-14 05:51:45 -04:00
const soundNames = {
harp: 'minecraft:block.note_block.harp',
basedrum: 'minecraft:block.note_block.basedrum',
snare: 'minecraft:block.note_block.snare',
hat: 'minecraft:block.note_block.hat',
bass: 'minecraft:block.note_block.bass',
flute: 'minecraft:block.note_block.flute',
bell: 'minecraft:block.note_block.bell',
guitar: 'minecraft:block.note_block.guitar',
chime: 'minecraft:block.note_block.chime',
xylophone: 'minecraft:block.note_block.xylophone',
iron_xylophone: 'minecraft:block.note_block.iron_xylophone',
cow_bell: 'minecraft:block.note_block.cow_bell',
didgeridoo: 'minecraft:block.note_block.didgeridoo',
bit: 'minecraft:block.note_block.bit',
banjo: 'minecraft:block.note_block.banjo',
2022-11-27 02:35:28 -05:00
pling: 'minecraft:block.note_block.pling'
}
2022-08-14 05:51:45 -04:00
2022-11-27 02:35:28 -05:00
function inject (bot) {
bot.music = function () {}
bot.music.song = null
bot.music.loop = 0
bot.music.queue = []
let time = 0
let startTime = 0
let noteIndex = 0
bot.music.skip = function () {
2022-11-09 07:40:48 -05:00
if (bot.music.loop === 2) {
2022-11-27 02:35:28 -05:00
bot.music.queue.push(bot.music.queue.shift())
bot.music.play(bot.music.queue[0])
2022-11-09 07:40:48 -05:00
} else {
2022-11-27 02:35:28 -05:00
bot.music.queue.shift()
2022-11-09 07:40:48 -05:00
}
2022-11-27 02:35:28 -05:00
resetTime()
}
2022-10-31 08:17:42 -04:00
const interval = setInterval(async () => {
2022-12-29 00:05:11 -05:00
if (!bot.music.queue.length) return
bot.music.song = bot.music.queue[0]
time = Date.now() - startTime
bot.core.run('minecraft:title @a[tag=!nomusic] actionbar ' + JSON.stringify(toComponent()))
while (bot.music.song?.notes[noteIndex]?.time <= time) {
const note = bot.music.song.notes[noteIndex]
const floatingPitch = 2 ** ((note.pitch - 12) / 12.0)
bot.core.run(`minecraft:execute as @a[tag=!nomusic] at @s run playsound ${soundNames[note.instrument]} record @s ~ ~ ~ ${note.volume} ${floatingPitch}`)
noteIndex++
if (noteIndex >= bot.music.song.notes.length) {
if (bot.music.loop === 1) {
resetTime()
return
}
if (bot.music.loop === 2) {
resetTime()
bot.music.queue.push(bot.music.queue.shift())
bot.music.play(bot.music.queue[0])
return
}
bot.music.queue.shift()
if (!bot.music.queue[0]) {
bot.tellraw('@a', { text: 'Finished playing every song in the queue' })
bot.music.stop()
return
}
if (bot.music.queue[0].notes.length > 0) {
if (bot.music.queue.length !== 1) resetTime()
bot.music.play(bot.music.queue[0])
return
2022-08-14 05:51:45 -04:00
}
}
2022-12-29 00:05:11 -05:00
}
2022-11-27 02:35:28 -05:00
}, 50)
2022-08-14 05:51:45 -04:00
2022-11-30 04:45:20 -05:00
bot.on('end', () => {
2022-11-27 02:35:28 -05:00
clearInterval(interval)
})
2022-08-29 06:31:43 -04:00
2022-12-30 03:40:17 -05:00
bot.music.load = async function (buffer, fallbackName = '[unknown]') {
let song
switch (path.extname(fallbackName)) {
case '.nbs':
song = convertNBS(buffer)
2022-12-31 03:49:56 -05:00
if (song.name === '') song.name = fallbackName
2022-12-30 03:40:17 -05:00
break
case '.txt':
song = parseTXTSong(buffer.toString())
2022-12-31 03:49:56 -05:00
song.name = fallbackName
2022-12-30 03:40:17 -05:00
break
default:
// eslint-disable-next-line no-case-declarations
const midi = new Midi(buffer)
song = convertMidi(midi)
if (song.name === '') song.name = fallbackName
break
}
2022-11-27 02:35:28 -05:00
return song
}
2022-08-14 05:51:45 -04:00
2022-11-27 02:35:28 -05:00
bot.music.play = function () {
if (bot.music.queue.length === 1) resetTime()
}
2022-08-14 05:51:45 -04:00
2022-11-27 02:35:28 -05:00
bot.music.stop = function () {
bot.music.song = null
bot.music.loop = 0
bot.music.queue = []
resetTime()
}
2022-08-14 05:51:45 -04:00
2022-11-27 02:35:28 -05:00
function resetTime () {
time = 0
startTime = Date.now()
noteIndex = 0
2022-08-14 05:51:45 -04:00
}
2022-11-27 02:35:28 -05:00
function formatTime (time) {
const seconds = Math.floor(time / 1000)
2022-08-14 05:51:45 -04:00
2022-11-27 02:35:28 -05:00
return `${Math.floor(seconds / 60)}:${(seconds % 60).toString().padStart(2, '0')}`
2022-08-14 05:51:45 -04:00
}
2022-11-27 02:35:28 -05:00
function toComponent () {
2022-08-14 05:51:45 -04:00
const component = [
2022-12-08 06:20:10 -05:00
// { text: '[', color: 'dark_gray' },
// { text: 'ChomeNS Bot', color: 'yellow' },
// { text: '] ', color: 'dark_gray' },
2022-11-27 02:35:28 -05:00
{ text: 'Now Playing', color: 'gold' },
{ text: ' | ', color: 'dark_gray' },
{ text: bot.music.song.name, color: 'green' },
{ text: ' | ', color: 'dark_gray' },
{ text: formatTime(time), color: 'gray' },
{ text: ' / ', color: 'dark_gray' },
{ text: formatTime(bot.music.song.length), color: 'gray' },
{ text: ' | ', color: 'dark_gray' },
{ text: noteIndex, color: 'gray' },
{ text: ' / ', color: 'dark_gray' },
{ text: bot.music.song.notes.length, color: 'gray' }
]
2022-08-14 05:51:45 -04:00
if (bot.music.loop === 1) {
2022-11-27 02:35:28 -05:00
component.push({ text: ' | ', color: 'dark_gray' })
component.push({ text: 'Looping Current', color: 'green' })
}
if (bot.music.loop === 2) {
2022-11-27 02:35:28 -05:00
component.push({ text: ' | ', color: 'dark_gray' })
component.push({ text: 'Looping All', color: 'green' })
2022-08-14 05:51:45 -04:00
}
2022-11-27 02:35:28 -05:00
return component
2022-08-14 05:51:45 -04:00
}
}
2022-11-27 02:35:28 -05:00
module.exports = { inject }