mirror of
https://github.com/kolbytn/mindcraft.git
synced 2025-09-10 03:53:07 +02:00
commit
906c7c32ad
7 changed files with 70 additions and 67 deletions
|
@ -3,6 +3,7 @@ import { writeFile, readFile, unlink } from 'fs';
|
|||
export class Coder {
|
||||
constructor(agent) {
|
||||
this.agent = agent;
|
||||
this.queued_code = '';
|
||||
this.current_code = '';
|
||||
this.file_counter = 0;
|
||||
this.fp = './agent_code/';
|
||||
|
@ -19,7 +20,7 @@ export class Coder {
|
|||
}
|
||||
|
||||
queueCode(code) {
|
||||
this.current_code = this.santitizeCode(code);
|
||||
this.queued_code = this.santitizeCode(code);
|
||||
}
|
||||
|
||||
santitizeCode(code) {
|
||||
|
@ -30,15 +31,9 @@ export class Coder {
|
|||
return code;
|
||||
}
|
||||
}
|
||||
// this may cause problems in callback functions
|
||||
code = code.replaceAll(';\n', '; if(bot.interrupt_code) {log(bot, "Code interrupted.");return;}\n');
|
||||
return code;
|
||||
}
|
||||
|
||||
hasCode() {
|
||||
return this.current_code.length > 0;
|
||||
}
|
||||
|
||||
writeFilePromise(filename, src) {
|
||||
// makes it so we can await this function
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -55,10 +50,12 @@ export class Coder {
|
|||
|
||||
// returns {success: bool, message: string, interrupted: bool}
|
||||
async execute() {
|
||||
if (!this.current_code) return {success: false, message: "No code to execute.", interrupted: false};
|
||||
if (!this.queued_code) return {success: false, message: "No code to execute.", interrupted: false};
|
||||
if (!this.code_template) return {success: false, message: "Code template not loaded.", interrupted: false};
|
||||
let src = '';
|
||||
for (let line of this.current_code.split('\n')) {
|
||||
// this may cause problems in callback functions
|
||||
let code = this.queued_code.replaceAll(';\n', '; if(bot.interrupt_code) {log(bot, "Code interrupted.");return;}\n');
|
||||
for (let line of code.split('\n')) {
|
||||
src += ` ${line}\n`;
|
||||
}
|
||||
src = this.code_template.replace('/* CODE HERE */', src);
|
||||
|
@ -86,7 +83,8 @@ export class Coder {
|
|||
console.log('executing code...\n');
|
||||
let execution_file = await import('.'+filename);
|
||||
await this.stop();
|
||||
|
||||
this.current_code = this.queued_code;
|
||||
|
||||
this.executing = true;
|
||||
await execution_file.main(this.agent.bot);
|
||||
this.executing = false;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { readFileSync } from 'fs';
|
||||
|
||||
import { getCraftingTable, getNearbyMobTypes, getNearbyPlayerNames, getNearbyBlockTypes, getInventoryCounts } from './world.js';
|
||||
import { getNearestBlock, getNearbyMobTypes, getNearbyPlayerNames, getNearbyBlockTypes, getInventoryCounts } from './world.js';
|
||||
import { getAllItems } from './mcdata.js';
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ export function getInventory(bot) {
|
|||
let inventory = getInventoryCounts(bot);
|
||||
let res = 'INVENTORY';
|
||||
for (const item in inventory) {
|
||||
if (inventory[item] > 0)
|
||||
if (inventory[item] && inventory[item] > 0)
|
||||
res += `\n- ${item}: ${inventory[item]}`;
|
||||
}
|
||||
if (res == 'INVENTORY') {
|
||||
|
@ -62,7 +62,7 @@ export function getNearbyEntities(bot) {
|
|||
|
||||
|
||||
export function getCraftable(bot) {
|
||||
const table = getCraftingTable(bot);
|
||||
const table = getNearestBlock(bot, 'crafting_table');
|
||||
let res = 'CRAFTABLE_ITEMS';
|
||||
for (const item of getAllItems()) {
|
||||
let recipes = bot.recipesFor(item.id, null, 1, table);
|
||||
|
|
|
@ -25,11 +25,6 @@
|
|||
{"role": "assistant", "content": "Here!"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "user", "content": "sarah_O.o: can you fly up in the air?"},
|
||||
{"role": "assistant", "content": "I can't do that."}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "user", "content": "joe: Follow me!"},
|
||||
{"role": "assistant", "content": "Sure!\n```\n// I am going to follow joe.\nawait skills.followPlayer(bot, 'joe');\n```"}
|
||||
|
@ -45,5 +40,12 @@
|
|||
[
|
||||
{"role": "user", "content": "billybob: stop"},
|
||||
{"role": "assistant", "content": "```\n// I am going to write empty code to stop whatever I am doing\n```"}
|
||||
],
|
||||
|
||||
[
|
||||
{"role": "user", "content": "maya: go to the nearest oak log"},
|
||||
{"role": "assistant", "content": "```\n// I am navigating to the nearest oak log.\nawait skills.goToPosition(bot, nearestOakLog.x, nearestOakLog.y, nearestOakLog.z);\n```"},
|
||||
{"role": "system", "content": "Code output:\n!!Code threw exception!! Error: ReferenceError: nearestOakLog is not defined\n Write code to fix the problem and try again."},
|
||||
{"role": "assistant", "content": "Apologies, I made an error. Let me try that again.```\n// I am navigating to the nearest oak log.\nlet position = world.getNearestBlock(bot, 'oak_log', 20);\nawait skills.goToPosition(bot, position.x, position.y, position.z);\n```"}
|
||||
]
|
||||
]
|
|
@ -63,7 +63,7 @@ export class History {
|
|||
if (this.memory != '') {
|
||||
memory_prompt += ' Include information from your previous memory if it is still relevant. Your output will replace your previous memory.';
|
||||
}
|
||||
memory_prompt += ' Your output should use one of the following formats:\n';
|
||||
memory_prompt += ' Your output should be a brief list of things you have learned using the following formats:\n';
|
||||
memory_prompt += '- When the player... output...\n';
|
||||
memory_prompt += '- I learned that player [name]...\n';
|
||||
|
||||
|
@ -85,7 +85,7 @@ export class History {
|
|||
for (let example of examples) {
|
||||
let messages = '';
|
||||
for (let turn of example) {
|
||||
if (turn.role == 'user')
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
|
@ -97,7 +97,7 @@ export class History {
|
|||
async setExamples() {
|
||||
let messages = '';
|
||||
for (let turn of this.turns) {
|
||||
if (turn.role == 'user')
|
||||
if (turn.role != 'assistant')
|
||||
messages += turn.content.substring(turn.content.indexOf(':')+1).trim() + '\n';
|
||||
}
|
||||
messages = messages.trim();
|
||||
|
|
|
@ -23,6 +23,9 @@ export function getItemId(item) {
|
|||
return mcdata.itemsByName[item].id;
|
||||
}
|
||||
|
||||
export function getItemName(itemId) {
|
||||
return mcdata.items[itemId].name;
|
||||
}
|
||||
|
||||
export function getAllItems(ignore) {
|
||||
if (!ignore) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { getItemId } from "./mcdata.js";
|
||||
import { getCraftingTable, getInventoryCounts, getInventoryStacks, getNearbyMobs, getNearbyBlocks } from "./world.js";
|
||||
import { getNearestBlock, getInventoryCounts, getInventoryStacks, getNearbyMobs, getNearbyBlocks } from "./world.js";
|
||||
import pf from 'mineflayer-pathfinder';
|
||||
import Vec3 from 'vec3';
|
||||
|
||||
|
@ -8,18 +8,36 @@ export function log(bot, message) {
|
|||
}
|
||||
|
||||
|
||||
export async function craftItem(bot, itemName) {
|
||||
export async function craftItem(bot, itemName, num=1) {
|
||||
/**
|
||||
* Attempt to craft the given item.
|
||||
* @param {MinecraftBot} bot, reference to the minecraft bot.
|
||||
* @param {string} item_name, the item name to craft.
|
||||
* @param {number} num, the number of items to craft. Defaults to 1.
|
||||
* @returns {Promise<boolean>} true if the item was crafted, false otherwise.
|
||||
* @example
|
||||
* await skills.craftItem(bot, "wooden_pickaxe");
|
||||
* await skills.craftItem(bot, "wooden_pickaxe", 2);
|
||||
**/
|
||||
const table = getCraftingTable(bot);
|
||||
let recipes = bot.recipesFor(getItemId(itemName), null, 1, table);
|
||||
await bot.craft(recipes[0], 1, null);
|
||||
|
||||
let recipes = bot.recipesFor(getItemId(itemName), null, num, null); // get recipes that don't require a crafting table
|
||||
let craftingTable = undefined;
|
||||
if (!recipes || recipes.length === 0) {
|
||||
craftingTable = getNearestBlock(bot, 'crafting_table', 6);
|
||||
if (craftingTable === null){
|
||||
log(bot, `You either do not have enough resources to craft ${itemName} or it requires a crafting table, but there is none nearby.`)
|
||||
return false;
|
||||
}
|
||||
recipes = bot.recipesFor(getItemId(itemName), null, num, craftingTable);
|
||||
}
|
||||
if (!recipes || recipes.length === 0) {
|
||||
log(bot, `You do not have the resources to craft ${num} ${itemName}(s).`);
|
||||
return false;
|
||||
}
|
||||
const recipe = recipes[0];
|
||||
|
||||
console.log('crafting...');
|
||||
await bot.craft(recipe, num, craftingTable);
|
||||
console.log('crafted');
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -216,7 +234,7 @@ export async function giveToPlayer(bot, itemType, username) {
|
|||
let player = bot.players[username].entity
|
||||
if (!player)
|
||||
return false;
|
||||
if (getInventoryCounts(bot)[itemType] == 0)
|
||||
if (!getInventoryCounts(bot)[itemType])
|
||||
return false;
|
||||
await goToPlayer(bot, username);
|
||||
let pos = player.position;
|
||||
|
|
|
@ -1,16 +1,27 @@
|
|||
import { getAllBlockIds, getAllBlocks, getAllItems } from './mcdata.js';
|
||||
import { getAllBlockIds } from './mcdata.js';
|
||||
|
||||
|
||||
export function getCraftingTable(bot) {
|
||||
const blocks = getNearbyBlocks(bot, 50);
|
||||
let table = null;
|
||||
for (const block of blocks) {
|
||||
if (block.name == 'crafting_table') {
|
||||
table = block;
|
||||
break;
|
||||
}
|
||||
export function getNearestBlock(bot, block_type, distance=16) {
|
||||
/**
|
||||
* Get the position of the nearest block of the given type.
|
||||
* @param {Bot} bot - The bot to get the nearest block for.
|
||||
* @param {string} block_type - The name of the block to search for.
|
||||
* @param {number} distance - The maximum distance to search, default 16.
|
||||
* @returns {Block} - The nearest block of the given type.
|
||||
* @example
|
||||
* let coalBlock = world.getNearestBlock(bot, 'coal_ore', 16);
|
||||
**/
|
||||
let block_locs = bot.findBlocks({
|
||||
matching: (block) => {
|
||||
return block && block.type === bot.registry.blocksByName[block_type].id
|
||||
},
|
||||
maxDistance: distance,
|
||||
count: 1
|
||||
});
|
||||
if (block_locs.length > 0) {
|
||||
return bot.blockAt(block_locs[0]);
|
||||
}
|
||||
return table;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,16 +110,6 @@ export function getInventoryCounts(bot) {
|
|||
inventory[item.name] = item.count;
|
||||
}
|
||||
}
|
||||
for (const item of getAllItems()) {
|
||||
if (!inventory.hasOwnProperty(item.name)) {
|
||||
inventory[item.name] = 0;
|
||||
}
|
||||
}
|
||||
for (const item of getAllBlocks()) {
|
||||
if (!inventory.hasOwnProperty(item.name)) {
|
||||
inventory[item.name] = 0;
|
||||
}
|
||||
}
|
||||
return inventory;
|
||||
}
|
||||
|
||||
|
@ -181,22 +182,3 @@ export function getNearbyBlockTypes(bot) {
|
|||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
|
||||
export function getNearestBlockPosition(bot, blockType) {
|
||||
/**
|
||||
* Get the position of the nearest block of the given type.
|
||||
* @param {Bot} bot - The bot to get the nearest block for.
|
||||
* @param {string} blockType - The type of the block to search for.
|
||||
* @returns {Vec3} - The position of the nearest block of the given type if found else null.
|
||||
* @example
|
||||
* let position = world.getNearestBlockPosition(bot, 'coal_ore');
|
||||
**/
|
||||
let blocks = getNearbyBlocks(bot, 16);
|
||||
for (let i = 0; i < blocks.length; i++) {
|
||||
if (blocks[i].name == blockType) {
|
||||
return blocks[i].position;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue