sandcatbot-monorepo/sSandCatBot/parser.js

462 lines
12 KiB
JavaScript
Raw Permalink Normal View History

var fs = require("fs");
var util = require("./util.js");
var instruments_map = require("./instruments_map.json");
var config = require("./config.json");
var indexjs = require("./index.js");
var handler = require("./command-handler.js");
var playing = false;
var tuning = false;
var interval = null;
var nowPlaying = {
"song_name": undefined,
"time": {
"current": -1,
"full": -1
},
"url": undefined,
"addedBy": undefined
};
var cancelTune = false;
var cancelPlay = false;
function resetNowPlaying() {
nowPlaying = {
"song_name": undefined,
"time": {
"current": -1,
"full": -1
},
"url": undefined,
"addedBy": undefined
};
}
function isValidFile(file) {
if(file == null) return false;
return fs.existsSync(file) && fs.statSync(file).isFile();
}
function parse(file) {
if (!isValidFile(file)) {
console.log(`File ${file} is not a valid file!`);
return null;
}
let data = fs.readFileSync(file).toString();
if (data == null || typeof(data) != "string")
return null;
data = data.split("\n").map(line => line.replace(/\r/, ""));
/*data = data.filter(line => {
if (line == null) return false;
let split = line.split(":");
try {
let tick = parseInt(split[0]);
let pitch = parseInt(split[1]);
let instrument = parseInt(split[2]);
return tick != null && pitch != null && instrument != null;
} catch(e) {
return false;
}
});*/
let parsed = [];
data.forEach((line) => {
let split = line.split(":");
if(split[0] == null || split[1] == null || split[2] == null) return;
let tick = parseInt(split[0]);
let pitch = parseInt(split[1]);
let instrument = parseInt(split[2]);
parsed.push({tick, pitch, instrument});
});
return parsed;
}
function songInfo(file) {
if (!isValidFile(file)) {
console.log(`Error: ${file} is invalid!`);
return null;
}
// lines shit
let lines = fs.readFileSync(file)
if (lines instanceof Buffer) lines = lines.toString();
if (lines == null || typeof(lines) != "string") return null;
lines = lines.split("\n").map(line => line.replace(/\r/, ""));
//filter out bad lines
lines = lines.filter(line => {
if (line == null) return false;
let split = line.split(":");
let tick = split[0];
let pitch = split[1];
let instrument = split[2];
return !(isNaN(tick) || pitch < 0 || pitch > 24 || instrument < 0 || instrument > 15);
});
if (lines.length == 0) {
console.log(`Error: ${file} is invalid!`);
return null;
}
let used_pitches = [];
let used_instruments = [];
let noteblocks_list = [];
let noteblocksByInstrument = {};
let songlength = 0;
lines.forEach(line => {
let split = line.split(":");
if(split[0] == undefined || split[1] == undefined || split[2] == undefined) return;
let tick = parseInt(split[0]);
let pitch = parseInt(split[1]);
let instrument = parseInt(split[2]);
if (!used_pitches.includes(pitch))
used_pitches.push(pitch);
if (!used_instruments.includes(instrument))
used_instruments.push(instrument);
if (noteblocks_list.filter(obj => obj.pitch == pitch && obj.instrument == instrument).length == 0)
noteblocks_list.push({pitch, instrument});
if (noteblocksByInstrument[instrument] == null)
noteblocksByInstrument[instrument] = [instrument];
else if (!noteblocksByInstrument[instrument].includes(pitch))
noteblocksByInstrument[instrument].push(pitch);
if (tick > songlength)
songlength = tick;
});
return {
used_pitches,
used_instruments,
noteblocks_list,
noteblocksByInstrument,
minimunNoteblocks: used_pitches.length,
songlength
};
}
function tuneNoteblocks(file, noteblocks_1, instruments_enabled = false, callback = null) {/*
tuning = true;
if(callback == null) callback = function(res, err) {if(res){console.log(res)} if(err){console.log(err)} };
if (!isValidFile(file)) {
if(file.toString().startsWith("http")) {
callback(undefined, `${file} appears to be a invalid notebot file, try ${handler.prefix}playurl`); //Tells the user to use the playurl command if it starts with "http"
}
callback(undefined, `The file ${file} could not be found!`);
tuning = false;
resetNowPlaying();
return;
}
var noteblocks = util.clone(noteblocks_1);
var info = songInfo(file);
if(info == null) {
callback(undefined, `Failed to get songinfo for ${file}`);
tuning = false;
resetNowPlaying();
return;
}
if (noteblocks.length < info.minimunNoteblocks) {
callback(undefined, `${file} needs atleast ${info.minimunNoteblocks} noteblocks, ${info.minimunNoteblocks - noteblocks.length} are missing`);
tuning = false;
resetNowPlaying();
return;
}
var pitches = info.used_pitches;
var tuned = [];
var untuned = [];
var tuneLater = [];
var nbByInst = info.noteblocksByInstrument;
if(!instruments_enabled) {
noteblocks.forEach((noteblock) => {
if (pitches.includes(noteblock.pitch) && !tuned.includes(noteblock)) {
tuned.push(noteblock);
util.remove(noteblocks, noteblock);
}
if(pitches.length == 0) {
tuning = false;
callback("Done tuning!", undefined);
return;
}
});
} else {
noteblocks.forEach((noteblock) => {
if (nbByInst[noteblock.instrumentid] == null) return;
if(nbByInst[noteblock.instrumentid].includes(noteblock.pitch)) {
tuned.push(noteblock);
var idx = nbByInst[noteblock.instrumentid].indexOf(noteblock.pitch);
nbByInst[noteblock.instrumentid].splice(idx, 1);
} else {
untuned.push(noteblock);
}
});
untuned.forEach((noteblock) => {
if (nbByInst[noteblock.instrumentid].length > 0 && !tuned.includes(noteblock)) {
let pitch = nbByInst[noteblock.instrumentid].shift();
tuneLater.push({noteblock, pitch});
}
})
var missing_instruments = Object.keys(nbByInst).map(key => nbByInst[key]).filter(instrument => instrument.length > 0);
if (missing_instruments.length > 0) {
let missing = {};
Object.keys(nbByInst).forEach(key => {
if (nbByInst[key].length > 0)
missing[key] = nbByInst[key].length;
});
let message = Object.keys(missing).map(key => {
return `&r${instruments_map.lowercase[key]}/&7${instruments_map.blocks[key]} &r(&c${missing[key]}&r)`;
}).join(", ");
console.log(`Missing Instruments: ${message}`);
callback(undefined, `Missing Instruments: ${util.colors(message)}`);
instruments_enabled = false;
}
}
*/
function next() {
/*if (instruments_enabled) {
if(tuneLater[0] == null) {*/
tuning = false;
cancelTune = false;
callback("Done tuning!", undefined);
return;
/*}
if (tuneLater[0].noteblock != null)
tuneNoteblock(tuneLater[0].noteblock, tuneLater[0].pitch, (success) => {
tuned.push(tuneLater[0].noteblock);
tuneLater.shift();
if(cancelTune) {
callback(undefined, undefined);
cancelTune = false;
tuning = false;
resetNowPlaying();
return;
}
if (tuneLater.length > 0) {
next();
} else {
tuning = false;
cancelTune = false;
callback("Done tuning!", undefined);
}
});
} else {
if(noteblocks[0] == null || pitches[0] == null) return;
tuneNoteblock(noteblocks[0], pitches[0], (success) => {
tuned.push(noteblocks[0]);
pitches.shift();
noteblocks.shift();
if(cancelTune) {
callback(undefined, undefined);
cancelTune = false;
tuning = false;
resetNowPlaying();
return;
}
if(pitches.length > 0) {
next();
} else {
tuning = false;
cancelTune = false;
callback("Done tuning!", undefined);
}
});
}
*/}
next();
}
function tuneNoteblock(block, pitch, callback) {
if(block == null) {
callback(false);
return;
}
if(block.pitch == pitch) {
callback(true);
return;
}
let play_times = 0;
if (pitch - block.pitch < 0)
play_times = 25-(block.pitch-pitch);
else
play_times = pitch-block.pitch;
var timeouts = []
for (i = 0; i < play_times; i++) {
if(cancelTune) {
for(i = 0; i < timeouts.length; i++) {
clearTimeout(timeouts[i]);
}
callback(false);
cancelTune = false;
tuning = false;
resetNowPlaying();
return;
}
timeouts[i] = setTimeout(() => {
indexjs.getBot()._client.write('block_place', {
location: block.position,
direction: 1,
hand: 0,
cursorX: 0.5,
cursorY: 0.5,
cursorZ: 0.5
});
}, config.settings.tune_speed*i);
if(i == play_times-1) {
setTimeout(() => {
callback(true);
}, config.settings.tune_speed*i);
}
}
block.pitch = pitch;
}
function timeConverter(duration) {
duration = duration * 50;//1 tick = 50ms
let milliseconds = parseInt((duration % 1000) / 100),
seconds = Math.floor((duration / 1000) % 60),
minutes = Math.floor((duration / (1000 * 60)) % 60),
hours = Math.floor((duration / (1000 * 60 * 60)) % 24);
return {
h: hours,
min: minutes,
sec: seconds,
ms: milliseconds
}
}
function play(bot, noteblocks, file) {
if (playing == true || tuning == true)
return false;
if (!isValidFile(file))
return false;
playing = true;
var parsed = parse(file);
var info = songInfo(file);
let tick = 0;
if(info !== null) {
nowPlaying.time.full = info.songlength;
}
interval = setInterval(function() {
if (interval != this) {
clearInterval(this);
return;
}
if (Object.keys(parsed).length <= 1) {
bot.chat(util.infoMessage(`Finished playing`));
clearInterval(this);
interval = null;
playing = false;
cancelPlay = false;
resetNowPlaying();
return;
}
parsed.forEach((note, i, arr) => {
if(cancelPlay) {
clearInterval(this);
cancelPlay = false;
playing = false;
resetNowPlaying();
return;
}
var foundBlock = null;
if (tick >= note.tick) {
/*noteblocks.forEach(noteblock => {
if (noteblock.pitch == note.pitch && noteblock.instrumentid == note.instrument) {
foundBlock = noteblock;
}
});
*/arr.splice(i, 1);/*
if(foundBlock == null) {
console.log("not found:", note);
} else {
playNoteblock(bot, foundBlock);
}*/
let floatingpitch = Math.pow(2, (note.pitch-12) / 12.0);
bot.chat(`/playsound block.note_block.${instruments_map.lowercase[note.instrument]} player @a ~ ~ ~ 2000000 ${floatingpitch}`);
}
});
tick++;
nowPlaying.time.current = tick;
}, 1000/20); // every tick = 50ms
}
function playNoteblock(bot, noteblock) {
bot._client.write('block_dig', {
status: 0,
location: noteblock.position,
face: 1
});
bot._client.write('block_dig', {
status: 1,
location: noteblock.position,
face: 1
});
}
module.exports.timeConverter = timeConverter;
module.exports.tuneNoteblocks = tuneNoteblocks;
module.exports.tuneNoteblock = tuneNoteblock;
module.exports.parse = parse;
module.exports.play = play;
module.exports.songInfo = songInfo;
module.exports.isValidFile = isValidFile;
module.exports.getNowPlaying = () => {return nowPlaying};
module.exports.editNowPlaying = (song_name, current, full, url, addedBy) => {
song_name != undefined ? nowPlaying.song_name = song_name : undefined;
current != undefined ? nowPlaying.time.current = current : undefined;
full != undefined ? nowPlaying.time.full = full : undefined;
url != undefined ? nowPlaying.url = url : undefined;
addedBy != undefined ? nowPlaying.addedBy = addedBy : undefined;
};
module.exports.isTuning = () => {return tuning};
module.exports.isPlaying = () => {return playing};
module.exports.setcancelTune = (b) => {cancelTune = b};
module.exports.setcancelPlay = (b) => {cancelPlay = b};