This commit is contained in:
2025-05-04 19:22:31 -04:00
parent ddc6f2d167
commit 7c26d2f0a3
15 changed files with 958 additions and 318 deletions

View File

@ -47,9 +47,11 @@ class CJbot{
this.host = args.host;
this.auth = args.auth || 'microsoft';
this.version = args.version || '1.20.1';
this.hasAi = args.hasAi;
//
this.pluginsWanted = args.plugins || {};
// States if the bot should connect when its loaded
this.autoReConnect = 'autoConnect' in args ? args.autoReConnect : true;
this.autoConnect = 'autoConnect' in args ? args.autoConnect : true;
@ -61,9 +63,10 @@ class CJbot{
}
connect(){
console.log('CJbot.connect');
return new Promise((resolve, reject) =>{
try{
// Create the mineflayer instance
this.bot = mineflayer.createBot({
host: this.host,
username: this.username,
@ -83,6 +86,7 @@ class CJbot{
// to the caller of the function
this.bot.on('end', (reason, ...args)=>{
console.log(this.name, 'Connection ended:', reason, ...args);
this.pluginUnloadAll();
this.isReady = false;
reject(reason);
});
@ -90,18 +94,27 @@ class CJbot{
// When the bot is ready, return to the caller success
this.bot.on('spawn', async()=>{
console.log('CJbot.connect on spawn')
await sleep(2000);
this.__onReady();
resolve();
this.pluginLoadAll();
});
// Set a timer to try to connect again in 30 seconds if the bot is
// not connected
setTimeout(async ()=>{try{
if(this.autoReConnect && !this.isReady) await this.connect();
}catch(error){
console.error('minecraft.js | connect | setTimeout |', this.name, ' ', error)
}}, 30000);
/* setTimeout(async ()=>{
try{
if(this.autoReConnect && !this.isReady){
console.log()
await this.connect();
}
}catch(error){
console.error('minecraft.js | connect | setTimeout |', this.name, ' ', error)
}
}, 30000);*/
}catch(error){
console.log('CJbot.connect Error', error);
reject(error);
}
@ -140,6 +153,7 @@ class CJbot{
// Start chat listeners
this.__listen();
this.bot.on('title', (...args)=>console.log('on title', args))
// this.bot.on('path_update', (...args)=>{ console.log('EVENT path_update', args) })
// this.bot.on('goal_updated', (...args)=>{ console.log('EVENT goal_updated', args) })
// this.bot.on('path_reset', (...args)=>{ console.log('EVENT path_reset', args) })
@ -196,20 +210,21 @@ class CJbot{
// Listen for ending events and call connect again
__autoReConnect(){
try{
console.log('auto connect function')
this.on('end', async (reason)=>{
console.error('_autorestart MC on end', reason)
console.log('auto re-connect function')
this.on('kicked', (...args)=>console.log('CJbot.__autoReConnect on kick', args))
this.on('end', async (...args)=>{
console.error('CJbot.__autoReConnect on end', args)
await sleep(30000)
this.connect()
});
this.on('kick', console.error)
this.on('error', (error)=>{
console.error('MC on error', error);
this.connect();
// this.connect();
});
}catch(error){
console.error('error in __autoReConnect', error);
@ -242,6 +257,12 @@ class CJbot{
plunginsLoaded = {};
pluginLoadAll(){
for(let pluginName in this.pluginsWanted){
this.pluginLoad(pluginName, this.pluginsWanted[pluginName]);
}
}
async pluginLoad(pluginName, opts){
console.log('CJbot.pluginLoad', pluginName)
let plugin = new this.constructor.plungins[pluginName]({...opts, bot:this})
@ -252,13 +273,26 @@ class CJbot{
async pluginUnload(name){
console.log('CJbot.pluginUnload', name)
if(this.plunginsLoaded[name]){
await this.plunginsLoaded[name].unload();
this.plunginsLoaded[name].unload();
delete this.plunginsLoaded[name];
console.log('CJbot.pluginUnload', name, 'done');
return true;
}
}
async pluginUnloadAll(){
console.log('CJbot.pluginUnloadAll');
for(let pluginName in this.plunginsLoaded){
console.log('CJbot.pluginUnloadAll loop', pluginName)
try{
await this.plunginsLoaded[pluginName].unload()
delete this.plunginsLoaded[pluginName];
}catch(error){
console.log('CJbot.pluginUnload loop error:', error)
}
}
}
/* Chat and messaging*/
__listen(){
@ -438,50 +472,59 @@ class CJbot{
});
}
isWithinRange(target, range=2) {
isWithinRange(target, range=2){
const botPos = this.bot.entity.position;
const distance = botPos.distanceTo(target);
return distance <= range+.9;
}
async _goTo(block, range=2){
try{
}catch(error){
if(error.message === 'Not supported block identifier'){
console.log('found block error')
await sleep(1000);
block = this.__blockOrVec(block);
}
console.log('other', error)
playerWithinBlock(player, block, range){
let playerData = this.bot.players[player];
if(!playerData || !playerData.entity) return; // Skip if no entity info
// Calculate the distance between the player and the block
let distance = playerData.entity.position.distanceTo(block.position);
console.log('CJbot.playerWithinBlock', distance, range, distance < range)
if(!range){
return distance;
}
try{
}catch(error){
if(error.name === 'GoalChanged') return await this._goTo(block, range);
console.log('error in _goTo', error.name, '|', error.message);
}
return distance < range;
}
areGoalsWithinRange(goal1, goal2) {
const dx = goal1.x - goal2.x;
const dy = goal1.y - goal2.y;
const dz = goal1.z - goal2.z;
const distanceSq = dx * dx + dy * dy + dz * dz;
// Compare with the maximum allowed squared range (rangeSq)
return distanceSq <= goal1.rangeSq && distanceSq <= goal2.rangeSq;
}
async goTo(options) {
let range = options.range || 2;
let block = this.__blockOrVec(options.where);
while(!this.isWithinRange(this.__blockOrVec(options.where).position, range)){
try{
console.log('goal', this.bot.pathfinder.goal);
if(this.bot.pathfinder.isMoving()){
await sleep(500);
console.log('the bot is moving...')
console.log('the bot is moving...');
continue;
}
await this.bot.pathfinder.goto(
new GoalNear(...block.position.toArray(), range)
);
}catch(error){
await sleep(500);
// await sleep(500);
console.log('CJbot.goTo while loop error:', error)
// await this.bot.pathfinder.setGoal(null);
await this.bot.pathfinder.stop();
// await this.bot.pathfinder.stop();
await sleep(500);
}
}
@ -565,7 +608,6 @@ class CJbot{
return window;
}
async checkItemsFromContainer(containerBlock, itemName, count){
let currentSlot = 0;
let foundCount = 0;
@ -594,42 +636,56 @@ class CJbot{
let window = await this.openContainer(chestBlock);
let itemCount = 0
let currentSlot = 0;
for(let slot of window.slots){
if(currentSlot++ === window.inventoryStart) break;
if(!slot) continue;
// if(!slot || slot.name !== 'shulker_box') continue;
console.log('slot:', slot)
if(!slot || slot.name !== 'shulker_box') continue;
// console.log('slot:', slot)
if(slot.nbt){
// console.log(slot.nbt)
console.log('BlockEntityTag:', slot.nbt.value.BlockEntityTag.value.Items.value.value)
// console.log('nbt', slot.nbt, slot.nbt.value.BlockEntityTag)
// console.log('BlockEntityTag:', slot.nbt.value.BlockEntityTag.value.Items.value.value)
for(let shulkerSlot of slot.nbt.value.BlockEntityTag.value.Items.value.value){
console.log('shulkerSlot', shulkerSlot)
if(shulkerSlot.id?.value !== `minecraft:${item}`) continue;
itemCount += shulkerSlot.Count.value
}
if(this.bot.registry.itemsByName[item].stackSize * 27 === itemCount){
console.log('found full shulker');
this.bot.moveSlotItem(currentSlot, window.inventoryStart);
break;
}
}
}
await window.close();
/* // Get the inventory of the chest block
const chestInventory = chestBlock.getInventory();
// Iterate through the chest's inventory
chestInventory.forEach((slot, index) => {
// Check if the slot contains a shulker box
if (slot && slot.type === 'shulker_box') {
// Retrieve the shulker's inventory
const shulkerInventory = slot.getInventory();
// Check if the slot contains a shulker box
if (slot && slot.type === 'shulker_box') {
// Retrieve the shulker's inventory
const shulkerInventory = slot.getInventory();
// Check if the shulker is full of the specified item
const isFull = shulkerInventory.every(shulkerSlot => {
console.log('shulkerSlot', shulkerSlot)
return shulkerSlot && shulkerSlot.id === item.id && shulkerSlot.count === 64; // Assuming max stack size is 64
});
// Check if the shulker is full of the specified item
const isFull = shulkerInventory.every(shulkerSlot => {
console.log('shulkerSlot', shulkerSlot)
return shulkerSlot && shulkerSlot.id === item.id && shulkerSlot.count === 64; // Assuming max stack size is 64
});
// If full, add the shulker box to the list
if (isFull) {
fullShulkers.push(slot);
}
}
// If full, add the shulker box to the list
if (isFull) {
fullShulkers.push(slot);
}
}
});
return fullShulkers;*/