From 5482a5dc7ec70602c8af59cffae77205fda8d9e1 Mon Sep 17 00:00:00 2001 From: MaxRobinsonTheGreat Date: Thu, 10 Oct 2024 17:40:00 -0500 Subject: [PATCH] improved unstuck mode, goal resuming --- src/agent/coder.js | 7 +++++-- src/agent/library/skills.js | 39 +++++++++++++++---------------------- src/agent/modes.js | 28 +++++++++++++++++--------- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/src/agent/coder.js b/src/agent/coder.js index 7067348..d608efb 100644 --- a/src/agent/coder.js +++ b/src/agent/coder.js @@ -102,6 +102,7 @@ export class Coder { if (this.agent.bot.interrupt_code) return interrupt_return; console.log(messages) + this.agent.bot.modes.pause('unstuck'); let res = await this.agent.prompter.promptCoding(JSON.parse(JSON.stringify(messages))); if (this.agent.bot.interrupt_code) return interrupt_return; @@ -132,6 +133,7 @@ export class Coder { agent_history.add('system', 'Failed to stage code, something is wrong.'); return {success: false, message: null, interrupted: false, timedout: false}; } + this.agent.bot.modes.unpause('unstuck'); code_return = await this.execute(async ()=>{ return await execution_file.main(this.agent.bot); }, settings.code_timeout_mins); @@ -158,11 +160,12 @@ export class Coder { } async executeResume(func=null, timeout=10) { - if (func != null) { // start new resume + const new_resume = func != null; + if (new_resume) { // start new resume this.resume_func = func; this.resume_name = this.cur_action_name; } - if (this.resume_func != null && this.agent.isIdle() && !this.agent.self_prompter.on) { + if (this.resume_func != null && this.agent.isIdle() && (!this.agent.self_prompter.on || new_resume)) { this.cur_action_name = this.resume_name; let res = await this.execute(this.resume_func, timeout); this.cur_action_name = ''; diff --git a/src/agent/library/skills.js b/src/agent/library/skills.js index 0782562..a4605d7 100644 --- a/src/agent/library/skills.js +++ b/src/agent/library/skills.js @@ -181,6 +181,7 @@ export async function smeltItem(bot, itemName, num=1) { let total = 0; let collected_last = true; let smelted_item = null; + bot.mods.pause('unstuck'); await new Promise(resolve => setTimeout(resolve, 200)); while (total < num) { await new Promise(resolve => setTimeout(resolve, 10000)); @@ -202,6 +203,7 @@ export async function smeltItem(bot, itemName, num=1) { } } await bot.closeWindow(furnace); + bot.mods.unpause('unstuck'); if (placedFurnace) { await collectBlock(bot, 'furnace', 1); @@ -560,10 +562,14 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont return true; } - let block = bot.inventory.items().find(item => item.name === blockType); + + let item_name = blockType; + if (item_name == "redstone_wire") + item_name = "redstone"; + let block = bot.inventory.items().find(item => item.name === item_name); if (!block && bot.game.gameMode === 'creative') { - await bot.creative.setInventorySlot(36, mc.makeItem(blockType, 1)); // 36 is first hotbar slot - block = bot.inventory.items().find(item => item.name === blockType); + await bot.creative.setInventorySlot(36, mc.makeItem(item_name, 1)); // 36 is first hotbar slot + block = bot.inventory.items().find(item => item.name === item_name); } if (!block) { log(bot, `Don't have any ${blockType} to place.`); @@ -624,7 +630,7 @@ export async function placeBlock(bot, blockType, x, y, z, placeOn='bottom', dont const pos = bot.entity.position; const pos_above = pos.plus(Vec3(0,1,0)); - const dont_move_for = ['torch', 'redstone_torch', 'redstone', 'lever', 'button', 'rail', 'detector_rail', 'powered_rail', 'activator_rail', 'tripwire_hook', 'tripwire', 'water_bucket']; + const dont_move_for = ['torch', 'redstone_torch', 'redstone_wire', 'lever', 'button', 'rail', 'detector_rail', 'powered_rail', 'activator_rail', 'tripwire_hook', 'tripwire', 'water_bucket']; if (!dont_move_for.includes(blockType) && (pos.distanceTo(targetBlock.position) < 1 || pos_above.distanceTo(targetBlock.position) < 1)) { // too close let goal = new pf.goals.GoalNear(targetBlock.position.x, targetBlock.position.y, targetBlock.position.z, 2); @@ -964,33 +970,19 @@ export async function followPlayer(bot, username, distance=4) { bot.pathfinder.setGoal(new pf.goals.GoalFollow(player, distance), true); log(bot, `You are now actively following player ${username}.`); - let last_time = Date.now(); - let stuck_time = 0; - let last_pos = bot.entity.position.clone(); while (!bot.interrupt_code) { await new Promise(resolve => setTimeout(resolve, 500)); - const delta = Date.now() - last_time; // in cheat mode, if the distance is too far, teleport to the player if (bot.modes.isOn('cheat') && bot.entity.position.distanceTo(player.position) > 100 && player.isOnGround) { await goToPlayer(bot, username); } if (bot.modes.isOn('unstuck')) { - const far_away = bot.entity.position.distanceTo(player.position) > distance + 1; - if (far_away && bot.entity.position.distanceTo(last_pos) <= 2) { - stuck_time += delta; - if (stuck_time > 10000) { - log(bot, `Got stuck, attempting to move away.`); - bot.pathfinder.stop(); - await moveAway(bot, 4); - return false; - } - } - else { - stuck_time = 0; - last_pos = bot.entity.position.clone(); - } + const is_nearby = bot.entity.position.distanceTo(player.position) <= distance + 1; + if (is_nearby) + bot.modes.pause('unstuck'); + else + bot.modes.unpause('unstuck'); } - last_time = Date.now(); } return true; } @@ -1066,6 +1058,7 @@ export async function stay(bot) { * await skills.stay(bot); **/ bot.modes.pause('self_preservation'); + bot.modes.pause('unstuck'); bot.modes.pause('cowardice'); bot.modes.pause('self_defense'); bot.modes.pause('hunting'); diff --git a/src/agent/modes.js b/src/agent/modes.js index 8d7c4ed..c5e1c33 100644 --- a/src/agent/modes.js +++ b/src/agent/modes.js @@ -77,7 +77,7 @@ const modes = [ { name: 'unstuck', description: 'Attempt to get unstuck when in the same place for a while. Interrupts some actions.', - interrupts: ['collectBlocks', 'goToPlayer', 'collectAllBlocks', 'goToPlace'], + interrupts: ['all'], on: true, active: false, prev_location: null, @@ -86,7 +86,11 @@ const modes = [ last_time: Date.now(), max_stuck_time: 20, update: async function (agent) { - if (agent.isIdle()) return; + if (agent.isIdle()) { + this.prev_location = null; + this.stuck_time = 0; + return; // don't get stuck when idle + } const bot = agent.bot; if (this.prev_location && this.prev_location.distanceTo(bot.entity.position) < this.distance) { this.stuck_time += (Date.now() - this.last_time) / 1000; @@ -98,7 +102,9 @@ const modes = [ if (this.stuck_time > this.max_stuck_time) { say(agent, 'I\'m stuck!'); execute(this, agent, async () => { + const crashTimeout = setTimeout(() => { throw new Error('Bot was stuck and could not get unstuck.'); }, 10000); await skills.moveAway(bot, 5); + clearTimeout(crashTimeout); }); } this.last_time = Date.now(); @@ -287,6 +293,17 @@ class ModeController { this.modes_map[mode_name].paused = true; } + unpause(mode_name) { + this.modes_map[mode_name].paused = false; + } + + unPauseAll() { + for (let mode of this.modes_list) { + if (mode.paused) console.log(`Unpausing mode ${mode.name}`); + mode.paused = false; + } + } + getMiniDocs() { // no descriptions let res = 'Agent Modes:'; for (let mode of this.modes_list) { @@ -305,13 +322,6 @@ class ModeController { return res; } - unPauseAll() { - for (let mode of this.modes_list) { - if (mode.paused) console.log(`Unpausing mode ${mode.name}`); - mode.paused = false; - } - } - async update() { if (this.agent.isIdle()) { this.unPauseAll();