This commit is contained in:
2024-10-11 09:46:18 -04:00
parent 84c45695b7
commit ddc6f2d167
15 changed files with 1504 additions and 559 deletions

View File

@ -1,5 +1,7 @@
'use strict';
const axios = require('axios');
const conf = require('../conf');
const {sleep} = require('../utils');
@ -11,11 +13,80 @@ const {
} = require("@google/generative-ai");
class Ai{
constructor(prompt){
this.prompt = prompt;
this.start();
constructor(args){
this.bot = args.bot;
this.promptName = args.promptName;
this.prompCustom = args.prompCustom || '';
this.intervalLength = args.intervalLength || 30;
this.intervalStop;
this.messageListener;
}
async init(){
await this.start();
this.bot.on('onReady', async (argument)=>{
try{
await sleep(1000);
let messages = [''];
this.messageListener = this.bot.on('message', (message, type)=>{
if(type === 'game_info') return;
if(message.toString().startsWith('<') && message.toString().split('>')[0].includes(this.bot.bot.entity.username)){
console.log('message blocked from message array')
return;
}
console.log(`Message ${type}: ${message.toString()}`)
messages.push('>', message.toString());
});
this.intervalStop = setInterval(async ()=>{
let result;
// if(messages.length ===0) return;
try{
result = await this.chat(JSON.stringify({
messages, currentTime:Date.now()+1}
));
}catch(error){
console.log('error AI API', error, result);
messages = [];
return ;
}
try{
messages = [''];
if(!result.response.text()) return;
for(let message of JSON.parse(result.response.text())){
console.log('toSay', message.delay, message.text);
if(message.text === '___') return;
setTimeout(async (message)=>{
await this.bot.sayAiSafe(message.text);
}, message.delay*1000, message);
}
}catch(error){
console.log('Error in AI message loop', error, result);
if(result || result.response || result.response.text()){
console.log(result.response.text())
}
}
}, this.intervalLength*1000);
}catch(error){
console.log('error in onReady', error);
}
});
}
async unload(){
if(this.intervalStop){
clearInterval(this.intervalStop);
this.intervalStop = undefined;
}
this.messageListener();
return true;
}
__settings(history){
@ -63,13 +134,26 @@ class Ai{
}
}
start(history){
async start(history){
const genAI = new GoogleGenerativeAI(conf.ai.key);
const model = genAI.getGenerativeModel({
model: "gemini-1.5-flash",
});
let bulbaItems = await axios.get('https://webstore.bulbastore.uk/api/listings');
bulbaItems = bulbaItems.data.listings.map(i=>i.listing_name);
console.log('AI for prompts', conf.ai.prompts)
this.prompt = conf.ai.prompts[this.promptName](
this.bot.bot.entity.username,
conf.ai.interval,
Object.values(this.bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n'),
bulbaItems,
this.prompCustom,
);
this.session = model.startChat({
...this.__settings(history),
// systemInstruction: this.prompt,
@ -91,7 +175,6 @@ class Ai{
};
await sleep(500);
this.session.params.history.pop();
console.log('current history', this.session.params.history);
this.start(this.session.params.history);
return await this.chat(message, retryCount++)
}
@ -103,5 +186,5 @@ class Ai{
module.exports = {Ai};
module.exports = Ai;
// run();

View File

@ -0,0 +1,64 @@
'use strict';
const conf = require('../conf');
const {sleep} = require('../utils');
class Craft{
constructor(args){
this.bot = args.bot;
this.interval = args.interval;
this.target = args.target;
this.intervalStop;
this.isAction = true;
}
async init(){
this.bot.on('onReady', async ()=>{
this.bot.bot.setControlState('jump', true);
setTimeout(()=> this.bot.bot.setControlState('jump', false), 2000);
await sleep(2000);
let chest = this.bot.findChestBySign('FILLED BOXES');
await this.bot.goTo({
where: chest,
range: 3,
});
await this.bot.getFullShulkersFromChest(chest, {id:3});
// goto 'FILLED BOXES' box
// get 4 boxes of 'prismarine_shard'
// get 5 boxes of 'prismarine_crystals'
// place boxes
});
}
unload(){
if(this.intervalStop){
clearInterval(this.intervalStop);
this.intervalStop = undefined;
}
return true;
}
async goToSpot(){
await this.bot.goTo({
where: this.bot.findBlockBySign('guardian\nattack spot'),
range: 0,
});
}
async swing(){
this.intervalStop = setInterval(()=>{
try{
this.bot.bot.attack(
this.bot.bot.nearestEntity(
entity => entity.name.toLowerCase() === 'guardian'
)
);
}catch(error){}
}, 4000);
}
}
module.exports = Craft;

View File

@ -1,32 +1,112 @@
module.exports = {
'help': {
desc: `Print the allowed commands.`,
async function(from){
console.log('called help', from)
let intro = [
'I am a bot owned and operated by',
'wmantly <wmantly@gmail.com>',
'You have access to the following commands:'
]
await this.whisper(from, ...intro, ...this.__reduceCommands(from).map(command =>
`${command} -- ${this.commands[command].desc || ''}`
));
}
desc: `Print the allowed commands.`,
async function(from){
console.log('called help', from)
let intro = [
'I am a bot owned and operated by',
'wmantly <wmantly@gmail.com>',
'You have access to the following commands:'
]
await this.whisper(from, ...intro, ...this.__reduceCommands(from).map(command =>
`${command} -- ${this.commands[command].desc || ''}`
));
}
},
'say': {
desc: `Make the bot say stuff in chat`,
allowed: ['wmantly', 'useless666', 'tux4242', 'pi_chef', '1_cut',],
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, ...messages){
await this.say((messages || []).join(' '));
}
async function(from, ...messages){
await this.say((messages || []).join(' '));
}
},
'plugins': {
desc: 'List the plugins',
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, botName){
if(botName){
if(botName in this.constructor.bots){
this.whisper(from, `${Object.keys(this.constructor.bots[botName].plunginsLoaded)}`)
}
}
}
},
'unload': {
desc: `Make bot unload plugin`,
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, botName, plugin) {
this.whisper(from, `Unloading ${plugin}`);
if(botName in this.constructor.bots){
let bot = this.constructor.bots[botName];
let status = await bot.pluginUnload(plugin);
return this.whisper(from, `plugin status ${status}`);
}
this.whisper(from, '?')
}
},
'load': {
desc: `Make bot load/unload plugin`,
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, botName, plugin) {
this.whisper(from, `Loading ${plugin}`);
if(botName in this.constructor.bots){
let bot = this.constructor.bots[botName];
let status = await bot.pluginLoad(plugin);
return this.whisper(from, `plugin status ${status}`);
}
this.whisper(from, '?')
}
},
'guardian': {
desc:'',
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, botName, action) {
this.whisper(from, `Loading ${plugin}`);
if(botName in this.constructor.bots){
let bot = this.constructor.bots[botName];
let status = await bot.pluginLoad(plugin);
return this.whisper(from, `plugin status ${status}`);
}
this.whisper(from, '?')
}
},
'ai': {
desc: `Make bot load/unload plugin`,
allowed: ['wmantly', 'useless666', 'tux4242',],
ignoreLock: true,
async function(from, botName, personality, ...custom) {
if(botName in this.constructor.bots ){
let bot = this.constructor.bots[botName];
if(bot.isReady){
let status = await bot.pluginLoad('Ai', {
promptName: personality,
prompCustom: custom,
});
return this.whisper(from, `plugin status ${status}`);
}
}
this.whisper(from, '?')
}
},
'logon': {
desc: `Have bot log on for 10 seconds'`,
allowed: ['wmantly', 'useless666', 'tux4242', 'pi_chef', '1_cut',],
ignoreLock: true,
async function(from, botName){
async function(from, botName, time){
this.__unLockCommand();
if(botName in this.constructor.bots){
@ -35,11 +115,11 @@ module.exports = {
if(!bot.isReady){
try{
await bot.connect();
var clear = setTimeout(()=> bot.quit(), 10000);
var clear = setTimeout(()=> bot.quit(), time ? parseInt(time)*1000 : 10000);
bot.whisper(from, 'I am ready')
}catch(error){
console.log('inv error connecting to bot');
this.whisper('Bot is not available right now, try again in 30 seconds.');
this.whisper(from, 'Bot is not available right now, try again in 30 seconds.');
}
}else{
await this.whisper(from, `Bot ${bot.bot.entity.username} Already online`);

View File

@ -98,12 +98,18 @@ module.exports = {
console.log('inv error connecting to bot');
this.whisper('Bot is not available right now, try again in 30 seconds.');
}
var clear = setTimeout(()=> bot.quit(), 10000);
var clear = setTimeout(()=>{
bot.pluginUnload('Tp');
bot.quit()
}, 10000);
}
await bot.pluginLoad('Tp');
await bot.bot.chat(`/invite ${from}`);
await bot.whisper(from, `accept invite from ${bot.bot.entity.username} within 10 seconds...`);
bot.on('message', (message) =>{
bot.on('message', async (message) =>{
if(message.toString() === `${from} teleported to you.`){
await bot.pluginUnload('Tp');
if(clear){
clearTimeout(clear);
bot.quit();

View File

@ -8,81 +8,81 @@ const customerSlots = [5, 6, 7, 8, 14, 15, 16, 17, 23, 24, 25, 26];
function findChestBySign(bot, text){
let sign = bot.bot.findBlock({
useExtraInfo: true,
maxDistance: 32,
matching: (block)=> {
if(block.name.includes('sign') && block.signText.includes(text)){
return true;
}
}
});
let sign = bot.bot.findBlock({
useExtraInfo: true,
maxDistance: 32,
matching: (block)=> {
if(block.name.includes('sign') && block.signText.includes(text)){
return true;
}
}
});
return bot.bot.findBlock({
point: sign.position,
// maxDistance: 1,
useExtraInfo: true,
matching: block => block.name === 'chest'
});
return bot.bot.findBlock({
point: sign.position,
// maxDistance: 1,
useExtraInfo: true,
matching: block => block.name === 'chest'
});
}
module.exports = {
'.trade': {
desc: 'Bot will take trade requests',
async function(from){
/*
todo
'.trade': {
desc: 'Bot will take trade requests',
async function(from){
/*
todo
* Do... something if the users chest is full
* Do... something if the users chest is full
*/
*/
// Make the user has a chest then can add too.
let chestBlock = findChestBySign(this, from);
if(!chestBlock) return this.whisper(from, `You aren't allowed to trade with me...`);
// Make the user has a chest then can add too.
let chestBlock = findChestBySign(this, from);
if(!chestBlock) return this.whisper(from, `You aren't allowed to trade with me...`);
await this.say('/trade accept');
let window = await this.once('windowOpen');
await this.say('/trade accept');
let window = await this.once('windowOpen');
// If the process is taking to long, just stop
let timeoutCheck = setTimeout(()=>{
this.bot.closeWindow('window');
this.bot.removeAllListeners('windowOpen');
this.whisper(from, `I have things to do, I cant wait on you all day!`)
}, 120000);
// If the process is taking to long, just stop
let timeoutCheck = setTimeout(()=>{
this.bot.closeWindow('window');
this.bot.removeAllListeners('windowOpen');
this.whisper(from, `I have things to do, I cant wait on you all day!`)
}, 120000);
// Check to see if the remote user has agreed to the trade.
let confirmationCheck = setInterval(async ()=>{
if(window.containerItems().filter(item => item?.slot == 53)[0].name == 'lime_dye'){
this.bot.moveSlotItem(37, 37);
}
}, 500);
// Check to see if the remote user has agreed to the trade.
let confirmationCheck = setInterval(async ()=>{
if(window.containerItems().filter(item => item?.slot == 53)[0].name == 'lime_dye'){
this.bot.moveSlotItem(37, 37);
}
}, 500);
// Clean up when the trade is done
await this.once('windowClose');
clearInterval(confirmationCheck);
// Clean up when the trade is done
await this.once('windowClose');
clearInterval(confirmationCheck);
// If the trade took so long it timed out, just kill the whole thing.
if(timeoutCheck._destroyed) return;
clearTimeout(timeoutCheck)
// If the trade took so long it timed out, just kill the whole thing.
if(timeoutCheck._destroyed) return;
clearTimeout(timeoutCheck)
// Give MC a moment
// await sleep(1000);
// Give MC a moment
// await sleep(1000);
let goBack = await this.goToReturn({where: chestBlock, reTry: true})
let goBack = await this.goToReturn({where: chestBlock, reTry: true})
let isPutAway = await this.dumpToChest(chestBlock)
let isPutAway = await this.dumpToChest(chestBlock)
await goBack();
await goBack();
await this.whisper(from, `I put ${isPutAway ? 'all' : 'some'} items in your chest.`);
}
},
'test': {
desc: 'go away',
allowed: ['useless666'],
async function(from){
let chestBlock = findChestBySign(this, from);
}
}
await this.whisper(from, `I put ${isPutAway ? 'all' : 'some'} items in your chest.`);
}
},
'test': {
desc: 'go away',
allowed: ['useless666'],
async function(from){
let chestBlock = findChestBySign(this, from);
}
}
}

187
nodejs/controller/craft.js Normal file
View File

@ -0,0 +1,187 @@
'use strict';
const conf = require('../conf');
const {sleep, nextTick} = require('../utils');
class Craft{
constructor(args){
this.bot = args.bot;
this.interval = args.interval;
this.target = args.target;
this.intervalStop;
this.isAction = true;
}
init(){
return new Promise(async (resolve, reject)=>{
this.bot.on('onReady', async ()=>{
try{
await sleep(500);
await this.bot.goTo({
where: this.bot.findBlockBySign('bot walk 2').position,
range: 0,
});
await this.bot.goTo({
where: this.bot.findBlockBySign('bot walk 1').position,
range: 0,
});
await this.bot.goTo({
where: this.bot.findBlockBySign('bot walk 2').position,
range: 0,
});
let hasItems = await this.getItems();
while(hasItems){
await this.craft();
hasItems = await this.getItems();
}
return resolve();
}catch(error){
reject(error);
}
});
});
}
unload(){
if(this.intervalStop){
clearInterval(this.intervalStop);
this.intervalStop = undefined;
}
return true;
}
async getItems(){
/*
shards
*/
let prismarine_shardChest = this.bot.findChestBySign('prismarine_shard');
await this.bot.goTo({
where: prismarine_shardChest.position,
range: 2,
});
let hasShard = await this.bot.checkItemsFromContainer(
prismarine_shardChest, 'prismarine_shard', 64*4
);
/*
crystals
*/
let prismarine_crystalsChest = this.bot.findChestBySign('crystals');
await this.bot.goTo({
where: prismarine_crystalsChest.position,
range: 2,
});
let hasCrystals = await this.bot.checkItemsFromContainer(
prismarine_crystalsChest, 'prismarine_crystals', 64*5
);
if(!hasShard || !hasCrystals) return false;
/*
get
*/
await sleep(3000);
await this.bot.getItemsFromChest(
prismarine_shardChest, 'prismarine_shard', 64*4
);
await sleep(1000);
await this.bot.getItemsFromChest(
prismarine_crystalsChest, 'prismarine_crystals', 64*5
);
return true;
}
async craft(){
// Ensure the bot has enough items (4 shards and 5 crystals for 1 lantern)
let prismarineShardsCount = this.bot.bot.inventory.count(this.bot.mcData.itemsByName.prismarine_shard.id);
let prismarineCrystalsCount = this.bot.bot.inventory.count(this.bot.mcData.itemsByName.prismarine_crystals.id);
if(prismarineShardsCount < 4 || prismarineCrystalsCount < 5){
console.log("Not enough materials to craft 64 Sea Lanterns.");
return;
}else{
console.log('good to make sea_lantern!')
}
// Hold onto the closest crafting table
let craftingTable = this.bot.bot.findBlock({
matching: this.bot.mcData.blocksByName.crafting_table.id,
maxDistance: 64
});
await this.bot.goTo({
where: craftingTable.position,
range: 1,
});
// Hold onto the recipe
let recipe = this.bot.bot.recipesAll(
this.bot.mcData.itemsByName.sea_lantern.id,
null,
craftingTable
)[0];
let window = await this.bot.openCraftingTable(craftingTable);
// Move these into openCrating function
let windowOnce = (event)=> new Promise((resolve, reject)=> window.once(event, resolve));
let inventory = ()=> window.slots.slice(window.inventoryStart, window.inventoryEnd)
// Move the items into the crafting grid
let slotCount = 1;
for(let shapeRow of recipe.inShape){
for(let shape of shapeRow){
this.bot.bot.moveSlotItem(
inventory().find((element)=> element && element.type === shape.id).slot,
slotCount
);
await windowOnce(`updateSlot:${slotCount}`);
slotCount++;
}
}
// Wait for the server to catch up.
await sleep(500);
// Craft each item until all are gone.
let craftedCount = 0;
while(window.slots[0]){
await this.bot.bot.moveSlotItem(
window.craftingResultSlot,
38 // dont hard code this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
);
craftedCount++;
await windowOnce(`updateSlot:0`);
await sleep(50); // wait for the client to catchup
}
await window.close();
/*
Dump items to chest
*/
let seaLanternChest = this.bot.findChestBySign('sea_lantern');
await this.bot.goTo({
where: seaLanternChest.position,
range: 4,
});
await this.bot.dumpToChest(seaLanternChest, 'sea_lantern')
}
}
module.exports = Craft;

View File

@ -0,0 +1,53 @@
'use strict';
const conf = require('../conf');
const {sleep, nextTick} = require('../utils');
class GuardianFarm{
constructor(args){
this.bot = args.bot;
this.isDangerous = true;
this.isAction = true;
}
async init(){
console.log('GuardianFarm started')
this.onReadyListen = this.bot.on('onReady', async ()=>{
await sleep(3000);
let lastTimeListen = this.bot.bot.time.timeOfDay;
this.onTimeListen = this.bot.bot.on('time', async ()=>{
let isDay = lastTimeListen < this.bot.bot.time.timeOfDay;
lastTimeListen = this.bot.bot.time.timeOfDay;
if(isDay){
await this.onNewDay();
}
});
await this.bot.pluginLoad('Swing');
});
return true;
}
unload(){
this.onReadyListen();
this.onTimeListen();
return true;
}
async onNewDay(){
try{
console.log('GuardianFarm.onNewDay new day!');
await this.bot.pluginUnload('Swing');
await this.bot.pluginLoad('Craft');
await this.bot.pluginUnload('Craft');
await this.bot.pluginLoad('Swing');
}catch(error){
console.error('Error in GuardianFarm.onNewDay:', error);
}
}
}
module.exports = GuardianFarm;

View File

@ -1,7 +1,5 @@
'use strict';
const axios = require('axios');
const {sleep} = require('../utils');
const conf = require('../conf');
const {CJbot} = require('../model/minecraft');
@ -10,7 +8,15 @@ const inventoryViewer = require('mineflayer-web-inventory');
const commands = require('./commands');
const {onJoin} = require('./player_list');
const {Ai} = require('./ai');
// const plugins = {
// Swing: require('./swing'),
// }
CJbot.pluginAdd(require('./swing'));
CJbot.pluginAdd(require('./craft'));
CJbot.pluginAdd(require('./tp'));
CJbot.pluginAdd(require('./ai'));
CJbot.pluginAdd(require('./guardianFarm'));
for(let name in conf.mc.bots){
if(CJbot.bots[name]) continue;
@ -23,81 +29,11 @@ for(let name in conf.mc.bots){
}
}
bot.on('onReady', async function(argument) {
// inventoryViewer(bot.bot);
try{
// onJoin(bot);
// await sleep(1000);
// bot.bot.setControlState('jump', true);
// setTimeout(()=> bot.bot.setControlState('jump', false), 5000);
if(bot.hasAi){
console.log(`${bot.bot.entity.username} has AI`);
let messages = [''];
let bulbaItems = await axios.get('https://webstore.bulbastore.uk/api/listings');
bulbaItems = bulbaItems.data.listings.map(i=>i.listing_name);
bot.bot.on('message', (message, type)=>{
if(type === 'game_info') return;
if(message.toString().startsWith('<') && message.toString().split('>')[0].includes(bot.bot.entity.username)) return;
console.log(`Message ${type}: ${message.toString()}`)
messages.push('>', message.toString());
});
await sleep(500);
let aiChat = new Ai(conf.ai.prompt(
bot.bot.entity.username,
conf.ai.interval,
Object.values(bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n'),
bulbaItems
))
setInterval(async ()=>{
let result;
// if(messages.length ===0) return;
try{
result = await aiChat.chat(JSON.stringify({
messages, currentTime:Date.now()+1}
));
}catch(error){
console.log('error AI API', error, result);
messages = [];
return ;
}
try{
messages = [''];
if(!result.response.text()) return;
for(let message of JSON.parse(result.response.text())){
console.log('toSay', message.delay, message.text);
if(message.text === '___') return;
setTimeout(async (message)=>{
await bot.sayAiSafe(message.text);
}, message.delay*1000, message);
}
}catch(error){
console.log('Error in AI message loop', error, result);
if(result || result.response || result.response.text()){
console.log(result.response.text())
}
}
}, conf.ai.interval*1000);
}
}catch(error){
console.log('error in onReady', error);
if(conf.mc.bots[name].plugins){
for(let pluginName in conf.mc.bots[name].plugins){
bot.pluginLoad(pluginName, conf.mc.bots[name].plugins[pluginName]);
}
});
bot.on('error', console.log);
// bot.on('message', function(message, type){
// console.log(`${type}: ${message.toString()}`)
// });
}
}
(async ()=>{try{

View File

@ -0,0 +1,60 @@
'use strict';
const conf = require('../conf');
const {sleep} = require('../utils');
class Swing{
constructor(args){
this.bot = args.bot;
this.target = args.target;
this.interval = args.interval;
this.intervalStop;
this.isDangerous = true;
this.isAction = true;
}
async init(){
this.onReadyListen = this.bot.on('onReady', async ()=>{
console.log('Swing.init onReady called');
try{
this.block = this.bot.findBlockBySign('guardian\nattack spot');
await this.goToSpot();
await this.swing();
}catch(error){
console.error('Error in Swing.init:', error)
}
});
return true;
}
unload(){
clearInterval(this.intervalStop);
this.intervalStop = null;
this.onReadyListen();
return true;
}
async goToSpot(){
await this.bot.goTo({
where: this.block,
range: 3,
});
}
async swing(){
this.intervalStop = setInterval(async ()=>{
try{
// console.log('attacking');
await this.bot.bot.attack(
this.bot.bot.nearestEntity(
entity => entity.name.toLowerCase() === 'guardian'
)
);
}catch(error){}
}, 1010);
}
}
module.exports = Swing;

41
nodejs/controller/tp.js Normal file
View File

@ -0,0 +1,41 @@
'use strict';
const conf = require('../conf');
const {sleep} = require('../utils');
class Tp{
constructor(args){
this.bot = args.bot;
}
async init(){
for(let pluginName in this.bot.plunginsLoaded){
if(this.bot.plunginsLoaded[pluginName].isDangerous){
this.bot.pluginUnload(pluginName);
this.pluginToContinue = pluginName;
}
}
await this.bot.goTo({
where: this.bot.findBlockBySign('bot TP spot'),
range: 0,
});
this.cleatTimeout = setTimeout(()=>{
this.bot.pluginUnload(this.constructor.name)
}, 60000);
}
unload(){
if(this.cleatTimeout){
clearTimeout(this.cleatTimeout);
this.cleatTimeout = undefined;
}
if(this.pluginToContinue) this.bot.pluginLoad(this.pluginToContinue);
return true;
}
}
module.exports = Tp;