chomens-bot-js/plugins/music.js
ChomeNS f843316c60 music bossbar instead of actionbar
not tested but it prob works
2023-01-02 12:59:16 +07:00

172 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const path = require('path')
const { Midi } = require('@tonejs/midi')
const { convertMidi } = require('../util/midi_converter')
const convertNBS = require('../util/nbs_converter')
const parseTXTSong = require('../util/txt_song_parser')
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',
pling: 'minecraft:block.note_block.pling'
}
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 () {
if (bot.music.loop === 2) {
bot.music.queue.push(bot.music.queue.shift())
bot.music.play(bot.music.queue[0])
} else {
bot.music.queue.shift()
}
resetTime()
}
const interval = setInterval(async () => {
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()))
// is spamming commands in core as a self care a good idea?
// btw this is totallynotskidded™ from my song bot except the bossbarName
const bossbarName = 'chomens_bot:music' // maybe make this in the config?
bot.core.run(`minecraft:bossbar add ${bossbarName} ""`) // is setting the name to "" as a placeholder a good idea?
bot.core.run(`minecraft:bossbar set ${bossbarName} players @a[tag=!nomusic]`)
bot.core.run(`minecraft:bossbar set ${bossbarName} name ${JSON.stringify(toComponent())}`)
bot.core.run(`minecraft:bossbar set ${bossbarName} color yellow`) // should i use purple lol
bot.core.run(`minecraft:bossbar set ${bossbarName} visible true`)
bot.core.run(`minecraft:bossbar set ${bossbarName} value ${Math.floor(time)}`)
bot.core.run(`minecraft:bossbar set ${bossbarName} max ${bot.music.song.length}`)
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.core.run(`minecraft:bossbar remove ${bossbarName}`)
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
}
}
}
}, 50)
bot.on('end', () => {
clearInterval(interval)
})
bot.music.load = async function (buffer, fallbackName = '[unknown]') {
let song
switch (path.extname(fallbackName)) {
case '.nbs':
song = convertNBS(buffer)
if (song.name === '') song.name = fallbackName
break
case '.txt':
song = parseTXTSong(buffer.toString())
song.name = fallbackName
break
default:
// eslint-disable-next-line no-case-declarations
const midi = new Midi(buffer)
song = convertMidi(midi)
if (song.name === '') song.name = fallbackName
break
}
return song
}
bot.music.play = function () {
if (bot.music.queue.length === 1) resetTime()
}
bot.music.stop = function () {
bot.music.song = null
bot.music.loop = 0
bot.music.queue = []
resetTime()
}
function resetTime () {
time = 0
startTime = Date.now()
noteIndex = 0
}
function formatTime (time) {
const seconds = Math.floor(time / 1000)
return `${Math.floor(seconds / 60)}:${(seconds % 60).toString().padStart(2, '0')}`
}
function toComponent () {
const component = [
// { text: '[', color: 'dark_gray' },
// { text: 'ChomeNS Bot', color: 'yellow' },
// { text: '] ', color: 'dark_gray' },
// { 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' }
]
if (bot.music.loop === 1) {
component.push({ text: ' | ', color: 'dark_gray' })
component.push({ text: 'Looping Current', color: 'green' })
}
if (bot.music.loop === 2) {
component.push({ text: ' | ', color: 'dark_gray' })
component.push({ text: 'Looping All', color: 'green' })
}
return component
}
}
module.exports = { inject }