This commit is contained in:
William Mantly 2024-09-13 15:09:11 -04:00
parent 66ccf666b0
commit 2ab44224b4
5 changed files with 200 additions and 52 deletions

67
nodejs/controller/ai.js Normal file
View File

@ -0,0 +1,67 @@
'use strict';
const conf = require('../conf');
const {
GoogleGenerativeAI,
HarmCategory,
HarmBlockThreshold,
} = require("@google/generative-ai");
const genAI = new GoogleGenerativeAI(conf.ai.key);
const model = genAI.getGenerativeModel({
model: "gemini-1.5-flash",
});
const generationConfig = {
temperature: 1,
topP: 0.95,
topK: 64,
maxOutputTokens: 8192,
responseMimeType: "application/json",
};
async function run(name, interval, players) {
const chatSession = model.startChat({
generationConfig,
safetySettings:[
// See https://ai.google.dev/gemini-api/docs/safety-settings
{
category: HarmCategory.HARM_CATEGORY_HARASSMENT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
{
category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold: HarmBlockThreshold.BLOCK_NONE,
},
],
history: [
{
role: "user",
parts: [
{text: conf.ai.prompt(name, interval, players)},
],
},
{
role: "model",
parts: [
{text: "Chat stuff"},
],
}
],
});
return chatSession;
}
module.exports = {run};
// run();

View File

@ -7,7 +7,9 @@ const {CJbot} = require('../model/minecraft');
const inventoryViewer = require('mineflayer-web-inventory'); const inventoryViewer = require('mineflayer-web-inventory');
const commands = require('./commands'); const commands = require('./commands');
const {onJoin} = require('./player_list') const {onJoin} = require('./player_list');
const ai = require('./ai');
for(let name in conf.mc.bots){ for(let name in conf.mc.bots){
if(CJbot.bots[name]) continue; if(CJbot.bots[name]) continue;
@ -22,21 +24,72 @@ for(let name in conf.mc.bots){
bot.on('onReady', async function(argument) { bot.on('onReady', async function(argument) {
// inventoryViewer(bot.bot); // 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 = [];
onJoin(bot); bot.bot.on('message', (message, type)=>{
await sleep(1000); if(type === 'game_info') return;
bot.bot.setControlState('jump', true); if(message.toString().startsWith('<') && message.toString().split('>')[0].includes(bot.bot.entity.username)) return;
setTimeout(()=> bot.bot.setControlState('jump', false), 5000) console.log(`Message ${type}: ${message.toString()}`)
messages.push('>', message.toString());
});
}) await sleep(500);
// bot.on('message', function(...args){ let aiChat = await ai.run(
// console.log('message | ', ...args) bot.bot.entity.username,
// }) conf.ai.interval,
Object.values(bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n')
);
setInterval(async ()=>{
let result;
if(messages.length ===0) return;
try{
result = await aiChat.sendMessage(messages);
}catch(error){
console.log('error AI API', error, result);
messages = [];
return ;
} }
(async ()=>{
try{ 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);
}
}, conf.ai.interval*1000);
}
}catch(error){
console.log('error in onReady', error);
}
});
bot.on('error', console.log);
// bot.on('message', function(message, type){
// console.log(`${type}: ${message.toString()}`)
// });
}
(async ()=>{try{
for(let name in CJbot.bots){ for(let name in CJbot.bots){
let bot = CJbot.bots[name]; let bot = CJbot.bots[name];
if(bot.autoConnect){ if(bot.autoConnect){

View File

@ -1,5 +1,7 @@
'use strict'; 'use strict';
process.env.DEBUG = 'mineflayer:*'; // Enables all debugging logs
const mineflayer = require('mineflayer'); const mineflayer = require('mineflayer');
const minecraftData = require('minecraft-data'); const minecraftData = require('minecraft-data');
const { pathfinder, Movements, goals: { GoalNear } } = require('mineflayer-pathfinder'); const { pathfinder, Movements, goals: { GoalNear } } = require('mineflayer-pathfinder');
@ -46,6 +48,8 @@ class CJbot{
this.auth = args.auth || 'microsoft'; this.auth = args.auth || 'microsoft';
this.version = args.version || '1.20.1'; this.version = args.version || '1.20.1';
this.hasAi = args.hasAi;
// States if the bot should connect when its loaded // States if the bot should connect when its loaded
this.autoReConnect = 'autoConnect' in args ? args.autoReConnect : true; this.autoReConnect = 'autoConnect' in args ? args.autoReConnect : true;
this.autoConnect = 'autoConnect' in args ? args.autoConnect : true; this.autoConnect = 'autoConnect' in args ? args.autoConnect : true;
@ -57,7 +61,7 @@ class CJbot{
connect(){ connect(){
return new Promise((resolve, reject) =>{ return new Promise((resolve, reject) =>{
try{
// Create the mineflayer instance // Create the mineflayer instance
this.bot = mineflayer.createBot({ this.bot = mineflayer.createBot({
host: this.host, host: this.host,
@ -70,16 +74,16 @@ class CJbot{
// If an error happens before the login event, toss an error back to // If an error happens before the login event, toss an error back to
// the caller of the function // the caller of the function
let onError = this.bot.on('error', (m)=>{ let onError = this.bot.on('error', (m)=>{
console.log(this.bot.version, m.toString()) console.log(this.name, m.toString())
reject(m) reject(m)
}) })
// If the connection ends before the login event, toss an error back // If the connection ends before the login event, toss an error back
// to the caller of the function // to the caller of the function
this.bot.on('end', (m)=>{ this.bot.on('end', (reason, ...args)=>{
console.log(this.name, 'Connection ended:', m); console.log(this.name, 'Connection ended:', reason, ...args);
this.isReady = false; this.isReady = false;
reject(m); reject(reason);
}); });
// When the bot is ready, return to the caller success // When the bot is ready, return to the caller success
@ -95,6 +99,10 @@ class CJbot{
}catch(error){ }catch(error){
console.error('minecraft.js | connect | setTimeout |', this.name, ' ', error) console.error('minecraft.js | connect | setTimeout |', this.name, ' ', error)
}}, 30000); }}, 30000);
}catch(error){
reject(error);
}
}); });
} }
@ -119,25 +127,25 @@ class CJbot{
// Call the internal listeners when the bot is ready // Call the internal listeners when the bot is ready
for(let callback of this.listeners.onReady || []){ for(let callback of this.listeners.onReady || []){
console.log('calling listener', callback) console.log('calling listener', callback);
await callback.call(this) await callback.call(this);
} }
this.isReady = true; this.isReady = true;
this.__error() this.__error();
console.log('Bot is ready', this.bot.entity.username, this.username); console.log('Bot is ready', this.bot.entity.username, this.username);
// Start chat listeners // Start chat listeners
this.__listen(); this.__listen();
}catch(error){ }catch(error){
console.error('minecraft.js | __onReady | ', this.name, ' ', error) console.error('minecraft.js | __onReady | ', this.name, ' ', error);
}} }}
__startListeners(){ __startListeners(){
for(let event in this.listeners){ for(let event in this.listeners){
for(let callback of this.listeners[event]){ for(let callback of this.listeners[event]){
this.bot.on(event, callback) this.bot.on(event, callback);
} }
} }
} }
@ -264,7 +272,7 @@ class CJbot{
} }
__chatCoolDown(){ __chatCoolDown(){
return Math.floor(Math.random() * (3000 - 1500) + 1500); return Math.floor(Math.random() * (3000 - 2000) + 2000);
} }
async say(...messages){ async say(...messages){
@ -278,6 +286,16 @@ class CJbot{
} }
} }
async sayAiSafe(...messages){
for(let message of messages){
if(message.startsWith('/') && !(message.startsWith('/msg') || message.startsWith('/help'))){
console.log('bot tried to execute bad command', message);
message = '.'+message;
}
await this.say(message);
}
}
async whisper(to, ...messages){ async whisper(to, ...messages){
await this.say(...messages.map(message=>`/msg ${to} ${message}`)); await this.say(...messages.map(message=>`/msg ${to} ${message}`));
} }
@ -314,9 +332,9 @@ class CJbot{
console.error(`Chat command error on ${cmd} from ${from}\n`, error); console.error(`Chat command error on ${cmd} from ${from}\n`, error);
} }
this.__unLockCommand(); this.__unLockCommand();
}else{ }/*else{
this.whisper(from, `I dont know anything about ${cmd}`); this.whisper(from, `I dont know anything about ${cmd}`);
} }*/
}catch(error){ }catch(error){
console.error('minecraft.js | __doCommand |', this.name, ' ', error) console.error('minecraft.js | __doCommand |', this.name, ' ', error)
}} }}

View File

@ -9,6 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@google/generative-ai": "^0.17.1",
"axios": "^0.27.2", "axios": "^0.27.2",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"extend": "^3.0.2", "extend": "^3.0.2",
@ -45,6 +46,14 @@
"node": "10 || 12 || 14 || 16 || 18" "node": "10 || 12 || 14 || 16 || 18"
} }
}, },
"node_modules/@google/generative-ai": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/@google/generative-ai/-/generative-ai-0.17.1.tgz",
"integrity": "sha512-TgWz02c5l2XJlEDys81UVat5+Qg9xqmYah7tQt6xlsBwFvzIFPz64aZFGd1av2sxT22NsssqLATjNsusAIJICA==",
"engines": {
"node": ">=18.0.0"
}
},
"node_modules/@types/component-emitter": { "node_modules/@types/component-emitter": {
"version": "1.2.11", "version": "1.2.11",
"resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz",

View File

@ -17,6 +17,7 @@
}, },
"homepage": "https://github.com/wmantly/mc-cj-bot#readme", "homepage": "https://github.com/wmantly/mc-cj-bot#readme",
"dependencies": { "dependencies": {
"@google/generative-ai": "^0.17.1",
"axios": "^0.27.2", "axios": "^0.27.2",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"extend": "^3.0.2", "extend": "^3.0.2",