no code return, placeblock more reliable

This commit is contained in:
MaxRobinsonTheGreat 2023-11-12 23:19:58 -06:00
parent fed5a6d887
commit 54aa62de88
4 changed files with 69 additions and 70 deletions

View file

@ -2,7 +2,9 @@ import * as skills from '../utils/skills.js';
import * as world from '../utils/world.js';
import Vec3 from 'vec3';
const log = skills.log;
export async function main(bot) {
/* CODE HERE */
return true; // potentially redundant return statement, in case agent doesn't return anything
log(bot, 'Code finished.');
}

View file

@ -80,17 +80,19 @@ export class Coder {
console.log('executing code...\n');
let execution_file = await import('.'+filename);
this.stop();
let success = await execution_file.main(this.agent.bot);
console.log('code execution finished.', success)
let output = this.agent.bot.output ? 'Code output: \n' + this.agent.bot.output : '';
// if there is output, add it to the message
if (success)
output += 'Code execution finished successfully.';
else
output += 'Code execution failed!';
console.log(output)
await execution_file.main(this.agent.bot);
let output = this.agent.bot.output;
const MAX_OUT = 1000;
if (output.length > MAX_OUT) {
// get the first and last part of the output and combine them with a message in between that says the output was truncated
output = `Code output is very long (${output.length} chars) and has been shortened.\n
First outputs:\n${output.substring(0, MAX_OUT/2)}\n...skipping many lines.\nFinal outputs:\n ${output.substring(output.length - MAX_OUT/2)}`;
}
else {
output = 'Code output:\n' + output;
}
this.clear();
return {success, message: output};
return {success:true, message: output};
} catch (err) {
console.error("Code execution triggered catch:" + err);
let message = 'Code output: \n' + this.agent.bot.output + '\n';

View file

@ -8,13 +8,13 @@ let history_examples = [
{'role': 'assistant', 'content': 'I see some oak logs, dirt, and cobblestone.'},
{'role': 'user', 'content': 'zZZn98: come here'},
{'role': 'assistant', 'content': '```// I am going to navigate to zZZn98.\nreturn await skills.goToPlayer(bot, "zZZn98");```'},
{'role': 'assistant', 'content': '```// I am going to navigate to zZZn98.\nawait skills.goToPlayer(bot, "zZZn98");```'},
{'role': 'system', 'content': 'Code execution finished successfully.'},
{'role': 'assistant', 'content': 'Here!'},
{'role': 'user', 'content': 'hanky: collect some sand for me please'},
{'role': 'assistant', 'content': 'Collecting sand...```// I am going to collect 3 sand and give to hanky.\n\
await skills.collectBlock(bot, "sand");\nreturn await skills.giveToPlayer(bot, "sand", "hanky");```'},
await skills.collectBlock(bot, "sand");\nawait skills.giveToPlayer(bot, "sand", "hanky");```'},
{'role': 'system', 'content': 'Code Output:\nYou have reached player hanky.\nCode execution finished successfully.'},
{'role': 'assistant', 'content': 'Here!'},
@ -23,12 +23,12 @@ let history_examples = [
{'role': 'user', 'content': 'hanky: kill that zombie!'},
{'role': 'assistant', 'content': "I'm attacking! ```//I'm going to attack the nearest zombie.\n\
return await skills.attackMob(bot, 'zombie');```"},
await skills.attackMob(bot, 'zombie');```"},
{'role': 'system', 'content': 'Code Output:\nNo zombie nearby\nCode execution failed!'},
{'role': 'assistant', 'content': 'I could not find a zombie nearby.'},
{'role': 'user', 'content': 'billybob: stop what you are doing'},
{'role': 'assistant', 'content': '```// I am going to write nothing to clear my code\n return true;```'},
{'role': 'assistant', 'content': '```// I am going to write nothing to clear my code\n```'},
]

View file

@ -3,13 +3,10 @@ import { getCraftingTable, getInventoryCounts, getInventoryStacks, getNearbyMobs
import pf from 'mineflayer-pathfinder';
import Vec3 from 'vec3';
function log(bot, message) {
export function log(bot, message) {
bot.output += message + '\n';
}
function f(x) {
return Math.floor(x);
}
export async function craftItem(bot, itemName) {
/**
@ -86,48 +83,53 @@ export async function breakBlockAt(bot, x, y, z) {
}
export async function placeBlock(bot, blockType, x, y, z, faceVec=new Vec3(0, 1, 0)) {
export async function placeBlock(bot, blockType, x, y, z) {
/**
* Place the given block type at the given position.
* Place the given block type at the given position. It will build off from any adjacent blocks. Will fail if there is a block in the way or nothing to build off of.
* @param {MinecraftBot} bot, reference to the minecraft bot.
* @param {string} blockType, the type of block to place.
* @param {number} x, the x coordinate of the block to place.
* @param {number} y, the y coordinate of the block to place.
* @param {number} z, the z coordinate of the block to place.
* @param {Vec3} faceVec, the face of the block to place against. Defaults to the top face.
* @returns {Promise<boolean>} true if the block was placed, false otherwise.
* @example
* let position = world.getPosition(bot);
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y, position.x, new Vec3(1, 0, 0));
* await skills.placeBlock(bot, "oak_log", position.x + 1, position.y - 1, position.x);
**/
// top face: new Vec3(0, 1, 0)
// bottom face: new Vec3(0, -1, 0)
// north face: new Vec3(0, 0, -1)
// south face: new Vec3(0, 0, 1)
// east face: new Vec3(1, 0, 0)
// west face: new Vec3(-1, 0, 0)
let referenceBlock = bot.blockAt(new Vec3(x, y, z));
console.log("reference block", referenceBlock.name)
// check if bot is blocking the block to place
// if (bot.entity.position.distanceTo(referenceBlock.position) < 2) {
// console.log("bot is blocking block to place")
// // move out of the way
// let pos = bot.entity.position;
// let dx = pos.x - referenceBlock.position.x;
// let dz = pos.z - referenceBlock.position.z;
// let moveVec = new Vec3(dx, 0, dz);
// await bot.pathfinder.setMovements(new pf.Movements(bot));
// bot.pathfinder.setGoal(new pf.goals.GoalBlock(referenceBlock.position.x + moveVec.x, referenceBlock.position.y, referenceBlock.position.z + moveVec.z));
// }
// all blocks that can be replaced by another block:
let blocks_to_allow = ['air', 'water', 'lava', 'grass', 'tall_grass'];
if (!blocks_to_allow.includes(referenceBlock.name)) {
log(bot, `Block at ${f(x)}, ${f(y)}, ${f(z)} is ${referenceBlock.name} and cannot be replaced.`);
const empty_blocks = ['air', 'water', 'lava'];
const targetBlock = bot.blockAt(new Vec3(x, y, z));
if (!empty_blocks.includes(targetBlock.name)) {
log(bot, `Cannot place block at ${targetBlock.position} because ${targetBlock.name} is in the way.`);
return false;
}
// get the buildoffblock and facevec based on whichever adjacent block is not empty
let buildOffBlock = null;
let faceVec = null;
const dirs = [Vec3(0, -1, 0), Vec3(0, 1, 0), Vec3(1, 0, 0), Vec3(-1, 0, 0), Vec3(0, 0, 1), Vec3(0, 0, -1)];
for (let d of dirs) {
const block = bot.blockAt(new Vec3(x, y, z).plus(d));
if (!empty_blocks.includes(block.name)) {
buildOffBlock = block;
faceVec = new Vec3(-d.x, -d.y, -d.z);
break;
}
}
if (!buildOffBlock) {
log(bot, `Cannot place block at ${targetBlock.position} because there is nothing to build off of.`);
return false;
}
console.log("buildOffBlock: ", buildOffBlock.position, buildOffBlock.name, "faceVec: ", faceVec)
// check if bot is in the way
console.log("bot position: ", bot.entity.position, "buildOffBlock.position: ", buildOffBlock.position.plus(faceVec), "distance: ", bot.entity.position.distanceTo(buildOffBlock.position.plus(faceVec)))
if (bot.entity.position.distanceTo(buildOffBlock.position.plus(faceVec)) < 0.5) {
log(bot, `Cannot place block at ${buildOffBlock.position} because you are in the way.`);
return false;
}
console.log("Placing on: ", buildOffBlock.position, buildOffBlock.name)
let block = bot.inventory.items().find(item => item.name === blockType);
if (!block) {
log(bot, `Don't have any ${blockType} to place.`);
@ -135,24 +137,21 @@ export async function placeBlock(bot, blockType, x, y, z, faceVec=new Vec3(0, 1,
}
await bot.equip(block, 'hand');
// placeblock's callback is broken (always returns error)
bot.placeBlock(referenceBlock, faceVec).catch(err => {});
// can still throw error if blocked by a bot player or mob, but takes a long time to timeout
bot.placeBlock(buildOffBlock, faceVec).catch(err => {console.log('placeBlock threw error, ignoring')});
console.log("placing block...")
// await to check if block was actually placed
return await new Promise((resolve) => {
setTimeout(() => {
let current = bot.blockAt(new Vec3(x, y, z));
console.log("Checking current block", current.name);
if (current.name !== blockType) {
console.log('Failed to place block')
log(bot, `Failed to place block ${blockType} at ${f(x)}, ${f(y)}, ${f(z)}, which is ${current.name}.`);
resolve(false);
} else {
console.log('Successfully placed block')
resolve(true);
}
}, 1000);
});
// wait and then check if the block was placed
await new Promise(resolve => setTimeout(resolve, 500));
const newBlock = bot.blockAt(buildOffBlock.position.plus(faceVec));
if (!newBlock) return false;
if (newBlock.name !== blockType) {
log(bot, `Failed to place ${blockType} at ${newBlock.position}.`);
return false;
}
console.log('block placed')
log(bot, `Successfully placed ${blockType} at ${newBlock.position}.`);
return true;
}
@ -241,11 +240,7 @@ export async function goToPlayer(bot, username) {
let pos = player.position;
let distance = 2;
await bot.pathfinder.goto(new pf.goals.GoalNear(pos.x, pos.y, pos.z, distance));
if (bot.entity.position.distanceTo(pos) > distance+1) {
log(bot, `Failed to reach player ${username} (${bot.entity.position.distanceTo(pos)}m away)`);
return false;
}
log(bot, `You have reached player ${username}.`);
log(bot, `You have reached your destination.`);
return true;
}