chomens-bot-js/plugins/music.js
2022-11-17 09:07:29 +07:00

146 lines
4.3 KiB
JavaScript

/* eslint-disable require-jsdoc */
/* eslint-disable max-len */
const {Midi} = require('@tonejs/midi');
const {convertMidi} = require('../util/midi_converter');
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 () => {
try {
if (!bot.music.queue.length) return;
bot.music.song = bot.music.queue[0];
time = Date.now() - startTime;
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++;
bot.core.run('minecraft:title @a[tag=!nomusic] actionbar ' + JSON.stringify(toComponent()));
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;
}
}
}
} catch (e) {}
}, 50);
bot.once('end', () => {
clearInterval(interval);
});
bot.music.load = function(buffer, fallbackName = '[unknown]') {
// TODO: NBS Support
const midi = new Midi(buffer);
const song = convertMidi(midi);
if (song.name === '') song.name = fallbackName;
return song;
};
bot.music.play = function(song) {
loop = song.loop;
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 = [
'§8[§eChomeNS Bot§8] ',
{text: 'Now Playing', color: 'gold'},
' §8| ',
{text: bot.music.song.name, color: 'green'},
' §8| ',
{text: formatTime(time), color: 'gray'},
' §8/ ',
{text: formatTime(bot.music.song.length), color: 'gray'},
' §8| ',
{text: noteIndex, color: 'gray'},
'§8 / ',
{text: bot.music.song.notes.length, color: 'gray'},
];
if (bot.music.loop === 1) {
component.push(' §8| ');
component.push('§aLooping Current');
}
if (bot.music.loop === 2) {
component.push(' §8| ');
component.push('§aLooping All');
}
return component;
}
}
module.exports = {inject};