forked from wmantly/mc-bot-town
273 lines
5.9 KiB
JavaScript
273 lines
5.9 KiB
JavaScript
'use strict';
|
|
|
|
const {sleep} = require('../utils');
|
|
const mineflayer = require('mineflayer');
|
|
|
|
|
|
class CJbot{
|
|
isReady = false;
|
|
listeners = {};
|
|
|
|
nextChatTime = 1500;
|
|
commandLock = false;
|
|
commandCollDownTime = 1500;
|
|
commands = {};
|
|
combatTag = false;
|
|
doLogOut = false;
|
|
|
|
constructor(args){
|
|
this.username = args.username;
|
|
this.password = args.password;
|
|
this.host = args.host;
|
|
this.auth = args.auth || 'microsoft';
|
|
this.version = args.version || '1.18.2';
|
|
this.autoReConnect = 'autoConnect' in args ? args.autoReConnect : true;
|
|
this.autoConnect = 'autoConnect' in args ? args.autoConnect : true;
|
|
|
|
if(this.autoConnect){
|
|
console.log('connecting', this.username, this.autoConnect)
|
|
this.connect();
|
|
}
|
|
|
|
if(this.autoReConnect){
|
|
this.__autoReConnect()
|
|
}
|
|
|
|
}
|
|
|
|
connect(){
|
|
return new Promise((resolve, reject) =>{
|
|
this.bot = mineflayer.createBot({
|
|
host: this.host,
|
|
username: this.username,
|
|
password: this.password,
|
|
version: this.version,
|
|
auth: this.auth,
|
|
});
|
|
|
|
// this.bot.on('message', (m)=> console.log(m.toString()))
|
|
this.bot.on('error', (m)=>{
|
|
console.log(this.bot.version, m.toString())
|
|
reject(m)
|
|
})
|
|
|
|
|
|
this.bot.on('end', reason =>{
|
|
console.log('Connection ended:', reason)
|
|
this.isReady = false
|
|
}
|
|
);
|
|
|
|
this.bot.on('login', ()=>{
|
|
this.__onReady()
|
|
resolve()
|
|
});
|
|
|
|
});
|
|
}
|
|
|
|
once(event){
|
|
return new Promise((resolve, reject)=> this.bot.once(event, resolve));
|
|
}
|
|
|
|
async __onReady(){
|
|
this.__startListeners();
|
|
|
|
console.log('listeners', this.listeners.onReady)
|
|
|
|
for(let callback of this.listeners.onReady || []){
|
|
console.log('calling listener', callback)
|
|
await callback(this)
|
|
}
|
|
|
|
this.isReady = true;
|
|
this.__error()
|
|
console.log('Bot is ready', this.bot.entity.username, this.username);
|
|
|
|
// Start chat listeners
|
|
this.__listen();
|
|
}
|
|
|
|
|
|
__startListeners(){
|
|
for(let event in this.listeners){
|
|
for(let callback of this.listeners[event]){
|
|
this.bot.on(event, callback)
|
|
}
|
|
}
|
|
}
|
|
|
|
on(event, callback){
|
|
if(!this.listeners[event]) this.listeners[event] = [];
|
|
|
|
this.listeners[event].push(callback);
|
|
|
|
if(this.isReady){
|
|
if(event === 'onReady') callback(this);
|
|
else this.bot.on(event, callback);
|
|
}
|
|
|
|
return event === 'onReady' ? true : ()=> this.bot.off(listener, callback);
|
|
}
|
|
|
|
__autoReConnect(){
|
|
console.log('auto connect function')
|
|
this.on('end', (reason)=>{
|
|
console.error('MC on end', reason)
|
|
|
|
|
|
this.connect()
|
|
});
|
|
|
|
this.bot.on('kick', console.error)
|
|
|
|
this.on('error', (error)=>{
|
|
console.error('MC on error', error);
|
|
|
|
this.connect();
|
|
});
|
|
}
|
|
|
|
__error(){
|
|
this.bot.on('error', (error)=>{
|
|
console.error(`ERROR!!! MC bot ${this.username} on ${this.host} had an error:\n`, error)
|
|
});
|
|
}
|
|
|
|
getPlayers(){
|
|
for (let [username, value] of Object.entries(this.bot.players)){
|
|
value.lvl = Number(value.displayName.extra[0].text)
|
|
}
|
|
|
|
return this.bot.players;
|
|
}
|
|
|
|
|
|
/* Chat and messaging*/
|
|
|
|
__listen(){
|
|
this.bot.on('chat', (from, message)=>{
|
|
|
|
// Ignore messages from this bot
|
|
if(from === this.bot.entity.username) return;
|
|
|
|
// Filter messages to this bot
|
|
if(message.startsWith(this.bot.entity.username)){
|
|
this.__doCommand(
|
|
from,
|
|
message.replace(`${this.bot.entity.username} ` , ' ').trim()
|
|
)
|
|
}
|
|
});
|
|
|
|
this.bot.on('whisper', (from, message)=>{
|
|
this.__doCommand(
|
|
from,
|
|
message.replace(`${this.bot.entity.username} ` , ' ').trim()
|
|
)
|
|
});
|
|
|
|
this.bot.on('message', (message, type)=>{
|
|
if(message.toString().includes(' invited you to teleport to him.')){
|
|
// teleport invite
|
|
|
|
// console.log('ChatBot on message', message.toString())
|
|
this.__doCommand(message.toString().split(' ')[0], '.invite');
|
|
}
|
|
|
|
if(message.toString().includes('You are combat tagged by')){
|
|
try{
|
|
this.combatTag = true;
|
|
console.log('was attacked by')
|
|
let attacker = message.toString().split('. ')[0].replace('You are combat tagged by ', '')
|
|
console.log('was attacked by', attacker)
|
|
// teleport invite
|
|
this.whisper(attacker, 'Please do not attack me, I am a bot.')
|
|
|
|
}catch(error){
|
|
console.log('error!!!!!!', error)
|
|
}
|
|
|
|
}
|
|
|
|
if(message.toString().includes('You are no longer in combat. You may now logout.')){
|
|
this.combatTag = false
|
|
if(this.doLogOut){
|
|
this.quit()
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
quit(force){
|
|
if(!this.combatTag){
|
|
this.bot.quit();
|
|
}else{
|
|
console.log('stoped logout due to combatTag')
|
|
this.doLogOut = true;
|
|
}
|
|
}
|
|
|
|
__chatCoolDown(){
|
|
return Math.floor(Math.random() * (3000 - 1500) + 1500);
|
|
}
|
|
|
|
async say(...messages){
|
|
for(let message of messages){
|
|
if(this.nextChatTime > Date.now()){
|
|
await sleep(this.nextChatTime-Date.now()+1)
|
|
}
|
|
|
|
this.bot.chat(message);
|
|
this.nextChatTime = Date.now() + this.__chatCoolDown();
|
|
}
|
|
}
|
|
|
|
async whisper(to, ...messages){
|
|
await this.say(...messages.map(message=>`/msg ${to} ${message}`));
|
|
}
|
|
|
|
/* Commands */
|
|
|
|
async __unLockCommand(time){
|
|
await sleep(this.commandCollDownTime);
|
|
this.commandLock = false;
|
|
}
|
|
|
|
__reduceCommands(from){
|
|
return Object.keys(this.commands).filter(command =>{
|
|
if (this.commands[command].allowed && !this.commands[command].allowed.includes(from)) return false;
|
|
return true;
|
|
});
|
|
}
|
|
|
|
async __doCommand(from, command){
|
|
if(this.commandLock){
|
|
this.whisper(from, `cool down, try again in ${this.commandCollDownTime/1000} seconds...`);
|
|
return ;
|
|
}
|
|
|
|
let [cmd, ...parts] = command.split(/\s+/);
|
|
|
|
if(this.__reduceCommands(from).includes(cmd)){
|
|
this.commandLock = true;
|
|
try{
|
|
await this.commands[cmd].function.call(this, from, ...parts);
|
|
}catch(error){
|
|
this.whisper(from, `The command encountered an error.`);
|
|
console.error(`Chat command error on ${cmd} from ${from}\n`, error);
|
|
}
|
|
this.__unLockCommand();
|
|
}else{
|
|
this.whisper(from, `I dont know anything about ${cmd}`);
|
|
}
|
|
}
|
|
|
|
addCommand(name, obj){
|
|
if(this.commands[name]) return false;
|
|
this.commands[name] = obj;
|
|
}
|
|
}
|
|
|
|
module.exports = {CJbot};
|