art round 1
This commit is contained in:
272
nodejs/model/minecraft.js
Normal file
272
nodejs/model/minecraft.js
Normal file
@ -0,0 +1,272 @@
|
||||
'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};
|
Reference in New Issue
Block a user