chipmunkbot3/plugins/music.js
2024-04-05 20:57:08 -04:00

128 lines
3.5 KiB
JavaScript

const fs = require('fs')
const convertMidi = require('../util/convert-midi.js')
const convertNBS = require('../util/nbs-converter.js')
function inject (bot) {
bot.music = {
playing: false,
queue: [],
nowPlaying: undefined,
looping: false,
_interval: null,
_playNextSong,
skip,
stop,
play
}
bot.music.nowPlaying = {
name: '',
tick: {
current: null,
total: null
// npt: null
}
}
setInterval(() => {
if (!bot.music.playing) return
const msg = [
{ text: 'Now Playing', ...bot.styles.primary },
{ text: ' | ', color: 'dark_gray' },
{ text: bot.music.nowPlaying.name, ...bot.styles.secondary, bold: true },
{ text: ' | ', color: 'dark_gray' },
format(bot.music.nowPlaying.time),
{ text: ' / ', color: 'gray' },
format(bot.music.nowPlaying.length)
// { text: ' (', color: 'dark_gray' },
// bot.music.nowPlaying.note.npt + ' npt',
// { text: ')', color: 'dark_gray' }
]
if (bot.music.looping) {
msg.push({ text: ' | ', color: 'dark_gray' })
msg.push({ text: 'Looping', ...bot.styles.secondary })
}
bot.core.run('title @a actionbar ' + JSON.stringify(msg))
}, 500)
function _playNextSong () {
const song = bot.music.queue.shift()
if (song != null) play(song)
}
function skip () {
clearInterval(bot.music._interval)
bot.music.playing = false
if (bot.music.queue.length !== 0) _playNextSong()
}
function stop () {
bot.music.queue = []
clearInterval(bot.music._interval)
bot.music.playing = false
}
function play (filepath) {
// set stuff up
let song
try {
if (filepath.endsWith('.nbs')) {
song = convertNBS(fs.readFileSync(filepath), filepath)
} else song = convertMidi(filepath)
song.time = 0
bot.music.nowPlaying = song
} catch (err) {
bot.tellraw({ text: err.message, ...bot.styles.error }, '@a')
return
}
// play the music lol
bot.tellraw([
{ text: 'Now playing ', ...bot.styles.primary },
{ text: song.name, ...bot.styles.secondary }
], '@a')
bot.music.playing = true
bot.music.looping = song.loop
let startTime = (new Date()).valueOf()
let notes = [ ...song.notes ]
bot.music._interval = setInterval(async () => {
const time = (new Date()).valueOf() - startTime
song.time = time
notes.forEach(async (note, i) => {
if (time >= note.time) {
const floatingpitch = Math.pow(2, (note.pitch - 12) / 12.0)
bot.core.run(`minecraft:execute at @a run playsound block.note_block.${note.instrument} record @p ~ ~ ~ ${note.volume} ${floatingpitch}`)
notes.splice(i, 1)
}
})
song.time++
if (time > song.length) {
if (bot.music.looping) {
notes = [ ...song.notes ]
startTime = (new Date()).valueOf() + song.loopPosition
return
}
clearInterval(bot.music._interval)
bot.music.playing = false
bot.tellraw([
{ text: 'Finished playing ', color: 'green' },
{ text: bot.music.nowPlaying.name, color: 'dark_green' }
], '@a')
if (bot.music.queue.length !== 0) _playNextSong()
}
}, 50)
}
}
function format (ms) {
const s = ms / 1000
const seconds = Math.floor(s / 60).toString()
const minutes = Math.floor(s % 60).toString()
return seconds + ':' + (minutes.length <= 1 ? '0' : '') + minutes
}
module.exports = inject