From c43043fcc6358f34d84be6587c238be90e877c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=91=E5=8A=B2=E5=AE=87?= <137690584+isaacJinyu@users.noreply.github.com> Date: Wed, 27 Sep 2023 02:09:46 +0800 Subject: [PATCH] Add files via upload --- .../control_primitives_context/craftItem.js | 14 ++++++++ .../exploreUntil.js | 31 ++++++++++++++++ .../control_primitives_context/killMob.js | 12 +++++++ .../control_primitives_context/mineBlock.js | 15 ++++++++ .../control_primitives_context/mineflayer.js | 22 ++++++++++++ .../control_primitives_context/placeItem.js | 28 +++++++++++++++ .../control_primitives_context/smeltItem.js | 22 ++++++++++++ .../control_primitives_context/useChest.js | 35 +++++++++++++++++++ 8 files changed, 179 insertions(+) create mode 100644 metagpt/actions/minecraft/control_primitives_context/craftItem.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/exploreUntil.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/killMob.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/mineBlock.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/mineflayer.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/placeItem.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/smeltItem.js create mode 100644 metagpt/actions/minecraft/control_primitives_context/useChest.js diff --git a/metagpt/actions/minecraft/control_primitives_context/craftItem.js b/metagpt/actions/minecraft/control_primitives_context/craftItem.js new file mode 100644 index 000000000..806811d46 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/craftItem.js @@ -0,0 +1,14 @@ +// Craft 8 oak_planks from 2 oak_log (do the recipe 2 times): craftItem(bot, "oak_planks", 2); +// You must place a crafting table before calling this function +async function craftItem(bot, name, count = 1) { + const item = mcData.itemsByName[name]; + const craftingTable = bot.findBlock({ + matching: mcData.blocksByName.crafting_table.id, + maxDistance: 32, + }); + await bot.pathfinder.goto( + new GoalLookAtBlock(craftingTable.position, bot.world) + ); + const recipe = bot.recipesFor(item.id, null, 1, craftingTable)[0]; + await bot.craft(recipe, count, craftingTable); +} diff --git a/metagpt/actions/minecraft/control_primitives_context/exploreUntil.js b/metagpt/actions/minecraft/control_primitives_context/exploreUntil.js new file mode 100644 index 000000000..55c62a453 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/exploreUntil.js @@ -0,0 +1,31 @@ +/* +Explore until find an iron_ore, use Vec3(0, -1, 0) because iron ores are usually underground +await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => { + const iron_ore = bot.findBlock({ + matching: mcData.blocksByName["iron_ore"].id, + maxDistance: 32, + }); + return iron_ore; +}); + +Explore until find a pig, use Vec3(1, 0, 1) because pigs are usually on the surface +let pig = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => { + const pig = bot.nearestEntity((entity) => { + return ( + entity.name === "pig" && + entity.position.distanceTo(bot.entity.position) < 32 + ); + }); + return pig; +}); +*/ +async function exploreUntil(bot, direction, maxTime = 60, callback) { + /* + Implementation of this function is omitted. + direction: Vec3, can only contain value of -1, 0 or 1 + maxTime: number, the max time for exploration + callback: function, early stop condition, will be called each second, exploration will stop if return value is not null + + Return: null if explore timeout, otherwise return the return value of callback + */ +} diff --git a/metagpt/actions/minecraft/control_primitives_context/killMob.js b/metagpt/actions/minecraft/control_primitives_context/killMob.js new file mode 100644 index 000000000..670ca9753 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/killMob.js @@ -0,0 +1,12 @@ +// Kill a pig and collect the dropped item: killMob(bot, "pig", 300); +async function killMob(bot, mobName, timeout = 300) { + const entity = bot.nearestEntity( + (entity) => + entity.name === mobName && + entity.position.distanceTo(bot.entity.position) < 32 + ); + await bot.pvp.attack(entity); + await bot.pathfinder.goto( + new GoalBlock(entity.position.x, entity.position.y, entity.position.z) + ); +} diff --git a/metagpt/actions/minecraft/control_primitives_context/mineBlock.js b/metagpt/actions/minecraft/control_primitives_context/mineBlock.js new file mode 100644 index 000000000..c6a7559e6 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/mineBlock.js @@ -0,0 +1,15 @@ +// Mine 3 cobblestone: mineBlock(bot, "stone", 3); +async function mineBlock(bot, name, count = 1) { + const blocks = bot.findBlocks({ + matching: (block) => { + return block.name === name; + }, + maxDistance: 32, + count: count, + }); + const targets = []; + for (let i = 0; i < Math.min(blocks.length, count); i++) { + targets.push(bot.blockAt(blocks[i])); + } + await bot.collectBlock.collect(targets, { ignoreNoPath: true }); +} diff --git a/metagpt/actions/minecraft/control_primitives_context/mineflayer.js b/metagpt/actions/minecraft/control_primitives_context/mineflayer.js new file mode 100644 index 000000000..43217885c --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/mineflayer.js @@ -0,0 +1,22 @@ +await bot.pathfinder.goto(goal); // A very useful function. This function may change your main-hand equipment. +// Following are some Goals you can use: +new GoalNear(x, y, z, range); // Move the bot to a block within the specified range of the specified block. `x`, `y`, `z`, and `range` are `number` +new GoalXZ(x, z); // Useful for long-range goals that don't have a specific Y level. `x` and `z` are `number` +new GoalGetToBlock(x, y, z); // Not get into the block, but get directly adjacent to it. Useful for fishing, farming, filling bucket, and beds. `x`, `y`, and `z` are `number` +new GoalFollow(entity, range); // Follow the specified entity within the specified range. `entity` is `Entity`, `range` is `number` +new GoalPlaceBlock(position, bot.world, {}); // Position the bot in order to place a block. `position` is `Vec3` +new GoalLookAtBlock(position, bot.world, {}); // Path into a position where a blockface of the block at position is visible. `position` is `Vec3` + +// These are other Mineflayer functions you can use: +bot.isABed(bedBlock); // Return true if `bedBlock` is a bed +bot.blockAt(position); // Return the block at `position`. `position` is `Vec3` + +// These are other Mineflayer async functions you can use: +await bot.equip(item, destination); // Equip the item in the specified destination. `item` is `Item`, `destination` can only be "hand", "head", "torso", "legs", "feet", "off-hand" +await bot.consume(); // Consume the item in the bot's hand. You must equip the item to consume first. Useful for eating food, drinking potions, etc. +await bot.fish(); // Let bot fish. Before calling this function, you must first get to a water block and then equip a fishing rod. The bot will automatically stop fishing when it catches a fish +await bot.sleep(bedBlock); // Sleep until sunrise. You must get to a bed block first +await bot.activateBlock(block); // This is the same as right-clicking a block in the game. Useful for buttons, doors, etc. You must get to the block first +await bot.lookAt(position); // Look at the specified position. You must go near the position before you look at it. To fill bucket with water, you must lookAt first. `position` is `Vec3` +await bot.activateItem(); // This is the same as right-clicking to use the item in the bot's hand. Useful for using buckets, etc. You must equip the item to activate first +await bot.useOn(entity); // This is the same as right-clicking an entity in the game. Useful for shearing sheep, equipping harnesses, etc. You must get to the entity first diff --git a/metagpt/actions/minecraft/control_primitives_context/placeItem.js b/metagpt/actions/minecraft/control_primitives_context/placeItem.js new file mode 100644 index 000000000..99e06089c --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/placeItem.js @@ -0,0 +1,28 @@ +// Place a crafting_table near the player, Vec3(1, 0, 0) is just an example, you shouldn't always use that: placeItem(bot, "crafting_table", bot.entity.position.offset(1, 0, 0)); +async function placeItem(bot, name, position) { + const item = bot.inventory.findInventoryItem(mcData.itemsByName[name].id); + // find a reference block + const faceVectors = [ + new Vec3(0, 1, 0), + new Vec3(0, -1, 0), + new Vec3(1, 0, 0), + new Vec3(-1, 0, 0), + new Vec3(0, 0, 1), + new Vec3(0, 0, -1), + ]; + let referenceBlock = null; + let faceVector = null; + for (const vector of faceVectors) { + const block = bot.blockAt(position.minus(vector)); + if (block?.name !== "air") { + referenceBlock = block; + faceVector = vector; + break; + } + } + // You must first go to the block position you want to place + await bot.pathfinder.goto(new GoalPlaceBlock(position, bot.world, {})); + // You must equip the item right before calling placeBlock + await bot.equip(item, "hand"); + await bot.placeBlock(referenceBlock, faceVector); +} diff --git a/metagpt/actions/minecraft/control_primitives_context/smeltItem.js b/metagpt/actions/minecraft/control_primitives_context/smeltItem.js new file mode 100644 index 000000000..0a3c76257 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/smeltItem.js @@ -0,0 +1,22 @@ +// Smelt 1 raw_iron into 1 iron_ingot using 1 oak_planks as fuel: smeltItem(bot, "raw_iron", "oak_planks"); +// You must place a furnace before calling this function +async function smeltItem(bot, itemName, fuelName, count = 1) { + const item = mcData.itemsByName[itemName]; + const fuel = mcData.itemsByName[fuelName]; + const furnaceBlock = bot.findBlock({ + matching: mcData.blocksByName.furnace.id, + maxDistance: 32, + }); + await bot.pathfinder.goto( + new GoalLookAtBlock(furnaceBlock.position, bot.world) + ); + const furnace = await bot.openFurnace(furnaceBlock); + for (let i = 0; i < count; i++) { + await furnace.putFuel(fuel.id, null, 1); + await furnace.putInput(item.id, null, 1); + // Wait 12 seconds for the furnace to smelt the item + await bot.waitForTicks(12 * 20); + await furnace.takeOutput(); + } + await furnace.close(); +} diff --git a/metagpt/actions/minecraft/control_primitives_context/useChest.js b/metagpt/actions/minecraft/control_primitives_context/useChest.js new file mode 100644 index 000000000..e80af3fd9 --- /dev/null +++ b/metagpt/actions/minecraft/control_primitives_context/useChest.js @@ -0,0 +1,35 @@ +// Get a torch from chest at (30, 65, 100): getItemFromChest(bot, new Vec3(30, 65, 100), {"torch": 1}); +// This function will work no matter how far the bot is from the chest. +async function getItemFromChest(bot, chestPosition, itemsToGet) { + await moveToChest(bot, chestPosition); + const chestBlock = bot.blockAt(chestPosition); + const chest = await bot.openContainer(chestBlock); + for (const name in itemsToGet) { + const itemByName = mcData.itemsByName[name]; + const item = chest.findContainerItem(itemByName.id); + await chest.withdraw(item.type, null, itemsToGet[name]); + } + await closeChest(bot, chestBlock); +} +// Deposit a torch into chest at (30, 65, 100): depositItemIntoChest(bot, new Vec3(30, 65, 100), {"torch": 1}); +// This function will work no matter how far the bot is from the chest. +async function depositItemIntoChest(bot, chestPosition, itemsToDeposit) { + await moveToChest(bot, chestPosition); + const chestBlock = bot.blockAt(chestPosition); + const chest = await bot.openContainer(chestBlock); + for (const name in itemsToDeposit) { + const itemByName = mcData.itemsByName[name]; + const item = bot.inventory.findInventoryItem(itemByName.id); + await chest.deposit(item.type, null, itemsToDeposit[name]); + } + await closeChest(bot, chestBlock); +} +// Check the items inside the chest at (30, 65, 100): checkItemInsideChest(bot, new Vec3(30, 65, 100)); +// You only need to call this function once without any action to finish task of checking items inside the chest. +async function checkItemInsideChest(bot, chestPosition) { + await moveToChest(bot, chestPosition); + const chestBlock = bot.blockAt(chestPosition); + await bot.openContainer(chestBlock); + // You must close the chest after opening it if you are asked to open a chest + await closeChest(bot, chestBlock); +}