From 8a40ff03c4cc4c9791e121d58a94ec674f03cc4e Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Wed, 24 Jan 2024 17:24:52 -0600 Subject: [PATCH] fixed multiplayer chat, misc fixes --- src/agent/agent.js | 25 +++++++++++++++++++------ src/agent/commands/actions.js | 2 +- src/agent/commands/queries.js | 7 ++++++- src/agent/modes.js | 2 ++ src/agent/skills.js | 7 +++++-- 5 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/agent/agent.js b/src/agent/agent.js index 3c4f7b6..730d584 100644 --- a/src/agent/agent.js +++ b/src/agent/agent.js @@ -67,6 +67,12 @@ export class Agent { }); } + cleanChat(message) { + // newlines are interpreted as separate chats, which triggers spam filters. replace them with spaces + message = message.replaceAll('\n', ' '); + return this.bot.chat(message); + } + async handleMessage(source, message) { if (!!source && !!message) await this.history.add(source, message); @@ -81,8 +87,8 @@ export class Agent { let truncated_msg = message.substring(0, message.indexOf(user_command_name)).trim(); this.history.add(source, truncated_msg); } - if (execute_res) - this.bot.chat(execute_res); + if (execute_res) + this.cleanChat(execute_res); return; } @@ -103,7 +109,7 @@ export class Agent { let pre_message = res.substring(0, res.indexOf(command_name)).trim(); - this.bot.chat(`${pre_message} *used ${command_name.substring(1)}*`); + this.cleanChat(`${pre_message} *used ${command_name.substring(1)}*`); let execute_res = await executeCommand(this, res); console.log('Agent executed:', command_name, 'and got:', execute_res); @@ -114,7 +120,7 @@ export class Agent { break; } else { // conversation response - this.bot.chat(res); + this.cleanChat(res); console.log('Purely conversational response:', res); break; } @@ -125,13 +131,20 @@ export class Agent { } startUpdateLoop() { - this.bot.on('end', () => { - console.warn('Bot disconnected! Killing agent process.') + this.bot.on('error' , (err) => { + console.error('Error event!', err); + }); + this.bot.on('end', (reason) => { + console.warn('Bot disconnected! Killing agent process.', reason) process.exit(1); }); this.bot.on('death', () => { this.coder.stop(); }); + this.bot.on('kicked', (reason) => { + console.warn('Bot kicked!', reason); + process.exit(1); + }); this.bot.on('messagestr', async (message, _, jsonMsg) => { if (jsonMsg.translate && jsonMsg.translate.startsWith('death') && message.startsWith(this.name)) { console.log('Agent died: ', message); diff --git a/src/agent/commands/actions.js b/src/agent/commands/actions.js index b2d4297..236a3db 100644 --- a/src/agent/commands/actions.js +++ b/src/agent/commands/actions.js @@ -107,7 +107,7 @@ export const actionsList = [ description: 'Attack and kill the nearest entity of a given type.', params: {'type': '(string) The type of entity to attack.'}, perform: wrapExecution(async (agent, type) => { - await skills.attackMob(agent.bot, type, true); + await skills.attackNearest(agent.bot, type, true); }) }, { diff --git a/src/agent/commands/queries.js b/src/agent/commands/queries.js index 4f84ac4..495603e 100644 --- a/src/agent/commands/queries.js +++ b/src/agent/commands/queries.js @@ -19,7 +19,12 @@ export const queryList = [ res += `\n- Health: ${Math.round(bot.health)} / 20`; res += `\n- Hunger: ${Math.round(bot.food)} / 20`; res += `\n- Biome: ${getBiomeName(bot)}`; - res += `\n- Weather: ${bot.weather}`; + let weather = "clear"; + if (bot.rainState > 0) + weather = "Rain"; + if (bot.thunderState > 0) + weather = "Thunderstorm"; + res += `\n- Weather: ${weather}`; // let block = bot.blockAt(pos); // res += `\n- Artficial light: ${block.skyLight}`; // res += `\n- Sky light: ${block.light}`; diff --git a/src/agent/modes.js b/src/agent/modes.js index a1a642f..a2ac1a2 100644 --- a/src/agent/modes.js +++ b/src/agent/modes.js @@ -53,6 +53,8 @@ const modes = [ let item = world.getNearestEntityWhere(agent.bot, entity => entity.name === 'item', 8); if (item) { execute(this, agent, async () => { + // wait 2 seconds for the item to settle + await new Promise(resolve => setTimeout(resolve, 2000)); await skills.pickupNearbyItem(agent.bot); }); } diff --git a/src/agent/skills.js b/src/agent/skills.js index 81de507..af9e96b 100644 --- a/src/agent/skills.js +++ b/src/agent/skills.js @@ -186,7 +186,7 @@ export async function attackNearest(bot, mobType, kill=true) { * @param {boolean} kill, whether or not to continue attacking until the mob is dead. Defaults to true. * @returns {Promise} true if the mob was attacked, false if the mob type was not found. * @example - * await skills.attackMob(bot, "zombie", true); + * await skills.attackNearest(bot, "zombie", true); **/ const mob = bot.nearestEntity(entity => entity.name && entity.name.toLowerCase() === mobType.toLowerCase()); if (mob) { @@ -248,7 +248,7 @@ export async function defendSelf(bot, range=8) { let enemy = getNearestEntityWhere(bot, entity => isHostile(entity), range); while (enemy) { equipHighestAttack(bot); - if (bot.entity.position.distanceTo(enemy.position) > 4 && enemy.name !== 'creeper') { + if (bot.entity.position.distanceTo(enemy.position) > 4 && enemy.name !== 'creeper' && enemy.name !== 'phantom') { try { bot.pathfinder.setMovements(new pf.Movements(bot)); await bot.pathfinder.goto(new pf.goals.GoalFollow(enemy, 2), true); @@ -263,6 +263,7 @@ export async function defendSelf(bot, range=8) { return false; } } + bot.pvp.stop(); if (attacked) log(bot, `Successfully defended self.`); else @@ -678,12 +679,14 @@ export async function goToBed(bot) { export function isHuntable(mob) { + if (!mob || !mob.name) return false; const animals = ['chicken', 'cod', 'cow', 'llama', 'mooshroom', 'pig', 'pufferfish', 'rabbit', 'salmon', 'sheep', 'squid', 'tropical_fish', 'turtle']; return animals.includes(mob.name.toLowerCase()) && !mob.metadata[16]; // metadata 16 is not baby } export function isHostile(mob) { + if (!mob || !mob.name) return false; return (mob.type === 'mob' || mob.type === 'hostile') && mob.name !== 'iron_golem' && mob.name !== 'snow_golem'; }