[
  {
    "path": ".github/ISSUE_TEMPLATE/voyager-issue-template.md",
    "content": "---\nname: Voyager Issue Template\nabout: Create an issue to Voyager\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n### Before submitting an issue, make sure you read the [FAQ.md](FAQ.md)\n\n### Briefly describe your issue\n...\n### Please provide your python, nodejs, Minecraft, and Fabric versions here\n...\n### [If applicable] Please provide the Minefalyer and Minecraft logs, you can find the log under `logs` folder\n...\n### [If applicable] Please provide the GPT conversations that are printed each round.\n...\n"
  },
  {
    "path": ".github/workflows/close_issue.yml",
    "content": "name: Close inactive issues\non:\n  schedule:\n    - cron: \"30 1 * * *\"\n\njobs:\n  close-issues:\n    runs-on: ubuntu-latest\n    permissions:\n      issues: write\n      pull-requests: write\n    steps:\n      - uses: actions/stale@v5\n        with:\n          days-before-issue-stale: 30\n          days-before-issue-close: 14\n          stale-issue-label: \"stale\"\n          stale-issue-message: \"This issue is stale because it has been open for 30 days with no activity.\"\n          close-issue-message: \"This issue was closed because it has been inactive for 14 days since being marked as stale.\"\n          days-before-pr-stale: -1\n          days-before-pr-close: -1\n          repo-token: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".gitignore",
    "content": "ckpt*\n\n# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\n*.egg-info/\n.installed.cfg\n*.egg\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n.hypothesis/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\n.static_storage/\n.media/\nlocal_settings.py\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/build/\n\n# PyBuilder\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# pyenv\n.python-version\n\n# celery beat schedule file\ncelerybeat-schedule\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\n# env/\nvenv/\n# ENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n\n# Mac\n.DS_Store\n\n# MuJoCo License key\nmjkey.txt\n\n.mujocomanip_temp_model.xml\n\n# Python IDE\n.idea\n\n# Locally generated files\ndump.rdb\n*.local.ipynb\nruns/\ntemp*\ndebug_*\n*.swp\n\n.tabnine_root\n\nlogs/\nplot_iter.py\n*.svg"
  },
  {
    "path": "FAQ.md",
    "content": "# Frequently Asked Questions\n* [I got connection error after I click on the Azure login link and login to Microsoft account.](#i-got-a-connection-error-after-i-click-on-the-azure-login-link-and-login-to-my-microsoft-account)\n* [I got `KeyError: 'access_token'` after I copied the link](#i-got-keyerror-accesstoken-after-i-copied-the-link)\n* [I got `Subprocess Mineflayer failed to start` error.](#i-got-subprocess-mineflayer-failed-to-start-error)\n* [I saw the bot left and rejoin the game after each task.](#i-saw-the-bot-left-and-rejoin-the-game-after-each-task)\n* [How to show the bot's first-person perspective?](#how-to-show-the-bots-first-person-view)\n* [Can I use GPT-3.5 instead of GPT-4?](#can-i-use-gpt-35-instead-of-gpt-4)\n* [What's the estimated cost of running Voyager?](#whats-the-estimated-cost-of-running-voyager)\n\n## I got a connection error after I click on the Azure login link and login to my Microsoft account.\n\nIt's normal that you get a connection refused or 404 error after you log in. You will still see the new URL in your browser. You just need to copy and paste that link. It should contain things like `code=M.C....` in that link.\n\n## I got `KeyError: 'access_token'` after I copied the link\n\nWhile testing Voyager, we use Redirect URI Type: `Public client/native (mobile & desktop)` in the app registration for Azure Login. However, according to the report in issue [#34](https://github.com/MineDojo/Voyager/issues/34#issuecomment-1567007133), the URI Type was changed to \"Web\" and it resolved the problem. Feel free to attempt both URI Types to determine which one works for you. If all the approaches fail, please refer to the original tutorial in [minecraft-launcher-lib](https://minecraft-launcher-lib.readthedocs.io/en/stable/tutorial/microsoft_login.html).\n\nUpdate: This is probably a Microsoft's bug. See [issue #80 in minecraft-launcher-lib](https://codeberg.org/JakobDev/minecraft-launcher-lib/issues/80). If you cannot solve this problem, you can try to use the [Minecraft Official Launcher](./installation/minecraft_instance_install.md#option-2-minecraft-official-launcher) and use mc_port to run.\n## I got `Subprocess Mineflayer failed to start` error.\n\nThere are many reasons that may cause this problem. You can try with following solutions:\n1. Make sure you install nodejs and the dependency packages correctly. You can use the following command to check your installation:\n    ```bash\n    cd voyager/env/mineflayer\n    node index.js\n    ```\n   If you see `Server started on port {PORT}`, then your installation is correct. You can kill the process by `Ctrl+C`.\n2. Make sure you install Fabric correctly. You should be able to select the Fabric version in the Minecraft launcher. \n3. Each Mineflayer process can only listen to one port. If you want to start multiple instances of `Voyager`, you need to manually change the port when initialization:\n    ```python\n    from voyager import Voyager\n    voyager = Voyager(\n        server_port=3001, # default is 3000\n        ...\n    )\n    ```\n   \n## I saw the bot left and rejoin the game after each task.\n\nAfter completing each task, we'll reset the environment, which means the bot will exit and rejoin the game. This reset is necessary to synchronize Mineflayer with the Minecraft game. We do this because certain commands we utilize might result in lag on the Mineflayer side, causing the inventory stored in Mineflayer to differ from the actual inventory in the game. However, if you wish to avoid the reset, you can use `voyager.learn(reset_env=False)` and consider increasing the `env_wait_ticks` value. This will provide Mineflayer with additional time to sync with the Minecraft game.\n\n\n## How to show the bot's first-person view?\n\nDue to the Mineflayer's limitation, we currently can not directly get the bot's view in the game. Although there's a plugin called [prismarine-viewer](https://github.com/PrismarineJS/prismarine-viewer), the video quality is not good enough, so we opt not to use it. Our demo video is generated by [replay-mod](https://www.replaymod.com/). We start the recording and let the bot play for hours, then come back to the recording and render the view from the bot.\n\n\n## Can I use GPT-3.5 instead of GPT-4?\n\nIt's highly recommended to use GPT-4. GPT-3.5 falls behind in terms of code quality and reasoning ability compared to GPT-4. Moreover, GPT-3.5 has a limited context length, which means it may provide incomplete responses. If you insist on using GPT-3.5, it is essential to configure it with `skill_manager_retrieval_top_k` ≤ 2 to reduce the context length of the prompt.\n\n## What's the estimated cost of running Voyager?\n\nUsing Voyager for approximately 160 iterations using GPT-4 will cost you around 50 USD. It's important to keep a close eye on your OpenAI API expenses and avoid unnecessary spending. Once Voyager begins running, it's recommended to monitor the bot's behavior for a period and ensure that it successfully completes some tasks."
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2023 MineDojo Team\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Voyager: An Open-Ended Embodied Agent with Large Language Models\n<div align=\"center\">\n\n[[Website]](https://voyager.minedojo.org/)\n[[Arxiv]](https://arxiv.org/abs/2305.16291)\n[[PDF]](https://voyager.minedojo.org/assets/documents/voyager.pdf)\n[[Tweet]](https://twitter.com/DrJimFan/status/1662115266933972993?s=20)\n\n[![Python Version](https://img.shields.io/badge/Python-3.9-blue.svg)](https://github.com/MineDojo/Voyager)\n[![GitHub license](https://img.shields.io/github/license/MineDojo/Voyager)](https://github.com/MineDojo/Voyager/blob/main/LICENSE)\n______________________________________________________________________\n\n\nhttps://github.com/MineDojo/Voyager/assets/25460983/ce29f45b-43a5-4399-8fd8-5dd105fd64f2\n\n![](images/pull.png)\n\n\n</div>\n\nWe introduce Voyager, the first LLM-powered embodied lifelong learning agent\nin Minecraft that continuously explores the world, acquires diverse skills, and\nmakes novel discoveries without human intervention. Voyager consists of three\nkey components: 1) an automatic curriculum that maximizes exploration, 2) an\never-growing skill library of executable code for storing and retrieving complex\nbehaviors, and 3) a new iterative prompting mechanism that incorporates environment\nfeedback, execution errors, and self-verification for program improvement.\nVoyager interacts with GPT-4 via blackbox queries, which bypasses the need for\nmodel parameter fine-tuning. The skills developed by Voyager are temporally\nextended, interpretable, and compositional, which compounds the agent’s abilities\nrapidly and alleviates catastrophic forgetting. Empirically, Voyager shows\nstrong in-context lifelong learning capability and exhibits exceptional proficiency\nin playing Minecraft. It obtains 3.3× more unique items, travels 2.3× longer\ndistances, and unlocks key tech tree milestones up to 15.3× faster than prior SOTA.\nVoyager is able to utilize the learned skill library in a new Minecraft world to\nsolve novel tasks from scratch, while other techniques struggle to generalize.\n\nIn this repo, we provide Voyager code. This codebase is under [MIT License](LICENSE).\n\n# Installation\nVoyager requires Python ≥ 3.9 and Node.js ≥ 16.13.0. We have tested on Ubuntu 20.04, Windows 11, and macOS. You need to follow the instructions below to install Voyager.\n\n## Python Install\n```\ngit clone https://github.com/MineDojo/Voyager\ncd Voyager\npip install -e .\n```\n\n## Node.js Install\nIn addition to the Python dependencies, you need to install the following Node.js packages:\n```\ncd voyager/env/mineflayer\nnpm install -g npx\nnpm install\ncd mineflayer-collectblock\nnpx tsc\ncd ..\nnpm install\n```\n\n## Minecraft Instance Install\n\nVoyager depends on Minecraft game. You need to install Minecraft game and set up a Minecraft instance.\n\nFollow the instructions in [Minecraft Login Tutorial](installation/minecraft_instance_install.md) to set up your Minecraft Instance.\n\n## Fabric Mods Install\n\nYou need to install fabric mods to support all the features in Voyager. Remember to use the correct Fabric version of all the mods. \n\nFollow the instructions in [Fabric Mods Install](installation/fabric_mods_install.md) to install the mods.\n\n# Getting Started\nVoyager uses OpenAI's GPT-4 as the language model. You need to have an OpenAI API key to use Voyager. You can get one from [here](https://platform.openai.com/account/api-keys).\n\nAfter the installation process, you can run Voyager by:\n```python\nfrom voyager import Voyager\n\n# You can also use mc_port instead of azure_login, but azure_login is highly recommended\nazure_login = {\n    \"client_id\": \"YOUR_CLIENT_ID\",\n    \"redirect_url\": \"https://127.0.0.1/auth-response\",\n    \"secret_value\": \"[OPTIONAL] YOUR_SECRET_VALUE\",\n    \"version\": \"fabric-loader-0.14.18-1.19\", # the version Voyager is tested on\n}\nopenai_api_key = \"YOUR_API_KEY\"\n\nvoyager = Voyager(\n    azure_login=azure_login,\n    openai_api_key=openai_api_key,\n)\n\n# start lifelong learning\nvoyager.learn()\n```\n\n* If you are running with `Azure Login` for the first time, it will ask you to follow the command line instruction to generate a config file.\n* For `Azure Login`, you also need to select the world and open the world to LAN by yourself. After you run `voyager.learn()` the game will pop up soon, you need to:\n  1. Select `Singleplayer` and press `Create New World`.\n  2. Set Game Mode to `Creative` and Difficulty to `Peaceful`.\n  3. After the world is created, press `Esc` key and press `Open to LAN`.\n  4. Select `Allow cheats: ON` and press `Start LAN World`. You will see the bot join the world soon. \n\n# Resume from a checkpoint during learning\n\nIf you stop the learning process and want to resume from a checkpoint later, you can instantiate Voyager by:\n```python\nfrom voyager import Voyager\n\nvoyager = Voyager(\n    azure_login=azure_login,\n    openai_api_key=openai_api_key,\n    ckpt_dir=\"YOUR_CKPT_DIR\",\n    resume=True,\n)\n```\n\n# Run Voyager for a specific task with a learned skill library\n\nIf you want to run Voyager for a specific task with a learned skill library, you should first pass the skill library directory to Voyager:\n```python\nfrom voyager import Voyager\n\n# First instantiate Voyager with skill_library_dir.\nvoyager = Voyager(\n    azure_login=azure_login,\n    openai_api_key=openai_api_key,\n    skill_library_dir=\"./skill_library/trial1\", # Load a learned skill library.\n    ckpt_dir=\"YOUR_CKPT_DIR\", # Feel free to use a new dir. Do not use the same dir as skill library because new events will still be recorded to ckpt_dir. \n    resume=False, # Do not resume from a skill library because this is not learning.\n)\n```\nThen, you can run task decomposition. Notice: Occasionally, the task decomposition may not be logical. If you notice the printed sub-goals are flawed, you can rerun the decomposition.\n```python\n# Run task decomposition\ntask = \"YOUR TASK\" # e.g. \"Craft a diamond pickaxe\"\nsub_goals = voyager.decompose_task(task=task)\n```\nFinally, you can run the sub-goals with the learned skill library:\n```python\nvoyager.inference(sub_goals=sub_goals)\n```\n\nFor all valid skill libraries, see [Learned Skill Libraries](skill_library/README.md).\n\n# FAQ\nIf you have any questions, please check our [FAQ](FAQ.md) first before opening an issue.\n\n# Paper and Citation\n\nIf you find our work useful, please consider citing us! \n\n```bibtex\n@article{wang2023voyager,\n  title   = {Voyager: An Open-Ended Embodied Agent with Large Language Models},\n  author  = {Guanzhi Wang and Yuqi Xie and Yunfan Jiang and Ajay Mandlekar and Chaowei Xiao and Yuke Zhu and Linxi Fan and Anima Anandkumar},\n  year    = {2023},\n  journal = {arXiv preprint arXiv: Arxiv-2305.16291}\n}\n```\n\nDisclaimer: This project is strictly for research purposes, and not an official product from NVIDIA.\n"
  },
  {
    "path": "installation/fabric_mods_install.md",
    "content": "# Fabric Mods Install\nIn this tutorial, we will install the Fabric launcher and 5 mods. Remember to use the correct Fabric version that matches your game version (1.19) of all the mods. \n1. You can download the latest Fabric Installer from [here](https://fabricmc.net/use/installer/). For Windows users, just download the `.exe` file. For Mac or Ubuntu users, download the jar file and call `java -jar fabric-installer-0.11.2.jar` to install. Select game version to be `1.19` and loader version to be `0.14.18`. It will automatically detect your Minecraft game install location.\n2. After installing Fabric, you will have a `YOUR_MINECRAFT_GAME_LOCATION/mods` folder. You need to put all the mods under this folder. Also, you will have a `YOUR_MINECRAFT_GAME_LOCATION/versions/fabric-loader-0.14.18-1.19`. This is the version you will run the game with. \n3. Here are 4 mods that can be directly downloaded to `YOUR_MINECRAFT_GAME_LOCATION/mods` folder: \n   * [Fabric API](https://modrinth.com/mod/fabric-api/version/0.58.0+1.19): Basic Fabric APIs.\n   * [Mod Menu](https://cdn.modrinth.com/data/mOgUt4GM/versions/4.0.4/modmenu-4.0.4.jar): Used to manage all the mods that you download.\n   * [Complete Config](https://www.curseforge.com/minecraft/mc-mods/completeconfig/download/3821056): Dependency of server pause.\n   * [Multi Server Pause](https://www.curseforge.com/minecraft/mc-mods/multiplayer-server-pause-fabric/download/3822586): Used to pause the server when waiting for GPT-4 to reply.\n4. For the last mod [Better Respawn](https://github.com/xieleo5/better-respawn/tree/1.19), you need to manually clone and compile.\n   \n   * After you clone the repo, remove the `'forge'` string in the last line of `settings.gradle`. Then run `gradlew build` to compile the mod. You will find the compiled jar file in `better-respawn/fabric/build/libs/better-respawn-fabric-1.19-2.0.0.jar`. Put the jar file to the mod folder.\n     * You will need a Java Runtime Environment v17+ to build `better-respawn`. Some newer JRE versions will error during build. Find the JRE v17 archive [here](https://www.oracle.com/java/technologies/javase/jdk17-archive-downloads.html).\n   * After you launch the game, go to `YOUR_MINECRAFT_GAME_LOCATION/config/better-respawn`, and modify the properties file with:\n      ```\n      respawn_block_range=32\n      max_respawn_distance=32\n      min_respawn_distance=0\n      ```\n5. Don't forget to change the `version` in `azure_login` to `fabric-loader-0.14.18-1.19` that you are using. You can find it under `YOUR_MINECRAFT_GAME_LOCATION/version` folder.\n\nYou can return to [README.md](../README.md#getting-started) and getting started now.\n"
  },
  {
    "path": "installation/minecraft_instance_install.md",
    "content": "# Minecraft Instance Install\nTo start using Voyager, you should first make sure to have an official [Minecraft](https://www.minecraft.net/) game (version 1.19) installed. \n\nThere are two ways to start a Minecraft instance for Voyager. Sometimes GPT-4 will write an infinite loop that runs forever. In this case, there'll be a request timeout. Using Azure login can automatically resume the running if there's a request timeout.\n\n## Option 1: Microsoft Azure Login (Recommended)\nUsing this method will allow Voyager to automatically resume when there's a request timeout. This is dependent on the [minecraft-launcher-lib](https://minecraft-launcher-lib.readthedocs.io/en/stable/tutorial/microsoft_login.html#let-the-user-log-in) library.\n\n1. Sign in to [Azure Portal](https://portal.azure.com/).\n2. Go to [Azure Active Directory](https://portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Overview).\n3. Click on the `App Registrations` tab on the left panel.\n4. Click on the `New registration` button.\n5. Fill the form with the following values:\n    - Name: `YOUR_APP_NAME`\n    - Supported account types: `Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts`\n    - Redirect URI Type: `Public client/native (mobile & desktop)`, Value: `https://127.0.0.1/auth-response` (If you get `KeyError: 'access_token'` in the end, you can try to change the type to `Web`, see [FAQ](https://github.com/MineDojo/Voyager/blob/main/FAQ.md) for more information)\n6. Click on the `Register` button.\n7. The `Application (client) ID` will be your `client_id`.\n8. [Optional] Go to the `Certificates & Secrets` tab and click on the `New client secret` button. Fill the description by yourself. After you click `Add`, you will see your value, this will be your `secret_value`.\n9. Go to your Minecraft install location `YOUR_MINECRAFT_GAME_LOCATION/versions`, and check all the versions you have. All the folder names are your valid `version` value. \n\nAfter these steps, you will finally get your azure_login information:\n```python\nazure_login = {\n    \"client_id\": \"CLIENT_ID FROM STEP 7\",\n    \"redirect_url\": \"https://127.0.0.1/auth-response\",\n    \"secret_value\": \"[OPTIONAL] SECRET_KEY FROM STEP 8\",\n    \"version\": \"MINECRAFT VERSION YOU WANT TO USE\",\n}\n```\n**Voyager use `fabric-loader-0.14.18-1.19` version to run all the experiments.** You may not have this version currently, you can move on to the [Fabric Mods Install](fabric_mods_install.md#fabric-mods-install) section and follow the instructions there to install the fabric version of the game.\n\n## Option 2: Minecraft Official Launcher\n\nAfter you install official Minecraft, you should have a Minecraft official launcher, open it, and follow the instructions here:\n1. Select the version you want to play and start the game.\n2. Select `Singleplayer` and create a new world.\n3. Set Game Mode to `Creative` and Difficulty to `Peaceful`.\n4. After the world is created, press `Esc` and select `Open to LAN`.\n5. Select `Allow cheats: ON` and press `Start LAN World`.\n6. You will see a port number in the chat log, that is your `mc-port`, use this number to instantiate Voyager later.\n\n"
  },
  {
    "path": "requirements.txt",
    "content": "tqdm\nlangchain\njavascript\nsetuptools\nopenai\nchardet\ncchardet\nchromadb==0.3.29\ntiktoken\nrequests\nsetuptools\ngymnasium\npsutil\nminecraft_launcher_lib\n"
  },
  {
    "path": "setup.py",
    "content": "import os\nimport pathlib\nimport pkg_resources\nfrom setuptools import setup, find_packages\n\n\nPKG_NAME = \"voyager\"\nVERSION = \"0.1\"\nEXTRAS = {}\n\n\ndef _read_file(fname):\n    # this_dir = os.path.abspath(os.path.dirname(__file__))\n    # with open(os.path.join(this_dir, fname)) as f:\n    with pathlib.Path(fname).open(encoding=\"utf-8\") as fp:\n        return fp.read()\n\n\ndef _read_install_requires():\n    with pathlib.Path(\"requirements.txt\").open() as fp:\n        return [\n            str(requirement) for requirement in pkg_resources.parse_requirements(fp)\n        ]\n\n\ndef _fill_extras(extras):\n    if extras:\n        extras[\"all\"] = list(set([item for group in extras.values() for item in group]))\n    return extras\n\n\nsetup(\n    name=PKG_NAME,\n    version=VERSION,\n    author=f\"MineDojo Team\",\n    url=\"https://github.com/MineDojo/Voyager\",\n    description=\"research project\",\n    long_description=_read_file(\"README.md\"),\n    long_description_content_type=\"text/markdown\",\n    keywords=[\n        \"Open-Ended Learning\",\n        \"Lifelong Learning\",\n        \"Embodied Agents\",\n        \"Large Language Models\",\n    ],\n    license=\"MIT License\",\n    packages=find_packages(include=f\"{PKG_NAME}.*\"),\n    include_package_data=True,\n    zip_safe=False,\n    install_requires=_read_install_requires(),\n    extras_require=_fill_extras(EXTRAS),\n    python_requires=\">=3.9\",\n    classifiers=[\n        \"Development Status :: 5 - Production/Stable\",\n        \"Topic :: Scientific/Engineering :: Artificial Intelligence\",\n        \"Environment :: Console\",\n        \"Programming Language :: Python :: 3.9\",\n    ],\n)\n"
  },
  {
    "path": "skill_library/README.md",
    "content": "# Learned Skill Libraries\n\n## Ours\n\n* [skill_library/trial1](trial1)\n* [skill_library/trial2](trial2)\n* [skill_library/trial3](trial3)\n\n## Community Contributions\n\n* [daswer123/Voyager_checkpoint](https://github.com/daswer123/Voyager_checkpoint)\n* [swen128/Voyager_checkpoint](https://github.com/swen128/Voyager_checkpoint)\n* [DeveloperHarris/voyager_checkpoint](https://github.com/DeveloperHarris/voyager_checkpoint)\n\n### How to resume from a community contribution\nFirst, you need to clone or download their repo. Then, the resume is the same as using ours skill libraries. Just set `skill_library_dir=COMMUNITY_CKPT_DIR` where `COMMUNITY_CKPT_DIR` is the ckpt dir inside the folder you just downloaded.\n\n## How to Contribute\n\nAfter you run the learning process, you will see a checkpoint directory like:\n```\n.\n├── action\n│   └── chest_memory.json\n├── curriculum\n│   ├── completed_tasks.json\n│   ├── failed_tasks.json\n│   ├── qa_cache.json\n│   └── vectordb\n├── events\n└── skill\n    ├── code\n    │   ├── catchThreeFishWithCheck.js\n    │   ├── collectBamboo.js\n    │   ├── ...\n    ├── description\n    │   ├── catchThreeFishWithCheck.txt\n    │   ├── collectBamboo.txt\n    │   └── ...\n    ├── skills.json\n    └── vectordb\n```\n\nOnly `YOUR_CKPT_DIR/skill` is a learned skill library, which you can share with others. Create a pull request and add your skill library link to this page.\n"
  },
  {
    "path": "skill_library/trial1/skill/code/collectBamboo.js",
    "content": "async function collectBamboo(bot) {\n  // Equip the iron sword\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n  await bot.equip(ironSword, \"hand\");\n\n  // Find bamboo plants using the exploreUntil function\n  const bambooPlants = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const bambooPlants = bot.findBlocks({\n      matching: block => block.name === \"bamboo\",\n      maxDistance: 32,\n      count: 10\n    });\n    return bambooPlants.length >= 10 ? bambooPlants : null;\n  });\n  if (!bambooPlants) {\n    bot.chat(\"Could not find enough bamboo plants.\");\n    return;\n  }\n\n  // Break 10 bamboo plants using the iron sword\n  for (const bambooPlant of bambooPlants) {\n    const block = bot.blockAt(bambooPlant);\n    await bot.dig(block);\n  }\n  bot.chat(\"Broke 10 bamboo plants.\");\n\n  // Collect the dropped bamboo items\n  for (const bambooPlant of bambooPlants) {\n    await bot.pathfinder.goto(new GoalBlock(bambooPlant.x, bambooPlant.y, bambooPlant.z));\n  }\n  bot.chat(\"Collected 10 bamboo.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/collectFiveCactusBlocks.js",
    "content": "async function collectFiveCactusBlocks(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find 5 cactus blocks using the exploreUntil function\n  const cactusBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const cactusBlocks = bot.findBlocks({\n      matching: block => block.name === \"cactus\",\n      maxDistance: 32,\n      count: 5\n    });\n    return cactusBlocks.length >= 5 ? cactusBlocks : null;\n  });\n  if (!cactusBlocks) {\n    bot.chat(\"Could not find enough cactus blocks.\");\n    return;\n  }\n\n  // Mine the 5 cactus blocks using the mineBlock function\n  await mineBlock(bot, \"cactus\", 5);\n  bot.chat(\"5 cactus blocks mined.\");\n\n  // Collect the dropped cactus items\n  for (const cactusBlock of cactusBlocks) {\n    await bot.pathfinder.goto(new GoalBlock(cactusBlock.x, cactusBlock.y, cactusBlock.z));\n  }\n  bot.chat(\"Collected 5 cactus blocks.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/cookPorkchops.js",
    "content": "async function cookPorkchops(bot) {\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Place the furnace near the bot\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 2 porkchops using the available coal as fuel\n  await smeltItem(bot, \"porkchop\", \"coal\", 2);\n  bot.chat(\"2 porkchops cooked.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/cookSevenMutton.js",
    "content": "async function cookSevenMutton(bot) {\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Find a suitable position to place the furnace\n  const furnacePosition = await findSuitablePosition(bot);\n  if (!furnacePosition) {\n    bot.chat(\"Could not find a suitable position to place the furnace.\");\n    return;\n  }\n\n  // Place the furnace at the suitable position\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 7 raw mutton using the available coal as fuel\n  await smeltItem(bot, \"mutton\", \"coal\", 7);\n  bot.chat(\"7 mutton cooked.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftAcaciaPlanksAndSticks.js",
    "content": "async function craftAcaciaPlanksAndSticks(bot) {\n  // Check if there are enough acacia logs in the inventory\n  const acaciaLogsCount = bot.inventory.count(mcData.itemsByName.acacia_log.id);\n\n  // If not, mine more acacia logs\n  if (acaciaLogsCount < 5) {\n    await mineBlock(bot, \"acacia_log\", 5 - acaciaLogsCount);\n    bot.chat(\"Mined acacia logs.\");\n  }\n\n  // Craft 20 acacia planks from acacia logs\n  await craftItem(bot, \"acacia_planks\", 5);\n  bot.chat(\"Crafted 20 acacia planks.\");\n\n  // Check if there are enough acacia planks in the inventory to craft 10 sticks\n  const acaciaPlanksCount = bot.inventory.count(mcData.itemsByName.acacia_planks.id);\n\n  // If not, mine more acacia logs and craft more acacia planks\n  if (acaciaPlanksCount < 5) {\n    await mineBlock(bot, \"acacia_log\", 5 - acaciaLogsCount);\n    bot.chat(\"Mined more acacia logs.\");\n    await craftItem(bot, \"acacia_planks\", 5 - acaciaPlanksCount);\n    bot.chat(\"Crafted more acacia planks.\");\n  }\n\n  // Craft 10 sticks from acacia planks\n  await craftItem(bot, \"stick\", 3);\n  bot.chat(\"Crafted 10 sticks.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftBucket.js",
    "content": "async function craftBucket(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\n  if (ironIngotsCount < 3) {\n    await mineBlock(bot, \"iron_ore\", 3 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 3 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a bucket using the crafting table\n  await craftItem(bot, \"bucket\", 1);\n  bot.chat(\"Crafted a bucket.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftChest.js",
    "content": "async function craftChest(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 8) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((8 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a chest using the crafting table\n  await craftItem(bot, \"chest\", 1);\n  bot.chat(\"Crafted a chest.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftCopperBlock.js",
    "content": "async function craftCopperBlock(bot) {\n  // Check if there are enough copper ingots in the inventory\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\n\n  // If not enough copper ingots, mine copper ores and smelt them into copper ingots\n  if (copperIngotsCount < 9) {\n    await mineBlock(bot, \"copper_ore\", 9 - copperIngotsCount);\n    bot.chat(\"Collected copper ores.\");\n    await smeltItem(bot, \"copper_ore\", \"coal\", 9 - copperIngotsCount);\n    bot.chat(\"Smelted copper ores into copper ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a copper block using the crafting table\n  await craftItem(bot, \"copper_block\", 1);\n  bot.chat(\"Crafted a copper block.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftCraftingTable.js",
    "content": "async function craftCraftingTable(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 4) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((4 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Craft a crafting table using oak planks\n  await craftItem(bot, \"crafting_table\", 1);\n  bot.chat(\"Crafted a crafting table.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftFurnace.js",
    "content": "async function craftFurnace(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n\n  // If not, mine the required cobblestones\n  if (cobblestoneCount < 8) {\n    await mineBlock(bot, \"stone\", 8 - cobblestoneCount);\n    bot.chat(\"Collected cobblestone.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a furnace using the crafting table\n  await craftItem(bot, \"furnace\", 1);\n  bot.chat(\"Crafted a furnace.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronAxe.js",
    "content": "async function craftIronAxe(bot) {\n  // Check if there are enough iron ingots and sticks in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough iron ingots or sticks, collect the required items\n  if (ironIngotsCount < 3) {\n    await mineBlock(bot, \"iron_ore\", 3 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 3 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron axe using the crafting table\n  await craftItem(bot, \"iron_axe\", 1);\n  bot.chat(\"Crafted an iron axe.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronChestplate.js",
    "content": "async function craftIronChestplate(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\n  if (ironIngotsCount < 8) {\n    await mineBlock(bot, \"iron_ore\", 8 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 8 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron chestplate using the crafting table\n  await craftItem(bot, \"iron_chestplate\", 1);\n  bot.chat(\"Crafted an iron chestplate.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronHelmet.js",
    "content": "async function craftIronHelmet(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\n  if (ironIngotsCount < 5) {\n    await mineBlock(bot, \"iron_ore\", 5 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 5 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron helmet using the crafting table\n  await craftItem(bot, \"iron_helmet\", 1);\n  bot.chat(\"Crafted an iron helmet.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronHelmetV2.js",
    "content": "async function craftIronHelmet(bot) {\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron helmet using the crafting table\n  await craftItem(bot, \"iron_helmet\", 1);\n  bot.chat(\"Crafted an iron helmet.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronLeggingsAndBoots.js",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\n  if (ironIngotsCount < 11) {\n    await mineBlock(bot, \"iron_ore\", 11 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 11 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft iron leggings using the crafting table\n  await craftItem(bot, \"iron_leggings\", 1);\n  bot.chat(\"Crafted iron leggings.\");\n\n  // Craft iron boots using the crafting table\n  await craftItem(bot, \"iron_boots\", 1);\n  bot.chat(\"Crafted iron boots.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronPickaxe.js",
    "content": "async function craftIronPickaxe(bot) {\n  // Check if there are enough iron ingots and sticks in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough iron ingots or sticks, collect the required items\n  if (ironIngotsCount < 3) {\n    await mineBlock(bot, \"iron_ore\", 3 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 3 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron pickaxe using the crafting table\n  await craftItem(bot, \"iron_pickaxe\", 1);\n  bot.chat(\"Crafted an iron pickaxe.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronPickaxeV2.js",
    "content": "async function craftIronPickaxe(bot) {\n  // Check if there are enough iron ingots and sticks in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough iron ingots or sticks, collect the required items\n  if (ironIngotsCount < 3) {\n    await mineBlock(bot, \"iron_ore\", 3 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 3 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron pickaxe using the crafting table\n  await craftItem(bot, \"iron_pickaxe\", 1);\n  bot.chat(\"Crafted an iron pickaxe.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronShovel.js",
    "content": "async function craftIronShovel(bot) {\n  // Check if there are enough iron ingots and sticks in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough iron ingots or sticks, collect the required items\n  if (ironIngotsCount < 1) {\n    await mineBlock(bot, \"iron_ore\", 1);\n    bot.chat(\"Collected iron ore.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 1);\n    bot.chat(\"Smelted iron ore into iron ingot.\");\n  }\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Find a suitable position to place the crafting table\n  const suitablePosition = bot.entity.position.offset(1, 0, 0);\n  const block = bot.blockAt(suitablePosition);\n  if (block.name === \"grass_block\" || block.name === \"dirt\") {\n    await bot.dig(block);\n  }\n\n  // Place the crafting table at the suitable position\n  await placeItem(bot, \"crafting_table\", suitablePosition);\n\n  // Craft an iron shovel using the crafting table\n  await craftItem(bot, \"iron_shovel\", 1);\n  bot.chat(\"Crafted an iron shovel.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftIronSword.js",
    "content": "async function craftIronSword(bot) {\n  // Check if there are enough iron ingots and sticks in the inventory\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough iron ingots or sticks, collect the required items\n  if (ironIngotsCount < 2) {\n    await mineBlock(bot, \"iron_ore\", 2 - ironIngotsCount);\n    bot.chat(\"Collected iron ores.\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", 2 - ironIngotsCount);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n  if (sticksCount < 1) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron sword using the crafting table\n  await craftItem(bot, \"iron_sword\", 1);\n  bot.chat(\"Crafted an iron sword.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftLightningRod.js",
    "content": "async function findSuitablePosition(bot) {\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\n  for (const offset of offsets) {\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\n    const block = bot.blockAt(position);\n    if (block.name === \"air\") {\n      return position;\n    }\n  }\n  return null;\n}\n\nasync function craftLightningRod(bot) {\n  // Find a suitable position to place the crafting table\n  const craftingTablePosition = await findSuitablePosition(bot);\n\n  // Place the crafting table at the found position\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Check if there are enough copper ingots in the inventory\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\n\n  // If not enough copper ingots, mine copper ores and smelt them into copper ingots\n  if (copperIngotsCount < 3) {\n    await mineBlock(bot, \"copper_ore\", 3 - copperIngotsCount);\n    bot.chat(\"Collected copper ores.\");\n    await smeltItem(bot, \"copper_ore\", \"coal\", 3 - copperIngotsCount);\n    bot.chat(\"Smelted copper ores into copper ingots.\");\n  }\n\n  // Craft a lightning rod using the crafting table\n  await craftItem(bot, \"lightning_rod\", 1);\n  bot.chat(\"Crafted a lightning rod.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftOakPlanksAndSticks.js",
    "content": "async function craftOakPlanksAndSticks(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 8) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((8 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not, craft sticks from oak planks\n  if (sticksCount < 4) {\n    await craftItem(bot, \"stick\", 2);\n    bot.chat(\"Crafted sticks.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftScaffolding.js",
    "content": "async function craftScaffolding(bot) {\n  // Check if we have a crafting table in the inventory\n  const craftingTableCount = bot.inventory.count(mcData.itemsByName.crafting_table.id);\n\n  // If not, craft a crafting table\n  if (craftingTableCount === 0) {\n    await craftItem(bot, \"crafting_table\", 1);\n    bot.chat(\"Crafted a crafting table.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft 10 scaffolding using the crafting table\n  await craftItem(bot, \"scaffolding\", 1);\n  bot.chat(\"Crafted 10 scaffolding.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftShears.js",
    "content": "async function craftShears(bot) {\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a pair of shears using the crafting table\n  await craftItem(bot, \"shears\", 1);\n  bot.chat(\"Crafted a pair of shears.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftShieldImproved.js",
    "content": "async function craftShieldImproved(bot) {\n  // Check if there are enough oak planks in the inventory\n  let oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, check if there are enough oak logs in the inventory\n  if (oakPlanksCount < 6) {\n    let oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((6 - oakPlanksCount) / 4);\n\n    // If not, explore to find and mine oak logs\n    if (oakLogsCount < planksToCraft) {\n      await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n        const oak_log = bot.findBlock({\n          matching: mcData.blocksByName[\"oak_log\"].id,\n          maxDistance: 32\n        });\n        return oak_log;\n      });\n      await mineBlock(bot, \"oak_log\", planksToCraft - oakLogsCount);\n      bot.chat(\"Collected oak logs.\");\n    }\n\n    // Craft oak planks from oak logs\n    await craftItem(bot, \"oak_planks\", planksToCraft);\n    bot.chat(\"Crafted oak planks.\");\n    oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n  }\n\n  // Check if there are enough iron ingots in the inventory\n  let ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n\n  // If not, explore to find and mine iron ores\n  if (ironIngotsCount < 1) {\n    await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\n      const iron_ore = bot.findBlock({\n        matching: mcData.blocksByName[\"iron_ore\"].id,\n        maxDistance: 32\n      });\n      return iron_ore;\n    });\n    await mineBlock(bot, \"iron_ore\", 1);\n    bot.chat(\"Collected iron ores.\");\n\n    // Smelt iron ores into iron ingots\n    await smeltItem(bot, \"iron_ore\", \"coal\", 1);\n    bot.chat(\"Smelted iron ores into iron ingots.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a shield using the crafting table\n  await craftItem(bot, \"shield\", 1);\n  bot.chat(\"Crafted a shield.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftStonePickaxe.js",
    "content": "async function craftStonePickaxe(bot) {\n  // Check if there are enough cobblestone and sticks in the inventory\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough cobblestone or sticks, collect the required items\n  if (cobblestoneCount < 3) {\n    await mineBlock(bot, \"stone\", 3 - cobblestoneCount);\n    bot.chat(\"Collected cobblestone.\");\n  }\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone pickaxe using the crafting table\n  await craftItem(bot, \"stone_pickaxe\", 1);\n  bot.chat(\"Crafted a stone pickaxe.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftStoneShovel.js",
    "content": "async function craftStoneShovel(bot) {\n  // Check if there are enough cobblestone and sticks in the inventory\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not enough cobblestone, mine cobblestone\n  if (cobblestoneCount < 1) {\n    await mineBlock(bot, \"stone\", 1);\n    bot.chat(\"Collected cobblestone.\");\n  }\n\n  // If not enough sticks, craft sticks\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone shovel using the crafting table\n  await craftItem(bot, \"stone_shovel\", 1);\n  bot.chat(\"Crafted a stone shovel.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftWhiteBed.js",
    "content": "async function craftWhiteBed(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 3) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((3 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Check if there are enough white wool in the inventory\n  const whiteWoolCount = bot.inventory.count(mcData.itemsByName.white_wool.id);\n  if (whiteWoolCount < 3) {\n    bot.chat(\"Not enough white wool to craft a bed.\");\n    return;\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a white bed using the crafting table\n  await craftItem(bot, \"white_bed\", 1);\n  bot.chat(\"Crafted a white bed.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftWoodenHoe.js",
    "content": "async function craftWoodenHoe(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 2) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((2 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not, craft sticks from oak planks\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a wooden hoe using the crafting table\n  await craftItem(bot, \"wooden_hoe\", 1);\n  bot.chat(\"Crafted a wooden hoe.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/craftWoodenPickaxe.js",
    "content": "async function craftWoodenPickaxe(bot) {\n  // check if crafting table is in the inventory\n  const craftingTableCount = bot.inventory.count(\n    mcData.itemsByName.crafting_table.id\n  );\n\n  // If not, craft a crafting table\n  if (craftingTableCount === 0) {\n    await craftCraftingTable(bot);\n  }\n\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 6) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((6 - oakPlanksCount) / 4);\n    if (oakLogsCount < planksToCraft) {\n      await mineBlock(bot, \"oak_log\", planksToCraft - oakLogsCount);\n    }\n    await craftItem(bot, \"oak_planks\", planksToCraft);\n    bot.chat(\"Crafted oak planks.\");\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not, craft sticks from oak planks\n  if (sticksCount < 2) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a wooden pickaxe using the crafting table\n  await craftItem(bot, \"wooden_pickaxe\", 1);\n  bot.chat(\"Crafted a wooden pickaxe.\");\n}\n"
  },
  {
    "path": "skill_library/trial1/skill/code/craftWoodenSword.js",
    "content": "async function craftWoodenSword(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\n\n  // If not, craft oak planks from oak logs\n  if (oakPlanksCount < 2) {\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\n    const planksToCraft = Math.ceil((2 - oakPlanksCount) / 4);\n    if (oakLogsCount >= planksToCraft) {\n      await craftItem(bot, \"oak_planks\", planksToCraft);\n      bot.chat(\"Crafted oak planks.\");\n    } else {\n      bot.chat(\"Not enough oak logs to craft oak planks.\");\n      return;\n    }\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n\n  // If not, craft sticks from oak planks\n  if (sticksCount < 1) {\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Crafted sticks.\");\n  }\n\n  // Place the crafting table near the bot\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a wooden sword using the crafting table\n  await craftItem(bot, \"wooden_sword\", 1);\n  bot.chat(\"Crafted a wooden sword.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/eatCookedPorkchop.js",
    "content": "async function eatCookedPorkchop(bot) {\n  // Equip the cooked porkchop in the bot's hand\n  const cookedPorkchop = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_porkchop.id);\n  await bot.equip(cookedPorkchop, \"hand\");\n\n  // Consume the cooked porkchop\n  await bot.consume();\n\n  // Send a chat message to indicate the task is completed\n  bot.chat(\"Ate 1 cooked porkchop.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/eatTwoCookedMutton.js",
    "content": "async function eatTwoCookedMutton(bot) {\n  // Check if there are 2 cooked mutton in the inventory\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\n  if (!cookedMutton || cookedMutton.count < 2) {\n    bot.chat(\"Not enough cooked mutton in the inventory.\");\n    return;\n  }\n\n  // Equip the cooked mutton in the bot's hand\n  await bot.equip(cookedMutton, \"hand\");\n\n  // Consume the cooked mutton twice\n  await bot.consume();\n  await bot.consume();\n\n  // Send a chat message to indicate the task is completed\n  bot.chat(\"Ate 2 cooked mutton.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/equipIronArmor.js",
    "content": "async function equipIronArmor(bot) {\n  // Find the iron_leggings, iron_boots, and iron_helmet in the inventory\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName.iron_leggings.id);\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName.iron_boots.id);\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName.iron_helmet.id);\n\n  // Equip the iron_leggings, iron_boots, and iron_helmet in the appropriate slots (legs, feet, and head)\n  if (ironLeggings) {\n    await bot.equip(ironLeggings, \"legs\");\n    bot.chat(\"Equipped iron leggings.\");\n  } else {\n    bot.chat(\"Iron leggings not found in inventory.\");\n  }\n  if (ironBoots) {\n    await bot.equip(ironBoots, \"feet\");\n    bot.chat(\"Equipped iron boots.\");\n  } else {\n    bot.chat(\"Iron boots not found in inventory.\");\n  }\n  if (ironHelmet) {\n    await bot.equip(ironHelmet, \"head\");\n    bot.chat(\"Equipped iron helmet.\");\n  } else {\n    bot.chat(\"Iron helmet not found in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/equipIronChestplate.js",
    "content": "async function equipIronChestplate(bot) {\n  // Find the iron chestplate in the inventory\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName.iron_chestplate.id);\n\n  // Equip the iron chestplate\n  if (ironChestplate) {\n    await bot.equip(ironChestplate, \"torso\");\n    bot.chat(\"Equipped iron chestplate.\");\n  } else {\n    bot.chat(\"Iron chestplate not found in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/equipIronSword.js",
    "content": "async function equipIronSword(bot) {\n  // Find the iron sword in the inventory\n  let ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n\n  // If the iron sword is not found in the inventory, check the chest\n  if (!ironSword) {\n    const chestPosition = new Vec3(89, 41, 206);\n    const itemsToGet = {\n      \"iron_sword\": 1\n    };\n    await getItemFromChest(bot, chestPosition, itemsToGet);\n    ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n  }\n\n  // Equip the iron sword\n  if (ironSword) {\n    await bot.equip(ironSword, \"hand\");\n    bot.chat(\"Equipped iron sword.\");\n  } else {\n    bot.chat(\"Iron sword not found in inventory or chest.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/fillBucketWithWater.js",
    "content": "async function fillBucketWithWater(bot) {\n  // Find a water block nearby\n  const waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const water = bot.findBlock({\n      matching: mcData.blocksByName.water.id,\n      maxDistance: 32,\n    });\n    return water;\n  });\n  if (!waterBlock) {\n    bot.chat(\"Could not find water.\");\n    return;\n  }\n\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\n  // Go to the water block\n  await bot.pathfinder.goto(\n    new GoalGetToBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z)\n  );\n\n  // Equip the bucket\n  const bucket = bot.inventory.findInventoryItem(mcData.itemsByName.bucket.id);\n  await bot.equip(bucket, \"hand\");\n\n  // Look at the water block\n  await bot.lookAt(waterBlock.position);\n\n  // Activate the bucket to collect water\n  await bot.activateItem();\n  bot.chat(\"Filled the bucket with water.\");\n}\n"
  },
  {
    "path": "skill_library/trial1/skill/code/killFourSheep.js",
    "content": "async function killFourSheep(bot) {\n  // Equip the wooden sword\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\n  await bot.equip(woodenSword, \"hand\");\n\n  // Find and kill the first three sheep\n  for (let i = 1; i <= 3; i++) {\n    await killMob(bot, \"sheep\", 300);\n    bot.chat(`Killed sheep ${i}.`);\n  }\n\n  // Find and kill the fourth sheep\n  await killMob(bot, \"sheep\", 300);\n  bot.chat(\"Killed the fourth sheep.\");\n\n  // Collect the dropped items from the killed sheep\n  const sheepDrops = [\"wool\", \"raw_mutton\"];\n  for (const drop of sheepDrops) {\n    const droppedItem = bot.findBlock({\n      matching: block => block.name === drop,\n      maxDistance: 32\n    });\n    if (droppedItem) {\n      await bot.pathfinder.goto(new GoalBlock(droppedItem.position.x, droppedItem.position.y, droppedItem.position.z));\n    }\n  }\n  bot.chat(\"Collected dropped items from the killed sheep.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/killOneEnderman.js",
    "content": "async function killOneEnderman(bot) {\n  // Equip the iron sword\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n  await bot.equip(ironSword, \"hand\");\n\n  // Find the nearest enderman\n  const enderman = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const enderman = bot.nearestEntity(entity => {\n      return entity.name === \"enderman\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    return enderman;\n  });\n  if (!enderman) {\n    bot.chat(\"Could not find an enderman.\");\n    return;\n  }\n\n  // Kill the enderman using the iron sword\n  await killMob(bot, \"enderman\", 300);\n  bot.chat(\"Killed an enderman.\");\n\n  // Collect the dropped items\n  await bot.pathfinder.goto(new GoalBlock(enderman.position.x, enderman.position.y, enderman.position.z));\n  bot.chat(\"Collected dropped items.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/killOnePig.js",
    "content": "async function killOnePig(bot) {\n  // Equip the wooden sword\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\n  await bot.equip(woodenSword, \"hand\");\n\n  // Find the nearest pig\n  const pig = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const pig = bot.nearestEntity(entity => {\n      return entity.name === \"pig\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    return pig;\n  });\n  if (!pig) {\n    bot.chat(\"Could not find a pig.\");\n    return;\n  }\n\n  // Kill the pig using the wooden sword\n  await killMob(bot, \"pig\", 300);\n  bot.chat(\"Killed a pig.\");\n\n  // Collect the dropped items\n  await bot.pathfinder.goto(new GoalBlock(pig.position.x, pig.position.y, pig.position.z));\n  bot.chat(\"Collected dropped items.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/killOneSpider.js",
    "content": "async function killOneSpider(bot) {\n  // Equip the iron sword\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n  await bot.equip(ironSword, \"hand\");\n\n  // Find the nearest spider\n  const spider = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const spider = bot.nearestEntity(entity => {\n      return entity.name === \"spider\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    return spider;\n  });\n  if (!spider) {\n    bot.chat(\"Could not find a spider.\");\n    return;\n  }\n\n  // Kill the spider using the iron sword\n  await killMob(bot, \"spider\", 300);\n  bot.chat(\"Killed a spider.\");\n\n  // Collect the dropped items\n  await bot.pathfinder.goto(new GoalBlock(spider.position.x, spider.position.y, spider.position.z));\n  bot.chat(\"Collected dropped items.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/killOneZombie.js",
    "content": "async function killOneZombie(bot) {\n  // Equip the iron sword\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\n  await bot.equip(ironSword, \"hand\");\n\n  // Find the nearest zombie\n  const zombie = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const zombie = bot.nearestEntity(entity => {\n      return entity.name === \"zombie\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    return zombie;\n  });\n  if (!zombie) {\n    bot.chat(\"Could not find a zombie.\");\n    return;\n  }\n\n  // Kill the zombie using the iron sword\n  await killMob(bot, \"zombie\", 300);\n  bot.chat(\"Killed a zombie.\");\n\n  // Collect the dropped items\n  await bot.pathfinder.goto(new GoalBlock(zombie.position.x, zombie.position.y, zombie.position.z));\n  bot.chat(\"Collected dropped items.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/killTwoPigs.js",
    "content": "async function killTwoPigs(bot) {\n  // Equip the wooden sword\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\n  await bot.equip(woodenSword, \"hand\");\n\n  // Find and kill the first pig\n  await killMob(bot, \"pig\", 300);\n  bot.chat(\"Killed the first pig.\");\n\n  // Find and kill the second pig\n  await killMob(bot, \"pig\", 300);\n  bot.chat(\"Killed the second pig.\");\n\n  // Collect the dropped items from the killed pigs\n  const pigDrops = [\"raw_porkchop\"];\n  for (const drop of pigDrops) {\n    const droppedItem = bot.findBlock({\n      matching: block => block.name === drop,\n      maxDistance: 32\n    });\n    if (droppedItem) {\n      await bot.pathfinder.goto(new GoalBlock(droppedItem.position.x, droppedItem.position.y, droppedItem.position.z));\n    }\n  }\n  bot.chat(\"Collected dropped items from the killed pigs.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveCoalOres.js",
    "content": "async function mineFiveCoalOres(bot) {\n  // Equip the wooden pickaxe\n  const woodenPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_pickaxe.id);\n  await bot.equip(woodenPickaxe, \"hand\");\n\n  // Find 5 coal_ore blocks\n  const coalOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const coalOres = bot.findBlocks({\n      matching: block => block.name === \"coal_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return coalOres.length >= 5 ? coalOres : null;\n  });\n  if (!coalOres) {\n    bot.chat(\"Could not find enough coal ores.\");\n    return;\n  }\n\n  // Mine the 5 coal_ore blocks\n  await mineBlock(bot, \"coal_ore\", 5);\n  bot.chat(\"5 coal ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveCoalOresV2.js",
    "content": "async function mineFiveCoalOres(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find 5 coal_ore blocks\n  const coalOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const coalOres = bot.findBlocks({\n      matching: block => block.name === \"coal_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return coalOres.length >= 5 ? coalOres : null;\n  });\n  if (!coalOres) {\n    bot.chat(\"Could not find enough coal ores.\");\n    return;\n  }\n\n  // Mine the 5 coal_ore blocks\n  await mineBlock(bot, \"coal_ore\", 5);\n  bot.chat(\"5 coal ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveCopperOres.js",
    "content": "async function mineFiveCopperOres(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find 5 copper_ore blocks\n  const copperOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const copperOres = bot.findBlocks({\n      matching: block => block.name === \"copper_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return copperOres.length >= 5 ? copperOres : null;\n  });\n  if (!copperOres) {\n    bot.chat(\"Could not find enough copper ores.\");\n    return;\n  }\n\n  // Mine the 5 copper_ore blocks\n  await mineBlock(bot, \"copper_ore\", 5);\n  bot.chat(\"5 copper ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveCopperOresV2.js",
    "content": "async function mineFiveCopperOres(bot) {\n  // Check if the bot already has 5 or more copper ores in the inventory\n  const copperOres = bot.inventory.items().filter(item => item.name === \"copper_ore\");\n  const totalCopperOres = copperOres.reduce((total, item) => total + item.count, 0);\n  if (totalCopperOres >= 5) {\n    bot.chat(\"Task already completed. There are already \" + totalCopperOres + \" copper ores in the inventory.\");\n  } else {\n    bot.chat(\"Need to mine \" + (5 - totalCopperOres) + \" more copper ores.\");\n    // You can call the mineFiveCopperOres function from the previous response here\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveIronOres.js",
    "content": "async function mineFiveIronOres(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find 5 iron_ore blocks\n  const ironOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const ironOres = bot.findBlocks({\n      matching: block => block.name === \"iron_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return ironOres.length >= 5 ? ironOres : null;\n  });\n  if (!ironOres) {\n    bot.chat(\"Could not find enough iron ores.\");\n    return;\n  }\n\n  // Mine the 5 iron_ore blocks\n  await mineBlock(bot, \"iron_ore\", 5);\n  bot.chat(\"5 iron ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveIronOresV2.js",
    "content": "async function mineFiveIronOres(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find 5 iron_ore blocks\n  const ironOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const ironOres = bot.findBlocks({\n      matching: block => block.name === \"iron_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return ironOres.length >= 5 ? ironOres : null;\n  });\n  if (!ironOres) {\n    bot.chat(\"Could not find enough iron ores.\");\n    return;\n  }\n\n  // Mine the 5 iron_ore blocks\n  await mineBlock(bot, \"iron_ore\", 5);\n  bot.chat(\"5 iron ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineFiveLapisLazuliOres.js",
    "content": "async function mineFiveLapisLazuliOres(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find 5 lapis_lazuli_ore blocks\n  const lapisOres = await exploreUntil(bot, new Vec3(1, -1, 1), 60, () => {\n    const lapisOres = bot.findBlocks({\n      matching: block => block.name === \"lapis_ore\",\n      maxDistance: 32,\n      count: 5\n    });\n    return lapisOres.length >= 5 ? lapisOres : null;\n  });\n  if (!lapisOres) {\n    bot.chat(\"Could not find enough lapis lazuli ores.\");\n    return;\n  }\n\n  // Mine the 5 lapis_lazuli_ore blocks\n  await mineBlock(bot, \"lapis_ore\", 5);\n  bot.chat(\"5 lapis lazuli ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineTenCobblestone.js",
    "content": "async function mineTenCobblestone(bot) {\n  // Check if the bot has a pickaxe in the inventory\n  const pickaxe = bot.inventory.items().find(item => item.name.endsWith(\"_pickaxe\"));\n\n  // If not, craft a wooden pickaxe using the available resources in the inventory\n  if (!pickaxe) {\n    await craftWoodenPickaxe(bot);\n  } else {\n    // Equip the pickaxe\n    await bot.equip(pickaxe, \"hand\");\n  }\n\n  // Use the exploreUntil function to find cobblestone blocks\n  const cobblestoneBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const cobblestoneBlocks = bot.findBlocks({\n      matching: block => block.name === \"stone\",\n      maxDistance: 32,\n      count: 10\n    });\n    return cobblestoneBlocks.length >= 10 ? cobblestoneBlocks : null;\n  });\n  if (!cobblestoneBlocks) {\n    bot.chat(\"Could not find enough cobblestone.\");\n    return;\n  }\n\n  // Mine 10 cobblestone blocks using the mineBlock function\n  await mineBlock(bot, \"stone\", 10);\n  bot.chat(\"10 cobblestone mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineThreeMoreOakLogs.js",
    "content": "async function mineThreeMoreOakLogs(bot) {\n  // Check the initial inventory for oak logs\n  const initialOakLogs = bot.inventory.count(mcData.itemsByName.oak_log.id);\n\n  // Find 3 oak_log blocks\n  const oakLogs = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const oakLogs = bot.findBlocks({\n      matching: block => block.name === \"oak_log\",\n      maxDistance: 32,\n      count: 3\n    });\n    return oakLogs.length >= 3 ? oakLogs : null;\n  });\n  if (!oakLogs) {\n    bot.chat(\"Could not find enough oak logs.\");\n    return;\n  }\n\n  // Mine the oak_log blocks\n  await mineBlock(bot, \"oak_log\", 3);\n  bot.chat(\"3 oak logs mined.\");\n\n  // Compare the final inventory with the initial inventory\n  const finalOakLogs = bot.inventory.count(mcData.itemsByName.oak_log.id);\n  if (finalOakLogs - initialOakLogs === 3) {\n    bot.chat(\"Successfully mined 3 more oak logs.\");\n  } else {\n    bot.chat(\"Failed to mine 3 more oak logs.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/mineWoodLog.js",
    "content": "async function mineWoodLog(bot) {\n  const woodLogNames = [\"oak_log\", \"birch_log\", \"spruce_log\", \"jungle_log\", \"acacia_log\", \"dark_oak_log\", \"mangrove_log\"];\n\n  // Find a wood log block\n  const woodLogBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    return bot.findBlock({\n      matching: block => woodLogNames.includes(block.name),\n      maxDistance: 32\n    });\n  });\n  if (!woodLogBlock) {\n    bot.chat(\"Could not find a wood log.\");\n    return;\n  }\n\n  // Mine the wood log block\n  await mineBlock(bot, woodLogBlock.name, 1);\n  bot.chat(\"Wood log mined.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/obtainOneMoreAcaciaLog.js",
    "content": "async function obtainOneMoreAcaciaLog(bot) {\n  // Check the initial inventory for acacia logs\n  const initialAcaciaLogs = bot.inventory.count(mcData.itemsByName.acacia_log.id);\n\n  // If the number of acacia logs is less than 5, find and mine one more acacia log\n  if (initialAcaciaLogs < 5) {\n    const acaciaLog = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      return bot.findBlock({\n        matching: block => block.name === \"acacia_log\",\n        maxDistance: 32\n      });\n    });\n    if (!acaciaLog) {\n      bot.chat(\"Could not find an acacia log.\");\n      return;\n    }\n    await mineBlock(bot, \"acacia_log\", 1);\n    bot.chat(\"1 more acacia log obtained.\");\n  }\n\n  // Check the final number of acacia logs in the inventory\n  const finalAcaciaLogs = bot.inventory.count(mcData.itemsByName.acacia_log.id);\n  if (finalAcaciaLogs >= 5) {\n    bot.chat(\"Successfully obtained 5 acacia logs.\");\n  } else {\n    bot.chat(\"Failed to obtain 5 acacia logs.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/smeltCactusIntoGreenDye.js",
    "content": "async function smeltCactusIntoGreenDye(bot) {\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Find a suitable position to place the furnace\n  const furnacePosition = await findSuitablePosition(bot);\n  if (!furnacePosition) {\n    bot.chat(\"Could not find a suitable position to place the furnace.\");\n    return;\n  }\n\n  // Place the furnace at the suitable position\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 5 cactus using the available coal as fuel\n  await smeltItem(bot, \"cactus\", \"coal\", 5);\n  bot.chat(\"5 cactus smelted into green dye.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/smeltFiveRawIron.js",
    "content": "async function smeltFiveRawIron(bot) {\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Place the furnace near the bot\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 5 raw iron using the available coal as fuel\n  await smeltItem(bot, \"raw_iron\", \"coal\", 5);\n  bot.chat(\"5 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/code/smeltFiveRawIronV2.js",
    "content": "async function findSuitablePosition(bot) {\n  const offsets = [\n    new Vec3(1, 0, 0),\n    new Vec3(-1, 0, 0),\n    new Vec3(0, 0, 1),\n    new Vec3(0, 0, -1),\n  ];\n  for (const offset of offsets) {\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\n    const block = bot.blockAt(position);\n    if (block.name === \"air\") {\n      return position;\n    }\n  }\n  return null;\n}\n\nasync function smeltFiveRawIron(bot) {\n  // Check if there is coal in the inventory\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  // If not enough coal, mine coal_ore to obtain coal\n  if (coalCount < 3) {\n    await mineBlock(bot, \"coal_ore\", 3 - coalCount);\n    bot.chat(\"Collected coal.\");\n  }\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(\n    mcData.itemsByName.furnace.id\n  );\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Find a suitable position to place the furnace\n  const furnacePosition = await findSuitablePosition(bot);\n  if (!furnacePosition) {\n    bot.chat(\"Could not find a suitable position to place the furnace.\");\n    return;\n  }\n\n  // Place the furnace at the suitable position\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 5 raw iron using the available coal as fuel\n  await smeltItem(bot, \"raw_iron\", \"coal\", 5);\n  bot.chat(\"5 raw iron smelted.\");\n}\n"
  },
  {
    "path": "skill_library/trial1/skill/code/smeltRawCopper.js",
    "content": "async function smeltRawCopper(bot) {\n  // Check if there is a furnace in the inventory\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n\n  // If not, craft a furnace using the available cobblestone\n  if (!furnaceItem) {\n    await craftFurnace(bot);\n  }\n\n  // Find a suitable position to place the furnace\n  const furnacePosition = await findSuitablePosition(bot);\n  if (!furnacePosition) {\n    bot.chat(\"Could not find a suitable position to place the furnace.\");\n    return;\n  }\n\n  // Place the furnace at the suitable position\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 19 raw copper using the available coal as fuel\n  await smeltItem(bot, \"raw_copper\", \"coal\", 19);\n  bot.chat(\"19 raw copper smelted.\");\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/collectBamboo.txt",
    "content": "async function collectBamboo(bot) {\n    // The function is about collecting 10 bamboo plants. It equips the iron sword and uses the `exploreUntil` function to find 10 bamboo plants within a certain distance. If enough bamboo plants are found, it breaks them using the iron sword and collects the dropped bamboo items by moving to their location. If not enough bamboo plants are found, it returns an error message.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/collectFiveCactusBlocks.txt",
    "content": "async function collectFiveCactusBlocks(bot) {\n    // The function is about collecting 5 cactus blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 cactus blocks using the `exploreUntil` function. If 5 cactus blocks are not found, return. Otherwise, mine the 5 cactus blocks using the `mineBlock` function. Finally, collect the dropped cactus items by moving to each block's location.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/cookPorkchops.txt",
    "content": "async function cookPorkchops(bot) {\n    // The function is about cooking 2 porkchops using a furnace and coal as fuel. First, it checks if there is a furnace in the inventory. If not, it crafts a furnace using cobblestone. Then, it places the furnace near the bot. Finally, it smelts 2 porkchops using coal as fuel and saves the event of cooking porkchops.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/cookSevenMutton.txt",
    "content": "async function cookSevenMutton(bot) {\n    // The function is about cooking 7 raw mutton using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. After that, it smelts 7 raw mutton using the available coal as fuel and saves the event of cooking 7 mutton.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftAcaciaPlanksAndSticks.txt",
    "content": "async function craftAcaciaPlanksAndSticks(bot) {\n    // The function is about crafting 20 acacia planks and 10 sticks. It checks if there are enough acacia logs in the inventory, and if not, it mines more acacia logs. Then it crafts 20 acacia planks from the acacia logs. If there are not enough acacia planks in the inventory to craft 10 sticks, it mines more acacia logs and crafts more acacia planks. Finally, it crafts 10 sticks from the acacia planks.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftBucket.txt",
    "content": "async function craftBucket(bot) {\n    // The function crafts a bucket using a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into iron ingots. Then, it places a crafting table near the bot and crafts a bucket using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftChest.txt",
    "content": "async function craftChest(bot) {\n    // The function crafts a chest using a crafting table and oak planks. If there are not enough oak planks in the inventory, it crafts oak planks from oak logs. Once there are enough oak planks, it places a crafting table near the bot and crafts a chest using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftCopperBlock.txt",
    "content": "async function craftCopperBlock(bot) {\n    // The function crafts a copper block using a crafting table. It first checks if there are enough copper ingots in the inventory, and if not, it mines copper ores and smelts them into copper ingots. Then it places a crafting table near the bot and crafts a copper block using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftCraftingTable.txt",
    "content": "async function craftCraftingTable(bot) {\n    // The function crafts a crafting table using oak planks. It first checks if there are enough oak planks in the inventory, and if not, crafts oak planks from oak logs. Then, it crafts a crafting table using the oak planks.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftFurnace.txt",
    "content": "async function craftFurnace(bot) {\n    // The function crafts a furnace using a crafting table and cobblestones. If there are not enough cobblestones in the inventory, it mines the required amount. Then, it places a crafting table near the bot and crafts a furnace using the crafting table. Finally, it sends a chat message indicating that a furnace has been crafted.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronAxe.txt",
    "content": "async function craftIronAxe(bot) {\n    // The function crafts an iron axe using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It then places a crafting table near the bot and crafts an iron axe using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronChestplate.txt",
    "content": "async function craftIronChestplate(bot) {\n    // The function crafts an iron chestplate using a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into iron ingots. Then it places a crafting table near the bot and crafts an iron chestplate using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronHelmet.txt",
    "content": "async function craftIronHelmet(bot) {\n    // The function crafts an iron helmet using a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into iron ingots. Then it places a crafting table near the bot and crafts an iron helmet using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronHelmetV2.txt",
    "content": "async function craftIronHelmet(bot) {\n    // The function is about crafting an iron helmet using a crafting table. First, place the crafting table near the bot. Then, craft an iron helmet using the crafting table and save it to the inventory.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronLeggingsAndBoots.txt",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n    // The function crafts iron leggings and boots using a crafting table. If there are not enough iron ingots in the inventory, the bot mines iron ores and smelts them into iron ingots. Then, the bot places a crafting table near itself and crafts iron leggings and boots using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronPickaxe.txt",
    "content": "async function craftIronPickaxe(bot) {\n    // The function crafts an iron pickaxe using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It then places a crafting table near the bot and crafts an iron pickaxe using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronPickaxeV2.txt",
    "content": "async function craftIronPickaxe(bot) {\n    // The function crafts an iron pickaxe using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It then places a crafting table near the bot and crafts an iron pickaxe using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronShovel.txt",
    "content": "async function craftIronShovel(bot) {\n    // The function crafts an iron shovel using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It finds a suitable position to place the crafting table and places it there. Then, it crafts an iron shovel using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftIronSword.txt",
    "content": "async function craftIronSword(bot) {\n    // The function crafts an iron sword using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, it collects the required items. It then places a crafting table near the bot and crafts an iron sword using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftLightningRod.txt",
    "content": "async function craftLightningRod(bot) {\n    // The function is about crafting a lightning rod. It first finds a suitable position to place the crafting table and places it there. Then it checks if there are enough copper ingots in the inventory, and if not, it mines copper ores and smelts them into copper ingots. Finally, it crafts a lightning rod using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftOakPlanksAndSticks.txt",
    "content": "async function craftOakPlanksAndSticks(bot) {\n    // The function checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. If there are not enough oak planks, it crafts them from oak logs. If there are not enough sticks, it crafts them from oak planks.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftScaffolding.txt",
    "content": "async function craftScaffolding(bot) {\n    // The function is about crafting 10 scaffolding using a crafting table. First, it checks if there is a crafting table in the inventory. If not, it crafts one. Then, it places the crafting table near the bot. After that, it crafts 10 scaffolding using the crafting table and saves the event.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftShears.txt",
    "content": "async function craftShears(bot) {\n    // The function is about crafting a pair of shears. First, place a crafting table near the bot. Then, craft a pair of shears using the crafting table. Finally, the bot will chat that it has crafted a pair of shears.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftShieldImproved.txt",
    "content": "async function craftShieldImproved(bot) {\n    // The function crafts a shield using oak planks and iron ingots. It checks if there are enough oak planks and iron ingots in the inventory, and if not, it explores the environment to find and collect the required materials. It then places a crafting table near the bot and crafts a shield using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftStonePickaxe.txt",
    "content": "async function craftStonePickaxe(bot) {\n    // The function crafts a stone pickaxe using cobblestone and sticks. It checks if there are enough cobblestone and sticks in the inventory, and if not, it collects the required items. Then, it places a crafting table near the bot and crafts a stone pickaxe using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftStoneShovel.txt",
    "content": "async function craftStoneShovel(bot) {\n    // The function crafts a stone shovel using cobblestone and sticks. It checks if there are enough cobblestone and sticks in the inventory, and if not, it mines cobblestone or crafts sticks. Then, it places a crafting table near the bot and crafts a stone shovel using the crafting table. Finally, it sends a chat message indicating that a stone shovel has been crafted.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftWhiteBed.txt",
    "content": "async function craftWhiteBed(bot) {\n    // The function crafts a white bed using oak planks and white wool. If there are not enough oak planks in the inventory, it crafts oak planks from oak logs. If there are not enough white wool in the inventory, it stops the function. Then, it places a crafting table near the bot and crafts a white bed using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftWoodenHoe.txt",
    "content": "async function craftWoodenHoe(bot) {\n    // The function crafts a wooden hoe using oak planks and sticks. If there are not enough oak planks, it crafts them from oak logs. If there are not enough sticks, it crafts them from oak planks. Then, it places a crafting table near the bot and uses it to craft a wooden hoe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftWoodenPickaxe.txt",
    "content": "async function craftWoodenPickaxe(bot) {\n    // The function crafts a wooden pickaxe using oak planks, sticks, and a crafting table. It checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. Then, it places a crafting table near the bot and uses it to craft a wooden pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/craftWoodenSword.txt",
    "content": "async function craftWoodenSword(bot) {\n    // The function crafts a wooden sword using oak planks, sticks, and a crafting table. It checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. Then, it places a crafting table near the bot and uses it to craft a wooden sword.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/eatCookedPorkchop.txt",
    "content": "async function eatCookedPorkchop(bot) {\n    // The function is about eating a cooked porkchop. It equips the cooked porkchop in the bot's hand, consumes it, and sends a chat message to indicate the task is completed.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/eatTwoCookedMutton.txt",
    "content": "async function eatTwoCookedMutton(bot) {\n    // The function is about eating two cooked muttons. It checks if there are at least 2 cooked muttons in the inventory, and if not, it returns. If there are 2 or more cooked muttons, it equips one in the bot's hand and consumes it twice. Finally, it sends a chat message to indicate that the task is completed.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/equipIronArmor.txt",
    "content": "async function equipIronArmor(bot) {\n    // The function is about equipping iron armor (leggings, boots, and helmet) in the appropriate slots (legs, feet, and head) if they are available in the inventory. If any of the items are not found in the inventory, the function will output a message indicating that the item is not available.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/equipIronChestplate.txt",
    "content": "async function equipIronChestplate(bot) {\n    // The function is about equipping an iron chestplate on the bot's torso. It first finds the iron chestplate in the inventory and then equips it. If the iron chestplate is not found in the inventory, it sends a message saying that it was not found.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/equipIronSword.txt",
    "content": "async function equipIronSword(bot) {\n    // The function is about equipping an iron sword. It first checks if the iron sword is in the inventory. If not, it checks a chest for the iron sword. If the iron sword is found, it is equipped in the hand. If the iron sword is not found, a message is sent to the chat.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/fillBucketWithWater.txt",
    "content": "async function fillBucketWithWater(bot) {\n    // This function fills a bucket with water by first finding a nearby water block. After locating the water block, the bot moves to it and equips the bucket in its hand. The bot then looks at the water block and activates the bucket to collect water.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killFourSheep.txt",
    "content": "async function killFourSheep(bot) {\n    // The function is about killing four sheep and collecting their drops. It equips a wooden sword and kills the first three sheep, then kills the fourth sheep. After that, it collects the dropped items from the killed sheep, which include wool and raw mutton.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killOneEnderman.txt",
    "content": "async function killOneEnderman(bot) {\n    // The function is about killing one enderman using an iron sword. First, equip the iron sword in the hand. Next, explore the environment until finding the nearest enderman within 32 blocks. Once an enderman is found, kill it using the iron sword. After killing the enderman, collect the dropped items by moving to the enderman's position.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killOnePig.txt",
    "content": "async function killOnePig(bot) {\n    // The function is about killing a pig using a wooden sword and collecting the dropped items. First, equip the wooden sword in the hand. Next, explore the environment until finding the nearest pig within 32 blocks. Once a pig is found, kill it using the wooden sword and collect the dropped items by moving to the pig's position.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killOneSpider.txt",
    "content": "async function killOneSpider(bot) {\n    // The function is about killing a spider using an iron sword. First, equip the iron sword in the hand. Then, explore the environment until finding the nearest spider within 32 blocks. Once a spider is found, kill it using the iron sword. After killing the spider, collect the dropped items by moving to the spider's position.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killOneZombie.txt",
    "content": "async function killOneZombie(bot) {\n    // The function is about killing a single zombie using an iron sword. First, equip the iron sword in the hand. Then, explore the environment until finding the nearest zombie within 32 blocks. Once a zombie is found, kill it using the iron sword and collect the dropped items.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/killTwoPigs.txt",
    "content": "async function killTwoPigs(bot) {\n    // The function is about killing two pigs and collecting their dropped items. The function equips a wooden sword and kills two pigs using the `killMob` function. After killing each pig, the function logs a message. Then, the function searches for dropped items from the killed pigs and collects them using the `pathfinder` module. Finally, the function logs a message indicating that the items have been collected.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveCoalOres.txt",
    "content": "async function mineFiveCoalOres(bot) {\n    // The function is about mining 5 coal ores using a wooden pickaxe. The function first equips the wooden pickaxe in the hand. Then, it explores the environment until it finds 5 coal_ore blocks within a maximum distance of 32 blocks. Once 5 coal_ore blocks are found, it mines them using the wooden pickaxe and saves the event of mining 5 coal ores. If it cannot find enough coal ores, it sends a chat message indicating that it could not find enough coal ores.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveCoalOresV2.txt",
    "content": "async function mineFiveCoalOres(bot) {\n    // The function is about mining 5 coal ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 coal_ore blocks. Once 5 coal_ore blocks are found, mine them using the stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveCopperOres.txt",
    "content": "async function mineFiveCopperOres(bot) {\n    // The function is about mining 5 copper ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 copper_ore blocks. Once 5 copper_ore blocks are found, mine them using the stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveCopperOresV2.txt",
    "content": "async function mineFiveCopperOres(bot) {\n    // The function checks if the bot already has 5 or more copper ores in the inventory. If not, it outputs how many more copper ores are needed to complete the task.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveIronOres.txt",
    "content": "async function mineFiveIronOres(bot) {\n    // The function is about mining 5 iron ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 iron_ore blocks. Once 5 iron_ore blocks are found, mine them using the stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveIronOresV2.txt",
    "content": "async function mineFiveIronOres(bot) {\n    // The function is about mining 5 iron ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 iron_ore blocks. Once 5 iron_ore blocks are found, mine them using the stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineFiveLapisLazuliOres.txt",
    "content": "async function mineFiveLapisLazuliOres(bot) {\n    // The function is about mining 5 lapis lazuli ores using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 lapis lazuli ore blocks. Once 5 lapis lazuli ore blocks are found, mine them using the iron pickaxe.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineTenCobblestone.txt",
    "content": "async function mineTenCobblestone(bot) {\n    // The function is about mining 10 cobblestones using a pickaxe. First, check if the bot has a pickaxe in the inventory. If not, craft a wooden pickaxe using the available resources in the inventory. If the pickaxe is available, equip the pickaxe in the hand. Next, use the exploreUntil function to find cobblestone blocks. Once 10 cobblestone blocks are found, mine them using the mineBlock function.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineThreeMoreOakLogs.txt",
    "content": "async function mineThreeMoreOakLogs(bot) {\n    // The function is about mining 3 oak logs. It first checks the initial inventory for oak logs. Then, it explores the environment until it finds 3 oak log blocks. If it cannot find enough oak logs, it returns. Otherwise, it mines the oak log blocks and compares the final inventory with the initial inventory to determine if it successfully mined 3 more oak logs.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/mineWoodLog.txt",
    "content": "async function mineWoodLog(bot) {\n    // The function is about mining a single wood log block. It searches for a wood log block by exploring the environment until it finds one of the seven types of wood logs. If a wood log block is found, it is mined and a success message is sent. If no wood log block is found, a failure message is sent.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/obtainOneMoreAcaciaLog.txt",
    "content": "async function obtainOneMoreAcaciaLog(bot) {\n    // The function checks if there are less than 5 acacia logs in the inventory, and if so, finds and mines one more acacia log. If the bot successfully obtains 5 acacia logs, it sends a success message, otherwise it sends a failure message.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/smeltCactusIntoGreenDye.txt",
    "content": "async function smeltCactusIntoGreenDye(bot) {\n    // The function is about smelting 5 cactus into green dye using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. Finally, it smelts the cactus using coal as fuel and saves the event of smelting 5 cactus into green dye.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/smeltFiveRawIron.txt",
    "content": "async function smeltFiveRawIron(bot) {\n    // The function is about smelting 5 raw iron using a furnace and coal as fuel. First, it checks if there is a furnace in the inventory, and if not, it crafts one. Then, it places the furnace near the bot. Finally, it smelts 5 raw iron using the available coal as fuel and sends a chat message when finished.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/smeltFiveRawIronV2.txt",
    "content": "async function smeltFiveRawIron(bot) {\n    // The function is about smelting 5 raw iron using a furnace and coal as fuel. If there is no furnace in the inventory, craft one using cobblestone. Find a suitable position to place the furnace and place it there. Then, smelt 5 raw iron using the available coal as fuel.\n}"
  },
  {
    "path": "skill_library/trial1/skill/description/smeltRawCopper.txt",
    "content": "async function smeltRawCopper(bot) {\n    // The function is about smelting 19 raw copper using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. Finally, it smelts the raw copper using the furnace and coal as fuel.\n}"
  },
  {
    "path": "skill_library/trial1/skill/skills.json",
    "content": "{\"mineWoodLog\": {\"code\": \"async function mineWoodLog(bot) {\\n  const woodLogNames = [\\\"oak_log\\\", \\\"birch_log\\\", \\\"spruce_log\\\", \\\"jungle_log\\\", \\\"acacia_log\\\", \\\"dark_oak_log\\\", \\\"mangrove_log\\\"];\\n\\n  // Find a wood log block\\n  const woodLogBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    return bot.findBlock({\\n      matching: block => woodLogNames.includes(block.name),\\n      maxDistance: 32\\n    });\\n  });\\n  if (!woodLogBlock) {\\n    bot.chat(\\\"Could not find a wood log.\\\");\\n    return;\\n  }\\n\\n  // Mine the wood log block\\n  await mineBlock(bot, woodLogBlock.name, 1);\\n  bot.chat(\\\"Wood log mined.\\\");\\n}\", \"description\": \"async function mineWoodLog(bot) {\\n    // The function is about mining a single wood log block. It searches for a wood log block by exploring the environment until it finds one of the seven types of wood logs. If a wood log block is found, it is mined and a success message is sent. If no wood log block is found, a failure message is sent.\\n}\"}, \"mineThreeMoreOakLogs\": {\"code\": \"async function mineThreeMoreOakLogs(bot) {\\n  // Check the initial inventory for oak logs\\n  const initialOakLogs = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n\\n  // Find 3 oak_log blocks\\n  const oakLogs = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const oakLogs = bot.findBlocks({\\n      matching: block => block.name === \\\"oak_log\\\",\\n      maxDistance: 32,\\n      count: 3\\n    });\\n    return oakLogs.length >= 3 ? oakLogs : null;\\n  });\\n  if (!oakLogs) {\\n    bot.chat(\\\"Could not find enough oak logs.\\\");\\n    return;\\n  }\\n\\n  // Mine the oak_log blocks\\n  await mineBlock(bot, \\\"oak_log\\\", 3);\\n  bot.chat(\\\"3 oak logs mined.\\\");\\n\\n  // Compare the final inventory with the initial inventory\\n  const finalOakLogs = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n  if (finalOakLogs - initialOakLogs === 3) {\\n    bot.chat(\\\"Successfully mined 3 more oak logs.\\\");\\n  } else {\\n    bot.chat(\\\"Failed to mine 3 more oak logs.\\\");\\n  }\\n}\", \"description\": \"async function mineThreeMoreOakLogs(bot) {\\n    // The function is about mining 3 oak logs. It first checks the initial inventory for oak logs. Then, it explores the environment until it finds 3 oak log blocks. If it cannot find enough oak logs, it returns. Otherwise, it mines the oak log blocks and compares the final inventory with the initial inventory to determine if it successfully mined 3 more oak logs.\\n}\"}, \"craftCraftingTable\": {\"code\": \"async function craftCraftingTable(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 4) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((4 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Craft a crafting table using oak planks\\n  await craftItem(bot, \\\"crafting_table\\\", 1);\\n  bot.chat(\\\"Crafted a crafting table.\\\");\\n}\", \"description\": \"async function craftCraftingTable(bot) {\\n    // The function crafts a crafting table using oak planks. It first checks if there are enough oak planks in the inventory, and if not, crafts oak planks from oak logs. Then, it crafts a crafting table using the oak planks.\\n}\"}, \"craftWoodenPickaxe\": {\"code\": \"async function craftWoodenPickaxe(bot) {\\n  // check if crafting table is in the inventory\\n  const craftingTableCount = bot.inventory.count(\\n    mcData.itemsByName.crafting_table.id\\n  );\\n\\n  // If not, craft a crafting table\\n  if (craftingTableCount === 0) {\\n    await craftCraftingTable(bot);\\n  }\\n\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 6) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((6 - oakPlanksCount) / 4);\\n    if (oakLogsCount < planksToCraft) {\\n      await mineBlock(bot, \\\"oak_log\\\", planksToCraft - oakLogsCount);\\n    }\\n    await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n    bot.chat(\\\"Crafted oak planks.\\\");\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not, craft sticks from oak planks\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a wooden pickaxe using the crafting table\\n  await craftItem(bot, \\\"wooden_pickaxe\\\", 1);\\n  bot.chat(\\\"Crafted a wooden pickaxe.\\\");\\n}\\n\", \"description\": \"async function craftWoodenPickaxe(bot) {\\n    // The function crafts a wooden pickaxe using oak planks, sticks, and a crafting table. It checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. Then, it places a crafting table near the bot and uses it to craft a wooden pickaxe.\\n}\"}, \"craftWoodenSword\": {\"code\": \"async function craftWoodenSword(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 2) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((2 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not, craft sticks from oak planks\\n  if (sticksCount < 1) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a wooden sword using the crafting table\\n  await craftItem(bot, \\\"wooden_sword\\\", 1);\\n  bot.chat(\\\"Crafted a wooden sword.\\\");\\n}\", \"description\": \"async function craftWoodenSword(bot) {\\n    // The function crafts a wooden sword using oak planks, sticks, and a crafting table. It checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. Then, it places a crafting table near the bot and uses it to craft a wooden sword.\\n}\"}, \"killOnePig\": {\"code\": \"async function killOnePig(bot) {\\n  // Equip the wooden sword\\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\\n  await bot.equip(woodenSword, \\\"hand\\\");\\n\\n  // Find the nearest pig\\n  const pig = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const pig = bot.nearestEntity(entity => {\\n      return entity.name === \\\"pig\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    return pig;\\n  });\\n  if (!pig) {\\n    bot.chat(\\\"Could not find a pig.\\\");\\n    return;\\n  }\\n\\n  // Kill the pig using the wooden sword\\n  await killMob(bot, \\\"pig\\\", 300);\\n  bot.chat(\\\"Killed a pig.\\\");\\n\\n  // Collect the dropped items\\n  await bot.pathfinder.goto(new GoalBlock(pig.position.x, pig.position.y, pig.position.z));\\n  bot.chat(\\\"Collected dropped items.\\\");\\n}\", \"description\": \"async function killOnePig(bot) {\\n    // The function is about killing a pig using a wooden sword and collecting the dropped items. First, equip the wooden sword in the hand. Next, explore the environment until finding the nearest pig within 32 blocks. Once a pig is found, kill it using the wooden sword and collect the dropped items by moving to the pig's position.\\n}\"}, \"killFourSheep\": {\"code\": \"async function killFourSheep(bot) {\\n  // Equip the wooden sword\\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\\n  await bot.equip(woodenSword, \\\"hand\\\");\\n\\n  // Find and kill the first three sheep\\n  for (let i = 1; i <= 3; i++) {\\n    await killMob(bot, \\\"sheep\\\", 300);\\n    bot.chat(`Killed sheep ${i}.`);\\n  }\\n\\n  // Find and kill the fourth sheep\\n  await killMob(bot, \\\"sheep\\\", 300);\\n  bot.chat(\\\"Killed the fourth sheep.\\\");\\n\\n  // Collect the dropped items from the killed sheep\\n  const sheepDrops = [\\\"wool\\\", \\\"raw_mutton\\\"];\\n  for (const drop of sheepDrops) {\\n    const droppedItem = bot.findBlock({\\n      matching: block => block.name === drop,\\n      maxDistance: 32\\n    });\\n    if (droppedItem) {\\n      await bot.pathfinder.goto(new GoalBlock(droppedItem.position.x, droppedItem.position.y, droppedItem.position.z));\\n    }\\n  }\\n  bot.chat(\\\"Collected dropped items from the killed sheep.\\\");\\n}\", \"description\": \"async function killFourSheep(bot) {\\n    // The function is about killing four sheep and collecting their drops. It equips a wooden sword and kills the first three sheep, then kills the fourth sheep. After that, it collects the dropped items from the killed sheep, which include wool and raw mutton.\\n}\"}, \"craftOakPlanksAndSticks\": {\"code\": \"async function craftOakPlanksAndSticks(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 8) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((8 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not, craft sticks from oak planks\\n  if (sticksCount < 4) {\\n    await craftItem(bot, \\\"stick\\\", 2);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n}\", \"description\": \"async function craftOakPlanksAndSticks(bot) {\\n    // The function checks if there are enough oak planks and sticks in the inventory, and crafts them if necessary. If there are not enough oak planks, it crafts them from oak logs. If there are not enough sticks, it crafts them from oak planks.\\n}\"}, \"mineFiveCoalOres\": {\"code\": \"async function mineFiveCoalOres(bot) {\\n  // Equip the stone pickaxe\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  await bot.equip(stonePickaxe, \\\"hand\\\");\\n\\n  // Find 5 coal_ore blocks\\n  const coalOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const coalOres = bot.findBlocks({\\n      matching: block => block.name === \\\"coal_ore\\\",\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return coalOres.length >= 5 ? coalOres : null;\\n  });\\n  if (!coalOres) {\\n    bot.chat(\\\"Could not find enough coal ores.\\\");\\n    return;\\n  }\\n\\n  // Mine the 5 coal_ore blocks\\n  await mineBlock(bot, \\\"coal_ore\\\", 5);\\n  bot.chat(\\\"5 coal ores mined.\\\");\\n}\", \"description\": \"async function mineFiveCoalOres(bot) {\\n    // The function is about mining 5 coal ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 coal_ore blocks. Once 5 coal_ore blocks are found, mine them using the stone pickaxe.\\n}\"}, \"mineTenCobblestone\": {\"code\": \"async function mineTenCobblestone(bot) {\\n  // Check if the bot has a pickaxe in the inventory\\n  const pickaxe = bot.inventory.items().find(item => item.name.endsWith(\\\"_pickaxe\\\"));\\n\\n  // If not, craft a wooden pickaxe using the available resources in the inventory\\n  if (!pickaxe) {\\n    await craftWoodenPickaxe(bot);\\n  } else {\\n    // Equip the pickaxe\\n    await bot.equip(pickaxe, \\\"hand\\\");\\n  }\\n\\n  // Use the exploreUntil function to find cobblestone blocks\\n  const cobblestoneBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const cobblestoneBlocks = bot.findBlocks({\\n      matching: block => block.name === \\\"stone\\\",\\n      maxDistance: 32,\\n      count: 10\\n    });\\n    return cobblestoneBlocks.length >= 10 ? cobblestoneBlocks : null;\\n  });\\n  if (!cobblestoneBlocks) {\\n    bot.chat(\\\"Could not find enough cobblestone.\\\");\\n    return;\\n  }\\n\\n  // Mine 10 cobblestone blocks using the mineBlock function\\n  await mineBlock(bot, \\\"stone\\\", 10);\\n  bot.chat(\\\"10 cobblestone mined.\\\");\\n}\", \"description\": \"async function mineTenCobblestone(bot) {\\n    // The function is about mining 10 cobblestones using a pickaxe. First, check if the bot has a pickaxe in the inventory. If not, craft a wooden pickaxe using the available resources in the inventory. If the pickaxe is available, equip the pickaxe in the hand. Next, use the exploreUntil function to find cobblestone blocks. Once 10 cobblestone blocks are found, mine them using the mineBlock function.\\n}\"}, \"craftStonePickaxe\": {\"code\": \"async function craftStonePickaxe(bot) {\\n  // Check if there are enough cobblestone and sticks in the inventory\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough cobblestone or sticks, collect the required items\\n  if (cobblestoneCount < 3) {\\n    await mineBlock(bot, \\\"stone\\\", 3 - cobblestoneCount);\\n    bot.chat(\\\"Collected cobblestone.\\\");\\n  }\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone pickaxe using the crafting table\\n  await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n  bot.chat(\\\"Crafted a stone pickaxe.\\\");\\n}\", \"description\": \"async function craftStonePickaxe(bot) {\\n    // The function crafts a stone pickaxe using cobblestone and sticks. It checks if there are enough cobblestone and sticks in the inventory, and if not, it collects the required items. Then, it places a crafting table near the bot and crafts a stone pickaxe using the crafting table.\\n}\"}, \"mineFiveIronOres\": {\"code\": \"async function mineFiveIronOres(bot) {\\n  // Equip the stone pickaxe\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  await bot.equip(stonePickaxe, \\\"hand\\\");\\n\\n  // Find 5 iron_ore blocks\\n  const ironOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const ironOres = bot.findBlocks({\\n      matching: block => block.name === \\\"iron_ore\\\",\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return ironOres.length >= 5 ? ironOres : null;\\n  });\\n  if (!ironOres) {\\n    bot.chat(\\\"Could not find enough iron ores.\\\");\\n    return;\\n  }\\n\\n  // Mine the 5 iron_ore blocks\\n  await mineBlock(bot, \\\"iron_ore\\\", 5);\\n  bot.chat(\\\"5 iron ores mined.\\\");\\n}\", \"description\": \"async function mineFiveIronOres(bot) {\\n    // The function is about mining 5 iron ores using a stone pickaxe. First, equip the stone pickaxe in the hand. Next, explore the environment until finding 5 iron_ore blocks. Once 5 iron_ore blocks are found, mine them using the stone pickaxe.\\n}\"}, \"craftFurnace\": {\"code\": \"async function craftFurnace(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n\\n  // If not, mine the required cobblestones\\n  if (cobblestoneCount < 8) {\\n    await mineBlock(bot, \\\"stone\\\", 8 - cobblestoneCount);\\n    bot.chat(\\\"Collected cobblestone.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a furnace using the crafting table\\n  await craftItem(bot, \\\"furnace\\\", 1);\\n  bot.chat(\\\"Crafted a furnace.\\\");\\n}\", \"description\": \"async function craftFurnace(bot) {\\n    // The function crafts a furnace using a crafting table and cobblestones. If there are not enough cobblestones in the inventory, it mines the required amount. Then, it places a crafting table near the bot and crafts a furnace using the crafting table. Finally, it sends a chat message indicating that a furnace has been crafted.\\n}\"}, \"smeltFiveRawIron\": {\"code\": \"async function findSuitablePosition(bot) {\\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\\n  for (const offset of offsets) {\\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\\n    const block = bot.blockAt(position);\\n    if (block.name === \\\"air\\\") {\\n      return position;\\n    }\\n  }\\n  return null;\\n}\\nasync function smeltFiveRawIron(bot) {\\n  // Check if there is coal in the inventory\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n\\n  // If not enough coal, mine coal_ore to obtain coal\\n  if (coalCount < 3) {\\n    await mineBlock(bot, \\\"coal_ore\\\", 3 - coalCount);\\n    bot.chat(\\\"Collected coal.\\\");\\n  }\\n  // Check if there is a furnace in the inventory\\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  // If not, craft a furnace using the available cobblestone\\n  if (!furnaceItem) {\\n    await craftFurnace(bot);\\n  }\\n  // Find a suitable position to place the furnace\\n  const furnacePosition = await findSuitablePosition(bot);\\n  if (!furnacePosition) {\\n    bot.chat(\\\"Could not find a suitable position to place the furnace.\\\");\\n    return;\\n  }\\n  // Place the furnace at the suitable position\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  // Smelt 5 raw iron using the available coal as fuel\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 5);\\n  bot.chat(\\\"5 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltFiveRawIron(bot) {\\n    // The function is about smelting 5 raw iron using a furnace and coal as fuel. If there is no furnace in the inventory, craft one using cobblestone. Find a suitable position to place the furnace and place it there. Then, smelt 5 raw iron using the available coal as fuel.\\n}\"}, \"craftIronPickaxe\": {\"code\": \"async function craftIronPickaxe(bot) {\\n  // Check if there are enough iron ingots and sticks in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough iron ingots or sticks, collect the required items\\n  if (ironIngotsCount < 3) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron pickaxe using the crafting table\\n  await craftItem(bot, \\\"iron_pickaxe\\\", 1);\\n  bot.chat(\\\"Crafted an iron pickaxe.\\\");\\n}\", \"description\": \"async function craftIronPickaxe(bot) {\\n    // The function crafts an iron pickaxe using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It then places a crafting table near the bot and crafts an iron pickaxe using the crafting table.\\n}\"}, \"craftIronSword\": {\"code\": \"async function craftIronSword(bot) {\\n  // Check if there are enough iron ingots and sticks in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough iron ingots or sticks, collect the required items\\n  if (ironIngotsCount < 2) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 2 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 2 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n  if (sticksCount < 1) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron sword using the crafting table\\n  await craftItem(bot, \\\"iron_sword\\\", 1);\\n  bot.chat(\\\"Crafted an iron sword.\\\");\\n}\", \"description\": \"async function craftIronSword(bot) {\\n    // The function crafts an iron sword using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, it collects the required items. It then places a crafting table near the bot and crafts an iron sword using the crafting table.\\n}\"}, \"cookPorkchops\": {\"code\": \"async function cookPorkchops(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n\\n  // If not, craft a furnace using the available cobblestone\\n  if (!furnaceItem) {\\n    await craftFurnace(bot);\\n  }\\n\\n  // Place the furnace near the bot\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 2 porkchops using the available coal as fuel\\n  await smeltItem(bot, \\\"porkchop\\\", \\\"coal\\\", 2);\\n  bot.chat(\\\"2 porkchops cooked.\\\");\\n}\", \"description\": \"async function cookPorkchops(bot) {\\n    // The function is about cooking 2 porkchops using a furnace and coal as fuel. First, it checks if there is a furnace in the inventory. If not, it crafts a furnace using cobblestone. Then, it places the furnace near the bot. Finally, it smelts 2 porkchops using coal as fuel and saves the event of cooking porkchops.\\n}\"}, \"mineFiveLapisLazuliOres\": {\"code\": \"async function mineFiveLapisLazuliOres(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find 5 lapis_lazuli_ore blocks\\n  const lapisOres = await exploreUntil(bot, new Vec3(1, -1, 1), 60, () => {\\n    const lapisOres = bot.findBlocks({\\n      matching: block => block.name === \\\"lapis_ore\\\",\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return lapisOres.length >= 5 ? lapisOres : null;\\n  });\\n  if (!lapisOres) {\\n    bot.chat(\\\"Could not find enough lapis lazuli ores.\\\");\\n    return;\\n  }\\n\\n  // Mine the 5 lapis_lazuli_ore blocks\\n  await mineBlock(bot, \\\"lapis_ore\\\", 5);\\n  bot.chat(\\\"5 lapis lazuli ores mined.\\\");\\n}\", \"description\": \"async function mineFiveLapisLazuliOres(bot) {\\n    // The function is about mining 5 lapis lazuli ores using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 lapis lazuli ore blocks. Once 5 lapis lazuli ore blocks are found, mine them using the iron pickaxe.\\n}\"}, \"craftIronAxe\": {\"code\": \"async function craftIronAxe(bot) {\\n  // Check if there are enough iron ingots and sticks in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough iron ingots or sticks, collect the required items\\n  if (ironIngotsCount < 3) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron axe using the crafting table\\n  await craftItem(bot, \\\"iron_axe\\\", 1);\\n  bot.chat(\\\"Crafted an iron axe.\\\");\\n}\", \"description\": \"async function craftIronAxe(bot) {\\n    // The function crafts an iron axe using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It then places a crafting table near the bot and crafts an iron axe using the crafting table.\\n}\"}, \"craftStoneShovel\": {\"code\": \"async function craftStoneShovel(bot) {\\n  // Check if there are enough cobblestone and sticks in the inventory\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough cobblestone, mine cobblestone\\n  if (cobblestoneCount < 1) {\\n    await mineBlock(bot, \\\"stone\\\", 1);\\n    bot.chat(\\\"Collected cobblestone.\\\");\\n  }\\n\\n  // If not enough sticks, craft sticks\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone shovel using the crafting table\\n  await craftItem(bot, \\\"stone_shovel\\\", 1);\\n  bot.chat(\\\"Crafted a stone shovel.\\\");\\n}\", \"description\": \"async function craftStoneShovel(bot) {\\n    // The function crafts a stone shovel using cobblestone and sticks. It checks if there are enough cobblestone and sticks in the inventory, and if not, it mines cobblestone or crafts sticks. Then, it places a crafting table near the bot and crafts a stone shovel using the crafting table. Finally, it sends a chat message indicating that a stone shovel has been crafted.\\n}\"}, \"cookSevenMutton\": {\"code\": \"async function cookSevenMutton(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n\\n  // If not, craft a furnace using the available cobblestone\\n  if (!furnaceItem) {\\n    await craftFurnace(bot);\\n  }\\n\\n  // Find a suitable position to place the furnace\\n  const furnacePosition = await findSuitablePosition(bot);\\n  if (!furnacePosition) {\\n    bot.chat(\\\"Could not find a suitable position to place the furnace.\\\");\\n    return;\\n  }\\n\\n  // Place the furnace at the suitable position\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 7 raw mutton using the available coal as fuel\\n  await smeltItem(bot, \\\"mutton\\\", \\\"coal\\\", 7);\\n  bot.chat(\\\"7 mutton cooked.\\\");\\n}\", \"description\": \"async function cookSevenMutton(bot) {\\n    // The function is about cooking 7 raw mutton using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. After that, it smelts 7 raw mutton using the available coal as fuel and saves the event of cooking 7 mutton.\\n}\"}, \"killTwoPigs\": {\"code\": \"async function killTwoPigs(bot) {\\n  // Equip the wooden sword\\n  const woodenSword = bot.inventory.findInventoryItem(mcData.itemsByName.wooden_sword.id);\\n  await bot.equip(woodenSword, \\\"hand\\\");\\n\\n  // Find and kill the first pig\\n  await killMob(bot, \\\"pig\\\", 300);\\n  bot.chat(\\\"Killed the first pig.\\\");\\n\\n  // Find and kill the second pig\\n  await killMob(bot, \\\"pig\\\", 300);\\n  bot.chat(\\\"Killed the second pig.\\\");\\n\\n  // Collect the dropped items from the killed pigs\\n  const pigDrops = [\\\"raw_porkchop\\\"];\\n  for (const drop of pigDrops) {\\n    const droppedItem = bot.findBlock({\\n      matching: block => block.name === drop,\\n      maxDistance: 32\\n    });\\n    if (droppedItem) {\\n      await bot.pathfinder.goto(new GoalBlock(droppedItem.position.x, droppedItem.position.y, droppedItem.position.z));\\n    }\\n  }\\n  bot.chat(\\\"Collected dropped items from the killed pigs.\\\");\\n}\", \"description\": \"async function killTwoPigs(bot) {\\n    // The function is about killing two pigs and collecting their dropped items. The function equips a wooden sword and kills two pigs using the `killMob` function. After killing each pig, the function logs a message. Then, the function searches for dropped items from the killed pigs and collects them using the `pathfinder` module. Finally, the function logs a message indicating that the items have been collected.\\n}\"}, \"eatCookedPorkchop\": {\"code\": \"async function eatCookedPorkchop(bot) {\\n  // Equip the cooked porkchop in the bot's hand\\n  const cookedPorkchop = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_porkchop.id);\\n  await bot.equip(cookedPorkchop, \\\"hand\\\");\\n\\n  // Consume the cooked porkchop\\n  await bot.consume();\\n\\n  // Send a chat message to indicate the task is completed\\n  bot.chat(\\\"Ate 1 cooked porkchop.\\\");\\n}\", \"description\": \"async function eatCookedPorkchop(bot) {\\n    // The function is about eating a cooked porkchop. It equips the cooked porkchop in the bot's hand, consumes it, and sends a chat message to indicate the task is completed.\\n}\"}, \"craftWoodenHoe\": {\"code\": \"async function craftWoodenHoe(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 2) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((2 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not, craft sticks from oak planks\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a wooden hoe using the crafting table\\n  await craftItem(bot, \\\"wooden_hoe\\\", 1);\\n  bot.chat(\\\"Crafted a wooden hoe.\\\");\\n}\", \"description\": \"async function craftWoodenHoe(bot) {\\n    // The function crafts a wooden hoe using oak planks and sticks. If there are not enough oak planks, it crafts them from oak logs. If there are not enough sticks, it crafts them from oak planks. Then, it places a crafting table near the bot and uses it to craft a wooden hoe.\\n}\"}, \"craftWhiteBed\": {\"code\": \"async function craftWhiteBed(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 3) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((3 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Check if there are enough white wool in the inventory\\n  const whiteWoolCount = bot.inventory.count(mcData.itemsByName.white_wool.id);\\n  if (whiteWoolCount < 3) {\\n    bot.chat(\\\"Not enough white wool to craft a bed.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a white bed using the crafting table\\n  await craftItem(bot, \\\"white_bed\\\", 1);\\n  bot.chat(\\\"Crafted a white bed.\\\");\\n}\", \"description\": \"async function craftWhiteBed(bot) {\\n    // The function crafts a white bed using oak planks and white wool. If there are not enough oak planks in the inventory, it crafts oak planks from oak logs. If there are not enough white wool in the inventory, it stops the function. Then, it places a crafting table near the bot and crafts a white bed using the crafting table.\\n}\"}, \"killOneEnderman\": {\"code\": \"async function killOneEnderman(bot) {\\n  // Equip the iron sword\\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n  await bot.equip(ironSword, \\\"hand\\\");\\n\\n  // Find the nearest enderman\\n  const enderman = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const enderman = bot.nearestEntity(entity => {\\n      return entity.name === \\\"enderman\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    return enderman;\\n  });\\n  if (!enderman) {\\n    bot.chat(\\\"Could not find an enderman.\\\");\\n    return;\\n  }\\n\\n  // Kill the enderman using the iron sword\\n  await killMob(bot, \\\"enderman\\\", 300);\\n  bot.chat(\\\"Killed an enderman.\\\");\\n\\n  // Collect the dropped items\\n  await bot.pathfinder.goto(new GoalBlock(enderman.position.x, enderman.position.y, enderman.position.z));\\n  bot.chat(\\\"Collected dropped items.\\\");\\n}\", \"description\": \"async function killOneEnderman(bot) {\\n    // The function is about killing one enderman using an iron sword. First, equip the iron sword in the hand. Next, explore the environment until finding the nearest enderman within 32 blocks. Once an enderman is found, kill it using the iron sword. After killing the enderman, collect the dropped items by moving to the enderman's position.\\n}\"}, \"craftIronChestplate\": {\"code\": \"async function craftIronChestplate(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n\\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\\n  if (ironIngotsCount < 8) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 8 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 8 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron chestplate using the crafting table\\n  await craftItem(bot, \\\"iron_chestplate\\\", 1);\\n  bot.chat(\\\"Crafted an iron chestplate.\\\");\\n}\", \"description\": \"async function craftIronChestplate(bot) {\\n    // The function crafts an iron chestplate using a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into iron ingots. Then it places a crafting table near the bot and crafts an iron chestplate using the crafting table.\\n}\"}, \"mineFiveCopperOres\": {\"code\": \"async function mineFiveCopperOres(bot) {\\n  // Check if the bot already has 5 or more copper ores in the inventory\\n  const copperOres = bot.inventory.items().filter(item => item.name === \\\"copper_ore\\\");\\n  const totalCopperOres = copperOres.reduce((total, item) => total + item.count, 0);\\n  if (totalCopperOres >= 5) {\\n    bot.chat(\\\"Task already completed. There are already \\\" + totalCopperOres + \\\" copper ores in the inventory.\\\");\\n  } else {\\n    bot.chat(\\\"Need to mine \\\" + (5 - totalCopperOres) + \\\" more copper ores.\\\");\\n    // You can call the mineFiveCopperOres function from the previous response here\\n  }\\n}\", \"description\": \"async function mineFiveCopperOres(bot) {\\n    // The function checks if the bot already has 5 or more copper ores in the inventory. If not, it outputs how many more copper ores are needed to complete the task.\\n}\"}, \"equipIronChestplate\": {\"code\": \"async function equipIronChestplate(bot) {\\n  // Find the iron chestplate in the inventory\\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName.iron_chestplate.id);\\n\\n  // Equip the iron chestplate\\n  if (ironChestplate) {\\n    await bot.equip(ironChestplate, \\\"torso\\\");\\n    bot.chat(\\\"Equipped iron chestplate.\\\");\\n  } else {\\n    bot.chat(\\\"Iron chestplate not found in inventory.\\\");\\n  }\\n}\", \"description\": \"async function equipIronChestplate(bot) {\\n    // The function is about equipping an iron chestplate on the bot's torso. It first finds the iron chestplate in the inventory and then equips it. If the iron chestplate is not found in the inventory, it sends a message saying that it was not found.\\n}\"}, \"smeltRawCopper\": {\"code\": \"async function smeltRawCopper(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n\\n  // If not, craft a furnace using the available cobblestone\\n  if (!furnaceItem) {\\n    await craftFurnace(bot);\\n  }\\n\\n  // Find a suitable position to place the furnace\\n  const furnacePosition = await findSuitablePosition(bot);\\n  if (!furnacePosition) {\\n    bot.chat(\\\"Could not find a suitable position to place the furnace.\\\");\\n    return;\\n  }\\n\\n  // Place the furnace at the suitable position\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 19 raw copper using the available coal as fuel\\n  await smeltItem(bot, \\\"raw_copper\\\", \\\"coal\\\", 19);\\n  bot.chat(\\\"19 raw copper smelted.\\\");\\n}\", \"description\": \"async function smeltRawCopper(bot) {\\n    // The function is about smelting 19 raw copper using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. Finally, it smelts the raw copper using the furnace and coal as fuel.\\n}\"}, \"craftIronHelmet\": {\"code\": \"async function craftIronHelmet(bot) {\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron helmet using the crafting table\\n  await craftItem(bot, \\\"iron_helmet\\\", 1);\\n  bot.chat(\\\"Crafted an iron helmet.\\\");\\n}\", \"description\": \"async function craftIronHelmet(bot) {\\n    // The function is about crafting an iron helmet using a crafting table. First, place the crafting table near the bot. Then, craft an iron helmet using the crafting table and save it to the inventory.\\n}\"}, \"craftChest\": {\"code\": \"async function craftChest(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, craft oak planks from oak logs\\n  if (oakPlanksCount < 8) {\\n    const oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((8 - oakPlanksCount) / 4);\\n    if (oakLogsCount >= planksToCraft) {\\n      await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n      bot.chat(\\\"Crafted oak planks.\\\");\\n    } else {\\n      bot.chat(\\\"Not enough oak logs to craft oak planks.\\\");\\n      return;\\n    }\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a chest using the crafting table\\n  await craftItem(bot, \\\"chest\\\", 1);\\n  bot.chat(\\\"Crafted a chest.\\\");\\n}\", \"description\": \"async function craftChest(bot) {\\n    // The function crafts a chest using a crafting table and oak planks. If there are not enough oak planks in the inventory, it crafts oak planks from oak logs. Once there are enough oak planks, it places a crafting table near the bot and crafts a chest using the crafting table.\\n}\"}, \"equipIronSword\": {\"code\": \"async function equipIronSword(bot) {\\n  // Find the iron sword in the inventory\\n  let ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n\\n  // If the iron sword is not found in the inventory, check the chest\\n  if (!ironSword) {\\n    const chestPosition = new Vec3(89, 41, 206);\\n    const itemsToGet = {\\n      \\\"iron_sword\\\": 1\\n    };\\n    await getItemFromChest(bot, chestPosition, itemsToGet);\\n    ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n  }\\n\\n  // Equip the iron sword\\n  if (ironSword) {\\n    await bot.equip(ironSword, \\\"hand\\\");\\n    bot.chat(\\\"Equipped iron sword.\\\");\\n  } else {\\n    bot.chat(\\\"Iron sword not found in inventory or chest.\\\");\\n  }\\n}\", \"description\": \"async function equipIronSword(bot) {\\n    // The function is about equipping an iron sword. It first checks if the iron sword is in the inventory. If not, it checks a chest for the iron sword. If the iron sword is found, it is equipped in the hand. If the iron sword is not found, a message is sent to the chat.\\n}\"}, \"craftLightningRod\": {\"code\": \"async function findSuitablePosition(bot) {\\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\\n  for (const offset of offsets) {\\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\\n    const block = bot.blockAt(position);\\n    if (block.name === \\\"air\\\") {\\n      return position;\\n    }\\n  }\\n  return null;\\n}\\n\\nasync function craftLightningRod(bot) {\\n  // Find a suitable position to place the crafting table\\n  const craftingTablePosition = await findSuitablePosition(bot);\\n\\n  // Place the crafting table at the found position\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Check if there are enough copper ingots in the inventory\\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\\n\\n  // If not enough copper ingots, mine copper ores and smelt them into copper ingots\\n  if (copperIngotsCount < 3) {\\n    await mineBlock(bot, \\\"copper_ore\\\", 3 - copperIngotsCount);\\n    bot.chat(\\\"Collected copper ores.\\\");\\n    await smeltItem(bot, \\\"copper_ore\\\", \\\"coal\\\", 3 - copperIngotsCount);\\n    bot.chat(\\\"Smelted copper ores into copper ingots.\\\");\\n  }\\n\\n  // Craft a lightning rod using the crafting table\\n  await craftItem(bot, \\\"lightning_rod\\\", 1);\\n  bot.chat(\\\"Crafted a lightning rod.\\\");\\n}\", \"description\": \"async function craftLightningRod(bot) {\\n    // The function is about crafting a lightning rod. It first finds a suitable position to place the crafting table and places it there. Then it checks if there are enough copper ingots in the inventory, and if not, it mines copper ores and smelts them into copper ingots. Finally, it crafts a lightning rod using the crafting table.\\n}\"}, \"craftCopperBlock\": {\"code\": \"async function craftCopperBlock(bot) {\\n  // Check if there are enough copper ingots in the inventory\\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\\n\\n  // If not enough copper ingots, mine copper ores and smelt them into copper ingots\\n  if (copperIngotsCount < 9) {\\n    await mineBlock(bot, \\\"copper_ore\\\", 9 - copperIngotsCount);\\n    bot.chat(\\\"Collected copper ores.\\\");\\n    await smeltItem(bot, \\\"copper_ore\\\", \\\"coal\\\", 9 - copperIngotsCount);\\n    bot.chat(\\\"Smelted copper ores into copper ingots.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a copper block using the crafting table\\n  await craftItem(bot, \\\"copper_block\\\", 1);\\n  bot.chat(\\\"Crafted a copper block.\\\");\\n}\", \"description\": \"async function craftCopperBlock(bot) {\\n    // The function crafts a copper block using a crafting table. It first checks if there are enough copper ingots in the inventory, and if not, it mines copper ores and smelts them into copper ingots. Then it places a crafting table near the bot and crafts a copper block using the crafting table.\\n}\"}, \"killOneSpider\": {\"code\": \"async function killOneSpider(bot) {\\n  // Equip the iron sword\\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n  await bot.equip(ironSword, \\\"hand\\\");\\n\\n  // Find the nearest spider\\n  const spider = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const spider = bot.nearestEntity(entity => {\\n      return entity.name === \\\"spider\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    return spider;\\n  });\\n  if (!spider) {\\n    bot.chat(\\\"Could not find a spider.\\\");\\n    return;\\n  }\\n\\n  // Kill the spider using the iron sword\\n  await killMob(bot, \\\"spider\\\", 300);\\n  bot.chat(\\\"Killed a spider.\\\");\\n\\n  // Collect the dropped items\\n  await bot.pathfinder.goto(new GoalBlock(spider.position.x, spider.position.y, spider.position.z));\\n  bot.chat(\\\"Collected dropped items.\\\");\\n}\", \"description\": \"async function killOneSpider(bot) {\\n    // The function is about killing a spider using an iron sword. First, equip the iron sword in the hand. Then, explore the environment until finding the nearest spider within 32 blocks. Once a spider is found, kill it using the iron sword. After killing the spider, collect the dropped items by moving to the spider's position.\\n}\"}, \"killOneZombie\": {\"code\": \"async function killOneZombie(bot) {\\n  // Equip the iron sword\\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n  await bot.equip(ironSword, \\\"hand\\\");\\n\\n  // Find the nearest zombie\\n  const zombie = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const zombie = bot.nearestEntity(entity => {\\n      return entity.name === \\\"zombie\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    return zombie;\\n  });\\n  if (!zombie) {\\n    bot.chat(\\\"Could not find a zombie.\\\");\\n    return;\\n  }\\n\\n  // Kill the zombie using the iron sword\\n  await killMob(bot, \\\"zombie\\\", 300);\\n  bot.chat(\\\"Killed a zombie.\\\");\\n\\n  // Collect the dropped items\\n  await bot.pathfinder.goto(new GoalBlock(zombie.position.x, zombie.position.y, zombie.position.z));\\n  bot.chat(\\\"Collected dropped items.\\\");\\n}\", \"description\": \"async function killOneZombie(bot) {\\n    // The function is about killing a single zombie using an iron sword. First, equip the iron sword in the hand. Then, explore the environment until finding the nearest zombie within 32 blocks. Once a zombie is found, kill it using the iron sword and collect the dropped items.\\n}\"}, \"craftIronLeggingsAndBoots\": {\"code\": \"async function craftIronLeggingsAndBoots(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n\\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\\n  if (ironIngotsCount < 11) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 11 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 11 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft iron leggings using the crafting table\\n  await craftItem(bot, \\\"iron_leggings\\\", 1);\\n  bot.chat(\\\"Crafted iron leggings.\\\");\\n\\n  // Craft iron boots using the crafting table\\n  await craftItem(bot, \\\"iron_boots\\\", 1);\\n  bot.chat(\\\"Crafted iron boots.\\\");\\n}\", \"description\": \"async function craftIronLeggingsAndBoots(bot) {\\n    // The function crafts iron leggings and boots using a crafting table. If there are not enough iron ingots in the inventory, the bot mines iron ores and smelts them into iron ingots. Then, the bot places a crafting table near itself and crafts iron leggings and boots using the crafting table.\\n}\"}, \"equipIronArmor\": {\"code\": \"async function equipIronArmor(bot) {\\n  // Find the iron_leggings, iron_boots, and iron_helmet in the inventory\\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName.iron_leggings.id);\\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName.iron_boots.id);\\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName.iron_helmet.id);\\n\\n  // Equip the iron_leggings, iron_boots, and iron_helmet in the appropriate slots (legs, feet, and head)\\n  if (ironLeggings) {\\n    await bot.equip(ironLeggings, \\\"legs\\\");\\n    bot.chat(\\\"Equipped iron leggings.\\\");\\n  } else {\\n    bot.chat(\\\"Iron leggings not found in inventory.\\\");\\n  }\\n  if (ironBoots) {\\n    await bot.equip(ironBoots, \\\"feet\\\");\\n    bot.chat(\\\"Equipped iron boots.\\\");\\n  } else {\\n    bot.chat(\\\"Iron boots not found in inventory.\\\");\\n  }\\n  if (ironHelmet) {\\n    await bot.equip(ironHelmet, \\\"head\\\");\\n    bot.chat(\\\"Equipped iron helmet.\\\");\\n  } else {\\n    bot.chat(\\\"Iron helmet not found in inventory.\\\");\\n  }\\n}\", \"description\": \"async function equipIronArmor(bot) {\\n    // The function is about equipping iron armor (leggings, boots, and helmet) in the appropriate slots (legs, feet, and head) if they are available in the inventory. If any of the items are not found in the inventory, the function will output a message indicating that the item is not available.\\n}\"}, \"craftShieldImproved\": {\"code\": \"async function craftShieldImproved(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  let oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n\\n  // If not, check if there are enough oak logs in the inventory\\n  if (oakPlanksCount < 6) {\\n    let oakLogsCount = bot.inventory.count(mcData.itemsByName.oak_log.id);\\n    const planksToCraft = Math.ceil((6 - oakPlanksCount) / 4);\\n\\n    // If not, explore to find and mine oak logs\\n    if (oakLogsCount < planksToCraft) {\\n      await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n        const oak_log = bot.findBlock({\\n          matching: mcData.blocksByName[\\\"oak_log\\\"].id,\\n          maxDistance: 32\\n        });\\n        return oak_log;\\n      });\\n      await mineBlock(bot, \\\"oak_log\\\", planksToCraft - oakLogsCount);\\n      bot.chat(\\\"Collected oak logs.\\\");\\n    }\\n\\n    // Craft oak planks from oak logs\\n    await craftItem(bot, \\\"oak_planks\\\", planksToCraft);\\n    bot.chat(\\\"Crafted oak planks.\\\");\\n    oakPlanksCount = bot.inventory.count(mcData.itemsByName.oak_planks.id);\\n  }\\n\\n  // Check if there are enough iron ingots in the inventory\\n  let ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n\\n  // If not, explore to find and mine iron ores\\n  if (ironIngotsCount < 1) {\\n    await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\\n      const iron_ore = bot.findBlock({\\n        matching: mcData.blocksByName[\\\"iron_ore\\\"].id,\\n        maxDistance: 32\\n      });\\n      return iron_ore;\\n    });\\n    await mineBlock(bot, \\\"iron_ore\\\", 1);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n\\n    // Smelt iron ores into iron ingots\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 1);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a shield using the crafting table\\n  await craftItem(bot, \\\"shield\\\", 1);\\n  bot.chat(\\\"Crafted a shield.\\\");\\n}\", \"description\": \"async function craftShieldImproved(bot) {\\n    // The function crafts a shield using oak planks and iron ingots. It checks if there are enough oak planks and iron ingots in the inventory, and if not, it explores the environment to find and collect the required materials. It then places a crafting table near the bot and crafts a shield using the crafting table.\\n}\"}, \"craftBucket\": {\"code\": \"async function craftBucket(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n\\n  // If not enough iron ingots, mine iron ores and smelt them into iron ingots\\n  if (ironIngotsCount < 3) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Collected iron ores.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 3 - ironIngotsCount);\\n    bot.chat(\\\"Smelted iron ores into iron ingots.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a bucket using the crafting table\\n  await craftItem(bot, \\\"bucket\\\", 1);\\n  bot.chat(\\\"Crafted a bucket.\\\");\\n}\", \"description\": \"async function craftBucket(bot) {\\n    // The function crafts a bucket using a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into iron ingots. Then, it places a crafting table near the bot and crafts a bucket using the crafting table.\\n}\"}, \"fillBucketWithWater\": {\"code\": \"async function fillBucketWithWater(bot) {\\n  // Find a water block nearby\\n  const waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const water = bot.findBlock({\\n      matching: mcData.blocksByName.water.id,\\n      maxDistance: 32,\\n    });\\n    return water;\\n  });\\n  if (!waterBlock) {\\n    bot.chat(\\\"Could not find water.\\\");\\n    return;\\n  }\\n\\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\\n  // Go to the water block\\n  await bot.pathfinder.goto(\\n    new GoalGetToBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z)\\n  );\\n\\n  // Equip the bucket\\n  const bucket = bot.inventory.findInventoryItem(mcData.itemsByName.bucket.id);\\n  await bot.equip(bucket, \\\"hand\\\");\\n\\n  // Look at the water block\\n  await bot.lookAt(waterBlock.position);\\n\\n  // Activate the bucket to collect water\\n  await bot.activateItem();\\n  bot.chat(\\\"Filled the bucket with water.\\\");\\n}\\n\", \"description\": \"async function fillBucketWithWater(bot) {\\n    // This function fills a bucket with water by first finding a nearby water block. After locating the water block, the bot moves to it and equips the bucket in its hand. The bot then looks at the water block and activates the bucket to collect water.\\n}\"}, \"craftIronShovel\": {\"code\": \"async function craftIronShovel(bot) {\\n  // Check if there are enough iron ingots and sticks in the inventory\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n\\n  // If not enough iron ingots or sticks, collect the required items\\n  if (ironIngotsCount < 1) {\\n    await mineBlock(bot, \\\"iron_ore\\\", 1);\\n    bot.chat(\\\"Collected iron ore.\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", 1);\\n    bot.chat(\\\"Smelted iron ore into iron ingot.\\\");\\n  }\\n  if (sticksCount < 2) {\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Crafted sticks.\\\");\\n  }\\n\\n  // Find a suitable position to place the crafting table\\n  const suitablePosition = bot.entity.position.offset(1, 0, 0);\\n  const block = bot.blockAt(suitablePosition);\\n  if (block.name === \\\"grass_block\\\" || block.name === \\\"dirt\\\") {\\n    await bot.dig(block);\\n  }\\n\\n  // Place the crafting table at the suitable position\\n  await placeItem(bot, \\\"crafting_table\\\", suitablePosition);\\n\\n  // Craft an iron shovel using the crafting table\\n  await craftItem(bot, \\\"iron_shovel\\\", 1);\\n  bot.chat(\\\"Crafted an iron shovel.\\\");\\n}\", \"description\": \"async function craftIronShovel(bot) {\\n    // The function crafts an iron shovel using a crafting table. It checks if there are enough iron ingots and sticks in the inventory, and if not, collects the required items. It finds a suitable position to place the crafting table and places it there. Then, it crafts an iron shovel using the crafting table.\\n}\"}, \"obtainOneMoreAcaciaLog\": {\"code\": \"async function obtainOneMoreAcaciaLog(bot) {\\n  // Check the initial inventory for acacia logs\\n  const initialAcaciaLogs = bot.inventory.count(mcData.itemsByName.acacia_log.id);\\n\\n  // If the number of acacia logs is less than 5, find and mine one more acacia log\\n  if (initialAcaciaLogs < 5) {\\n    const acaciaLog = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      return bot.findBlock({\\n        matching: block => block.name === \\\"acacia_log\\\",\\n        maxDistance: 32\\n      });\\n    });\\n    if (!acaciaLog) {\\n      bot.chat(\\\"Could not find an acacia log.\\\");\\n      return;\\n    }\\n    await mineBlock(bot, \\\"acacia_log\\\", 1);\\n    bot.chat(\\\"1 more acacia log obtained.\\\");\\n  }\\n\\n  // Check the final number of acacia logs in the inventory\\n  const finalAcaciaLogs = bot.inventory.count(mcData.itemsByName.acacia_log.id);\\n  if (finalAcaciaLogs >= 5) {\\n    bot.chat(\\\"Successfully obtained 5 acacia logs.\\\");\\n  } else {\\n    bot.chat(\\\"Failed to obtain 5 acacia logs.\\\");\\n  }\\n}\", \"description\": \"async function obtainOneMoreAcaciaLog(bot) {\\n    // The function checks if there are less than 5 acacia logs in the inventory, and if so, finds and mines one more acacia log. If the bot successfully obtains 5 acacia logs, it sends a success message, otherwise it sends a failure message.\\n}\"}, \"craftAcaciaPlanksAndSticks\": {\"code\": \"async function craftAcaciaPlanksAndSticks(bot) {\\n  // Check if there are enough acacia logs in the inventory\\n  const acaciaLogsCount = bot.inventory.count(mcData.itemsByName.acacia_log.id);\\n\\n  // If not, mine more acacia logs\\n  if (acaciaLogsCount < 5) {\\n    await mineBlock(bot, \\\"acacia_log\\\", 5 - acaciaLogsCount);\\n    bot.chat(\\\"Mined acacia logs.\\\");\\n  }\\n\\n  // Craft 20 acacia planks from acacia logs\\n  await craftItem(bot, \\\"acacia_planks\\\", 5);\\n  bot.chat(\\\"Crafted 20 acacia planks.\\\");\\n\\n  // Check if there are enough acacia planks in the inventory to craft 10 sticks\\n  const acaciaPlanksCount = bot.inventory.count(mcData.itemsByName.acacia_planks.id);\\n\\n  // If not, mine more acacia logs and craft more acacia planks\\n  if (acaciaPlanksCount < 5) {\\n    await mineBlock(bot, \\\"acacia_log\\\", 5 - acaciaLogsCount);\\n    bot.chat(\\\"Mined more acacia logs.\\\");\\n    await craftItem(bot, \\\"acacia_planks\\\", 5 - acaciaPlanksCount);\\n    bot.chat(\\\"Crafted more acacia planks.\\\");\\n  }\\n\\n  // Craft 10 sticks from acacia planks\\n  await craftItem(bot, \\\"stick\\\", 3);\\n  bot.chat(\\\"Crafted 10 sticks.\\\");\\n}\", \"description\": \"async function craftAcaciaPlanksAndSticks(bot) {\\n    // The function is about crafting 20 acacia planks and 10 sticks. It checks if there are enough acacia logs in the inventory, and if not, it mines more acacia logs. Then it crafts 20 acacia planks from the acacia logs. If there are not enough acacia planks in the inventory to craft 10 sticks, it mines more acacia logs and crafts more acacia planks. Finally, it crafts 10 sticks from the acacia planks.\\n}\"}, \"eatTwoCookedMutton\": {\"code\": \"async function eatTwoCookedMutton(bot) {\\n  // Check if there are 2 cooked mutton in the inventory\\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\\n  if (!cookedMutton || cookedMutton.count < 2) {\\n    bot.chat(\\\"Not enough cooked mutton in the inventory.\\\");\\n    return;\\n  }\\n\\n  // Equip the cooked mutton in the bot's hand\\n  await bot.equip(cookedMutton, \\\"hand\\\");\\n\\n  // Consume the cooked mutton twice\\n  await bot.consume();\\n  await bot.consume();\\n\\n  // Send a chat message to indicate the task is completed\\n  bot.chat(\\\"Ate 2 cooked mutton.\\\");\\n}\", \"description\": \"async function eatTwoCookedMutton(bot) {\\n    // The function is about eating two cooked muttons. It checks if there are at least 2 cooked muttons in the inventory, and if not, it returns. If there are 2 or more cooked muttons, it equips one in the bot's hand and consumes it twice. Finally, it sends a chat message to indicate that the task is completed.\\n}\"}, \"collectBamboo\": {\"code\": \"async function collectBamboo(bot) {\\n  // Equip the iron sword\\n  const ironSword = bot.inventory.findInventoryItem(mcData.itemsByName.iron_sword.id);\\n  await bot.equip(ironSword, \\\"hand\\\");\\n\\n  // Find bamboo plants using the exploreUntil function\\n  const bambooPlants = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const bambooPlants = bot.findBlocks({\\n      matching: block => block.name === \\\"bamboo\\\",\\n      maxDistance: 32,\\n      count: 10\\n    });\\n    return bambooPlants.length >= 10 ? bambooPlants : null;\\n  });\\n  if (!bambooPlants) {\\n    bot.chat(\\\"Could not find enough bamboo plants.\\\");\\n    return;\\n  }\\n\\n  // Break 10 bamboo plants using the iron sword\\n  for (const bambooPlant of bambooPlants) {\\n    const block = bot.blockAt(bambooPlant);\\n    await bot.dig(block);\\n  }\\n  bot.chat(\\\"Broke 10 bamboo plants.\\\");\\n\\n  // Collect the dropped bamboo items\\n  for (const bambooPlant of bambooPlants) {\\n    await bot.pathfinder.goto(new GoalBlock(bambooPlant.x, bambooPlant.y, bambooPlant.z));\\n  }\\n  bot.chat(\\\"Collected 10 bamboo.\\\");\\n}\", \"description\": \"async function collectBamboo(bot) {\\n    // The function is about collecting 10 bamboo plants. It equips the iron sword and uses the `exploreUntil` function to find 10 bamboo plants within a certain distance. If enough bamboo plants are found, it breaks them using the iron sword and collects the dropped bamboo items by moving to their location. If not enough bamboo plants are found, it returns an error message.\\n}\"}, \"craftScaffolding\": {\"code\": \"async function craftScaffolding(bot) {\\n  // Check if we have a crafting table in the inventory\\n  const craftingTableCount = bot.inventory.count(mcData.itemsByName.crafting_table.id);\\n\\n  // If not, craft a crafting table\\n  if (craftingTableCount === 0) {\\n    await craftItem(bot, \\\"crafting_table\\\", 1);\\n    bot.chat(\\\"Crafted a crafting table.\\\");\\n  }\\n\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft 10 scaffolding using the crafting table\\n  await craftItem(bot, \\\"scaffolding\\\", 1);\\n  bot.chat(\\\"Crafted 10 scaffolding.\\\");\\n}\", \"description\": \"async function craftScaffolding(bot) {\\n    // The function is about crafting 10 scaffolding using a crafting table. First, it checks if there is a crafting table in the inventory. If not, it crafts one. Then, it places the crafting table near the bot. After that, it crafts 10 scaffolding using the crafting table and saves the event.\\n}\"}, \"collectFiveCactusBlocks\": {\"code\": \"async function collectFiveCactusBlocks(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find 5 cactus blocks using the exploreUntil function\\n  const cactusBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const cactusBlocks = bot.findBlocks({\\n      matching: block => block.name === \\\"cactus\\\",\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return cactusBlocks.length >= 5 ? cactusBlocks : null;\\n  });\\n  if (!cactusBlocks) {\\n    bot.chat(\\\"Could not find enough cactus blocks.\\\");\\n    return;\\n  }\\n\\n  // Mine the 5 cactus blocks using the mineBlock function\\n  await mineBlock(bot, \\\"cactus\\\", 5);\\n  bot.chat(\\\"5 cactus blocks mined.\\\");\\n\\n  // Collect the dropped cactus items\\n  for (const cactusBlock of cactusBlocks) {\\n    await bot.pathfinder.goto(new GoalBlock(cactusBlock.x, cactusBlock.y, cactusBlock.z));\\n  }\\n  bot.chat(\\\"Collected 5 cactus blocks.\\\");\\n}\", \"description\": \"async function collectFiveCactusBlocks(bot) {\\n    // The function is about collecting 5 cactus blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 cactus blocks using the `exploreUntil` function. If 5 cactus blocks are not found, return. Otherwise, mine the 5 cactus blocks using the `mineBlock` function. Finally, collect the dropped cactus items by moving to each block's location.\\n}\"}, \"smeltCactusIntoGreenDye\": {\"code\": \"async function smeltCactusIntoGreenDye(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnaceItem = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n\\n  // If not, craft a furnace using the available cobblestone\\n  if (!furnaceItem) {\\n    await craftFurnace(bot);\\n  }\\n\\n  // Find a suitable position to place the furnace\\n  const furnacePosition = await findSuitablePosition(bot);\\n  if (!furnacePosition) {\\n    bot.chat(\\\"Could not find a suitable position to place the furnace.\\\");\\n    return;\\n  }\\n\\n  // Place the furnace at the suitable position\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 5 cactus using the available coal as fuel\\n  await smeltItem(bot, \\\"cactus\\\", \\\"coal\\\", 5);\\n  bot.chat(\\\"5 cactus smelted into green dye.\\\");\\n}\", \"description\": \"async function smeltCactusIntoGreenDye(bot) {\\n    // The function is about smelting 5 cactus into green dye using a furnace and coal as fuel. It checks if there is a furnace in the inventory, and if not, it crafts one. Then it finds a suitable position to place the furnace and places it there. Finally, it smelts the cactus using coal as fuel and saves the event of smelting 5 cactus into green dye.\\n}\"}, \"craftShears\": {\"code\": \"async function craftShears(bot) {\\n  // Place the crafting table near the bot\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a pair of shears using the crafting table\\n  await craftItem(bot, \\\"shears\\\", 1);\\n  bot.chat(\\\"Crafted a pair of shears.\\\");\\n}\", \"description\": \"async function craftShears(bot) {\\n    // The function is about crafting a pair of shears. First, place a crafting table near the bot. Then, craft a pair of shears using the crafting table. Finally, the bot will chat that it has crafted a pair of shears.\\n}\"}}"
  },
  {
    "path": "skill_library/trial2/skill/code/catchFiveFishSafely.js",
    "content": "async function catchFiveFishSafely(bot) {\n  // Check if the bot has a fishing rod in its inventory\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  if (!fishingRod) {\n    await craftFishingRod(bot);\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  }\n\n  // Find a nearby water block\n  let waterBlock;\n  while (!waterBlock) {\n    waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundWaterBlock = bot.findBlock({\n        matching: mcData.blocksByName.water.id,\n        maxDistance: 32\n      });\n      return foundWaterBlock;\n    });\n    if (!waterBlock) {\n      bot.chat(\"No path to the water block. Trying to find another water block...\");\n    }\n  }\n\n  // Move to a block adjacent to the water block\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\n\n  // Look at the water block\n  await bot.lookAt(waterBlock.position);\n\n  // Equip the fishing rod\n  await bot.equip(fishingRod, \"hand\");\n\n  // Fish in the water 5 times\n  for (let i = 0; i < 5; i++) {\n    try {\n      await bot.fish();\n      bot.chat(`Fish ${i + 1} caught.`);\n    } catch (error) {\n      if (error.message === \"Fishing cancelled\") {\n        bot.chat(\"Fishing was cancelled. Trying again...\");\n        i--; // Retry the same iteration\n      } else {\n        throw error;\n      }\n    }\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/catchThreeFish.js",
    "content": "async function catchThreeFish(bot) {\n  // Check if the bot has a fishing rod in its inventory\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  if (!fishingRod) {\n    await craftFishingRod(bot);\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  }\n\n  // Find a nearby water block\n  let waterBlock;\n  while (!waterBlock) {\n    waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundWaterBlock = bot.findBlock({\n        matching: mcData.blocksByName.water.id,\n        maxDistance: 32\n      });\n      return foundWaterBlock;\n    });\n    if (!waterBlock) {\n      bot.chat(\"No path to the water block. Trying to find another water block...\");\n    }\n  }\n\n  // Move to a block adjacent to the water block\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\n\n  // Look at the water block\n  await bot.lookAt(waterBlock.position);\n\n  // Equip the fishing rod\n  await bot.equip(fishingRod, \"hand\");\n\n  // Fish in the water 3 times\n  for (let i = 0; i < 3; i++) {\n    try {\n      await bot.fish();\n      bot.chat(`Fish ${i + 1} caught.`);\n    } catch (error) {\n      if (error.message === \"Fishing cancelled\") {\n        bot.chat(\"Fishing was cancelled. Trying again...\");\n        i--; // Retry the same iteration\n      } else {\n        throw error;\n      }\n    }\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/checkStonePickaxe.js",
    "content": "async function checkStonePickaxe(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (stonePickaxe) {\n    bot.chat(\"The bot already has a stone pickaxe in its inventory.\");\n  } else {\n    bot.chat(\"The bot does not have a stone pickaxe in its inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/chopDownSpruceLogs.js",
    "content": "async function chopDownSpruceLogs(bot) {\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\n  const logsToMine = 5 - spruceLogCount;\n  if (logsToMine > 0) {\n    bot.chat(\"Chopping down spruce logs...\");\n    await mineBlock(bot, \"spruce_log\", logsToMine);\n    bot.chat(\"Chopped down 5 spruce logs.\");\n  } else {\n    bot.chat(\"Already have 5 spruce logs in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/chopDownSpruceLogsV2.js",
    "content": "async function chopDownSpruceLogs(bot) {\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\n  const logsToMine = 5 - spruceLogCount;\n  if (logsToMine > 0) {\n    bot.chat(\"Chopping down spruce logs...\");\n    await mineBlock(bot, \"spruce_log\", logsToMine);\n    bot.chat(\"Chopped down 5 spruce logs.\");\n  } else {\n    bot.chat(\"Already have 5 spruce logs in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/chopSpruceLogs.js",
    "content": "async function chopSpruceLogs(bot) {\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\n  const logsToMine = 3 - spruceLogCount;\n  if (logsToMine > 0) {\n    bot.chat(\"Chopping down spruce logs...\");\n    await mineBlock(bot, \"spruce_log\", logsToMine);\n    bot.chat(\"Chopped down 3 spruce logs.\");\n  } else {\n    bot.chat(\"Already have 3 spruce logs in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/collectWaterWithBucket.js",
    "content": "async function collectWaterWithBucket(bot) {\n  const waterBlock = bot.findBlock({\n    matching: mcData.blocksByName.water.id,\n    maxDistance: 32\n  });\n  if (!waterBlock) {\n    bot.chat(\"No water block found nearby. Exploring...\");\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundWaterBlock = bot.findBlock({\n        matching: mcData.blocksByName.water.id,\n        maxDistance: 32\n      });\n      return foundWaterBlock;\n    });\n  }\n  const bucket = bot.inventory.findInventoryItem(mcData.itemsByName.bucket.id);\n  await bot.equip(bucket, \"hand\");\n  await bot.lookAt(waterBlock.position);\n  await bot.activateItem();\n  bot.chat(\"Water collected with bucket.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/cookMutton.js",
    "content": "async function cookMutton(bot) {\n  const rawMuttonCount = bot.inventory.count(mcData.itemsByName.mutton.id);\n  if (rawMuttonCount < 5) {\n    bot.chat(\"Not enough raw mutton to cook. Please collect more first.\");\n    return;\n  }\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  const requiredCoal = 5;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more coal...\");\n    await mineBlock(bot, \"coal_ore\", requiredCoal - coalCount);\n  }\n  await smeltItem(bot, \"mutton\", \"coal\", 5);\n  bot.chat(\"5 mutton cooked.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftBucket.js",
    "content": "async function craftBucket(bot) {\n  const requiredIronIngots = 3;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots to craft a bucket.\");\n    return;\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"bucket\", 1);\n  bot.chat(\"Bucket crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftChest.js",
    "content": "async function craftChest(bot) {\n  const requiredPlanks = 8;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Not enough spruce_planks. Mining a spruce_log and crafting more...\");\n    await mineBlock(bot, \"spruce_log\", 1);\n    await craftItem(bot, \"spruce_planks\", 1);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  bot.chat(\"Crafting a chest...\");\n  await craftItem(bot, \"chest\", 1);\n  bot.chat(\"Chest crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftEightSticks.js",
    "content": "async function craftEightSticks(bot) {\n  const requiredPlanks = 2;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Not enough spruce_planks. Mining a spruce_log and crafting more...\");\n    await mineBlock(bot, \"spruce_log\", 1);\n    await craftItem(bot, \"spruce_planks\", 1);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stick\", 2);\n  bot.chat(\"8 sticks crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftEightTorches.js",
    "content": "async function craftEightTorches(bot) {\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"torch\", 1);\n  bot.chat(\"8 torches crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftFishingRod.js",
    "content": "async function craftFishingRod(bot) {\n  // Check if we have enough strings\n  const requiredStrings = 2;\n  const stringsCount = bot.inventory.count(mcData.itemsByName.string.id);\n  if (stringsCount < requiredStrings) {\n    // Find and kill spiders to obtain strings\n    while (bot.inventory.count(mcData.itemsByName.string.id) < requiredStrings) {\n      bot.chat(\"Finding a spider to obtain strings...\");\n      const spider = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n        const spider = bot.nearestEntity(entity => {\n          return entity.name === \"spider\" && entity.position.distanceTo(bot.entity.position) < 32;\n        });\n        return spider;\n      });\n      if (spider) {\n        bot.chat(\"Spider found. Killing it...\");\n        await killMob(bot, \"spider\", 300);\n        bot.chat(\"Spider killed.\");\n      } else {\n        bot.chat(\"Could not find a spider. Trying again...\");\n      }\n    }\n  }\n\n  // Place a crafting table if not already placed\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n\n  // Craft a fishing rod using the 3 sticks and 2 strings\n  await craftItem(bot, \"fishing_rod\", 1);\n  bot.chat(\"Fishing rod crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftFurnace.js",
    "content": "async function craftFurnace(bot) {\n  const requiredCobblestones = 8;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones to craft a furnace.\");\n    return;\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"furnace\", 1);\n  bot.chat(\"Furnace crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronChestplate.js",
    "content": "async function craftIronChestplate(bot) {\n  const requiredIronIngots = 8;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots. Mining iron ores...\");\n    await mineBlock(bot, \"iron_ore\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ores mined. Smelting iron ingots...\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ingots smelted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"iron_chestplate\", 1);\n  bot.chat(\"Iron chestplate crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronHelmet.js",
    "content": "async function craftIronHelmet(bot) {\n  const requiredIronIngots = 5;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots to craft an iron helmet.\");\n    return;\n  }\n  let craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n    // Update the craftingTable variable after placing it\n    craftingTable = bot.blockAt(craftingTablePosition);\n  }\n  await craftItem(bot, \"iron_helmet\", 1);\n  bot.chat(\"Iron helmet crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronLeggingsAndBoots.js",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n  const requiredIronIngots = 11; // 7 for leggings, 4 for boots\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots. Mining iron ores...\");\n    await mineBlock(bot, \"iron_ore\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ores mined. Smelting iron ingots...\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ingots smelted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"iron_leggings\", 1);\n  bot.chat(\"Iron leggings crafted.\");\n  await craftItem(bot, \"iron_boots\", 1);\n  bot.chat(\"Iron boots crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronPickaxe.js",
    "content": "async function craftIronPickaxe(bot) {\n  const requiredIronIngots = 3;\n  const requiredSticks = 2;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (ironIngotsCount < requiredIronIngots || sticksCount < requiredSticks) {\n    bot.chat(\"Not enough iron ingots or sticks to craft an iron pickaxe.\");\n    return;\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"iron_pickaxe\", 1);\n  bot.chat(\"Iron pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronPickaxeWithMaterials.js",
    "content": "async function craftIronPickaxeWithMaterials(bot) {\n  const requiredIronIngots = 3;\n  const requiredSticks = 2;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots. Mining iron ores...\");\n    await mineBlock(bot, \"iron_ore\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ores mined. Smelting iron ingots...\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ingots smelted.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"iron_pickaxe\", 1);\n  bot.chat(\"Iron pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftIronSword.js",
    "content": "async function craftIronSword(bot) {\n  const requiredIronIngots = 2;\n  const requiredSticks = 1;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots. Mining iron ores...\");\n    await mineBlock(bot, \"iron_ore\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ores mined. Smelting iron ingots...\");\n    await smeltItem(bot, \"iron_ore\", \"coal\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ingots smelted.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"iron_sword\", 1);\n  bot.chat(\"Iron sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftShieldWithFurnace.js",
    "content": "async function craftShieldWithFurnace(bot) {\n  const requiredIronIngots = 1;\n  const requiredSprucePlanks = 6;\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\n  const sprucePlanksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  if (ironIngotsCount < requiredIronIngots) {\n    bot.chat(\"Not enough iron ingots. Smelting iron ingots...\");\n    const furnace = bot.findBlock({\n      matching: mcData.blocksByName.furnace.id,\n      maxDistance: 32\n    });\n    if (!furnace) {\n      const furnacePosition = bot.entity.position.offset(1, 0, 0);\n      await placeItem(bot, \"furnace\", furnacePosition);\n      bot.chat(\"Furnace placed.\");\n    }\n    await smeltItem(bot, \"raw_iron\", \"coal\", requiredIronIngots - ironIngotsCount);\n    bot.chat(\"Iron ingots smelted.\");\n  }\n  if (sprucePlanksCount < requiredSprucePlanks) {\n    bot.chat(\"Not enough spruce planks. Crafting more...\");\n    await craftItem(bot, \"spruce_planks\", requiredSprucePlanks - sprucePlanksCount);\n    bot.chat(\"Spruce planks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"shield\", 1);\n  bot.chat(\"Shield crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftSixteenTorches.js",
    "content": "async function craftSixteenTorches(bot) {\n  const requiredSticks = 4;\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"torch\", 2);\n  bot.chat(\"16 torches crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftSpyglass.js",
    "content": "async function craftSpyglass(bot) {\n  const requiredCopperIngots = 2;\n  const requiredAmethystShards = 1;\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\n  const amethystShardsCount = bot.inventory.count(mcData.itemsByName.amethyst_shard.id);\n  if (copperIngotsCount < requiredCopperIngots || amethystShardsCount < requiredAmethystShards) {\n    bot.chat(\"Not enough copper ingots or amethyst shards to craft a spyglass.\");\n    return;\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"spyglass\", 1);\n  bot.chat(\"Spyglass crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftSticks.js",
    "content": "async function craftSticks(bot) {\n  const requiredPlanks = 2;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Not enough spruce_planks. Mining a spruce_log and crafting more...\");\n    await mineBlock(bot, \"spruce_log\", 1);\n    await craftItem(bot, \"spruce_planks\", 1);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n  bot.chat(\"Crafting_table placed.\");\n  await craftItem(bot, \"stick\", 1);\n  bot.chat(\"4 sticks crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftStoneAxe.js",
    "content": "async function craftStoneAxe(bot) {\n  const requiredCobblestones = 3;\n  const requiredSticks = 2;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones. Mining more...\");\n    await mineBlock(bot, \"stone\", requiredCobblestones - cobblestoneCount);\n    bot.chat(\"Cobblestones mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stone_axe\", 1);\n  bot.chat(\"Stone axe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftStoneHoe.js",
    "content": "async function craftStoneHoe(bot) {\n  const requiredCobblestones = 2;\n  const requiredSticks = 2;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones. Mining more...\");\n    await mineBlock(bot, \"stone\", requiredCobblestones - cobblestoneCount);\n    bot.chat(\"Cobblestones mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stone_hoe\", 1);\n  bot.chat(\"Stone hoe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftStonePickaxe.js",
    "content": "async function craftStonePickaxe(bot) {\n  const requiredCobblestones = 3;\n  const requiredSticks = 2;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones. Mining more...\");\n    await mineBlock(bot, \"stone\", requiredCobblestones - cobblestoneCount);\n    bot.chat(\"Cobblestones mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  let craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stone_pickaxe\", 1);\n  bot.chat(\"Stone pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftStoneShovel.js",
    "content": "async function craftStoneShovel(bot) {\n  const requiredCobblestones = 1;\n  const requiredSticks = 2;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones. Mining more...\");\n    await mineBlock(bot, \"stone\", requiredCobblestones - cobblestoneCount);\n    bot.chat(\"Cobblestones mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stone_shovel\", 1);\n  bot.chat(\"Stone shovel crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftStoneSword.js",
    "content": "async function craftStoneSword(bot) {\n  const requiredCobblestones = 2;\n  const requiredSticks = 1;\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (cobblestoneCount < requiredCobblestones) {\n    bot.chat(\"Not enough cobblestones. Mining more...\");\n    await mineBlock(bot, \"stone\", requiredCobblestones - cobblestoneCount);\n    bot.chat(\"Cobblestones mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftSticks(bot);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"stone_sword\", 1);\n  bot.chat(\"Stone sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftTorches.js",
    "content": "async function craftTorches(bot) {\n  const requiredCoal = 2;\n  const requiredSticks = 2;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more...\");\n    await mineBlock(bot, \"coal_ore\", requiredCoal - coalCount);\n    bot.chat(\"Coal mined.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", 1);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"torch\", 1);\n  bot.chat(\"8 torches crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftTwentySprucePlanks.js",
    "content": "async function craftTwentySprucePlanks(bot) {\n  const requiredLogs = 5;\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\n  const logsToMine = requiredLogs - spruceLogCount;\n  if (logsToMine > 0) {\n    bot.chat(\"Not enough spruce logs. Chopping down more...\");\n    await mineBlock(bot, \"spruce_log\", logsToMine);\n    bot.chat(\"Spruce logs chopped down.\");\n  }\n  bot.chat(\"Crafting 20 spruce planks...\");\n  await craftItem(bot, \"spruce_planks\", requiredLogs);\n  bot.chat(\"20 spruce planks crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftWhiteBedWithExploration.js",
    "content": "async function craftWhiteBedWithExploration(bot) {\n  // Step 1: Explore the area to find and kill sheep to collect the required wool blocks if needed\n  const requiredWool = 3;\n  const woolCount = bot.inventory.count(mcData.itemsByName.white_wool.id);\n  if (woolCount < requiredWool) {\n    bot.chat(\"Collecting wool from sheep...\");\n    for (let i = 0; i < requiredWool - woolCount; i++) {\n      const sheep = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n        const sheep = bot.nearestEntity(entity => {\n          return entity.name === \"sheep\" && entity.position.distanceTo(bot.entity.position) < 32;\n        });\n        return sheep;\n      });\n      if (sheep) {\n        await killMob(bot, \"sheep\");\n      } else {\n        bot.chat(\"No sheep found. Please try again later.\");\n        return;\n      }\n    }\n    bot.chat(\"Wool collected.\");\n  }\n\n  // Step 2: Craft 2 more spruce planks if needed\n  const requiredPlanks = 3;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Crafting more spruce_planks...\");\n    await craftItem(bot, \"spruce_planks\", requiredPlanks - planksCount);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n\n  // Step 3: Place a crafting table if not already placed\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n\n  // Step 4: Craft a white bed using the 3 white wool blocks and 3 spruce planks\n  bot.chat(\"Crafting a white bed...\");\n  await craftItem(bot, \"white_bed\", 1);\n  bot.chat(\"White bed crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftWoodenHoe.js",
    "content": "async function craftWoodenHoe(bot) {\n  const requiredPlanks = 2;\n  const requiredSticks = 2;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Not enough spruce_planks. Crafting more...\");\n    await craftItem(bot, \"spruce_planks\", requiredPlanks - planksCount);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTable = bot.findBlock({\n    matching: mcData.blocksByName.crafting_table.id,\n    maxDistance: 32\n  });\n  if (!craftingTable) {\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    bot.chat(\"Crafting_table placed.\");\n  }\n  await craftItem(bot, \"wooden_hoe\", 1);\n  bot.chat(\"Wooden hoe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftWoodenPickaxe.js",
    "content": "async function craftWoodenPickaxe(bot) {\n  const requiredPlanks = 3;\n  const requiredSticks = 2;\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\n  if (planksCount < requiredPlanks) {\n    bot.chat(\"Not enough spruce_planks. Crafting more...\");\n    await craftItem(bot, \"spruce_planks\", requiredPlanks - planksCount);\n    bot.chat(\"Spruce_planks crafted.\");\n  }\n  if (sticksCount < requiredSticks) {\n    bot.chat(\"Not enough sticks. Crafting more...\");\n    await craftItem(bot, \"stick\", requiredSticks - sticksCount);\n    bot.chat(\"Sticks crafted.\");\n  }\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n  bot.chat(\"Crafting_table placed.\");\n  await craftItem(bot, \"wooden_pickaxe\", 1);\n  bot.chat(\"Wooden pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/craftWoodenPlanks.js",
    "content": "async function craftWoodenPlanks(bot) {\n  const logNames = [\"oak_log\", \"birch_log\", \"spruce_log\", \"jungle_log\", \"acacia_log\", \"dark_oak_log\", \"mangrove_log\"];\n  const plankNames = [\"oak_planks\", \"birch_planks\", \"spruce_planks\", \"jungle_planks\", \"acacia_planks\", \"dark_oak_planks\", \"mangrove_planks\"];\n  const logInInventory = logNames.find(logName => bot.inventory.count(mcData.itemsByName[logName].id) > 0);\n  if (!logInInventory) {\n    bot.chat(\"No wooden log in inventory. Mining a wooden log...\");\n    await mineWoodLog(bot);\n  }\n  const logIndex = logNames.indexOf(logInInventory);\n  const plankName = plankNames[logIndex];\n  bot.chat(`Crafting 4 ${plankName}...`);\n  await craftItem(bot, plankName, 1);\n  bot.chat(`4 ${plankName} crafted.`);\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/eatCookedMutton.js",
    "content": "async function eatCookedMutton(bot) {\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\n  await bot.equip(cookedMutton, \"hand\");\n  await bot.consume();\n  bot.chat(\"Cooked mutton eaten.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/eatCookedMuttonV2.js",
    "content": "async function eatCookedMutton(bot) {\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\n  await bot.equip(cookedMutton, \"hand\");\n  await bot.consume();\n  bot.chat(\"Cooked mutton eaten.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/eatCookedMuttonV3.js",
    "content": "async function eatCookedMutton(bot) {\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\n  await bot.equip(cookedMutton, \"hand\");\n  await bot.consume();\n  bot.chat(\"Cooked mutton eaten.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/equipIronArmor.js",
    "content": "async function equipIronArmor(bot) {\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName.iron_helmet.id);\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName.iron_chestplate.id);\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName.iron_leggings.id);\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName.iron_boots.id);\n  if (ironHelmet) {\n    await bot.equip(ironHelmet, \"head\");\n    bot.chat(\"Iron helmet equipped.\");\n  } else {\n    bot.chat(\"Iron helmet not found in inventory.\");\n  }\n  if (ironChestplate) {\n    await bot.equip(ironChestplate, \"torso\");\n    bot.chat(\"Iron chestplate equipped.\");\n  } else {\n    bot.chat(\"Iron chestplate not found in inventory.\");\n  }\n  if (ironLeggings) {\n    await bot.equip(ironLeggings, \"legs\");\n    bot.chat(\"Iron leggings equipped.\");\n  } else {\n    bot.chat(\"Iron leggings not found in inventory.\");\n  }\n  if (ironBoots) {\n    await bot.equip(ironBoots, \"feet\");\n    bot.chat(\"Iron boots equipped.\");\n  } else {\n    bot.chat(\"Iron boots not found in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/exploreCave.js",
    "content": "async function exploreCave(bot) {\n  const torches = bot.inventory.findInventoryItem(mcData.itemsByName.torch.id);\n  if (!torches) {\n    bot.chat(\"No torches found in inventory. Crafting torches...\");\n    await craftTorches(bot);\n  }\n  await bot.equip(mcData.itemsByName.torch.id, \"hand\");\n  const caveEntrance = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    return caveBlock;\n  });\n  if (!caveEntrance) {\n    bot.chat(\"No cave entrance found nearby.\");\n    return;\n  }\n  bot.chat(\"Cave entrance found. Exploring the cave...\");\n  await exploreUntil(bot, new Vec3(1, 0, 1), 300, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    if (caveBlock) {\n      bot.placeBlock(caveBlock, new Vec3(0, 1, 0));\n    }\n    const mob = bot.nearestEntity(entity => {\n      return entity.type === \"mob\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    if (mob) {\n      killMob(bot, mob.name, 300);\n    }\n    return null; // Continue exploring until the time limit is reached\n  });\n\n  bot.chat(\"Finished exploring the cave.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/exploreCaveAndGatherResources.js",
    "content": "async function exploreCaveAndGatherResources(bot) {\n  // Equip torches\n  const torches = bot.inventory.findInventoryItem(mcData.itemsByName.torch.id);\n  if (!torches) {\n    bot.chat(\"No torches found in inventory. Crafting torches...\");\n    await craftTorches(bot);\n  }\n  await bot.equip(mcData.itemsByName.torch.id, \"hand\");\n\n  // Find a cave entrance and start exploring\n  const caveEntrance = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    return caveBlock;\n  });\n  if (!caveEntrance) {\n    bot.chat(\"No cave entrance found nearby.\");\n    return;\n  }\n  bot.chat(\"Cave entrance found. Exploring the cave...\");\n\n  // Explore the cave and gather resources\n  await exploreUntil(bot, new Vec3(1, 0, 1), 300, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    if (caveBlock) {\n      bot.placeBlock(caveBlock, new Vec3(0, 1, 0));\n    }\n    const mob = bot.nearestEntity(entity => {\n      return entity.type === \"mob\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    if (mob) {\n      killMob(bot, mob.name, 300);\n    }\n    const ores = [\"coal_ore\", \"iron_ore\", \"gold_ore\", \"diamond_ore\"];\n    for (const ore of ores) {\n      const oreBlock = bot.findBlock({\n        matching: mcData.blocksByName[ore].id,\n        maxDistance: 32\n      });\n      if (oreBlock) {\n        mineBlock(bot, ore, 1);\n      }\n    }\n    return null; // Continue exploring until the time limit is reached\n  });\n\n  bot.chat(\"Finished exploring the cave and gathering resources.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/exploreCaveAndGatherResourcesV2.js",
    "content": "async function exploreCaveAndGatherResources(bot) {\n  // Equip torches\n  const torches = bot.inventory.findInventoryItem(mcData.itemsByName.torch.id);\n  if (!torches) {\n    bot.chat(\"No torches found in inventory. Crafting torches...\");\n    await craftTorches(bot);\n  }\n  await bot.equip(mcData.itemsByName.torch.id, \"hand\");\n\n  // Find a cave entrance and start exploring\n  const caveEntrance = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    return caveBlock;\n  });\n  if (!caveEntrance) {\n    bot.chat(\"No cave entrance found nearby.\");\n    return;\n  }\n  bot.chat(\"Cave entrance found. Exploring the cave...\");\n\n  // Explore the cave and gather resources\n  await exploreUntil(bot, new Vec3(1, 0, 1), 300, () => {\n    const caveBlock = bot.findBlock({\n      matching: block => {\n        return block && block.name === \"air\" && block.position && block.position.y < 60;\n      },\n      maxDistance: 32\n    });\n    if (caveBlock) {\n      bot.placeBlock(caveBlock, new Vec3(0, 1, 0));\n    }\n    const mob = bot.nearestEntity(entity => {\n      return entity.type === \"mob\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    if (mob) {\n      killMob(bot, mob.name, 300);\n    }\n    const ores = [\"coal_ore\", \"iron_ore\", \"gold_ore\", \"diamond_ore\"];\n    for (const ore of ores) {\n      const oreBlock = bot.findBlock({\n        matching: mcData.blocksByName[ore].id,\n        maxDistance: 32\n      });\n      if (oreBlock) {\n        mineBlock(bot, ore, 1);\n      }\n    }\n    return null; // Continue exploring until the time limit is reached\n  });\n\n  bot.chat(\"Finished exploring the cave and gathering resources.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/fishInNearbyWaterSafely.js",
    "content": "async function fishInNearbyWaterSafely(bot) {\n  // Check if the bot has a fishing rod in its inventory\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  if (!fishingRod) {\n    await craftFishingRod(bot);\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\n  }\n\n  // Find a nearby water block\n  const waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const foundWaterBlock = bot.findBlock({\n      matching: mcData.blocksByName.water.id,\n      maxDistance: 32\n    });\n    return foundWaterBlock;\n  });\n\n  // Move to a block adjacent to the water block\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\n\n  // Look at the water block\n  await bot.lookAt(waterBlock.position);\n\n  // Equip the fishing rod\n  await bot.equip(fishingRod, \"hand\");\n\n  // Check for hostile mobs nearby and kill them if necessary\n  const hostileMobs = [\"zombie\", \"skeleton\", \"creeper\"];\n  for (const mobName of hostileMobs) {\n    const mob = bot.nearestEntity(entity => {\n      return entity.name === mobName && entity.position.distanceTo(bot.entity.position) < 16;\n    });\n    if (mob) {\n      await killMob(bot, mobName, 300);\n    }\n  }\n\n  // Fish in the water\n  try {\n    await bot.fish();\n    bot.chat(\"Fished in the nearby water.\");\n  } catch (error) {\n    if (error.message === \"Fishing cancelled\") {\n      bot.chat(\"Fishing was cancelled. Trying again...\");\n      await fishInNearbyWaterSafely(bot);\n    } else {\n      throw error;\n    }\n  }\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineCoalOre.js",
    "content": "async function mineCoalOre(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (!stonePickaxe) {\n    bot.chat(\"No stone pickaxe found in inventory.\");\n    return;\n  }\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \"hand\");\n  const coalOreBlock = bot.findBlock({\n    matching: mcData.blocksByName.coal_ore.id,\n    maxDistance: 32\n  });\n  if (!coalOreBlock) {\n    bot.chat(\"No coal ore found nearby. Exploring...\");\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundCoalOre = bot.findBlock({\n        matching: mcData.blocksByName.coal_ore.id,\n        maxDistance: 32\n      });\n      return foundCoalOre;\n    });\n  }\n  await mineBlock(bot, \"coal_ore\", 1);\n  bot.chat(\"Coal ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineCopperOreWithStonePickaxe.js",
    "content": "async function mineCopperOreWithStonePickaxe(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (!stonePickaxe) {\n    bot.chat(\"No stone pickaxe found. Mining cobblestone and crafting one...\");\n    await mineBlock(bot, \"stone\", 3);\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    await craftItem(bot, \"stone_pickaxe\", 1);\n    bot.chat(\"Stone pickaxe crafted.\");\n  }\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \"hand\");\n  const copperOreBlock = bot.findBlock({\n    matching: mcData.blocksByName.copper_ore.id,\n    maxDistance: 32\n  });\n  if (!copperOreBlock) {\n    bot.chat(\"No copper ore found nearby. Exploring...\");\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundCopperOre = bot.findBlock({\n        matching: mcData.blocksByName.copper_ore.id,\n        maxDistance: 32\n      });\n      return foundCopperOre;\n    });\n  }\n  await mineBlock(bot, \"copper_ore\", 1);\n  bot.chat(\"Copper ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineFiveCoalOres.js",
    "content": "async function mineFiveCoalOres(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (!stonePickaxe) {\n    bot.chat(\"No stone pickaxe found in inventory.\");\n    return;\n  }\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \"hand\");\n  await mineBlock(bot, \"coal_ore\", 5);\n  bot.chat(\"5 coal ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineFiveCoalOresV2.js",
    "content": "async function mineFiveCoalOres(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (!stonePickaxe) {\n    bot.chat(\"No stone pickaxe found in inventory.\");\n    return;\n  }\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \"hand\");\n  await mineBlock(bot, \"coal_ore\", 5);\n  bot.chat(\"5 coal ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineFiveCopperOres.js",
    "content": "async function mineFiveCopperOres(bot) {\n  const copperOreCount = bot.inventory.count(mcData.itemsByName.copper_ore.id);\n  if (copperOreCount >= 5) {\n    bot.chat(\"Already have 5 copper ores in inventory.\");\n    return;\n  }\n  await bot.equip(mcData.itemsByName.iron_pickaxe.id, \"hand\");\n  await mineBlock(bot, \"copper_ore\", 5 - copperOreCount);\n  bot.chat(\"5 copper ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineFiveIronOres.js",
    "content": "async function mineFiveIronOres(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\n  if (!stonePickaxe && !ironPickaxe) {\n    bot.chat(\"No stone or iron pickaxe found. Mining cobblestone and crafting a stone pickaxe...\");\n    await mineBlock(bot, \"stone\", 3);\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    await craftItem(bot, \"stone_pickaxe\", 1);\n    bot.chat(\"Stone pickaxe crafted.\");\n  }\n  const pickaxeToUse = ironPickaxe || stonePickaxe;\n  await bot.equip(pickaxeToUse, \"hand\");\n  await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\n    const foundIronOre = bot.findBlock({\n      matching: mcData.blocksByName.iron_ore.id,\n      maxDistance: 32\n    });\n    return foundIronOre;\n  });\n  await mineBlock(bot, \"iron_ore\", 5);\n  bot.chat(\"5 iron ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineLapisOre.js",
    "content": "async function mineLapisOre(bot) {\n  const pickaxeTypes = [mcData.itemsByName.stone_pickaxe.id, mcData.itemsByName.iron_pickaxe.id, mcData.itemsByName.diamond_pickaxe.id, mcData.itemsByName.netherite_pickaxe.id];\n  let pickaxe = bot.inventory.items().find(item => pickaxeTypes.includes(item.type));\n  if (!pickaxe) {\n    bot.chat(\"No suitable pickaxe found. Mining cobblestone and crafting a stone pickaxe...\");\n    await mineBlock(bot, \"stone\", 3);\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    await craftItem(bot, \"stone_pickaxe\", 1);\n    pickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n    bot.chat(\"Stone pickaxe crafted.\");\n  }\n  await bot.equip(pickaxe, \"hand\");\n  const lapisOreBlock = await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\n    const foundLapisOre = bot.findBlock({\n      matching: mcData.blocksByName.lapis_ore.id,\n      maxDistance: 32\n    });\n    return foundLapisOre;\n  });\n  if (!lapisOreBlock) {\n    bot.chat(\"No lapis ore found nearby. Exploring...\");\n  }\n  await mineBlock(bot, \"lapis_ore\", 1);\n  bot.chat(\"Lapis ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineThreeIronOres.js",
    "content": "async function mineThreeIronOres(bot) {\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\n  if (!stonePickaxe) {\n    bot.chat(\"No stone pickaxe found. Mining cobblestone and crafting one...\");\n    await mineBlock(bot, \"stone\", 3);\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"crafting_table\", craftingTablePosition);\n    await craftItem(bot, \"stone_pickaxe\", 1);\n    bot.chat(\"Stone pickaxe crafted.\");\n  }\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \"hand\");\n  const ironOreBlock = await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\n    const foundIronOre = bot.findBlock({\n      matching: mcData.blocksByName.iron_ore.id,\n      maxDistance: 32\n    });\n    return foundIronOre;\n  });\n  if (!ironOreBlock) {\n    bot.chat(\"No iron ore found nearby. Exploring...\");\n  }\n  await mineBlock(bot, \"iron_ore\", 3);\n  bot.chat(\"3 iron ores mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/mineWoodLog.js",
    "content": "async function mineWoodLog(bot) {\n  const logNames = [\"oak_log\", \"birch_log\", \"spruce_log\", \"jungle_log\", \"acacia_log\", \"dark_oak_log\", \"mangrove_log\"];\n  const logBlock = bot.findBlock({\n    matching: block => logNames.includes(block.name),\n    maxDistance: 32\n  });\n  if (!logBlock) {\n    bot.chat(\"No wood log found nearby. Exploring...\");\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const foundLog = bot.findBlock({\n        matching: block => logNames.includes(block.name),\n        maxDistance: 32\n      });\n      return foundLog;\n    });\n  }\n  await mineBlock(bot, logBlock.name, 1);\n  bot.chat(\"Wood log mined.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/smeltOneRawIron.js",
    "content": "async function smeltOneRawIron(bot) {\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  await smeltItem(bot, \"raw_iron\", \"coal\", 1);\n  bot.chat(\"1 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/smeltRawCopper.js",
    "content": "async function smeltRawCopper(bot) {\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  const requiredCoal = 7;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more coal...\");\n    await mineCoalOre(bot);\n  }\n  await smeltItem(bot, \"raw_copper\", \"coal\", 7);\n  bot.chat(\"7 raw copper smelted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/smeltRawIron.js",
    "content": "async function smeltRawIron(bot) {\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  const requiredCoal = 3;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more coal...\");\n    await mineBlock(bot, \"coal_ore\", requiredCoal - coalCount);\n  }\n  await smeltItem(bot, \"raw_iron\", \"coal\", 3);\n  bot.chat(\"3 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/smeltSixRawIron.js",
    "content": "async function smeltSixRawIron(bot) {\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  const requiredCoal = 6;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more coal...\");\n    await mineBlock(bot, \"coal_ore\", requiredCoal - coalCount);\n  }\n  await smeltItem(bot, \"raw_iron\", \"coal\", 6);\n  bot.chat(\"6 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/code/smeltTwentyFiveIronIngots.js",
    "content": "async function smeltTwentyFiveIronIngots(bot) {\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\n  if (!furnaceInInventory) {\n    bot.chat(\"No furnace found in inventory. Please craft one first.\");\n    return;\n  }\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\n  if (blockAtFurnacePosition.name === \"coal_ore\") {\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\n  }\n  await placeItem(bot, \"furnace\", furnacePosition);\n  bot.chat(\"Furnace placed.\");\n  const requiredCoal = 25;\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\n  if (coalCount < requiredCoal) {\n    bot.chat(\"Not enough coal. Mining more coal...\");\n    await mineBlock(bot, \"coal_ore\", requiredCoal - coalCount);\n  }\n  await smeltItem(bot, \"raw_iron\", \"coal\", 25);\n  bot.chat(\"25 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/catchFiveFishSafely.txt",
    "content": "async function catchFiveFishSafely(bot) {\n    // The function is about catching five fish safely using a fishing rod. First, it checks if the bot has a fishing rod in its inventory. If not, it crafts one. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and fishes in the water five times. If fishing is cancelled, it retries the same iteration.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/catchThreeFish.txt",
    "content": "async function catchThreeFish(bot) {\n    // The function is about catching three fish using a fishing rod. First, it checks if the bot has a fishing rod in its inventory. If not, it crafts one. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and fishes in the water three times. If fishing is cancelled, it retries the same iteration.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/checkStonePickaxe.txt",
    "content": "async function checkStonePickaxe(bot) {\n    // The function checks if the bot has a stone pickaxe in its inventory and sends a chat message indicating whether it has one or not.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/chopDownSpruceLogs.txt",
    "content": "async function chopDownSpruceLogs(bot) {\n    // The function is about chopping down spruce logs until there are 5 in the inventory. It first checks how many spruce logs are in the inventory and calculates how many more need to be mined. If there are less than 5, it mines the remaining logs and saves the event. If there are already 5 logs in the inventory, it does nothing.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/chopDownSpruceLogsV2.txt",
    "content": "async function chopDownSpruceLogs(bot) {\n    // The function is about chopping down spruce logs until there are 5 in the inventory. It first checks how many spruce logs are in the inventory and calculates how many more need to be mined. If there are less than 5, it mines the remaining amount and saves the event. If there are already 5 spruce logs in the inventory, it does nothing.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/chopSpruceLogs.txt",
    "content": "async function chopSpruceLogs(bot) {\n    // The function is about chopping down spruce logs until there are 3 in the inventory. It first checks how many spruce logs are in the inventory and calculates how many more need to be mined. If there are less than 3, it mines the remaining logs and saves them in the inventory. If there are already 3 logs in the inventory, it does nothing.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/collectWaterWithBucket.txt",
    "content": "async function collectWaterWithBucket(bot) {\n    // The function is about collecting water with a bucket. It first searches for a water block within a certain distance. If no water block is found, it explores the environment until it finds one. Once a water block is found, it equips the bucket in the hand, looks at the water block, and activates the item to collect water. Finally, it sends a chat message indicating that water has been collected.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/cookMutton.txt",
    "content": "async function cookMutton(bot) {\n    // The function is about cooking 5 raw muttons using a furnace and coal. It first checks if there are at least 5 raw muttons in the inventory, and if not, it returns a message to collect more. Then it checks if there is a furnace in the inventory, and if not, it returns a message to craft one. It places the furnace next to the player and checks if there is enough coal in the inventory. If not, it mines coal until there are 5 pieces. Finally, it smelts 5 raw muttons using coal and returns a message that 5 muttons have been cooked.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftBucket.txt",
    "content": "async function craftBucket(bot) {\n    // The function crafts a bucket using 3 iron ingots. If there are not enough iron ingots, it returns. If there is no crafting table nearby, it places one. Then it crafts a bucket and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftChest.txt",
    "content": "async function craftChest(bot) {\n    // The function crafts a chest using spruce planks and a crafting table. If there are not enough spruce planks, it mines a spruce log and crafts more planks. If there is no crafting table nearby, it places one. Finally, it crafts a chest and logs the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftEightSticks.txt",
    "content": "async function craftEightSticks(bot) {\n    // The function crafts 8 sticks using spruce planks. If there are not enough spruce planks, it mines a spruce log and crafts more planks. If there is no crafting table nearby, it places one. Finally, it crafts 2 sticks and repeats the process until 8 sticks are crafted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftEightTorches.txt",
    "content": "async function craftEightTorches(bot) {\n    // The function is about crafting 8 torches. First, it checks if there is a crafting table nearby. If not, it places one. Then, it crafts 1 torch and saves it to the inventory. Finally, it outputs a message indicating that 8 torches have been crafted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftFishingRod.txt",
    "content": "async function craftFishingRod(bot) {\n    // The function crafts a fishing rod using 2 strings and 3 sticks. If there are not enough strings, the bot will find and kill spiders to obtain them. If a crafting table is not already placed, the bot will place one. Finally, the bot will craft a fishing rod and output a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftFurnace.txt",
    "content": "async function craftFurnace(bot) {\n    // The function crafts a furnace using 8 cobblestones and a crafting table. If there are not enough cobblestones, the function will return. If there is no crafting table nearby, the function will place one. Finally, the function crafts a furnace and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronChestplate.txt",
    "content": "async function craftIronChestplate(bot) {\n    // The function crafts an iron chestplate using iron ingots. If there are not enough iron ingots in the inventory, the bot will mine iron ores and smelt them into iron ingots. Then, the bot will search for a nearby crafting table and place one if it is not found. Finally, the bot will craft an iron chestplate and chat a message indicating that the item has been crafted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronHelmet.txt",
    "content": "async function craftIronHelmet(bot) {\n    // The function crafts an iron helmet using 5 iron ingots. If there are not enough iron ingots, it returns. If there is no crafting table nearby, it places one and updates the variable. Then, it crafts an iron helmet and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronLeggingsAndBoots.txt",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n    // The function crafts iron leggings and boots. It checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into ingots. If there is no crafting table nearby, it places one. Finally, it crafts one pair of iron leggings and one pair of iron boots.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronPickaxe.txt",
    "content": "async function craftIronPickaxe(bot) {\n    // The function crafts an iron pickaxe using 3 iron ingots and 2 sticks. It checks if there are enough resources in the inventory to craft the pickaxe, and if not, it returns. If there is a crafting table nearby, it crafts the pickaxe. If not, it places a crafting table and then crafts the pickaxe. Finally, it sends a chat message indicating that the iron pickaxe has been crafted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronPickaxeWithMaterials.txt",
    "content": "async function craftIronPickaxeWithMaterials(bot) {\n    // The function crafts an iron pickaxe using 3 iron ingots and 2 sticks. If there are not enough iron ingots, it mines iron ores and smelts them into ingots. If there are not enough sticks, it crafts them. If there is no crafting table nearby, it places one. Finally, it crafts an iron pickaxe and logs the result.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftIronSword.txt",
    "content": "async function craftIronSword(bot) {\n    // The function crafts an iron sword using 2 iron ingots and 1 stick. If there are not enough iron ingots, it mines iron ores and smelts them into ingots. If there are not enough sticks, it crafts them. It then looks for a crafting table within 32 blocks, and if it doesn't find one, it places one nearby. Finally, it crafts an iron sword and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftShieldWithFurnace.txt",
    "content": "async function craftShieldWithFurnace(bot) {\n    // The function crafts a shield using a furnace and a crafting table. It checks if there are enough iron ingots and spruce planks in the inventory, and if not, it smelts iron ingots and crafts spruce planks. If a furnace or a crafting table is not nearby, it places one. Finally, it crafts a shield using the crafting table and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftSixteenTorches.txt",
    "content": "async function craftSixteenTorches(bot) {\n    // The function crafts 16 torches using sticks and a crafting table. It checks if there are enough sticks in the inventory, and if not, crafts more. If there is no crafting table nearby, it places one. Finally, it crafts 16 torches and saves the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftSpyglass.txt",
    "content": "async function craftSpyglass(bot) {\n    // The function crafts a spyglass using 2 copper ingots and 1 amethyst shard. It checks if there are enough materials in the inventory, and if not, it returns. If there is a crafting table nearby, it crafts the spyglass. If not, it places a crafting table and then crafts the spyglass. Finally, it sends a chat message indicating that the spyglass has been crafted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftSticks.txt",
    "content": "async function craftSticks(bot) {\n    // The function crafts 4 sticks using a crafting table. If there are not enough spruce planks, it mines a spruce log and crafts the planks. Then, it places a crafting table next to the bot and crafts 4 sticks.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftStoneAxe.txt",
    "content": "async function craftStoneAxe(bot) {\n    // The function crafts a stone axe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone axe and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftStoneHoe.txt",
    "content": "async function craftStoneHoe(bot) {\n    // The function crafts a stone hoe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone hoe and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftStonePickaxe.txt",
    "content": "async function craftStonePickaxe(bot) {\n    // The function crafts a stone pickaxe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone pickaxe and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftStoneShovel.txt",
    "content": "async function craftStoneShovel(bot) {\n    // The function crafts a stone shovel using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone shovel and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftStoneSword.txt",
    "content": "async function craftStoneSword(bot) {\n    // The function crafts a stone sword using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone sword and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftTorches.txt",
    "content": "async function craftTorches(bot) {\n    // The function crafts 8 torches using coal and sticks. It checks if there is enough coal and sticks in the inventory, and if not, it mines coal or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts 8 torches and saves the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftTwentySprucePlanks.txt",
    "content": "async function craftTwentySprucePlanks(bot) {\n    // The function crafts 20 spruce planks using spruce logs. If there are not enough spruce logs in the inventory, it will mine the required amount. Once enough logs are available, it will craft 20 spruce planks and save the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftWhiteBedWithExploration.txt",
    "content": "async function craftWhiteBedWithExploration(bot) {\n    // The function crafts a white bed using 3 white wool blocks and 3 spruce planks. If there are not enough wool blocks, the bot explores the area to find and kill sheep to collect the wool. If there are not enough spruce planks, the bot crafts more. If there is no crafting table nearby, the bot places one.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftWoodenHoe.txt",
    "content": "async function craftWoodenHoe(bot) {\n    // The function crafts a wooden hoe using 2 spruce planks and 2 sticks. It checks if there are enough planks and sticks in the inventory, and crafts more if necessary. If there is no crafting table nearby, it places one. Finally, it crafts a wooden hoe and logs a message.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftWoodenPickaxe.txt",
    "content": "async function craftWoodenPickaxe(bot) {\n    // The function crafts a wooden pickaxe by checking if there are enough spruce planks and sticks in the inventory, and crafting more if necessary. It then places a crafting table and crafts a wooden pickaxe using the newly crafted items.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/craftWoodenPlanks.txt",
    "content": "async function craftWoodenPlanks(bot) {\n    // The function crafts 4 wooden planks using any type of wooden log available in the inventory. If there is no wooden log in the inventory, it will mine one. It then finds the index of the log in the `logNames` array and uses that index to determine the corresponding plank name in the `plankNames` array. Finally, it crafts 4 planks of the corresponding type and saves the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/eatCookedMutton.txt",
    "content": "async function eatCookedMutton(bot) {\n    // The function is about eating cooked mutton. It first checks if there is any cooked mutton in the inventory. If there is, it equips the cooked mutton in the hand and consumes it. Finally, it sends a chat message indicating that the cooked mutton has been eaten.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/eatCookedMuttonV2.txt",
    "content": "async function eatCookedMutton(bot) {\n    // The function is about eating cooked mutton. It first checks if there is any cooked mutton in the inventory. If there is, it equips the cooked mutton in the hand and consumes it. Finally, it sends a chat message indicating that the cooked mutton has been eaten.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/eatCookedMuttonV3.txt",
    "content": "async function eatCookedMutton(bot) {\n    // The function is about eating cooked mutton. It first checks if there is any cooked mutton in the inventory. If there is, it equips the cooked mutton in the hand and consumes it. Finally, it sends a chat message indicating that the cooked mutton has been eaten.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/equipIronArmor.txt",
    "content": "async function equipIronArmor(bot) {\n    // The function equips the player with iron armor if it is available in the inventory. It checks for the presence of each piece of iron armor (helmet, chestplate, leggings, and boots) and equips them one by one. If a piece of armor is not found in the inventory, it sends a message to the chat indicating that it is not available.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/exploreCave.txt",
    "content": "async function exploreCave(bot) {\n    // The function is about exploring a nearby cave. First, check if there are torches in the inventory. If not, craft torches. Equip the torches in the hand and explore the environment until finding a cave entrance. Once a cave entrance is found, explore the cave by placing torches and killing mobs until the time limit is reached.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/exploreCaveAndGatherResources.txt",
    "content": "async function exploreCaveAndGatherResources(bot) {\n    // The function is about exploring a nearby cave and gathering resources. First, equip torches and find a cave entrance. Once a cave entrance is found, explore the cave and gather resources such as coal, iron, gold, and diamond ores. While exploring, place torches to light up the cave, kill nearby mobs, and mine ores. The function will continue exploring until the time limit is reached. Finally, the function will output a message indicating that the exploration and resource gathering is finished.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/exploreCaveAndGatherResourcesV2.txt",
    "content": "async function exploreCaveAndGatherResources(bot) {\n    // The function is about exploring a nearby cave and gathering resources. First, equip torches and find a cave entrance. Once a cave entrance is found, explore the cave and gather resources such as coal, iron, gold, and diamond ores. While exploring, place torches to light up the cave, kill nearby mobs, and mine ores. The function will continue exploring until the time limit is reached. Finally, the function will output a message indicating that the exploration and resource gathering is finished.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/fishInNearbyWaterSafely.txt",
    "content": "async function fishInNearbyWaterSafely(bot) {\n    // The function is about fishing in a nearby water block safely. It first checks if the bot has a fishing rod in its inventory, and crafts one if it doesn't. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and checks for hostile mobs nearby, killing them if necessary. Finally, it fishes in the water and retries if the fishing is cancelled.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineCoalOre.txt",
    "content": "async function mineCoalOre(bot) {\n    // The function is about mining a single coal ore block using a stone pickaxe. First, it checks if a stone pickaxe is in the inventory. If not, it returns. If the stone pickaxe is available, it equips it in the hand. Next, it searches for a nearby coal ore block. If it is not found, it explores the environment until it finds one. Once a coal ore block is found, it mines it and sends a message to the chat.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineCopperOreWithStonePickaxe.txt",
    "content": "async function mineCopperOreWithStonePickaxe(bot) {\n    // The function is about mining a single copper ore block using a stone pickaxe. If the stone pickaxe is not in the inventory, the bot will mine 3 cobblestone blocks and craft a stone pickaxe. Once the stone pickaxe is available, it will be equipped in the hand. The bot will then explore the environment until finding a copper ore block. Once a copper ore block is found, the bot will mine it and save the event.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineFiveCoalOres.txt",
    "content": "async function mineFiveCoalOres(bot) {\n    // The function is about mining 5 coal ores using a stone pickaxe. First, check if a stone pickaxe is in the inventory. If not, return. If the stone pickaxe is available, equip the stone pickaxe in the hand. Next, mine a total of 5 coal ores using the stone pickaxe. Finally, send a chat message indicating that 5 coal ores have been mined.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineFiveCoalOresV2.txt",
    "content": "async function mineFiveCoalOres(bot) {\n    // The function is about mining 5 coal ores using a stone pickaxe. First, check if a stone pickaxe is in the inventory. If not, return. If the stone pickaxe is available, equip the stone pickaxe in the hand. Next, mine a total of 5 coal ores using the stone pickaxe. Finally, send a chat message indicating that 5 coal ores have been mined.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineFiveCopperOres.txt",
    "content": "async function mineFiveCopperOres(bot) {\n    // The function is about mining 5 copper ores using an iron pickaxe. It first checks if there are already 5 copper ores in the inventory, and if so, it returns. Otherwise, it equips the iron pickaxe in the hand and mines copper ores until there are 5 in the inventory. Finally, it sends a chat message indicating that 5 copper ores have been mined.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineFiveIronOres.txt",
    "content": "async function mineFiveIronOres(bot) {\n    // The function is about mining 5 iron ores using either a stone or iron pickaxe. If neither pickaxe is found in the inventory, the bot will mine cobblestone and craft a stone pickaxe. Once a pickaxe is available, the bot will equip it and explore the environment until finding an iron ore block. Once an iron ore block is found, the bot will mine a total of 5 iron ores using the equipped pickaxe.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineLapisOre.txt",
    "content": "async function mineLapisOre(bot) {\n    // The function is about mining a single lapis ore block using the best available pickaxe. If the bot does not have a suitable pickaxe, it will mine cobblestone and craft a stone pickaxe. Once the pickaxe is available, it will equip it and explore the environment until finding a lapis ore block. Once a lapis ore block is found, it will mine it and save the event of mining the lapis ore.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineThreeIronOres.txt",
    "content": "async function mineThreeIronOres(bot) {\n    // The function is about mining 3 iron ores using a stone pickaxe. If the stone pickaxe is not in the inventory, the bot will mine cobblestone and craft one. Once the stone pickaxe is available, it will be equipped in the hand. The bot will explore the environment until finding an iron ore block. Once an iron ore block is found, the bot will mine a total of 3 iron ores using the stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/mineWoodLog.txt",
    "content": "async function mineWoodLog(bot) {\n    // The function is about mining a single wood log. It first searches for a nearby wood log within a certain distance. If it cannot find one, it explores the environment until it finds a wood log. Once a wood log is found, it mines it and saves the event of mining the wood log.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/smeltOneRawIron.txt",
    "content": "async function smeltOneRawIron(bot) {\n    // The function is about smelting one raw iron using a furnace. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. It then places the furnace next to the bot and smelts one raw iron using coal as fuel. Finally, it sends a message indicating that one raw iron has been smelted.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/smeltRawCopper.txt",
    "content": "async function smeltRawCopper(bot) {\n    // The function is about smelting 7 raw copper using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. Then it places the furnace next to the bot and checks if there is coal ore nearby. If there is not enough coal in the inventory, it mines more coal ore. Finally, it smelts 7 raw copper using the furnace and coal.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/smeltRawIron.txt",
    "content": "async function smeltRawIron(bot) {\n    // The function is about smelting 3 raw iron using a furnace and coal. First, it checks if there is a furnace in the inventory, and if not, it returns a message to craft one. Then, it places the furnace next to the bot. If there is coal in the inventory, it uses it to smelt the raw iron. Otherwise, it mines coal ore to obtain the required amount of coal. Finally, it smelts the raw iron and returns a message indicating that the process is complete.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/smeltSixRawIron.txt",
    "content": "async function smeltSixRawIron(bot) {\n    // The function is about smelting 6 raw iron using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. It then places the furnace next to the player and checks if there is enough coal in the inventory. If there isn't, it mines coal until there are 6 pieces. Finally, it smelts 6 raw iron using the furnace and coal, and returns a message indicating that the process is complete.\n}"
  },
  {
    "path": "skill_library/trial2/skill/description/smeltTwentyFiveIronIngots.txt",
    "content": "async function smeltTwentyFiveIronIngots(bot) {\n    // The function is about smelting 25 raw iron ingots using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. Then it places the furnace next to the bot, and checks if there is enough coal in the inventory. If there isn't, it mines coal until there are 25 pieces. Finally, it smelts 25 raw iron ingots using the furnace and coal, and returns a message indicating that the process is complete.\n}"
  },
  {
    "path": "skill_library/trial2/skill/skills.json",
    "content": "{\"mineWoodLog\": {\"code\": \"async function mineWoodLog(bot) {\\n  const logNames = [\\\"oak_log\\\", \\\"birch_log\\\", \\\"spruce_log\\\", \\\"jungle_log\\\", \\\"acacia_log\\\", \\\"dark_oak_log\\\", \\\"mangrove_log\\\"];\\n  const logBlock = bot.findBlock({\\n    matching: block => logNames.includes(block.name),\\n    maxDistance: 32\\n  });\\n  if (!logBlock) {\\n    bot.chat(\\\"No wood log found nearby. Exploring...\\\");\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundLog = bot.findBlock({\\n        matching: block => logNames.includes(block.name),\\n        maxDistance: 32\\n      });\\n      return foundLog;\\n    });\\n  }\\n  await mineBlock(bot, logBlock.name, 1);\\n  bot.chat(\\\"Wood log mined.\\\");\\n}\", \"description\": \"async function mineWoodLog(bot) {\\n    // The function is about mining a single wood log. It first searches for a nearby wood log within a certain distance. If it cannot find one, it explores the environment until it finds a wood log. Once a wood log is found, it mines it and saves the event of mining the wood log.\\n}\"}, \"craftWoodenPlanks\": {\"code\": \"async function craftWoodenPlanks(bot) {\\n  const logNames = [\\\"oak_log\\\", \\\"birch_log\\\", \\\"spruce_log\\\", \\\"jungle_log\\\", \\\"acacia_log\\\", \\\"dark_oak_log\\\", \\\"mangrove_log\\\"];\\n  const plankNames = [\\\"oak_planks\\\", \\\"birch_planks\\\", \\\"spruce_planks\\\", \\\"jungle_planks\\\", \\\"acacia_planks\\\", \\\"dark_oak_planks\\\", \\\"mangrove_planks\\\"];\\n  const logInInventory = logNames.find(logName => bot.inventory.count(mcData.itemsByName[logName].id) > 0);\\n  if (!logInInventory) {\\n    bot.chat(\\\"No wooden log in inventory. Mining a wooden log...\\\");\\n    await mineWoodLog(bot);\\n  }\\n  const logIndex = logNames.indexOf(logInInventory);\\n  const plankName = plankNames[logIndex];\\n  bot.chat(`Crafting 4 ${plankName}...`);\\n  await craftItem(bot, plankName, 1);\\n  bot.chat(`4 ${plankName} crafted.`);\\n}\", \"description\": \"async function craftWoodenPlanks(bot) {\\n    // The function crafts 4 wooden planks using any type of wooden log available in the inventory. If there is no wooden log in the inventory, it will mine one. It then finds the index of the log in the `logNames` array and uses that index to determine the corresponding plank name in the `plankNames` array. Finally, it crafts 4 planks of the corresponding type and saves the event.\\n}\"}, \"craftWoodenPickaxe\": {\"code\": \"async function craftWoodenPickaxe(bot) {\\n  const requiredPlanks = 3;\\n  const requiredSticks = 2;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Not enough spruce_planks. Crafting more...\\\");\\n    await craftItem(bot, \\\"spruce_planks\\\", requiredPlanks - planksCount);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n  bot.chat(\\\"Crafting_table placed.\\\");\\n  await craftItem(bot, \\\"wooden_pickaxe\\\", 1);\\n  bot.chat(\\\"Wooden pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftWoodenPickaxe(bot) {\\n    // The function crafts a wooden pickaxe by checking if there are enough spruce planks and sticks in the inventory, and crafting more if necessary. It then places a crafting table and crafts a wooden pickaxe using the newly crafted items.\\n}\"}, \"mineCopperOreWithStonePickaxe\": {\"code\": \"async function mineCopperOreWithStonePickaxe(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  if (!stonePickaxe) {\\n    bot.chat(\\\"No stone pickaxe found. Mining cobblestone and crafting one...\\\");\\n    await mineBlock(bot, \\\"stone\\\", 3);\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n    bot.chat(\\\"Stone pickaxe crafted.\\\");\\n  }\\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \\\"hand\\\");\\n  const copperOreBlock = bot.findBlock({\\n    matching: mcData.blocksByName.copper_ore.id,\\n    maxDistance: 32\\n  });\\n  if (!copperOreBlock) {\\n    bot.chat(\\\"No copper ore found nearby. Exploring...\\\");\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundCopperOre = bot.findBlock({\\n        matching: mcData.blocksByName.copper_ore.id,\\n        maxDistance: 32\\n      });\\n      return foundCopperOre;\\n    });\\n  }\\n  await mineBlock(bot, \\\"copper_ore\\\", 1);\\n  bot.chat(\\\"Copper ore mined.\\\");\\n}\", \"description\": \"async function mineCopperOreWithStonePickaxe(bot) {\\n    // The function is about mining a single copper ore block using a stone pickaxe. If the stone pickaxe is not in the inventory, the bot will mine 3 cobblestone blocks and craft a stone pickaxe. Once the stone pickaxe is available, it will be equipped in the hand. The bot will then explore the environment until finding a copper ore block. Once a copper ore block is found, the bot will mine it and save the event.\\n}\"}, \"craftSticks\": {\"code\": \"async function craftSticks(bot) {\\n  const requiredPlanks = 2;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Not enough spruce_planks. Mining a spruce_log and crafting more...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", 1);\\n    await craftItem(bot, \\\"spruce_planks\\\", 1);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n  bot.chat(\\\"Crafting_table placed.\\\");\\n  await craftItem(bot, \\\"stick\\\", 1);\\n  bot.chat(\\\"4 sticks crafted.\\\");\\n}\", \"description\": \"async function craftSticks(bot) {\\n    // The function crafts 4 sticks using a crafting table. If there are not enough spruce planks, it mines a spruce log and crafts the planks. Then, it places a crafting table next to the bot and crafts 4 sticks.\\n}\"}, \"chopSpruceLogs\": {\"code\": \"async function chopSpruceLogs(bot) {\\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\\n  const logsToMine = 3 - spruceLogCount;\\n  if (logsToMine > 0) {\\n    bot.chat(\\\"Chopping down spruce logs...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", logsToMine);\\n    bot.chat(\\\"Chopped down 3 spruce logs.\\\");\\n  } else {\\n    bot.chat(\\\"Already have 3 spruce logs in inventory.\\\");\\n  }\\n}\", \"description\": \"async function chopSpruceLogs(bot) {\\n    // The function is about chopping down spruce logs until there are 3 in the inventory. It first checks how many spruce logs are in the inventory and calculates how many more need to be mined. If there are less than 3, it mines the remaining logs and saves them in the inventory. If there are already 3 logs in the inventory, it does nothing.\\n}\"}, \"chopDownSpruceLogs\": {\"code\": \"async function chopDownSpruceLogs(bot) {\\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\\n  const logsToMine = 5 - spruceLogCount;\\n  if (logsToMine > 0) {\\n    bot.chat(\\\"Chopping down spruce logs...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", logsToMine);\\n    bot.chat(\\\"Chopped down 5 spruce logs.\\\");\\n  } else {\\n    bot.chat(\\\"Already have 5 spruce logs in inventory.\\\");\\n  }\\n}\", \"description\": \"async function chopDownSpruceLogs(bot) {\\n    // The function is about chopping down spruce logs until there are 5 in the inventory. It first checks how many spruce logs are in the inventory and calculates how many more need to be mined. If there are less than 5, it mines the remaining amount and saves the event. If there are already 5 spruce logs in the inventory, it does nothing.\\n}\"}, \"craftTwentySprucePlanks\": {\"code\": \"async function craftTwentySprucePlanks(bot) {\\n  const requiredLogs = 5;\\n  const spruceLogCount = bot.inventory.count(mcData.itemsByName.spruce_log.id);\\n  const logsToMine = requiredLogs - spruceLogCount;\\n  if (logsToMine > 0) {\\n    bot.chat(\\\"Not enough spruce logs. Chopping down more...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", logsToMine);\\n    bot.chat(\\\"Spruce logs chopped down.\\\");\\n  }\\n  bot.chat(\\\"Crafting 20 spruce planks...\\\");\\n  await craftItem(bot, \\\"spruce_planks\\\", requiredLogs);\\n  bot.chat(\\\"20 spruce planks crafted.\\\");\\n}\", \"description\": \"async function craftTwentySprucePlanks(bot) {\\n    // The function crafts 20 spruce planks using spruce logs. If there are not enough spruce logs in the inventory, it will mine the required amount. Once enough logs are available, it will craft 20 spruce planks and save the event.\\n}\"}, \"mineCoalOre\": {\"code\": \"async function mineCoalOre(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  if (!stonePickaxe) {\\n    bot.chat(\\\"No stone pickaxe found in inventory.\\\");\\n    return;\\n  }\\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \\\"hand\\\");\\n  const coalOreBlock = bot.findBlock({\\n    matching: mcData.blocksByName.coal_ore.id,\\n    maxDistance: 32\\n  });\\n  if (!coalOreBlock) {\\n    bot.chat(\\\"No coal ore found nearby. Exploring...\\\");\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundCoalOre = bot.findBlock({\\n        matching: mcData.blocksByName.coal_ore.id,\\n        maxDistance: 32\\n      });\\n      return foundCoalOre;\\n    });\\n  }\\n  await mineBlock(bot, \\\"coal_ore\\\", 1);\\n  bot.chat(\\\"Coal ore mined.\\\");\\n}\", \"description\": \"async function mineCoalOre(bot) {\\n    // The function is about mining a single coal ore block using a stone pickaxe. First, it checks if a stone pickaxe is in the inventory. If not, it returns. If the stone pickaxe is available, it equips it in the hand. Next, it searches for a nearby coal ore block. If it is not found, it explores the environment until it finds one. Once a coal ore block is found, it mines it and sends a message to the chat.\\n}\"}, \"craftFurnace\": {\"code\": \"async function craftFurnace(bot) {\\n  const requiredCobblestones = 8;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones to craft a furnace.\\\");\\n    return;\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"furnace\\\", 1);\\n  bot.chat(\\\"Furnace crafted.\\\");\\n}\", \"description\": \"async function craftFurnace(bot) {\\n    // The function crafts a furnace using 8 cobblestones and a crafting table. If there are not enough cobblestones, the function will return. If there is no crafting table nearby, the function will place one. Finally, the function crafts a furnace and sends a chat message.\\n}\"}, \"smeltRawCopper\": {\"code\": \"async function smeltRawCopper(bot) {\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  const requiredCoal = 7;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more coal...\\\");\\n    await mineCoalOre(bot);\\n  }\\n  await smeltItem(bot, \\\"raw_copper\\\", \\\"coal\\\", 7);\\n  bot.chat(\\\"7 raw copper smelted.\\\");\\n}\", \"description\": \"async function smeltRawCopper(bot) {\\n    // The function is about smelting 7 raw copper using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. Then it places the furnace next to the bot and checks if there is coal ore nearby. If there is not enough coal in the inventory, it mines more coal ore. Finally, it smelts 7 raw copper using the furnace and coal.\\n}\"}, \"mineFiveCoalOres\": {\"code\": \"async function mineFiveCoalOres(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  if (!stonePickaxe) {\\n    bot.chat(\\\"No stone pickaxe found in inventory.\\\");\\n    return;\\n  }\\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \\\"hand\\\");\\n  await mineBlock(bot, \\\"coal_ore\\\", 5);\\n  bot.chat(\\\"5 coal ores mined.\\\");\\n}\", \"description\": \"async function mineFiveCoalOres(bot) {\\n    // The function is about mining 5 coal ores using a stone pickaxe. First, check if a stone pickaxe is in the inventory. If not, return. If the stone pickaxe is available, equip the stone pickaxe in the hand. Next, mine a total of 5 coal ores using the stone pickaxe. Finally, send a chat message indicating that 5 coal ores have been mined.\\n}\"}, \"craftStoneSword\": {\"code\": \"async function craftStoneSword(bot) {\\n  const requiredCobblestones = 2;\\n  const requiredSticks = 1;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones. Mining more...\\\");\\n    await mineBlock(bot, \\\"stone\\\", requiredCobblestones - cobblestoneCount);\\n    bot.chat(\\\"Cobblestones mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftSticks(bot);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stone_sword\\\", 1);\\n  bot.chat(\\\"Stone sword crafted.\\\");\\n}\", \"description\": \"async function craftStoneSword(bot) {\\n    // The function crafts a stone sword using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone sword and logs a message.\\n}\"}, \"mineThreeIronOres\": {\"code\": \"async function mineThreeIronOres(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  if (!stonePickaxe) {\\n    bot.chat(\\\"No stone pickaxe found. Mining cobblestone and crafting one...\\\");\\n    await mineBlock(bot, \\\"stone\\\", 3);\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n    bot.chat(\\\"Stone pickaxe crafted.\\\");\\n  }\\n  await bot.equip(mcData.itemsByName.stone_pickaxe.id, \\\"hand\\\");\\n  const ironOreBlock = await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\\n    const foundIronOre = bot.findBlock({\\n      matching: mcData.blocksByName.iron_ore.id,\\n      maxDistance: 32\\n    });\\n    return foundIronOre;\\n  });\\n  if (!ironOreBlock) {\\n    bot.chat(\\\"No iron ore found nearby. Exploring...\\\");\\n  }\\n  await mineBlock(bot, \\\"iron_ore\\\", 3);\\n  bot.chat(\\\"3 iron ores mined.\\\");\\n}\", \"description\": \"async function mineThreeIronOres(bot) {\\n    // The function is about mining 3 iron ores using a stone pickaxe. If the stone pickaxe is not in the inventory, the bot will mine cobblestone and craft one. Once the stone pickaxe is available, it will be equipped in the hand. The bot will explore the environment until finding an iron ore block. Once an iron ore block is found, the bot will mine a total of 3 iron ores using the stone pickaxe.\\n}\"}, \"smeltRawIron\": {\"code\": \"async function smeltRawIron(bot) {\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  const requiredCoal = 3;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more coal...\\\");\\n    await mineBlock(bot, \\\"coal_ore\\\", requiredCoal - coalCount);\\n  }\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 3);\\n  bot.chat(\\\"3 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltRawIron(bot) {\\n    // The function is about smelting 3 raw iron using a furnace and coal. First, it checks if there is a furnace in the inventory, and if not, it returns a message to craft one. Then, it places the furnace next to the bot. If there is coal in the inventory, it uses it to smelt the raw iron. Otherwise, it mines coal ore to obtain the required amount of coal. Finally, it smelts the raw iron and returns a message indicating that the process is complete.\\n}\"}, \"craftIronPickaxe\": {\"code\": \"async function craftIronPickaxe(bot) {\\n  const requiredIronIngots = 3;\\n  const requiredSticks = 2;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (ironIngotsCount < requiredIronIngots || sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough iron ingots or sticks to craft an iron pickaxe.\\\");\\n    return;\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"iron_pickaxe\\\", 1);\\n  bot.chat(\\\"Iron pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftIronPickaxe(bot) {\\n    // The function crafts an iron pickaxe using 3 iron ingots and 2 sticks. It checks if there are enough resources in the inventory to craft the pickaxe, and if not, it returns. If there is a crafting table nearby, it crafts the pickaxe. If not, it places a crafting table and then crafts the pickaxe. Finally, it sends a chat message indicating that the iron pickaxe has been crafted.\\n}\"}, \"mineFiveCopperOres\": {\"code\": \"async function mineFiveCopperOres(bot) {\\n  const copperOreCount = bot.inventory.count(mcData.itemsByName.copper_ore.id);\\n  if (copperOreCount >= 5) {\\n    bot.chat(\\\"Already have 5 copper ores in inventory.\\\");\\n    return;\\n  }\\n  await bot.equip(mcData.itemsByName.iron_pickaxe.id, \\\"hand\\\");\\n  await mineBlock(bot, \\\"copper_ore\\\", 5 - copperOreCount);\\n  bot.chat(\\\"5 copper ores mined.\\\");\\n}\", \"description\": \"async function mineFiveCopperOres(bot) {\\n    // The function is about mining 5 copper ores using an iron pickaxe. It first checks if there are already 5 copper ores in the inventory, and if so, it returns. Otherwise, it equips the iron pickaxe in the hand and mines copper ores until there are 5 in the inventory. Finally, it sends a chat message indicating that 5 copper ores have been mined.\\n}\"}, \"craftStoneAxe\": {\"code\": \"async function craftStoneAxe(bot) {\\n  const requiredCobblestones = 3;\\n  const requiredSticks = 2;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones. Mining more...\\\");\\n    await mineBlock(bot, \\\"stone\\\", requiredCobblestones - cobblestoneCount);\\n    bot.chat(\\\"Cobblestones mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stone_axe\\\", 1);\\n  bot.chat(\\\"Stone axe crafted.\\\");\\n}\", \"description\": \"async function craftStoneAxe(bot) {\\n    // The function crafts a stone axe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone axe and sends a chat message.\\n}\"}, \"mineFiveIronOres\": {\"code\": \"async function mineFiveIronOres(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.iron_pickaxe.id);\\n  if (!stonePickaxe && !ironPickaxe) {\\n    bot.chat(\\\"No stone or iron pickaxe found. Mining cobblestone and crafting a stone pickaxe...\\\");\\n    await mineBlock(bot, \\\"stone\\\", 3);\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n    bot.chat(\\\"Stone pickaxe crafted.\\\");\\n  }\\n  const pickaxeToUse = ironPickaxe || stonePickaxe;\\n  await bot.equip(pickaxeToUse, \\\"hand\\\");\\n  await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\\n    const foundIronOre = bot.findBlock({\\n      matching: mcData.blocksByName.iron_ore.id,\\n      maxDistance: 32\\n    });\\n    return foundIronOre;\\n  });\\n  await mineBlock(bot, \\\"iron_ore\\\", 5);\\n  bot.chat(\\\"5 iron ores mined.\\\");\\n}\", \"description\": \"async function mineFiveIronOres(bot) {\\n    // The function is about mining 5 iron ores using either a stone or iron pickaxe. If neither pickaxe is found in the inventory, the bot will mine cobblestone and craft a stone pickaxe. Once a pickaxe is available, the bot will equip it and explore the environment until finding an iron ore block. Once an iron ore block is found, the bot will mine a total of 5 iron ores using the equipped pickaxe.\\n}\"}, \"craftTorches\": {\"code\": \"async function craftTorches(bot) {\\n  const requiredCoal = 2;\\n  const requiredSticks = 2;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more...\\\");\\n    await mineBlock(bot, \\\"coal_ore\\\", requiredCoal - coalCount);\\n    bot.chat(\\\"Coal mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"torch\\\", 1);\\n  bot.chat(\\\"8 torches crafted.\\\");\\n}\", \"description\": \"async function craftTorches(bot) {\\n    // The function crafts 8 torches using coal and sticks. It checks if there is enough coal and sticks in the inventory, and if not, it mines coal or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts 8 torches and saves the event.\\n}\"}, \"exploreCave\": {\"code\": \"async function exploreCave(bot) {\\n  const torches = bot.inventory.findInventoryItem(mcData.itemsByName.torch.id);\\n  if (!torches) {\\n    bot.chat(\\\"No torches found in inventory. Crafting torches...\\\");\\n    await craftTorches(bot);\\n  }\\n  await bot.equip(mcData.itemsByName.torch.id, \\\"hand\\\");\\n  const caveEntrance = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const caveBlock = bot.findBlock({\\n      matching: block => {\\n        return block && block.name === \\\"air\\\" && block.position && block.position.y < 60;\\n      },\\n      maxDistance: 32\\n    });\\n    return caveBlock;\\n  });\\n  if (!caveEntrance) {\\n    bot.chat(\\\"No cave entrance found nearby.\\\");\\n    return;\\n  }\\n  bot.chat(\\\"Cave entrance found. Exploring the cave...\\\");\\n  await exploreUntil(bot, new Vec3(1, 0, 1), 300, () => {\\n    const caveBlock = bot.findBlock({\\n      matching: block => {\\n        return block && block.name === \\\"air\\\" && block.position && block.position.y < 60;\\n      },\\n      maxDistance: 32\\n    });\\n    if (caveBlock) {\\n      bot.placeBlock(caveBlock, new Vec3(0, 1, 0));\\n    }\\n    const mob = bot.nearestEntity(entity => {\\n      return entity.type === \\\"mob\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    if (mob) {\\n      killMob(bot, mob.name, 300);\\n    }\\n    return null; // Continue exploring until the time limit is reached\\n  });\\n\\n  bot.chat(\\\"Finished exploring the cave.\\\");\\n}\", \"description\": \"async function exploreCave(bot) {\\n    // The function is about exploring a nearby cave. First, check if there are torches in the inventory. If not, craft torches. Equip the torches in the hand and explore the environment until finding a cave entrance. Once a cave entrance is found, explore the cave by placing torches and killing mobs until the time limit is reached.\\n}\"}, \"smeltSixRawIron\": {\"code\": \"async function smeltSixRawIron(bot) {\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  const requiredCoal = 6;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more coal...\\\");\\n    await mineBlock(bot, \\\"coal_ore\\\", requiredCoal - coalCount);\\n  }\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 6);\\n  bot.chat(\\\"6 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltSixRawIron(bot) {\\n    // The function is about smelting 6 raw iron using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. It then places the furnace next to the player and checks if there is enough coal in the inventory. If there isn't, it mines coal until there are 6 pieces. Finally, it smelts 6 raw iron using the furnace and coal, and returns a message indicating that the process is complete.\\n}\"}, \"mineLapisOre\": {\"code\": \"async function mineLapisOre(bot) {\\n  const pickaxeTypes = [mcData.itemsByName.stone_pickaxe.id, mcData.itemsByName.iron_pickaxe.id, mcData.itemsByName.diamond_pickaxe.id, mcData.itemsByName.netherite_pickaxe.id];\\n  let pickaxe = bot.inventory.items().find(item => pickaxeTypes.includes(item.type));\\n  if (!pickaxe) {\\n    bot.chat(\\\"No suitable pickaxe found. Mining cobblestone and crafting a stone pickaxe...\\\");\\n    await mineBlock(bot, \\\"stone\\\", 3);\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n    pickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n    bot.chat(\\\"Stone pickaxe crafted.\\\");\\n  }\\n  await bot.equip(pickaxe, \\\"hand\\\");\\n  const lapisOreBlock = await exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\\n    const foundLapisOre = bot.findBlock({\\n      matching: mcData.blocksByName.lapis_ore.id,\\n      maxDistance: 32\\n    });\\n    return foundLapisOre;\\n  });\\n  if (!lapisOreBlock) {\\n    bot.chat(\\\"No lapis ore found nearby. Exploring...\\\");\\n  }\\n  await mineBlock(bot, \\\"lapis_ore\\\", 1);\\n  bot.chat(\\\"Lapis ore mined.\\\");\\n}\", \"description\": \"async function mineLapisOre(bot) {\\n    // The function is about mining a single lapis ore block using the best available pickaxe. If the bot does not have a suitable pickaxe, it will mine cobblestone and craft a stone pickaxe. Once the pickaxe is available, it will equip it and explore the environment until finding a lapis ore block. Once a lapis ore block is found, it will mine it and save the event of mining the lapis ore.\\n}\"}, \"craftBucket\": {\"code\": \"async function craftBucket(bot) {\\n  const requiredIronIngots = 3;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots to craft a bucket.\\\");\\n    return;\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"bucket\\\", 1);\\n  bot.chat(\\\"Bucket crafted.\\\");\\n}\", \"description\": \"async function craftBucket(bot) {\\n    // The function crafts a bucket using 3 iron ingots. If there are not enough iron ingots, it returns. If there is no crafting table nearby, it places one. Then it crafts a bucket and sends a chat message.\\n}\"}, \"craftStoneShovel\": {\"code\": \"async function craftStoneShovel(bot) {\\n  const requiredCobblestones = 1;\\n  const requiredSticks = 2;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones. Mining more...\\\");\\n    await mineBlock(bot, \\\"stone\\\", requiredCobblestones - cobblestoneCount);\\n    bot.chat(\\\"Cobblestones mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stone_shovel\\\", 1);\\n  bot.chat(\\\"Stone shovel crafted.\\\");\\n}\", \"description\": \"async function craftStoneShovel(bot) {\\n    // The function crafts a stone shovel using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone shovel and logs a message.\\n}\"}, \"checkStonePickaxe\": {\"code\": \"async function checkStonePickaxe(bot) {\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName.stone_pickaxe.id);\\n  if (stonePickaxe) {\\n    bot.chat(\\\"The bot already has a stone pickaxe in its inventory.\\\");\\n  } else {\\n    bot.chat(\\\"The bot does not have a stone pickaxe in its inventory.\\\");\\n  }\\n}\", \"description\": \"async function checkStonePickaxe(bot) {\\n    // The function checks if the bot has a stone pickaxe in its inventory and sends a chat message indicating whether it has one or not.\\n}\"}, \"craftEightTorches\": {\"code\": \"async function craftEightTorches(bot) {\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"torch\\\", 1);\\n  bot.chat(\\\"8 torches crafted.\\\");\\n}\", \"description\": \"async function craftEightTorches(bot) {\\n    // The function is about crafting 8 torches. First, it checks if there is a crafting table nearby. If not, it places one. Then, it crafts 1 torch and saves it to the inventory. Finally, it outputs a message indicating that 8 torches have been crafted.\\n}\"}, \"craftIronPickaxeWithMaterials\": {\"code\": \"async function craftIronPickaxeWithMaterials(bot) {\\n  const requiredIronIngots = 3;\\n  const requiredSticks = 2;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots. Mining iron ores...\\\");\\n    await mineBlock(bot, \\\"iron_ore\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ores mined. Smelting iron ingots...\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ingots smelted.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"iron_pickaxe\\\", 1);\\n  bot.chat(\\\"Iron pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftIronPickaxeWithMaterials(bot) {\\n    // The function crafts an iron pickaxe using 3 iron ingots and 2 sticks. If there are not enough iron ingots, it mines iron ores and smelts them into ingots. If there are not enough sticks, it crafts them. If there is no crafting table nearby, it places one. Finally, it crafts an iron pickaxe and logs the result.\\n}\"}, \"craftChest\": {\"code\": \"async function craftChest(bot) {\\n  const requiredPlanks = 8;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Not enough spruce_planks. Mining a spruce_log and crafting more...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", 1);\\n    await craftItem(bot, \\\"spruce_planks\\\", 1);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  bot.chat(\\\"Crafting a chest...\\\");\\n  await craftItem(bot, \\\"chest\\\", 1);\\n  bot.chat(\\\"Chest crafted.\\\");\\n}\", \"description\": \"async function craftChest(bot) {\\n    // The function crafts a chest using spruce planks and a crafting table. If there are not enough spruce planks, it mines a spruce log and crafts more planks. If there is no crafting table nearby, it places one. Finally, it crafts a chest and logs the event.\\n}\"}, \"craftEightSticks\": {\"code\": \"async function craftEightSticks(bot) {\\n  const requiredPlanks = 2;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Not enough spruce_planks. Mining a spruce_log and crafting more...\\\");\\n    await mineBlock(bot, \\\"spruce_log\\\", 1);\\n    await craftItem(bot, \\\"spruce_planks\\\", 1);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stick\\\", 2);\\n  bot.chat(\\\"8 sticks crafted.\\\");\\n}\", \"description\": \"async function craftEightSticks(bot) {\\n    // The function crafts 8 sticks using spruce planks. If there are not enough spruce planks, it mines a spruce log and crafts more planks. If there is no crafting table nearby, it places one. Finally, it crafts 2 sticks and repeats the process until 8 sticks are crafted.\\n}\"}, \"exploreCaveAndGatherResources\": {\"code\": \"async function exploreCaveAndGatherResources(bot) {\\n  // Equip torches\\n  const torches = bot.inventory.findInventoryItem(mcData.itemsByName.torch.id);\\n  if (!torches) {\\n    bot.chat(\\\"No torches found in inventory. Crafting torches...\\\");\\n    await craftTorches(bot);\\n  }\\n  await bot.equip(mcData.itemsByName.torch.id, \\\"hand\\\");\\n\\n  // Find a cave entrance and start exploring\\n  const caveEntrance = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const caveBlock = bot.findBlock({\\n      matching: block => {\\n        return block && block.name === \\\"air\\\" && block.position && block.position.y < 60;\\n      },\\n      maxDistance: 32\\n    });\\n    return caveBlock;\\n  });\\n  if (!caveEntrance) {\\n    bot.chat(\\\"No cave entrance found nearby.\\\");\\n    return;\\n  }\\n  bot.chat(\\\"Cave entrance found. Exploring the cave...\\\");\\n\\n  // Explore the cave and gather resources\\n  await exploreUntil(bot, new Vec3(1, 0, 1), 300, () => {\\n    const caveBlock = bot.findBlock({\\n      matching: block => {\\n        return block && block.name === \\\"air\\\" && block.position && block.position.y < 60;\\n      },\\n      maxDistance: 32\\n    });\\n    if (caveBlock) {\\n      bot.placeBlock(caveBlock, new Vec3(0, 1, 0));\\n    }\\n    const mob = bot.nearestEntity(entity => {\\n      return entity.type === \\\"mob\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    if (mob) {\\n      killMob(bot, mob.name, 300);\\n    }\\n    const ores = [\\\"coal_ore\\\", \\\"iron_ore\\\", \\\"gold_ore\\\", \\\"diamond_ore\\\"];\\n    for (const ore of ores) {\\n      const oreBlock = bot.findBlock({\\n        matching: mcData.blocksByName[ore].id,\\n        maxDistance: 32\\n      });\\n      if (oreBlock) {\\n        mineBlock(bot, ore, 1);\\n      }\\n    }\\n    return null; // Continue exploring until the time limit is reached\\n  });\\n\\n  bot.chat(\\\"Finished exploring the cave and gathering resources.\\\");\\n}\", \"description\": \"async function exploreCaveAndGatherResources(bot) {\\n    // The function is about exploring a nearby cave and gathering resources. First, equip torches and find a cave entrance. Once a cave entrance is found, explore the cave and gather resources such as coal, iron, gold, and diamond ores. While exploring, place torches to light up the cave, kill nearby mobs, and mine ores. The function will continue exploring until the time limit is reached. Finally, the function will output a message indicating that the exploration and resource gathering is finished.\\n}\"}, \"craftWhiteBedWithExploration\": {\"code\": \"async function craftWhiteBedWithExploration(bot) {\\n  // Step 1: Explore the area to find and kill sheep to collect the required wool blocks if needed\\n  const requiredWool = 3;\\n  const woolCount = bot.inventory.count(mcData.itemsByName.white_wool.id);\\n  if (woolCount < requiredWool) {\\n    bot.chat(\\\"Collecting wool from sheep...\\\");\\n    for (let i = 0; i < requiredWool - woolCount; i++) {\\n      const sheep = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n        const sheep = bot.nearestEntity(entity => {\\n          return entity.name === \\\"sheep\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n        });\\n        return sheep;\\n      });\\n      if (sheep) {\\n        await killMob(bot, \\\"sheep\\\");\\n      } else {\\n        bot.chat(\\\"No sheep found. Please try again later.\\\");\\n        return;\\n      }\\n    }\\n    bot.chat(\\\"Wool collected.\\\");\\n  }\\n\\n  // Step 2: Craft 2 more spruce planks if needed\\n  const requiredPlanks = 3;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Crafting more spruce_planks...\\\");\\n    await craftItem(bot, \\\"spruce_planks\\\", requiredPlanks - planksCount);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n\\n  // Step 3: Place a crafting table if not already placed\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n\\n  // Step 4: Craft a white bed using the 3 white wool blocks and 3 spruce planks\\n  bot.chat(\\\"Crafting a white bed...\\\");\\n  await craftItem(bot, \\\"white_bed\\\", 1);\\n  bot.chat(\\\"White bed crafted.\\\");\\n}\", \"description\": \"async function craftWhiteBedWithExploration(bot) {\\n    // The function crafts a white bed using 3 white wool blocks and 3 spruce planks. If there are not enough wool blocks, the bot explores the area to find and kill sheep to collect the wool. If there are not enough spruce planks, the bot crafts more. If there is no crafting table nearby, the bot places one.\\n}\"}, \"cookMutton\": {\"code\": \"async function cookMutton(bot) {\\n  const rawMuttonCount = bot.inventory.count(mcData.itemsByName.mutton.id);\\n  if (rawMuttonCount < 5) {\\n    bot.chat(\\\"Not enough raw mutton to cook. Please collect more first.\\\");\\n    return;\\n  }\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  const requiredCoal = 5;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more coal...\\\");\\n    await mineBlock(bot, \\\"coal_ore\\\", requiredCoal - coalCount);\\n  }\\n  await smeltItem(bot, \\\"mutton\\\", \\\"coal\\\", 5);\\n  bot.chat(\\\"5 mutton cooked.\\\");\\n}\", \"description\": \"async function cookMutton(bot) {\\n    // The function is about cooking 5 raw muttons using a furnace and coal. It first checks if there are at least 5 raw muttons in the inventory, and if not, it returns a message to collect more. Then it checks if there is a furnace in the inventory, and if not, it returns a message to craft one. It places the furnace next to the player and checks if there is enough coal in the inventory. If not, it mines coal until there are 5 pieces. Finally, it smelts 5 raw muttons using coal and returns a message that 5 muttons have been cooked.\\n}\"}, \"eatCookedMutton\": {\"code\": \"async function eatCookedMutton(bot) {\\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName.cooked_mutton.id);\\n  await bot.equip(cookedMutton, \\\"hand\\\");\\n  await bot.consume();\\n  bot.chat(\\\"Cooked mutton eaten.\\\");\\n}\", \"description\": \"async function eatCookedMutton(bot) {\\n    // The function is about eating cooked mutton. It first checks if there is any cooked mutton in the inventory. If there is, it equips the cooked mutton in the hand and consumes it. Finally, it sends a chat message indicating that the cooked mutton has been eaten.\\n}\"}, \"collectWaterWithBucket\": {\"code\": \"async function collectWaterWithBucket(bot) {\\n  const waterBlock = bot.findBlock({\\n    matching: mcData.blocksByName.water.id,\\n    maxDistance: 32\\n  });\\n  if (!waterBlock) {\\n    bot.chat(\\\"No water block found nearby. Exploring...\\\");\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundWaterBlock = bot.findBlock({\\n        matching: mcData.blocksByName.water.id,\\n        maxDistance: 32\\n      });\\n      return foundWaterBlock;\\n    });\\n  }\\n  const bucket = bot.inventory.findInventoryItem(mcData.itemsByName.bucket.id);\\n  await bot.equip(bucket, \\\"hand\\\");\\n  await bot.lookAt(waterBlock.position);\\n  await bot.activateItem();\\n  bot.chat(\\\"Water collected with bucket.\\\");\\n}\", \"description\": \"async function collectWaterWithBucket(bot) {\\n    // The function is about collecting water with a bucket. It first searches for a water block within a certain distance. If no water block is found, it explores the environment until it finds one. Once a water block is found, it equips the bucket in the hand, looks at the water block, and activates the item to collect water. Finally, it sends a chat message indicating that water has been collected.\\n}\"}, \"craftFishingRod\": {\"code\": \"async function craftFishingRod(bot) {\\n  // Check if we have enough strings\\n  const requiredStrings = 2;\\n  const stringsCount = bot.inventory.count(mcData.itemsByName.string.id);\\n  if (stringsCount < requiredStrings) {\\n    // Find and kill spiders to obtain strings\\n    while (bot.inventory.count(mcData.itemsByName.string.id) < requiredStrings) {\\n      bot.chat(\\\"Finding a spider to obtain strings...\\\");\\n      const spider = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n        const spider = bot.nearestEntity(entity => {\\n          return entity.name === \\\"spider\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n        });\\n        return spider;\\n      });\\n      if (spider) {\\n        bot.chat(\\\"Spider found. Killing it...\\\");\\n        await killMob(bot, \\\"spider\\\", 300);\\n        bot.chat(\\\"Spider killed.\\\");\\n      } else {\\n        bot.chat(\\\"Could not find a spider. Trying again...\\\");\\n      }\\n    }\\n  }\\n\\n  // Place a crafting table if not already placed\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n\\n  // Craft a fishing rod using the 3 sticks and 2 strings\\n  await craftItem(bot, \\\"fishing_rod\\\", 1);\\n  bot.chat(\\\"Fishing rod crafted.\\\");\\n}\", \"description\": \"async function craftFishingRod(bot) {\\n    // The function crafts a fishing rod using 2 strings and 3 sticks. If there are not enough strings, the bot will find and kill spiders to obtain them. If a crafting table is not already placed, the bot will place one. Finally, the bot will craft a fishing rod and output a message.\\n}\"}, \"fishInNearbyWaterSafely\": {\"code\": \"async function fishInNearbyWaterSafely(bot) {\\n  // Check if the bot has a fishing rod in its inventory\\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  if (!fishingRod) {\\n    await craftFishingRod(bot);\\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  }\\n\\n  // Find a nearby water block\\n  const waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const foundWaterBlock = bot.findBlock({\\n      matching: mcData.blocksByName.water.id,\\n      maxDistance: 32\\n    });\\n    return foundWaterBlock;\\n  });\\n\\n  // Move to a block adjacent to the water block\\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\\n\\n  // Look at the water block\\n  await bot.lookAt(waterBlock.position);\\n\\n  // Equip the fishing rod\\n  await bot.equip(fishingRod, \\\"hand\\\");\\n\\n  // Check for hostile mobs nearby and kill them if necessary\\n  const hostileMobs = [\\\"zombie\\\", \\\"skeleton\\\", \\\"creeper\\\"];\\n  for (const mobName of hostileMobs) {\\n    const mob = bot.nearestEntity(entity => {\\n      return entity.name === mobName && entity.position.distanceTo(bot.entity.position) < 16;\\n    });\\n    if (mob) {\\n      await killMob(bot, mobName, 300);\\n    }\\n  }\\n\\n  // Fish in the water\\n  try {\\n    await bot.fish();\\n    bot.chat(\\\"Fished in the nearby water.\\\");\\n  } catch (error) {\\n    if (error.message === \\\"Fishing cancelled\\\") {\\n      bot.chat(\\\"Fishing was cancelled. Trying again...\\\");\\n      await fishInNearbyWaterSafely(bot);\\n    } else {\\n      throw error;\\n    }\\n  }\\n}\", \"description\": \"async function fishInNearbyWaterSafely(bot) {\\n    // The function is about fishing in a nearby water block safely. It first checks if the bot has a fishing rod in its inventory, and crafts one if it doesn't. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and checks for hostile mobs nearby, killing them if necessary. Finally, it fishes in the water and retries if the fishing is cancelled.\\n}\"}, \"craftSpyglass\": {\"code\": \"async function craftSpyglass(bot) {\\n  const requiredCopperIngots = 2;\\n  const requiredAmethystShards = 1;\\n  const copperIngotsCount = bot.inventory.count(mcData.itemsByName.copper_ingot.id);\\n  const amethystShardsCount = bot.inventory.count(mcData.itemsByName.amethyst_shard.id);\\n  if (copperIngotsCount < requiredCopperIngots || amethystShardsCount < requiredAmethystShards) {\\n    bot.chat(\\\"Not enough copper ingots or amethyst shards to craft a spyglass.\\\");\\n    return;\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"spyglass\\\", 1);\\n  bot.chat(\\\"Spyglass crafted.\\\");\\n}\", \"description\": \"async function craftSpyglass(bot) {\\n    // The function crafts a spyglass using 2 copper ingots and 1 amethyst shard. It checks if there are enough materials in the inventory, and if not, it returns. If there is a crafting table nearby, it crafts the spyglass. If not, it places a crafting table and then crafts the spyglass. Finally, it sends a chat message indicating that the spyglass has been crafted.\\n}\"}, \"craftWoodenHoe\": {\"code\": \"async function craftWoodenHoe(bot) {\\n  const requiredPlanks = 2;\\n  const requiredSticks = 2;\\n  const planksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (planksCount < requiredPlanks) {\\n    bot.chat(\\\"Not enough spruce_planks. Crafting more...\\\");\\n    await craftItem(bot, \\\"spruce_planks\\\", requiredPlanks - planksCount);\\n    bot.chat(\\\"Spruce_planks crafted.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"wooden_hoe\\\", 1);\\n  bot.chat(\\\"Wooden hoe crafted.\\\");\\n}\", \"description\": \"async function craftWoodenHoe(bot) {\\n    // The function crafts a wooden hoe using 2 spruce planks and 2 sticks. It checks if there are enough planks and sticks in the inventory, and crafts more if necessary. If there is no crafting table nearby, it places one. Finally, it crafts a wooden hoe and logs a message.\\n}\"}, \"catchThreeFish\": {\"code\": \"async function catchThreeFish(bot) {\\n  // Check if the bot has a fishing rod in its inventory\\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  if (!fishingRod) {\\n    await craftFishingRod(bot);\\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  }\\n\\n  // Find a nearby water block\\n  let waterBlock;\\n  while (!waterBlock) {\\n    waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundWaterBlock = bot.findBlock({\\n        matching: mcData.blocksByName.water.id,\\n        maxDistance: 32\\n      });\\n      return foundWaterBlock;\\n    });\\n    if (!waterBlock) {\\n      bot.chat(\\\"No path to the water block. Trying to find another water block...\\\");\\n    }\\n  }\\n\\n  // Move to a block adjacent to the water block\\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\\n\\n  // Look at the water block\\n  await bot.lookAt(waterBlock.position);\\n\\n  // Equip the fishing rod\\n  await bot.equip(fishingRod, \\\"hand\\\");\\n\\n  // Fish in the water 3 times\\n  for (let i = 0; i < 3; i++) {\\n    try {\\n      await bot.fish();\\n      bot.chat(`Fish ${i + 1} caught.`);\\n    } catch (error) {\\n      if (error.message === \\\"Fishing cancelled\\\") {\\n        bot.chat(\\\"Fishing was cancelled. Trying again...\\\");\\n        i--; // Retry the same iteration\\n      } else {\\n        throw error;\\n      }\\n    }\\n  }\\n}\", \"description\": \"async function catchThreeFish(bot) {\\n    // The function is about catching three fish using a fishing rod. First, it checks if the bot has a fishing rod in its inventory. If not, it crafts one. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and fishes in the water three times. If fishing is cancelled, it retries the same iteration.\\n}\"}, \"craftShieldWithFurnace\": {\"code\": \"async function craftShieldWithFurnace(bot) {\\n  const requiredIronIngots = 1;\\n  const requiredSprucePlanks = 6;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sprucePlanksCount = bot.inventory.count(mcData.itemsByName.spruce_planks.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots. Smelting iron ingots...\\\");\\n    const furnace = bot.findBlock({\\n      matching: mcData.blocksByName.furnace.id,\\n      maxDistance: 32\\n    });\\n    if (!furnace) {\\n      const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n      await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n      bot.chat(\\\"Furnace placed.\\\");\\n    }\\n    await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ingots smelted.\\\");\\n  }\\n  if (sprucePlanksCount < requiredSprucePlanks) {\\n    bot.chat(\\\"Not enough spruce planks. Crafting more...\\\");\\n    await craftItem(bot, \\\"spruce_planks\\\", requiredSprucePlanks - sprucePlanksCount);\\n    bot.chat(\\\"Spruce planks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"shield\\\", 1);\\n  bot.chat(\\\"Shield crafted.\\\");\\n}\", \"description\": \"async function craftShieldWithFurnace(bot) {\\n    // The function crafts a shield using a furnace and a crafting table. It checks if there are enough iron ingots and spruce planks in the inventory, and if not, it smelts iron ingots and crafts spruce planks. If a furnace or a crafting table is not nearby, it places one. Finally, it crafts a shield using the crafting table and logs a message.\\n}\"}, \"smeltOneRawIron\": {\"code\": \"async function smeltOneRawIron(bot) {\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 1);\\n  bot.chat(\\\"1 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltOneRawIron(bot) {\\n    // The function is about smelting one raw iron using a furnace. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. It then places the furnace next to the bot and smelts one raw iron using coal as fuel. Finally, it sends a message indicating that one raw iron has been smelted.\\n}\"}, \"craftStoneHoe\": {\"code\": \"async function craftStoneHoe(bot) {\\n  const requiredCobblestones = 2;\\n  const requiredSticks = 2;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones. Mining more...\\\");\\n    await mineBlock(bot, \\\"stone\\\", requiredCobblestones - cobblestoneCount);\\n    bot.chat(\\\"Cobblestones mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stone_hoe\\\", 1);\\n  bot.chat(\\\"Stone hoe crafted.\\\");\\n}\", \"description\": \"async function craftStoneHoe(bot) {\\n    // The function crafts a stone hoe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone hoe and logs a message.\\n}\"}, \"craftStonePickaxe\": {\"code\": \"async function craftStonePickaxe(bot) {\\n  const requiredCobblestones = 3;\\n  const requiredSticks = 2;\\n  const cobblestoneCount = bot.inventory.count(mcData.itemsByName.cobblestone.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (cobblestoneCount < requiredCobblestones) {\\n    bot.chat(\\\"Not enough cobblestones. Mining more...\\\");\\n    await mineBlock(bot, \\\"stone\\\", requiredCobblestones - cobblestoneCount);\\n    bot.chat(\\\"Cobblestones mined.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  let craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"stone_pickaxe\\\", 1);\\n  bot.chat(\\\"Stone pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftStonePickaxe(bot) {\\n    // The function crafts a stone pickaxe using cobblestones and sticks. It checks if there are enough cobblestones and sticks in the inventory, and if not, it mines cobblestones or crafts sticks. If there is no crafting table nearby, it places one. Finally, it crafts a stone pickaxe and sends a chat message.\\n}\"}, \"craftSixteenTorches\": {\"code\": \"async function craftSixteenTorches(bot) {\\n  const requiredSticks = 4;\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", 1);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"torch\\\", 2);\\n  bot.chat(\\\"16 torches crafted.\\\");\\n}\", \"description\": \"async function craftSixteenTorches(bot) {\\n    // The function crafts 16 torches using sticks and a crafting table. It checks if there are enough sticks in the inventory, and if not, crafts more. If there is no crafting table nearby, it places one. Finally, it crafts 16 torches and saves the event.\\n}\"}, \"smeltTwentyFiveIronIngots\": {\"code\": \"async function smeltTwentyFiveIronIngots(bot) {\\n  const furnaceInInventory = bot.inventory.findInventoryItem(mcData.itemsByName.furnace.id);\\n  if (!furnaceInInventory) {\\n    bot.chat(\\\"No furnace found in inventory. Please craft one first.\\\");\\n    return;\\n  }\\n  let furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  const blockAtFurnacePosition = bot.blockAt(furnacePosition);\\n  if (blockAtFurnacePosition.name === \\\"coal_ore\\\") {\\n    furnacePosition = bot.entity.position.offset(-1, 0, 0);\\n  }\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n  bot.chat(\\\"Furnace placed.\\\");\\n  const requiredCoal = 25;\\n  const coalCount = bot.inventory.count(mcData.itemsByName.coal.id);\\n  if (coalCount < requiredCoal) {\\n    bot.chat(\\\"Not enough coal. Mining more coal...\\\");\\n    await mineBlock(bot, \\\"coal_ore\\\", requiredCoal - coalCount);\\n  }\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 25);\\n  bot.chat(\\\"25 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltTwentyFiveIronIngots(bot) {\\n    // The function is about smelting 25 raw iron ingots using a furnace and coal. It first checks if a furnace is in the inventory, and if not, it returns a message to craft one. Then it places the furnace next to the bot, and checks if there is enough coal in the inventory. If there isn't, it mines coal until there are 25 pieces. Finally, it smelts 25 raw iron ingots using the furnace and coal, and returns a message indicating that the process is complete.\\n}\"}, \"craftIronHelmet\": {\"code\": \"async function craftIronHelmet(bot) {\\n  const requiredIronIngots = 5;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots to craft an iron helmet.\\\");\\n    return;\\n  }\\n  let craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n    // Update the craftingTable variable after placing it\\n    craftingTable = bot.blockAt(craftingTablePosition);\\n  }\\n  await craftItem(bot, \\\"iron_helmet\\\", 1);\\n  bot.chat(\\\"Iron helmet crafted.\\\");\\n}\", \"description\": \"async function craftIronHelmet(bot) {\\n    // The function crafts an iron helmet using 5 iron ingots. If there are not enough iron ingots, it returns. If there is no crafting table nearby, it places one and updates the variable. Then, it crafts an iron helmet and sends a chat message.\\n}\"}, \"craftIronChestplate\": {\"code\": \"async function craftIronChestplate(bot) {\\n  const requiredIronIngots = 8;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots. Mining iron ores...\\\");\\n    await mineBlock(bot, \\\"iron_ore\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ores mined. Smelting iron ingots...\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ingots smelted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"iron_chestplate\\\", 1);\\n  bot.chat(\\\"Iron chestplate crafted.\\\");\\n}\", \"description\": \"async function craftIronChestplate(bot) {\\n    // The function crafts an iron chestplate using iron ingots. If there are not enough iron ingots in the inventory, the bot will mine iron ores and smelt them into iron ingots. Then, the bot will search for a nearby crafting table and place one if it is not found. Finally, the bot will craft an iron chestplate and chat a message indicating that the item has been crafted.\\n}\"}, \"craftIronSword\": {\"code\": \"async function craftIronSword(bot) {\\n  const requiredIronIngots = 2;\\n  const requiredSticks = 1;\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  const sticksCount = bot.inventory.count(mcData.itemsByName.stick.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots. Mining iron ores...\\\");\\n    await mineBlock(bot, \\\"iron_ore\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ores mined. Smelting iron ingots...\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ingots smelted.\\\");\\n  }\\n  if (sticksCount < requiredSticks) {\\n    bot.chat(\\\"Not enough sticks. Crafting more...\\\");\\n    await craftItem(bot, \\\"stick\\\", requiredSticks - sticksCount);\\n    bot.chat(\\\"Sticks crafted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"iron_sword\\\", 1);\\n  bot.chat(\\\"Iron sword crafted.\\\");\\n}\", \"description\": \"async function craftIronSword(bot) {\\n    // The function crafts an iron sword using 2 iron ingots and 1 stick. If there are not enough iron ingots, it mines iron ores and smelts them into ingots. If there are not enough sticks, it crafts them. It then looks for a crafting table within 32 blocks, and if it doesn't find one, it places one nearby. Finally, it crafts an iron sword and logs a message.\\n}\"}, \"craftIronLeggingsAndBoots\": {\"code\": \"async function craftIronLeggingsAndBoots(bot) {\\n  const requiredIronIngots = 11; // 7 for leggings, 4 for boots\\n  const ironIngotsCount = bot.inventory.count(mcData.itemsByName.iron_ingot.id);\\n  if (ironIngotsCount < requiredIronIngots) {\\n    bot.chat(\\\"Not enough iron ingots. Mining iron ores...\\\");\\n    await mineBlock(bot, \\\"iron_ore\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ores mined. Smelting iron ingots...\\\");\\n    await smeltItem(bot, \\\"iron_ore\\\", \\\"coal\\\", requiredIronIngots - ironIngotsCount);\\n    bot.chat(\\\"Iron ingots smelted.\\\");\\n  }\\n  const craftingTable = bot.findBlock({\\n    matching: mcData.blocksByName.crafting_table.id,\\n    maxDistance: 32\\n  });\\n  if (!craftingTable) {\\n    const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n    bot.chat(\\\"Crafting_table placed.\\\");\\n  }\\n  await craftItem(bot, \\\"iron_leggings\\\", 1);\\n  bot.chat(\\\"Iron leggings crafted.\\\");\\n  await craftItem(bot, \\\"iron_boots\\\", 1);\\n  bot.chat(\\\"Iron boots crafted.\\\");\\n}\", \"description\": \"async function craftIronLeggingsAndBoots(bot) {\\n    // The function crafts iron leggings and boots. It checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and smelts them into ingots. If there is no crafting table nearby, it places one. Finally, it crafts one pair of iron leggings and one pair of iron boots.\\n}\"}, \"catchFiveFishSafely\": {\"code\": \"async function catchFiveFishSafely(bot) {\\n  // Check if the bot has a fishing rod in its inventory\\n  let fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  if (!fishingRod) {\\n    await craftFishingRod(bot);\\n    fishingRod = bot.inventory.findInventoryItem(mcData.itemsByName.fishing_rod.id);\\n  }\\n\\n  // Find a nearby water block\\n  let waterBlock;\\n  while (!waterBlock) {\\n    waterBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const foundWaterBlock = bot.findBlock({\\n        matching: mcData.blocksByName.water.id,\\n        maxDistance: 32\\n      });\\n      return foundWaterBlock;\\n    });\\n    if (!waterBlock) {\\n      bot.chat(\\\"No path to the water block. Trying to find another water block...\\\");\\n    }\\n  }\\n\\n  // Move to a block adjacent to the water block\\n  const adjacentBlock = waterBlock.position.offset(0, 1, 0);\\n  await bot.pathfinder.goto(new GoalBlock(adjacentBlock.x, adjacentBlock.y, adjacentBlock.z));\\n\\n  // Look at the water block\\n  await bot.lookAt(waterBlock.position);\\n\\n  // Equip the fishing rod\\n  await bot.equip(fishingRod, \\\"hand\\\");\\n\\n  // Fish in the water 5 times\\n  for (let i = 0; i < 5; i++) {\\n    try {\\n      await bot.fish();\\n      bot.chat(`Fish ${i + 1} caught.`);\\n    } catch (error) {\\n      if (error.message === \\\"Fishing cancelled\\\") {\\n        bot.chat(\\\"Fishing was cancelled. Trying again...\\\");\\n        i--; // Retry the same iteration\\n      } else {\\n        throw error;\\n      }\\n    }\\n  }\\n}\", \"description\": \"async function catchFiveFishSafely(bot) {\\n    // The function is about catching five fish safely using a fishing rod. First, it checks if the bot has a fishing rod in its inventory. If not, it crafts one. Then, it finds a nearby water block and moves to a block adjacent to it. After looking at the water block, it equips the fishing rod and fishes in the water five times. If fishing is cancelled, it retries the same iteration.\\n}\"}, \"equipIronArmor\": {\"code\": \"async function equipIronArmor(bot) {\\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName.iron_helmet.id);\\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName.iron_chestplate.id);\\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName.iron_leggings.id);\\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName.iron_boots.id);\\n  if (ironHelmet) {\\n    await bot.equip(ironHelmet, \\\"head\\\");\\n    bot.chat(\\\"Iron helmet equipped.\\\");\\n  } else {\\n    bot.chat(\\\"Iron helmet not found in inventory.\\\");\\n  }\\n  if (ironChestplate) {\\n    await bot.equip(ironChestplate, \\\"torso\\\");\\n    bot.chat(\\\"Iron chestplate equipped.\\\");\\n  } else {\\n    bot.chat(\\\"Iron chestplate not found in inventory.\\\");\\n  }\\n  if (ironLeggings) {\\n    await bot.equip(ironLeggings, \\\"legs\\\");\\n    bot.chat(\\\"Iron leggings equipped.\\\");\\n  } else {\\n    bot.chat(\\\"Iron leggings not found in inventory.\\\");\\n  }\\n  if (ironBoots) {\\n    await bot.equip(ironBoots, \\\"feet\\\");\\n    bot.chat(\\\"Iron boots equipped.\\\");\\n  } else {\\n    bot.chat(\\\"Iron boots not found in inventory.\\\");\\n  }\\n}\", \"description\": \"async function equipIronArmor(bot) {\\n    // The function equips the player with iron armor if it is available in the inventory. It checks for the presence of each piece of iron armor (helmet, chestplate, leggings, and boots) and equips them one by one. If a piece of armor is not found in the inventory, it sends a message to the chat indicating that it is not available.\\n}\"}}"
  },
  {
    "path": "skill_library/trial3/skill/code/cookChicken.js",
    "content": "async function cookChicken(bot) {\n  // Check if there is a furnace in the inventory\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\"furnace\"].id);\n\n  // If there is no furnace, craft one using cobblestone\n  if (!furnace) {\n    await craftItem(bot, \"furnace\", 1);\n  }\n\n  // Place the furnace near the player\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt the raw chicken using coal as fuel in the furnace\n  await smeltItem(bot, \"chicken\", \"coal\", 1);\n\n  // Collect the cooked chicken\n  bot.chat(\"1 chicken cooked.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/cookRawBeef.js",
    "content": "async function cookRawBeef(bot) {\n  // Check if there is a furnace in the inventory\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\"furnace\"].id);\n\n  // If there is no furnace, craft one using cobblestone\n  if (!furnace) {\n    await craftItem(bot, \"furnace\", 1);\n  }\n\n  // Place the furnace near the player\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt the 6 raw beef using coal as fuel in the furnace\n  await smeltItem(bot, \"beef\", \"coal\", 6);\n\n  // Collect the cooked beef\n  bot.chat(\"6 raw beef cooked.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/cookRawMutton.js",
    "content": "async function cookRawMutton(bot) {\n  // Check if there is a furnace in the inventory\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\"furnace\"].id);\n\n  // If there is no furnace, craft one using cobblestone\n  if (!furnace) {\n    await craftItem(bot, \"furnace\", 1);\n  }\n\n  // Place the furnace near the player\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt the 4 raw mutton using coal as fuel in the furnace\n  await smeltItem(bot, \"mutton\", \"coal\", 4);\n\n  // Collect the cooked mutton\n  bot.chat(\"4 raw mutton cooked.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/cookThreeRawChicken.js",
    "content": "async function cookThreeRawChicken(bot) {\n  // Find a suitable location to place the furnace\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n\n  // Place the furnace\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 3 raw chicken using coal as fuel\n  await smeltItem(bot, \"chicken\", \"coal\", 3);\n  bot.chat(\"3 raw chicken cooked.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftBirchBoat.js",
    "content": "async function findSuitablePosition(bot) {\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\n  for (const offset of offsets) {\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\n    const blockBelow = bot.blockAt(position.offset(0, -1, 0));\n    if (blockBelow && blockBelow.name !== \"air\") {\n      return position;\n    }\n  }\n  return null;\n}\n\nasync function craftBirchBoat(bot) {\n  // Check if there are enough birch logs in the inventory\n  const birchLogs = bot.inventory.count(mcData.itemsByName[\"birch_log\"].id);\n  if (birchLogs < 5) {\n    // Mine more birch logs\n    await mineBlock(bot, \"birch_log\", 5 - birchLogs);\n  }\n\n  // Craft birch planks using birch logs\n  await craftItem(bot, \"birch_planks\", 5);\n\n  // Check if there is a crafting table in the inventory\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\"crafting_table\"].id);\n  if (!craftingTable) {\n    // Craft a crafting table\n    await craftItem(bot, \"crafting_table\", 1);\n  }\n\n  // Find a suitable position to place the crafting table\n  const craftingTablePosition = await findSuitablePosition(bot);\n  if (!craftingTablePosition) {\n    bot.chat(\"Failed to find a suitable position to place the crafting table. Please try again.\");\n    return;\n  }\n\n  // Place the crafting table at the suitable position\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a birch boat using birch planks and the crafting table\n  await craftItem(bot, \"birch_boat\", 1, craftingTablePosition);\n  bot.chat(\"Birch boat crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftBoneMeal.js",
    "content": "async function craftBoneMeal(bot) {\n  // Check if there are enough bones in the inventory\n  const bones = bot.inventory.count(mcData.itemsByName[\"bone\"].id);\n  if (bones < 2) {\n    bot.chat(\"Not enough bones to craft 4 bone meal.\");\n    return;\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft 4 bone meal using 2 bones and the crafting table\n  await craftItem(bot, \"bone_meal\", 2, craftingTablePosition);\n  bot.chat(\"4 bone meal crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftChest.js",
    "content": "async function craftChest(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\"oak_planks\"].id);\n  if (oakPlanks < 8) {\n    // Mine more oak logs\n    await mineBlock(bot, \"oak_log\", 8 - oakPlanks);\n    // Craft oak planks using oak logs\n    await craftItem(bot, \"oak_planks\", 8 - oakPlanks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a chest using oak planks with the crafting table\n  await craftItem(bot, \"chest\", 1, craftingTablePosition);\n  bot.chat(\"Chest crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftClock.js",
    "content": "async function craftClock(bot) {\n  // Check if there is a crafting table in the inventory\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\"crafting_table\"].id);\n\n  // If there is no crafting table, craft one using oak planks\n  if (!craftingTable) {\n    await craftItem(bot, \"crafting_table\", 1);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a clock using 4 gold ingots and 1 redstone dust with the crafting table\n  await craftItem(bot, \"clock\", 1, craftingTablePosition);\n  bot.chat(\"Clock crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftCopperBlock.js",
    "content": "async function craftCopperBlock(bot) {\n  // Check if there are enough copper ingots in the inventory\n  const copperIngots = bot.inventory.count(mcData.itemsByName[\"copper_ingot\"].id);\n  if (copperIngots < 9) {\n    bot.chat(\"Not enough copper ingots to craft a copper block.\");\n    return;\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a copper block using copper ingots and the crafting table\n  await craftItem(bot, \"copper_block\", 1, craftingTablePosition);\n  bot.chat(\"Copper block crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftDiamondSword.js",
    "content": "async function craftDiamondSword(bot) {\n  // Check if there are enough diamonds in the inventory\n  const diamonds = bot.inventory.count(mcData.itemsByName[\"diamond\"].id);\n  if (diamonds < 2) {\n    bot.chat(\"Not enough diamonds to craft a diamond sword.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 1) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 1 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a diamond sword using diamonds and sticks with the crafting table\n  await craftItem(bot, \"diamond_sword\", 1, craftingTablePosition);\n  bot.chat(\"Diamond sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftFurnace.js",
    "content": "async function craftFurnace(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 8) {\n    bot.chat(\"Not enough cobblestones to craft a furnace.\");\n    return;\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a furnace using cobblestones and the crafting table\n  await craftItem(bot, \"furnace\", 1, craftingTablePosition);\n  bot.chat(\"Furnace crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftIronChestplate.js",
    "content": "async function craftIronChestplate(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 8) {\n    // Mine iron ores\n    await mineBlock(bot, \"iron_ore\", 8 - ironIngots);\n\n    // Place a furnace near the player\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"furnace\", furnacePosition);\n\n    // Smelt iron ores into iron ingots\n    for (let i = 0; i < 8 - ironIngots; i++) {\n      await smeltItem(bot, \"raw_iron\", \"coal\");\n    }\n  }\n\n  // Check if there is a crafting table in the inventory\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\"crafting_table\"].id);\n  if (!craftingTable) {\n    // Craft a crafting table\n    await craftItem(bot, \"crafting_table\", 1);\n  }\n\n  // Try to place the crafting table near the player at different positions until it is successfully placed\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\n  let craftingTablePosition = null;\n  for (const offset of offsets) {\n    try {\n      craftingTablePosition = bot.entity.position.offset(offset.x, offset.y, offset.z);\n      await placeItem(bot, \"crafting_table\", craftingTablePosition);\n      break;\n    } catch (error) {\n      console.log(\"Error placing crafting_table:\", error.message);\n    }\n  }\n  if (!craftingTablePosition) {\n    bot.chat(\"Failed to place crafting table. Please try again.\");\n    return;\n  }\n\n  // Craft an iron chestplate using iron ingots and the crafting table\n  await craftItem(bot, \"iron_chestplate\", 1, craftingTablePosition);\n  bot.chat(\"Iron chestplate crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftIronHelmet.js",
    "content": "async function craftIronHelmet(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 5) {\n    // Mine iron ores\n    await mineBlock(bot, \"iron_ore\", 5 - ironIngots);\n\n    // Place a furnace near the player\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"furnace\", furnacePosition);\n\n    // Smelt iron ores into iron ingots\n    for (let i = 0; i < 5 - ironIngots; i++) {\n      await smeltItem(bot, \"raw_iron\", \"coal\");\n    }\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron helmet using iron ingots and the crafting table\n  await craftItem(bot, \"iron_helmet\", 1, craftingTablePosition);\n  bot.chat(\"Iron helmet crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftIronLeggingsAndBoots.js",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 11) {\n    // Mine iron ores\n    await mineBlock(bot, \"iron_ore\", 11 - ironIngots);\n\n    // Check if there are enough coal in the inventory\n    const coalCount = bot.inventory.count(mcData.itemsByName[\"coal\"].id);\n    if (coalCount < 11 - ironIngots) {\n      // Mine coal\n      await mineBlock(bot, \"coal_ore\", 11 - ironIngots - coalCount);\n    }\n\n    // Place a furnace near the player\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\n    await placeItem(bot, \"furnace\", furnacePosition);\n\n    // Smelt iron ores into iron ingots\n    for (let i = 0; i < 11 - ironIngots; i++) {\n      await smeltItem(bot, \"raw_iron\", \"coal\");\n    }\n  }\n\n  // Check if there is a crafting table in the inventory\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\"crafting_table\"].id);\n  if (!craftingTable) {\n    // Craft a crafting table\n    await craftItem(bot, \"crafting_table\", 1);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft iron leggings using the crafting table\n  await craftItem(bot, \"iron_leggings\", 1);\n\n  // Craft iron boots using the crafting table\n  await craftItem(bot, \"iron_boots\", 1);\n  bot.chat(\"Iron leggings and iron boots crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftIronPickaxe.js",
    "content": "async function craftIronPickaxe(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 3) {\n    bot.chat(\"Not enough iron ingots to craft an iron pickaxe.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron pickaxe using iron ingots and sticks with the crafting table\n  await craftItem(bot, \"iron_pickaxe\", 1, craftingTablePosition);\n  bot.chat(\"Iron pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftIronSword.js",
    "content": "async function craftIronSword(bot) {\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 2) {\n    bot.chat(\"Not enough iron ingots to craft an iron sword.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 1) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 1 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft an iron sword using iron ingots and sticks with the crafting table\n  await craftItem(bot, \"iron_sword\", 1, craftingTablePosition);\n  bot.chat(\"Iron sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftShield.js",
    "content": "async function craftShield(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\"oak_planks\"].id);\n  if (oakPlanks < 6) {\n    // Craft more oak planks using oak logs\n    await craftItem(bot, \"oak_planks\", 6 - oakPlanks);\n  }\n\n  // Check if there are enough iron ingots in the inventory\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\"iron_ingot\"].id);\n  if (ironIngots < 1) {\n    bot.chat(\"Not enough iron ingots to craft a shield.\");\n    return;\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a shield using oak planks and iron ingots with the crafting table\n  await craftItem(bot, \"shield\", 1, craftingTablePosition);\n  bot.chat(\"Shield crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneAxe.js",
    "content": "async function craftStoneAxe(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 3) {\n    bot.chat(\"Not enough cobblestones to craft a stone axe.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone axe using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_axe\", 1, craftingTablePosition);\n  bot.chat(\"Stone axe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneHoe.js",
    "content": "async function craftStoneHoe(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 2) {\n    bot.chat(\"Not enough cobblestones to craft a stone hoe.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone hoe using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_hoe\", 1, craftingTablePosition);\n  bot.chat(\"Stone hoe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneHoeV2.js",
    "content": "async function craftStoneHoe(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 2) {\n    bot.chat(\"Not enough cobblestones to craft a stone hoe.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone hoe using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_hoe\", 1, craftingTablePosition);\n  bot.chat(\"Stone hoe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStonePickaxe.js",
    "content": "async function craftStonePickaxe(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 3) {\n    bot.chat(\"Not enough cobblestones to craft a stone pickaxe.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone pickaxe using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_pickaxe\", 1, craftingTablePosition);\n  bot.chat(\"Stone pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneShovel.js",
    "content": "async function craftStoneShovel(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 1) {\n    bot.chat(\"Not enough cobblestones to craft a stone shovel.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone shovel using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_shovel\", 1, craftingTablePosition);\n  bot.chat(\"Stone shovel crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneSword.js",
    "content": "async function craftStoneSword(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 2) {\n    bot.chat(\"Not enough cobblestones to craft a stone sword.\");\n    return;\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 1) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 1 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone sword using cobblestones and sticks with the crafting table\n  await craftItem(bot, \"stone_sword\", 1, craftingTablePosition);\n  bot.chat(\"Stone sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftStoneTools.js",
    "content": "async function craftStoneTools(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 6) {\n    // Mine more cobblestones\n    await mineBlock(bot, \"stone\", 6 - cobblestones);\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 5) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 5 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a stone sword, a stone axe, and a stone shovel using the crafting table\n  await craftItem(bot, \"stone_sword\", 1, craftingTablePosition);\n  await craftItem(bot, \"stone_axe\", 1, craftingTablePosition);\n  await craftItem(bot, \"stone_shovel\", 1, craftingTablePosition);\n  bot.chat(\"Stone sword, stone axe, and stone shovel crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftTenCobblestoneWalls.js",
    "content": "async function craftTenCobblestoneWalls(bot) {\n  // Check if there are enough cobblestones in the inventory\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\"cobblestone\"].id);\n  if (cobblestones < 32) {\n    bot.chat(\"Not enough cobblestones to craft 10 cobblestone walls.\");\n    return;\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft 6 cobblestone walls using the crafting table\n  await craftItem(bot, \"cobblestone_wall\", 1, craftingTablePosition);\n\n  // Craft 6 more cobblestone walls using the crafting table\n  await craftItem(bot, \"cobblestone_wall\", 1, craftingTablePosition);\n  bot.chat(\"10 cobblestone walls crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftWoodenPickaxe.js",
    "content": "async function craftWoodenPickaxe(bot) {\n  // Check if there are enough oak logs in the inventory\n  const oakLogs = bot.inventory.count(mcData.itemsByName[\"oak_log\"].id);\n  if (oakLogs < 4) {\n    // Mine more oak logs\n    await mineBlock(bot, \"oak_log\", 4 - oakLogs);\n  }\n\n  // Craft a crafting table using oak logs\n  await craftItem(bot, \"crafting_table\", 1);\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft oak planks using oak logs\n  await craftItem(bot, \"oak_planks\", 4, craftingTablePosition);\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 2) {\n    // Craft sticks using oak planks\n    await craftItem(bot, \"stick\", 2 - sticks, craftingTablePosition);\n  }\n\n  // Craft a wooden pickaxe using oak planks and sticks with the crafting table\n  await craftItem(bot, \"wooden_pickaxe\", 1, craftingTablePosition);\n  bot.chat(\"Wooden pickaxe crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/craftWoodenSword.js",
    "content": "async function craftWoodenSword(bot) {\n  // Check if there are enough oak planks in the inventory\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\"oak_planks\"].id);\n  if (oakPlanks < 2) {\n    // Craft more oak planks using oak logs\n    await craftItem(bot, \"oak_planks\", 2 - oakPlanks);\n  }\n\n  // Check if there are enough sticks in the inventory\n  const sticks = bot.inventory.count(mcData.itemsByName[\"stick\"].id);\n  if (sticks < 1) {\n    // Craft more sticks using oak planks\n    await craftItem(bot, \"stick\", 1 - sticks);\n  }\n\n  // Place the crafting table near the player\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"crafting_table\", craftingTablePosition);\n\n  // Craft a wooden sword using oak planks and sticks with the crafting table\n  await craftItem(bot, \"wooden_sword\", 1, craftingTablePosition);\n  bot.chat(\"Wooden sword crafted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/eatCookedBeef.js",
    "content": "async function eatCookedBeef(bot) {\n  // Equip a cooked beef in the bot's hand\n  const cookedBeef = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_beef\"].id);\n  await bot.equip(cookedBeef, \"hand\");\n\n  // Consume the cooked beef\n  await bot.consume();\n  bot.chat(\"1 cooked beef eaten.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/eatCookedBeefV2.js",
    "content": "async function eatCookedBeef(bot) {\n  // Equip a cooked beef in the bot's hand\n  const cookedBeef = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_beef\"].id);\n  await bot.equip(cookedBeef, \"hand\");\n\n  // Consume the cooked beef\n  await bot.consume();\n  bot.chat(\"1 cooked beef eaten.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/eatCookedBeefV3.js",
    "content": "async function eatCookedBeef(bot) {\n  // Equip a cooked beef in the bot's hand\n  const cookedBeef = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_beef\"].id);\n  await bot.equip(cookedBeef, \"hand\");\n\n  // Consume the cooked beef\n  await bot.consume();\n  bot.chat(\"1 cooked beef eaten.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/eatCookedMutton.js",
    "content": "async function eatCookedMutton(bot) {\n  // Equip a cooked mutton in the bot's hand\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_mutton\"].id);\n  await bot.equip(cookedMutton, \"hand\");\n\n  // Consume the cooked mutton\n  await bot.consume();\n  bot.chat(\"1 cooked mutton eaten.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/eatCookedMuttonIfHungry.js",
    "content": "async function eatCookedMuttonIfHungry(bot) {\n  // Check if the bot's hunger is less than 20\n  if (bot.food < 20) {\n    // Equip the cooked mutton in the bot's hand\n    const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_mutton\"].id);\n    await bot.equip(cookedMutton, \"hand\");\n\n    // Consume the cooked mutton\n    await bot.consume();\n    bot.chat(\"1 cooked mutton eaten.\");\n  } else {\n    bot.chat(\"Hunger is full, no need to eat cooked mutton.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/equipIronChestplate.js",
    "content": "async function equipIronChestplate(bot) {\n  // Find the iron chestplate in the bot's inventory\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_chestplate\"].id);\n\n  // Equip the iron chestplate in the torso slot\n  await bot.equip(ironChestplate, \"torso\");\n  bot.chat(\"Iron chestplate equipped.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/equipIronHelmet.js",
    "content": "async function equipIronHelmet(bot) {\n  // Find the iron helmet in the bot's inventory\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_helmet\"].id);\n\n  // Equip the iron helmet in the head slot\n  await bot.equip(ironHelmet, \"head\");\n  bot.chat(\"Iron helmet equipped.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/equipIronLeggingsAndBoots.js",
    "content": "async function equipIronLeggingsAndBoots(bot) {\n  // Find the iron leggings and iron boots in the bot's inventory\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_leggings\"].id);\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_boots\"].id);\n\n  // Check if the bot has iron leggings and iron boots\n  if (ironLeggings && ironBoots) {\n    // Equip the iron leggings in the legs slot\n    await bot.equip(ironLeggings, \"legs\");\n\n    // Equip the iron boots in the feet slot\n    await bot.equip(ironBoots, \"feet\");\n\n    // Send a chat message to indicate that the iron leggings and iron boots have been equipped\n    bot.chat(\"Iron leggings and iron boots equipped.\");\n  } else {\n    bot.chat(\"Iron leggings and/or iron boots not found in inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/equipShield.js",
    "content": "async function equipShield(bot) {\n  // Find the shield in the bot's inventory\n  const shield = bot.inventory.findInventoryItem(mcData.itemsByName[\"shield\"].id);\n\n  // Equip the shield in the off-hand slot\n  await bot.equip(shield, \"off-hand\");\n  bot.chat(\"Shield equipped.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/killChickenWithIncreasedTime.js",
    "content": "async function killChickenWithIncreasedTime(bot) {\n  // Explore the area to find a chicken with an increased exploration time limit\n  const chicken = await exploreUntil(bot, new Vec3(1, 0, 1), 120, () => {\n    const chicken = bot.nearestEntity(entity => {\n      return entity.name === \"chicken\" && entity.position.distanceTo(bot.entity.position) < 32;\n    });\n    return chicken;\n  });\n  if (!chicken) {\n    bot.chat(\"No chicken found.\");\n    return;\n  }\n\n  // Equip a weapon (preferably a sword) to kill the chicken\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_sword\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_sword\"].id);\n  if (sword) {\n    await bot.equip(sword, \"hand\");\n  } else {\n    bot.chat(\"No sword found, using bare hands.\");\n  }\n\n  // Kill the chicken\n  await killMob(bot, \"chicken\", 300);\n\n  // Report the completion of the task\n  bot.chat(\"1 chicken killed.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/killThreeChickens.js",
    "content": "async function killThreeChickens(bot) {\n  // Equip a weapon (preferably a sword) to kill the chickens\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_sword\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_sword\"].id);\n  if (sword) {\n    await bot.equip(sword, \"hand\");\n  } else {\n    bot.chat(\"No sword found, using bare hands.\");\n  }\n\n  // Explore the area to find 3 chickens\n  let chickens = [];\n  while (chickens.length < 3) {\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const nearbyChicken = bot.nearestEntity(entity => {\n        return entity.name === \"chicken\" && entity.position.distanceTo(bot.entity.position) < 32;\n      });\n      if (nearbyChicken && !chickens.includes(nearbyChicken)) {\n        chickens.push(nearbyChicken);\n        return chickens.length === 3 ? chickens : null;\n      }\n      return null;\n    });\n  }\n\n  // Kill each chicken one by one\n  for (const chicken of chickens) {\n    await killMob(bot, chicken.name, 300);\n  }\n\n  // Report the completion of the task\n  bot.chat(\"3 chickens killed.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/killThreeCows.js",
    "content": "async function killThreeCows(bot) {\n  // Explore the area to find 3 cows\n  let cows = [];\n  while (cows.length < 3) {\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const nearbyCow = bot.nearestEntity(entity => {\n        return entity.name === \"cow\" && entity.position.distanceTo(bot.entity.position) < 32;\n      });\n      if (nearbyCow && !cows.includes(nearbyCow)) {\n        cows.push(nearbyCow);\n        return cows.length === 3 ? cows : null;\n      }\n      return null;\n    });\n  }\n\n  // Equip a weapon (preferably a sword) to kill the cows\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_sword\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_sword\"].id);\n  if (sword) {\n    await bot.equip(sword, \"hand\");\n  } else {\n    bot.chat(\"No sword found, using bare hands.\");\n  }\n\n  // Kill each cow one by one\n  for (const cow of cows) {\n    await killMob(bot, cow.name, 300);\n  }\n\n  // Report the completion of the task\n  bot.chat(\"3 cows killed.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/killThreeSheep.js",
    "content": "async function killThreeSheep(bot) {\n  // Equip a weapon (preferably a sword) to kill the sheep\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_sword\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_sword\"].id);\n  if (sword) {\n    await bot.equip(sword, \"hand\");\n  } else {\n    bot.chat(\"No sword found, using bare hands.\");\n  }\n\n  // Explore the area to find 3 sheep\n  let sheep = [];\n  while (sheep.length < 3) {\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const nearbySheep = bot.nearestEntity(entity => {\n        return entity.name === \"sheep\" && entity.position.distanceTo(bot.entity.position) < 32;\n      });\n      if (nearbySheep && !sheep.includes(nearbySheep)) {\n        sheep.push(nearbySheep);\n        return sheep.length === 3 ? sheep : null;\n      }\n      return null;\n    });\n  }\n\n  // Kill each sheep one by one\n  for (const singleSheep of sheep) {\n    await killMob(bot, singleSheep.name, 300);\n  }\n\n  // Report the completion of the task\n  bot.chat(\"3 sheep killed.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineDeepslateOres.js",
    "content": "async function mineDeepslateOres(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_pickaxe\"].id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find and mine 1 deepslate_redstone_ore\n  await mineBlock(bot, \"deepslate_redstone_ore\", 1);\n  bot.chat(\"1 deepslate_redstone_ore mined.\");\n\n  // Find and mine 1 deepslate_gold_ore\n  await mineBlock(bot, \"deepslate_gold_ore\", 1);\n  bot.chat(\"1 deepslate_gold_ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineEightCobblestone.js",
    "content": "async function mineEightCobblestone(bot) {\n  // Equip the wooden pickaxe\n  const woodenPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_pickaxe\"].id);\n  await bot.equip(woodenPickaxe, \"hand\");\n\n  // Find stone blocks\n  const stoneBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const stone = bot.findBlock({\n      matching: mcData.blocksByName[\"stone\"].id,\n      maxDistance: 32\n    });\n    return stone;\n  });\n\n  // Mine 8 cobblestone\n  await mineBlock(bot, \"stone\", 8);\n  bot.chat(\"8 cobblestone mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineFiveCoalOre.js",
    "content": "async function mineFiveCoalOre(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_pickaxe\"].id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find 5 coal ore blocks\n  const coalOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const coalOres = bot.findBlocks({\n      matching: mcData.blocksByName[\"coal_ore\"].id,\n      maxDistance: 32,\n      count: 5\n    });\n    return coalOres.length >= 5 ? coalOres : null;\n  });\n\n  // Mine the 5 coal ore blocks\n  await mineBlock(bot, \"coal_ore\", 5);\n  bot.chat(\"5 coal ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineFiveCopperOre.js",
    "content": "async function mineFiveCopperOre(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_pickaxe\"].id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find 5 copper ore blocks\n  const copperOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const copperOres = bot.findBlocks({\n      matching: mcData.blocksByName[\"copper_ore\"].id,\n      maxDistance: 32,\n      count: 5\n    });\n    return copperOres.length >= 5 ? copperOres : null;\n  });\n\n  // Mine the 5 copper ore blocks\n  await mineBlock(bot, \"copper_ore\", 5);\n  bot.chat(\"5 copper ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineFourCoalOre.js",
    "content": "async function mineFourCoalOre(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_pickaxe\"].id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find and mine 4 coal ore blocks\n  await mineBlock(bot, \"coal_ore\", 4);\n  bot.chat(\"4 coal ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineTenCobbledDeepslateBelowY0.js",
    "content": "async function mineTenCobbledDeepslateBelowY0(bot) {\n  // Equip the iron pickaxe\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"iron_pickaxe\"].id);\n  await bot.equip(ironPickaxe, \"hand\");\n\n  // Find cobbled_deepslate blocks below Y=0\n  const cobbledDeepslateBlocks = await exploreUntil(bot, new Vec3(1, -1, 1), 60, () => {\n    const cobbledDeepslate = bot.findBlock({\n      matching: mcData.blocksByName[\"cobbled_deepslate\"].id,\n      maxDistance: 32,\n      position: pos => pos.y < 0\n    });\n    return cobbledDeepslate;\n  });\n\n  // Mine 10 cobbled_deepslate blocks\n  await mineBlock(bot, \"cobbled_deepslate\", 10);\n  bot.chat(\"10 cobbled_deepslate mined below Y=0.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineThreeIronOre.js",
    "content": "async function mineThreeIronOre(bot) {\n  // Equip the stone pickaxe\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"stone_pickaxe\"].id);\n  await bot.equip(stonePickaxe, \"hand\");\n\n  // Find and mine 3 iron ore blocks\n  await mineBlock(bot, \"iron_ore\", 3);\n  bot.chat(\"3 iron ore mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineThreeMoreOakLogs.js",
    "content": "async function mineThreeMoreOakLogs(bot) {\n  for (let i = 0; i < 3; i++) {\n    const oakLogBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n      const oakLog = bot.findBlock({\n        matching: mcData.blocksByName[\"oak_log\"].id,\n        maxDistance: 32\n      });\n      return oakLog;\n    });\n    if (!oakLogBlock) {\n      bot.chat(\"Could not find an oak log.\");\n      return;\n    }\n    await mineBlock(bot, \"oak_log\", 1);\n  }\n  bot.chat(\"3 more oak logs mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/mineWoodLog.js",
    "content": "async function mineWoodLog(bot) {\n  const logNames = [\"oak_log\", \"birch_log\", \"spruce_log\", \"jungle_log\", \"acacia_log\", \"dark_oak_log\", \"mangrove_log\"];\n\n  // Find a wood log block\n  const logBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    for (const logName of logNames) {\n      const log = bot.findBlock({\n        matching: mcData.blocksByName[logName].id,\n        maxDistance: 32\n      });\n      if (log) return log;\n    }\n    return null;\n  });\n  if (!logBlock) {\n    bot.chat(\"Could not find a wood log.\");\n    return;\n  }\n\n  // Mine the wood log block\n  await mineBlock(bot, logBlock.name, 1);\n  bot.chat(\"Wood log mined.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/obtainBirchLogs.js",
    "content": "async function obtainBirchLogs(bot) {\n  // Check if there are enough birch logs in the inventory\n  const birchLogs = bot.inventory.count(mcData.itemsByName[\"birch_log\"].id);\n  const logsNeeded = 5 - birchLogs;\n  if (logsNeeded > 0) {\n    // Mine the required number of birch logs\n    await mineBlock(bot, \"birch_log\", logsNeeded);\n    bot.chat(\"5 birch logs obtained.\");\n  } else {\n    bot.chat(\"Already have 5 birch logs in the inventory.\");\n  }\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/openChestAndCheckContents.js",
    "content": "async function openChestAndCheckContents(bot) {\n  const targetChestPosition = new Vec3(5, 61, 134);\n\n  // Find the chest at the specified position\n  const chestPosition = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const chest = bot.findBlock({\n      matching: mcData.blocksByName[\"chest\"].id,\n      maxDistance: 32,\n      position: targetChestPosition\n    });\n    return chest ? chest.position : null;\n  });\n\n  // Check the contents of the chest\n  await checkItemInsideChest(bot, chestPosition);\n  bot.chat(\"Chest at (5, 61, 134) opened and contents checked.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/plantOakSapling.js",
    "content": "async function plantOakSapling(bot) {\n  // Find a suitable location to plant the oak sapling\n  const targetBlock = bot.findBlock({\n    matching: block => {\n      return block.name === \"grass_block\" || block.name === \"dirt\";\n    },\n    maxDistance: 32\n  });\n  if (!targetBlock) {\n    bot.chat(\"Could not find a suitable location to plant the oak sapling.\");\n    return;\n  }\n\n  // Go to the location\n  await bot.pathfinder.goto(new GoalBlock(targetBlock.position.x, targetBlock.position.y, targetBlock.position.z));\n\n  // Equip the oak sapling in the bot's hand\n  const oakSapling = bot.inventory.findInventoryItem(mcData.itemsByName[\"oak_sapling\"].id);\n  await bot.equip(oakSapling, \"hand\");\n\n  // Right-click on the ground to plant the oak sapling\n  await bot.activateBlock(targetBlock);\n\n  // Send a chat message to indicate the oak sapling has been planted\n  bot.chat(\"Oak sapling planted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/smeltCopperOre.js",
    "content": "async function smeltCopperOre(bot) {\n  // Check if there is a furnace in the inventory\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\"furnace\"].id);\n\n  // If there is no furnace, craft one using cobblestone\n  if (!furnace) {\n    await craftItem(bot, \"furnace\", 1);\n  }\n\n  // Place the furnace near the player\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Find a copper ore block\n  const copperOre = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const copperOre = bot.findBlock({\n      matching: mcData.blocksByName[\"copper_ore\"].id,\n      maxDistance: 32\n    });\n    return copperOre;\n  });\n\n  // Mine the copper ore block\n  await mineBlock(bot, \"copper_ore\", 1);\n\n  // Smelt the raw copper using coal as fuel in the furnace\n  await smeltItem(bot, \"raw_copper\", \"coal\", 1);\n\n  // Collect the smelted copper ingot\n  bot.chat(\"1 copper ore smelted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/smeltFiveRawCopper.js",
    "content": "async function smeltFiveRawCopper(bot) {\n  // Find a suitable location to place the furnace\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n\n  // Place the furnace\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 5 raw copper using coal as fuel\n  await smeltItem(bot, \"raw_copper\", \"coal\", 5);\n  bot.chat(\"5 raw copper smelted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/smeltFiveRawGold.js",
    "content": "async function smeltFiveRawGold(bot) {\n  // Check if there is a furnace in the inventory\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\"furnace\"].id);\n\n  // If there is no furnace, craft one using cobblestone\n  if (!furnace) {\n    await craftItem(bot, \"furnace\", 1);\n  }\n\n  // Place the furnace near the player\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt the 5 raw gold using coal as fuel in the furnace\n  await smeltItem(bot, \"raw_gold\", \"coal\", 5);\n\n  // Collect the smelted gold ingots\n  bot.chat(\"5 raw gold smelted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/smeltRawIron.js",
    "content": "async function smeltRawIron(bot) {\n  // Find a suitable location to place the furnace\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n\n  // Place the furnace\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 3 raw iron using coal as fuel\n  await smeltItem(bot, \"raw_iron\", \"coal\", 3);\n  bot.chat(\"3 raw iron smelted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/smeltThreeRawCopper.js",
    "content": "async function smeltThreeRawCopper(bot) {\n  // Find a suitable location to place the furnace\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\n\n  // Place the furnace\n  await placeItem(bot, \"furnace\", furnacePosition);\n\n  // Smelt 3 raw copper using coal as fuel\n  await smeltItem(bot, \"raw_copper\", \"coal\", 3);\n  bot.chat(\"3 raw copper smelted.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/code/waitAndEatCookedMutton.js",
    "content": "async function waitAndEatCookedMutton(bot) {\n  // Wait until the bot's hunger is less than 20\n  while (bot.food >= 20) {\n    await bot.waitForTicks(20);\n  }\n\n  // Equip a cooked mutton in the bot's hand\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\"cooked_mutton\"].id);\n  await bot.equip(cookedMutton, \"hand\");\n\n  // Consume the cooked mutton\n  await bot.consume();\n  bot.chat(\"1 cooked mutton eaten.\");\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/cookChicken.txt",
    "content": "async function cookChicken(bot) {\n    // The function is about cooking a raw chicken using a furnace and coal as fuel. First, it checks if there is a furnace in the inventory. If not, it crafts one using cobblestone. Then, it places the furnace near the player. Next, it smelts the raw chicken using coal as fuel in the furnace. Finally, it collects the cooked chicken and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/cookRawBeef.txt",
    "content": "async function cookRawBeef(bot) {\n    // The function is about cooking 6 raw beef using a furnace and coal as fuel. It first checks if there is a furnace in the inventory, and if not, crafts one using cobblestone. Then, it places the furnace near the player and smelts the 6 raw beef using coal as fuel in the furnace. Finally, it collects the cooked beef and sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/cookRawMutton.txt",
    "content": "async function cookRawMutton(bot) {\n    // The function is about cooking 4 raw mutton using a furnace and coal as fuel. If there is no furnace in the inventory, the bot will craft one using cobblestone. Then, the bot will place the furnace near the player and smelt the 4 raw mutton using coal as fuel. Finally, the bot will collect the cooked mutton and print a message in the chat.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/cookThreeRawChicken.txt",
    "content": "async function cookThreeRawChicken(bot) {\n    // The function is about cooking 3 raw chicken using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 3 raw chicken using coal as fuel and sends a chat message indicating that the chicken has been cooked.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftBirchBoat.txt",
    "content": "async function craftBirchBoat(bot) {\n    // The function crafts a birch boat using birch logs and a crafting table. It first checks if there are enough birch logs in the inventory, and if not, mines more. Then, it crafts birch planks using the birch logs. If there is no crafting table in the inventory, it crafts one. It finds a suitable position to place the crafting table and places it there. Finally, it crafts a birch boat using the birch planks and the crafting table.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftBoneMeal.txt",
    "content": "async function craftBoneMeal(bot) {\n    // The function is about crafting 4 bone meal using 2 bones and a crafting table. It first checks if there are enough bones in the inventory, and if not, it returns. Then, it places a crafting table near the player using the `placeItem` helper function. Finally, it crafts 4 bone meal using 2 bones and the crafting table, and sends a chat message indicating that the bone meal has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftChest.txt",
    "content": "async function craftChest(bot) {\n    // The function crafts a chest using oak planks. It checks if there are enough oak planks in the inventory, and if not, it mines oak logs and crafts oak planks. It then places a crafting table near the player and crafts a chest using oak planks with the crafting table. Finally, it sends a chat message indicating that the chest has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftClock.txt",
    "content": "async function craftClock(bot) {\n    // The function crafts a clock using 4 gold ingots and 1 redstone dust. It first checks if there is a crafting table in the inventory, and if not, crafts one using oak planks. Then, it places the crafting table near the player. Finally, it crafts a clock using the crafting table and saves the event of crafting a clock.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftCopperBlock.txt",
    "content": "async function craftCopperBlock(bot) {\n    // The function crafts a copper block using 9 copper ingots and a crafting table. It first checks if there are enough copper ingots in the inventory, and if not, it returns. Then, it places a crafting table near the player and crafts a copper block using the crafting table. Finally, it sends a chat message indicating that the copper block has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftDiamondSword.txt",
    "content": "async function craftDiamondSword(bot) {\n    // The function crafts a diamond sword using diamonds and sticks. It first checks if there are enough diamonds and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a diamond sword. Finally, it sends a chat message indicating that the diamond sword has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftFurnace.txt",
    "content": "async function craftFurnace(bot) {\n    // The function crafts a furnace using cobblestones and a crafting table. It first checks if there are enough cobblestones in the inventory. If there are, it places a crafting table near the player and crafts a furnace using the cobblestones and the crafting table. Finally, it sends a chat message indicating that the furnace has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftIronChestplate.txt",
    "content": "async function craftIronChestplate(bot) {\n    // The function crafts an iron chestplate using iron ingots and a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores, places a furnace, and smelts the ores into ingots. Then it checks if there is a crafting table in the inventory, and if not, it crafts one. Next, it tries to place the crafting table near the player at different positions until it is successfully placed. Finally, it crafts an iron chestplate using the iron ingots and the crafting table.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftIronHelmet.txt",
    "content": "async function craftIronHelmet(bot) {\n    // The function crafts an iron helmet using iron ingots and a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores, places a furnace, and smelts the ores into ingots. Then it places a crafting table near the player and crafts an iron helmet using the ingots and the crafting table. Finally, it sends a chat message indicating that the iron helmet has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftIronLeggingsAndBoots.txt",
    "content": "async function craftIronLeggingsAndBoots(bot) {\n    // The function crafts iron leggings and boots. It checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and coal to smelt them into iron ingots. It then checks if there is a crafting table in the inventory, and if not, it crafts one. The function places the crafting table and a furnace near the player, and uses the furnace to smelt the iron ores. Finally, it crafts iron leggings and boots using the crafting table.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftIronPickaxe.txt",
    "content": "async function craftIronPickaxe(bot) {\n    // The function crafts an iron pickaxe using iron ingots and sticks. It first checks if there are enough iron ingots and sticks in the inventory, and crafts more sticks if necessary. Then it places a crafting table near the player and uses it to craft an iron pickaxe. Finally, it sends a chat message indicating that the iron pickaxe has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftIronSword.txt",
    "content": "async function craftIronSword(bot) {\n    // The function crafts an iron sword using iron ingots and sticks. It first checks if there are enough iron ingots and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts an iron sword using the crafting table. Finally, it sends a chat message indicating that the iron sword has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftShield.txt",
    "content": "async function craftShield(bot) {\n    // The function crafts a shield using oak planks and iron ingots. It checks if there are enough oak planks and iron ingots in the inventory, and crafts more oak planks if necessary. If there are not enough iron ingots, it returns. It then places a crafting table near the player and crafts a shield using the crafting table. Finally, it sends a chat message indicating that the shield has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneAxe.txt",
    "content": "async function craftStoneAxe(bot) {\n    // The function crafts a stone axe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone axe using the cobblestones and sticks with the crafting table. Finally, it sends a chat message indicating that the stone axe has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneHoe.txt",
    "content": "async function craftStoneHoe(bot) {\n    // The function crafts a stone hoe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone hoe using the cobblestones and sticks with the crafting table. Finally, it sends a chat message indicating that the stone hoe has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneHoeV2.txt",
    "content": "async function craftStoneHoe(bot) {\n    // The function crafts a stone hoe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone hoe using the cobblestones and sticks with the crafting table. Finally, it sends a chat message indicating that the stone hoe has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStonePickaxe.txt",
    "content": "async function craftStonePickaxe(bot) {\n    // The function crafts a stone pickaxe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a stone pickaxe.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneShovel.txt",
    "content": "async function craftStoneShovel(bot) {\n    // The function crafts a stone shovel using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a stone shovel. Finally, it sends a chat message indicating that the stone shovel has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneSword.txt",
    "content": "async function craftStoneSword(bot) {\n    // The function crafts a stone sword using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough cobblestones, it returns. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone sword using the crafting table. Finally, it sends a chat message indicating that the stone sword has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftStoneTools.txt",
    "content": "async function craftStoneTools(bot) {\n    // The function crafts stone tools (sword, axe, and shovel) using a crafting table. It checks if there are enough cobblestones and sticks in the inventory, and mines more cobblestones or crafts more sticks if necessary. Then, it places a crafting table near the player and crafts the stone tools using the crafting table. Finally, it sends a chat message indicating that the tools have been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftTenCobblestoneWalls.txt",
    "content": "async function craftTenCobblestoneWalls(bot) {\n    // The function crafts 10 cobblestone walls using a crafting table. It first checks if there are enough cobblestones in the inventory, and if not, it returns. Then, it places a crafting table near the player and crafts 6 cobblestone walls using the crafting table. It repeats the process to craft 6 more cobblestone walls and outputs a message when the process is complete.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftWoodenPickaxe.txt",
    "content": "async function craftWoodenPickaxe(bot) {\n    // The function crafts a wooden pickaxe using oak logs, oak planks, and sticks. It first checks if there are enough oak logs in the inventory, and if not, mines more. Then, it crafts a crafting table using oak logs and places it near the player. Next, it crafts oak planks using oak logs and checks if there are enough sticks in the inventory. If not, it crafts sticks using oak planks. Finally, it crafts a wooden pickaxe using oak planks and sticks with the crafting table.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/craftWoodenSword.txt",
    "content": "async function craftWoodenSword(bot) {\n    // The function crafts a wooden sword using oak planks and sticks. It checks if there are enough oak planks and sticks in the inventory, and crafts more if necessary. It then places a crafting table near the player and uses it to craft a wooden sword. Finally, it sends a chat message indicating that the wooden sword has been crafted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/eatCookedBeef.txt",
    "content": "async function eatCookedBeef(bot) {\n    // The function is about making the bot eat a cooked beef. It equips a cooked beef in the bot's hand and then consumes it. Finally, it sends a message to the chat saying that 1 cooked beef has been eaten.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/eatCookedBeefV2.txt",
    "content": "async function eatCookedBeef(bot) {\n    // The function is about making the bot eat a cooked beef. It equips a cooked beef in the bot's hand and then consumes it. Finally, it sends a message to the chat indicating that one cooked beef has been eaten.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/eatCookedBeefV3.txt",
    "content": "async function eatCookedBeef(bot) {\n    // The function is about making the bot eat a cooked beef. It equips a cooked beef in the bot's hand and then consumes it. Finally, it sends a message to the chat indicating that one cooked beef has been eaten.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/eatCookedMutton.txt",
    "content": "async function eatCookedMutton(bot) {\n    // The function is about making the bot eat a cooked mutton. First, it equips a cooked mutton in the bot's hand. Then, it consumes the cooked mutton and sends a chat message indicating that 1 cooked mutton has been eaten.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/eatCookedMuttonIfHungry.txt",
    "content": "async function eatCookedMuttonIfHungry(bot) {\n    // The function checks if the bot's hunger is less than 20, and if so, equips and consumes a cooked mutton to restore hunger. If the hunger is already full, it will not eat the cooked mutton.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/equipIronChestplate.txt",
    "content": "async function equipIronChestplate(bot) {\n    // The function equips an iron chestplate in the torso slot of the bot's armor. It first finds the iron chestplate in the bot's inventory and then equips it using the `bot.equip` function. Finally, it sends a chat message confirming that the iron chestplate has been equipped.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/equipIronHelmet.txt",
    "content": "async function equipIronHelmet(bot) {\n    // The function is about equipping an iron helmet in the head slot of the bot's inventory. It first finds the iron helmet in the bot's inventory and then equips it in the head slot. Finally, it sends a chat message confirming that the iron helmet has been equipped.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/equipIronLeggingsAndBoots.txt",
    "content": "async function equipIronLeggingsAndBoots(bot) {\n    // The function equips the bot with iron leggings and iron boots if they are available in the inventory, and sends a chat message indicating that they have been equipped. If the items are not found in the inventory, it sends a chat message indicating that they were not found.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/equipShield.txt",
    "content": "async function equipShield(bot) {\n    // The function equips a shield in the off-hand slot of the bot's inventory. It first finds the shield in the bot's inventory and then equips it in the off-hand slot. Finally, it sends a chat message confirming that the shield has been equipped.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/killChickenWithIncreasedTime.txt",
    "content": "async function killChickenWithIncreasedTime(bot) {\n    // The function is about killing a chicken with an increased exploration time limit. It explores the area to find a chicken within a certain distance. If a chicken is found, it equips a sword (if available) to kill the chicken. Otherwise, it uses bare hands. After killing the chicken, it reports the completion of the task.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/killThreeChickens.txt",
    "content": "async function killThreeChickens(bot) {\n    // The function is about killing 3 chickens. First, it equips a sword to kill the chickens, and if there is no sword, it uses bare hands. Then, it explores the environment to find 3 chickens within a 32 block radius. Once 3 chickens are found, it kills each chicken one by one using the equipped weapon. Finally, it reports the completion of the task by sending a chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/killThreeCows.txt",
    "content": "async function killThreeCows(bot) {\n    // The function is about killing 3 cows. It explores the environment to find 3 cows within a certain distance. Once 3 cows are found, it equips a sword (if available) to kill the cows one by one. If no sword is found, it uses bare hands. After killing all 3 cows, it reports the completion of the task.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/killThreeSheep.txt",
    "content": "async function killThreeSheep(bot) {\n    // The function is about killing 3 sheep. First, it equips a weapon (preferably a sword) to kill the sheep. Then, it explores the environment to find 3 sheep. Once 3 sheep are found, it kills each sheep one by one. Finally, it reports the completion of the task by sending a chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineDeepslateOres.txt",
    "content": "async function mineDeepslateOres(bot) {\n    // The function is about mining 1 deepslate_redstone_ore and 1 deepslate_gold_ore using an iron pickaxe. The function first equips the iron pickaxe in the hand. Then, it finds and mines 1 deepslate_redstone_ore and 1 deepslate_gold_ore using the mineBlock function. Finally, it sends a chat message indicating the number of ores mined.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineEightCobblestone.txt",
    "content": "async function mineEightCobblestone(bot) {\n    // The function is about mining 8 cobblestones using a wooden pickaxe. It equips the wooden pickaxe and explores the environment until finding a stone block. Once a stone block is found, it mines a total of 8 cobblestone blocks using the wooden pickaxe. Finally, it sends a chat message indicating that 8 cobblestones have been mined.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineFiveCoalOre.txt",
    "content": "async function mineFiveCoalOre(bot) {\n    // The function is about mining 5 coal ore blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 coal ore blocks. Once 5 coal ore blocks are found, mine them using the iron pickaxe and save the event of mining 5 coal ore blocks.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineFiveCopperOre.txt",
    "content": "async function mineFiveCopperOre(bot) {\n    // The function is about mining 5 copper ore blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 copper ore blocks. Once 5 copper ore blocks are found, mine them using the iron pickaxe and save the event of mining 5 copper ore.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineFourCoalOre.txt",
    "content": "async function mineFourCoalOre(bot) {\n    // The function is about mining 4 coal ore blocks using a stone pickaxe. The function equips the stone pickaxe in the hand and then mines 4 coal ore blocks. Once the mining is complete, the function sends a chat message indicating that 4 coal ore blocks have been mined.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineTenCobbledDeepslateBelowY0.txt",
    "content": "async function mineTenCobbledDeepslateBelowY0(bot) {\n    // The function is about mining 10 cobbled_deepslate blocks below Y=0 using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding a cobbled_deepslate block below Y=0. Once 10 cobbled_deepslate blocks are found, mine them using the iron pickaxe. Finally, a message is sent to the chat indicating that 10 cobbled_deepslate blocks have been mined below Y=0.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineThreeIronOre.txt",
    "content": "async function mineThreeIronOre(bot) {\n    // The function is about mining 3 iron ore blocks using a stone pickaxe. The function equips the stone pickaxe in the hand and then mines 3 iron ore blocks. Once the mining is complete, the function sends a chat message indicating that 3 iron ore blocks have been mined.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineThreeMoreOakLogs.txt",
    "content": "async function mineThreeMoreOakLogs(bot) {\n    // The function is about mining three oak logs. It uses a for loop to mine three oak logs. It explores the environment until finding an oak log block, and then mines one oak log block. If it cannot find an oak log block, it returns. Once three oak logs are mined, it sends a chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/mineWoodLog.txt",
    "content": "async function mineWoodLog(bot) {\n    // The function is about mining a single wood log block. It searches for any of the seven types of wood logs within a certain distance. Once a wood log block is found, it is mined using the `mineBlock` function. If no wood log block is found, the function returns and a message is sent to the chat.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/obtainBirchLogs.txt",
    "content": "async function obtainBirchLogs(bot) {\n    // The function is about obtaining 5 birch logs. It checks if there are enough birch logs in the inventory and mines the required number of birch logs if necessary. Once 5 birch logs are obtained, it sends a chat message. If there are already 5 birch logs in the inventory, it sends a different chat message.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/openChestAndCheckContents.txt",
    "content": "async function openChestAndCheckContents(bot) {\n    // The function is about finding a chest at a specified position, opening it, and checking its contents. It uses the `exploreUntil` helper function to find the chest and the `checkItemInsideChest` helper function to check the contents of the chest. The position of the chest is specified by `targetChestPosition`. Once the chest is found, the function checks its contents and sends a chat message indicating that the chest has been opened and its contents have been checked.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/plantOakSapling.txt",
    "content": "async function plantOakSapling(bot) {\n    // The function is about finding a suitable location to plant an oak sapling, going to that location, equipping the oak sapling in the bot's hand, right-clicking on the ground to plant the oak sapling, and sending a chat message to indicate the oak sapling has been planted. If a suitable location cannot be found, the function will return without planting the oak sapling.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/smeltCopperOre.txt",
    "content": "async function smeltCopperOre(bot) {\n    // The function is about smelting one copper ore block into a copper ingot using a furnace and coal as fuel. First, check if there is a furnace in the inventory. If not, craft one using cobblestone. Then, place the furnace near the player. Next, explore the environment until finding a copper ore block. Once a copper ore block is found, mine it and smelt the raw copper using coal as fuel in the furnace. Finally, collect the smelted copper ingot.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/smeltFiveRawCopper.txt",
    "content": "async function smeltFiveRawCopper(bot) {\n    // The function is about smelting 5 raw copper using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 5 raw copper using coal as fuel and sends a chat message indicating that 5 raw copper has been smelted.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/smeltFiveRawGold.txt",
    "content": "async function smeltFiveRawGold(bot) {\n    // The function is about smelting 5 raw gold into gold ingots using a furnace and coal as fuel. If there is no furnace in the inventory, the bot will craft one using cobblestone. Then, the bot will place the furnace near the player and smelt the 5 raw gold using coal as fuel. Finally, the bot will collect the smelted gold ingots and print a message in the chat.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/smeltRawIron.txt",
    "content": "async function smeltRawIron(bot) {\n    // The function is about smelting 3 raw iron using coal as fuel. First, find a suitable location to place the furnace. Then, place the furnace at the found location. Finally, smelt 3 raw iron using coal as fuel and save the event of smelting 3 raw iron.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/smeltThreeRawCopper.txt",
    "content": "async function smeltThreeRawCopper(bot) {\n    // The function is about smelting 3 raw copper using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 3 raw copper using coal as fuel and saves the event of smelting 3 raw copper.\n}"
  },
  {
    "path": "skill_library/trial3/skill/description/waitAndEatCookedMutton.txt",
    "content": "async function waitAndEatCookedMutton(bot) {\n    // The function waits until the bot's hunger is less than 20, equips a cooked mutton in the bot's hand, consumes it, and then sends a chat message indicating that 1 cooked mutton has been eaten.\n}"
  },
  {
    "path": "skill_library/trial3/skill/skills.json",
    "content": "{\"mineWoodLog\": {\"code\": \"async function mineWoodLog(bot) {\\n  const logNames = [\\\"oak_log\\\", \\\"birch_log\\\", \\\"spruce_log\\\", \\\"jungle_log\\\", \\\"acacia_log\\\", \\\"dark_oak_log\\\", \\\"mangrove_log\\\"];\\n\\n  // Find a wood log block\\n  const logBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    for (const logName of logNames) {\\n      const log = bot.findBlock({\\n        matching: mcData.blocksByName[logName].id,\\n        maxDistance: 32\\n      });\\n      if (log) return log;\\n    }\\n    return null;\\n  });\\n  if (!logBlock) {\\n    bot.chat(\\\"Could not find a wood log.\\\");\\n    return;\\n  }\\n\\n  // Mine the wood log block\\n  await mineBlock(bot, logBlock.name, 1);\\n  bot.chat(\\\"Wood log mined.\\\");\\n}\", \"description\": \"async function mineWoodLog(bot) {\\n    // The function is about mining a single wood log block. It searches for any of the seven types of wood logs within a certain distance. Once a wood log block is found, it is mined using the `mineBlock` function. If no wood log block is found, the function returns and a message is sent to the chat.\\n}\"}, \"mineThreeMoreOakLogs\": {\"code\": \"async function mineThreeMoreOakLogs(bot) {\\n  for (let i = 0; i < 3; i++) {\\n    const oakLogBlock = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const oakLog = bot.findBlock({\\n        matching: mcData.blocksByName[\\\"oak_log\\\"].id,\\n        maxDistance: 32\\n      });\\n      return oakLog;\\n    });\\n    if (!oakLogBlock) {\\n      bot.chat(\\\"Could not find an oak log.\\\");\\n      return;\\n    }\\n    await mineBlock(bot, \\\"oak_log\\\", 1);\\n  }\\n  bot.chat(\\\"3 more oak logs mined.\\\");\\n}\", \"description\": \"async function mineThreeMoreOakLogs(bot) {\\n    // The function is about mining three oak logs. It uses a for loop to mine three oak logs. It explores the environment until finding an oak log block, and then mines one oak log block. If it cannot find an oak log block, it returns. Once three oak logs are mined, it sends a chat message.\\n}\"}, \"craftWoodenPickaxe\": {\"code\": \"async function craftWoodenPickaxe(bot) {\\n  // Check if there are enough oak logs in the inventory\\n  const oakLogs = bot.inventory.count(mcData.itemsByName[\\\"oak_log\\\"].id);\\n  if (oakLogs < 4) {\\n    // Mine more oak logs\\n    await mineBlock(bot, \\\"oak_log\\\", 4 - oakLogs);\\n  }\\n\\n  // Craft a crafting table using oak logs\\n  await craftItem(bot, \\\"crafting_table\\\", 1);\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft oak planks using oak logs\\n  await craftItem(bot, \\\"oak_planks\\\", 4, craftingTablePosition);\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks, craftingTablePosition);\\n  }\\n\\n  // Craft a wooden pickaxe using oak planks and sticks with the crafting table\\n  await craftItem(bot, \\\"wooden_pickaxe\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Wooden pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftWoodenPickaxe(bot) {\\n    // The function crafts a wooden pickaxe using oak logs, oak planks, and sticks. It first checks if there are enough oak logs in the inventory, and if not, mines more. Then, it crafts a crafting table using oak logs and places it near the player. Next, it crafts oak planks using oak logs and checks if there are enough sticks in the inventory. If not, it crafts sticks using oak planks. Finally, it crafts a wooden pickaxe using oak planks and sticks with the crafting table.\\n}\"}, \"craftWoodenSword\": {\"code\": \"async function craftWoodenSword(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\\\"oak_planks\\\"].id);\\n  if (oakPlanks < 2) {\\n    // Craft more oak planks using oak logs\\n    await craftItem(bot, \\\"oak_planks\\\", 2 - oakPlanks);\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 1) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 1 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a wooden sword using oak planks and sticks with the crafting table\\n  await craftItem(bot, \\\"wooden_sword\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Wooden sword crafted.\\\");\\n}\", \"description\": \"async function craftWoodenSword(bot) {\\n    // The function crafts a wooden sword using oak planks and sticks. It checks if there are enough oak planks and sticks in the inventory, and crafts more if necessary. It then places a crafting table near the player and uses it to craft a wooden sword. Finally, it sends a chat message indicating that the wooden sword has been crafted.\\n}\"}, \"mineEightCobblestone\": {\"code\": \"async function mineEightCobblestone(bot) {\\n  // Equip the wooden pickaxe\\n  const woodenPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"wooden_pickaxe\\\"].id);\\n  await bot.equip(woodenPickaxe, \\\"hand\\\");\\n\\n  // Find stone blocks\\n  const stoneBlocks = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const stone = bot.findBlock({\\n      matching: mcData.blocksByName[\\\"stone\\\"].id,\\n      maxDistance: 32\\n    });\\n    return stone;\\n  });\\n\\n  // Mine 8 cobblestone\\n  await mineBlock(bot, \\\"stone\\\", 8);\\n  bot.chat(\\\"8 cobblestone mined.\\\");\\n}\", \"description\": \"async function mineEightCobblestone(bot) {\\n    // The function is about mining 8 cobblestones using a wooden pickaxe. It equips the wooden pickaxe and explores the environment until finding a stone block. Once a stone block is found, it mines a total of 8 cobblestone blocks using the wooden pickaxe. Finally, it sends a chat message indicating that 8 cobblestones have been mined.\\n}\"}, \"craftStonePickaxe\": {\"code\": \"async function craftStonePickaxe(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 3) {\\n    bot.chat(\\\"Not enough cobblestones to craft a stone pickaxe.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone pickaxe using cobblestones and sticks with the crafting table\\n  await craftItem(bot, \\\"stone_pickaxe\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftStonePickaxe(bot) {\\n    // The function crafts a stone pickaxe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a stone pickaxe.\\n}\"}, \"mineFourCoalOre\": {\"code\": \"async function mineFourCoalOre(bot) {\\n  // Equip the stone pickaxe\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_pickaxe\\\"].id);\\n  await bot.equip(stonePickaxe, \\\"hand\\\");\\n\\n  // Find and mine 4 coal ore blocks\\n  await mineBlock(bot, \\\"coal_ore\\\", 4);\\n  bot.chat(\\\"4 coal ore mined.\\\");\\n}\", \"description\": \"async function mineFourCoalOre(bot) {\\n    // The function is about mining 4 coal ore blocks using a stone pickaxe. The function equips the stone pickaxe in the hand and then mines 4 coal ore blocks. Once the mining is complete, the function sends a chat message indicating that 4 coal ore blocks have been mined.\\n}\"}, \"craftFurnace\": {\"code\": \"async function craftFurnace(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 8) {\\n    bot.chat(\\\"Not enough cobblestones to craft a furnace.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a furnace using cobblestones and the crafting table\\n  await craftItem(bot, \\\"furnace\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Furnace crafted.\\\");\\n}\", \"description\": \"async function craftFurnace(bot) {\\n    // The function crafts a furnace using cobblestones and a crafting table. It first checks if there are enough cobblestones in the inventory. If there are, it places a crafting table near the player and crafts a furnace using the cobblestones and the crafting table. Finally, it sends a chat message indicating that the furnace has been crafted.\\n}\"}, \"mineThreeIronOre\": {\"code\": \"async function mineThreeIronOre(bot) {\\n  // Equip the stone pickaxe\\n  const stonePickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_pickaxe\\\"].id);\\n  await bot.equip(stonePickaxe, \\\"hand\\\");\\n\\n  // Find and mine 3 iron ore blocks\\n  await mineBlock(bot, \\\"iron_ore\\\", 3);\\n  bot.chat(\\\"3 iron ore mined.\\\");\\n}\", \"description\": \"async function mineThreeIronOre(bot) {\\n    // The function is about mining 3 iron ore blocks using a stone pickaxe. The function equips the stone pickaxe in the hand and then mines 3 iron ore blocks. Once the mining is complete, the function sends a chat message indicating that 3 iron ore blocks have been mined.\\n}\"}, \"smeltRawIron\": {\"code\": \"async function smeltRawIron(bot) {\\n  // Find a suitable location to place the furnace\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n\\n  // Place the furnace\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 3 raw iron using coal as fuel\\n  await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\", 3);\\n  bot.chat(\\\"3 raw iron smelted.\\\");\\n}\", \"description\": \"async function smeltRawIron(bot) {\\n    // The function is about smelting 3 raw iron using coal as fuel. First, find a suitable location to place the furnace. Then, place the furnace at the found location. Finally, smelt 3 raw iron using coal as fuel and save the event of smelting 3 raw iron.\\n}\"}, \"craftIronPickaxe\": {\"code\": \"async function craftIronPickaxe(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 3) {\\n    bot.chat(\\\"Not enough iron ingots to craft an iron pickaxe.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron pickaxe using iron ingots and sticks with the crafting table\\n  await craftItem(bot, \\\"iron_pickaxe\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Iron pickaxe crafted.\\\");\\n}\", \"description\": \"async function craftIronPickaxe(bot) {\\n    // The function crafts an iron pickaxe using iron ingots and sticks. It first checks if there are enough iron ingots and sticks in the inventory, and crafts more sticks if necessary. Then it places a crafting table near the player and uses it to craft an iron pickaxe. Finally, it sends a chat message indicating that the iron pickaxe has been crafted.\\n}\"}, \"smeltCopperOre\": {\"code\": \"async function smeltCopperOre(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"furnace\\\"].id);\\n\\n  // If there is no furnace, craft one using cobblestone\\n  if (!furnace) {\\n    await craftItem(bot, \\\"furnace\\\", 1);\\n  }\\n\\n  // Place the furnace near the player\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Find a copper ore block\\n  const copperOre = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const copperOre = bot.findBlock({\\n      matching: mcData.blocksByName[\\\"copper_ore\\\"].id,\\n      maxDistance: 32\\n    });\\n    return copperOre;\\n  });\\n\\n  // Mine the copper ore block\\n  await mineBlock(bot, \\\"copper_ore\\\", 1);\\n\\n  // Smelt the raw copper using coal as fuel in the furnace\\n  await smeltItem(bot, \\\"raw_copper\\\", \\\"coal\\\", 1);\\n\\n  // Collect the smelted copper ingot\\n  bot.chat(\\\"1 copper ore smelted.\\\");\\n}\", \"description\": \"async function smeltCopperOre(bot) {\\n    // The function is about smelting one copper ore block into a copper ingot using a furnace and coal as fuel. First, check if there is a furnace in the inventory. If not, craft one using cobblestone. Then, place the furnace near the player. Next, explore the environment until finding a copper ore block. Once a copper ore block is found, mine it and smelt the raw copper using coal as fuel in the furnace. Finally, collect the smelted copper ingot.\\n}\"}, \"smeltThreeRawCopper\": {\"code\": \"async function smeltThreeRawCopper(bot) {\\n  // Find a suitable location to place the furnace\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n\\n  // Place the furnace\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 3 raw copper using coal as fuel\\n  await smeltItem(bot, \\\"raw_copper\\\", \\\"coal\\\", 3);\\n  bot.chat(\\\"3 raw copper smelted.\\\");\\n}\", \"description\": \"async function smeltThreeRawCopper(bot) {\\n    // The function is about smelting 3 raw copper using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 3 raw copper using coal as fuel and saves the event of smelting 3 raw copper.\\n}\"}, \"craftStoneSword\": {\"code\": \"async function craftStoneSword(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 2) {\\n    bot.chat(\\\"Not enough cobblestones to craft a stone sword.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 1) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 1 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone sword using cobblestones and sticks with the crafting table\\n  await craftItem(bot, \\\"stone_sword\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone sword crafted.\\\");\\n}\", \"description\": \"async function craftStoneSword(bot) {\\n    // The function crafts a stone sword using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough cobblestones, it returns. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone sword using the crafting table. Finally, it sends a chat message indicating that the stone sword has been crafted.\\n}\"}, \"mineFiveCopperOre\": {\"code\": \"async function mineFiveCopperOre(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_pickaxe\\\"].id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find 5 copper ore blocks\\n  const copperOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const copperOres = bot.findBlocks({\\n      matching: mcData.blocksByName[\\\"copper_ore\\\"].id,\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return copperOres.length >= 5 ? copperOres : null;\\n  });\\n\\n  // Mine the 5 copper ore blocks\\n  await mineBlock(bot, \\\"copper_ore\\\", 5);\\n  bot.chat(\\\"5 copper ore mined.\\\");\\n}\", \"description\": \"async function mineFiveCopperOre(bot) {\\n    // The function is about mining 5 copper ore blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 copper ore blocks. Once 5 copper ore blocks are found, mine them using the iron pickaxe and save the event of mining 5 copper ore.\\n}\"}, \"smeltFiveRawCopper\": {\"code\": \"async function smeltFiveRawCopper(bot) {\\n  // Find a suitable location to place the furnace\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n\\n  // Place the furnace\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 5 raw copper using coal as fuel\\n  await smeltItem(bot, \\\"raw_copper\\\", \\\"coal\\\", 5);\\n  bot.chat(\\\"5 raw copper smelted.\\\");\\n}\", \"description\": \"async function smeltFiveRawCopper(bot) {\\n    // The function is about smelting 5 raw copper using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 5 raw copper using coal as fuel and sends a chat message indicating that 5 raw copper has been smelted.\\n}\"}, \"craftStoneShovel\": {\"code\": \"async function craftStoneShovel(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 1) {\\n    bot.chat(\\\"Not enough cobblestones to craft a stone shovel.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone shovel using cobblestones and sticks with the crafting table\\n  await craftItem(bot, \\\"stone_shovel\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone shovel crafted.\\\");\\n}\", \"description\": \"async function craftStoneShovel(bot) {\\n    // The function crafts a stone shovel using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a stone shovel. Finally, it sends a chat message indicating that the stone shovel has been crafted.\\n}\"}, \"craftCopperBlock\": {\"code\": \"async function craftCopperBlock(bot) {\\n  // Check if there are enough copper ingots in the inventory\\n  const copperIngots = bot.inventory.count(mcData.itemsByName[\\\"copper_ingot\\\"].id);\\n  if (copperIngots < 9) {\\n    bot.chat(\\\"Not enough copper ingots to craft a copper block.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a copper block using copper ingots and the crafting table\\n  await craftItem(bot, \\\"copper_block\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Copper block crafted.\\\");\\n}\", \"description\": \"async function craftCopperBlock(bot) {\\n    // The function crafts a copper block using 9 copper ingots and a crafting table. It first checks if there are enough copper ingots in the inventory, and if not, it returns. Then, it places a crafting table near the player and crafts a copper block using the crafting table. Finally, it sends a chat message indicating that the copper block has been crafted.\\n}\"}, \"killChickenWithIncreasedTime\": {\"code\": \"async function killChickenWithIncreasedTime(bot) {\\n  // Explore the area to find a chicken with an increased exploration time limit\\n  const chicken = await exploreUntil(bot, new Vec3(1, 0, 1), 120, () => {\\n    const chicken = bot.nearestEntity(entity => {\\n      return entity.name === \\\"chicken\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n    });\\n    return chicken;\\n  });\\n  if (!chicken) {\\n    bot.chat(\\\"No chicken found.\\\");\\n    return;\\n  }\\n\\n  // Equip a weapon (preferably a sword) to kill the chicken\\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_sword\\\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\\\"wooden_sword\\\"].id);\\n  if (sword) {\\n    await bot.equip(sword, \\\"hand\\\");\\n  } else {\\n    bot.chat(\\\"No sword found, using bare hands.\\\");\\n  }\\n\\n  // Kill the chicken\\n  await killMob(bot, \\\"chicken\\\", 300);\\n\\n  // Report the completion of the task\\n  bot.chat(\\\"1 chicken killed.\\\");\\n}\", \"description\": \"async function killChickenWithIncreasedTime(bot) {\\n    // The function is about killing a chicken with an increased exploration time limit. It explores the area to find a chicken within a certain distance. If a chicken is found, it equips a sword (if available) to kill the chicken. Otherwise, it uses bare hands. After killing the chicken, it reports the completion of the task.\\n}\"}, \"cookChicken\": {\"code\": \"async function cookChicken(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"furnace\\\"].id);\\n\\n  // If there is no furnace, craft one using cobblestone\\n  if (!furnace) {\\n    await craftItem(bot, \\\"furnace\\\", 1);\\n  }\\n\\n  // Place the furnace near the player\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt the raw chicken using coal as fuel in the furnace\\n  await smeltItem(bot, \\\"chicken\\\", \\\"coal\\\", 1);\\n\\n  // Collect the cooked chicken\\n  bot.chat(\\\"1 chicken cooked.\\\");\\n}\", \"description\": \"async function cookChicken(bot) {\\n    // The function is about cooking a raw chicken using a furnace and coal as fuel. First, it checks if there is a furnace in the inventory. If not, it crafts one using cobblestone. Then, it places the furnace near the player. Next, it smelts the raw chicken using coal as fuel in the furnace. Finally, it collects the cooked chicken and sends a chat message.\\n}\"}, \"killThreeCows\": {\"code\": \"async function killThreeCows(bot) {\\n  // Explore the area to find 3 cows\\n  let cows = [];\\n  while (cows.length < 3) {\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const nearbyCow = bot.nearestEntity(entity => {\\n        return entity.name === \\\"cow\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n      });\\n      if (nearbyCow && !cows.includes(nearbyCow)) {\\n        cows.push(nearbyCow);\\n        return cows.length === 3 ? cows : null;\\n      }\\n      return null;\\n    });\\n  }\\n\\n  // Equip a weapon (preferably a sword) to kill the cows\\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_sword\\\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\\\"wooden_sword\\\"].id);\\n  if (sword) {\\n    await bot.equip(sword, \\\"hand\\\");\\n  } else {\\n    bot.chat(\\\"No sword found, using bare hands.\\\");\\n  }\\n\\n  // Kill each cow one by one\\n  for (const cow of cows) {\\n    await killMob(bot, cow.name, 300);\\n  }\\n\\n  // Report the completion of the task\\n  bot.chat(\\\"3 cows killed.\\\");\\n}\", \"description\": \"async function killThreeCows(bot) {\\n    // The function is about killing 3 cows. It explores the environment to find 3 cows within a certain distance. Once 3 cows are found, it equips a sword (if available) to kill the cows one by one. If no sword is found, it uses bare hands. After killing all 3 cows, it reports the completion of the task.\\n}\"}, \"cookRawBeef\": {\"code\": \"async function cookRawBeef(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"furnace\\\"].id);\\n\\n  // If there is no furnace, craft one using cobblestone\\n  if (!furnace) {\\n    await craftItem(bot, \\\"furnace\\\", 1);\\n  }\\n\\n  // Place the furnace near the player\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt the 6 raw beef using coal as fuel in the furnace\\n  await smeltItem(bot, \\\"beef\\\", \\\"coal\\\", 6);\\n\\n  // Collect the cooked beef\\n  bot.chat(\\\"6 raw beef cooked.\\\");\\n}\", \"description\": \"async function cookRawBeef(bot) {\\n    // The function is about cooking 6 raw beef using a furnace and coal as fuel. It first checks if there is a furnace in the inventory, and if not, crafts one using cobblestone. Then, it places the furnace near the player and smelts the 6 raw beef using coal as fuel in the furnace. Finally, it collects the cooked beef and sends a chat message.\\n}\"}, \"eatCookedBeef\": {\"code\": \"async function eatCookedBeef(bot) {\\n  // Equip a cooked beef in the bot's hand\\n  const cookedBeef = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"cooked_beef\\\"].id);\\n  await bot.equip(cookedBeef, \\\"hand\\\");\\n\\n  // Consume the cooked beef\\n  await bot.consume();\\n  bot.chat(\\\"1 cooked beef eaten.\\\");\\n}\", \"description\": \"async function eatCookedBeef(bot) {\\n    // The function is about making the bot eat a cooked beef. It equips a cooked beef in the bot's hand and then consumes it. Finally, it sends a message to the chat indicating that one cooked beef has been eaten.\\n}\"}, \"killThreeChickens\": {\"code\": \"async function killThreeChickens(bot) {\\n  // Equip a weapon (preferably a sword) to kill the chickens\\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_sword\\\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\\\"wooden_sword\\\"].id);\\n  if (sword) {\\n    await bot.equip(sword, \\\"hand\\\");\\n  } else {\\n    bot.chat(\\\"No sword found, using bare hands.\\\");\\n  }\\n\\n  // Explore the area to find 3 chickens\\n  let chickens = [];\\n  while (chickens.length < 3) {\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const nearbyChicken = bot.nearestEntity(entity => {\\n        return entity.name === \\\"chicken\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n      });\\n      if (nearbyChicken && !chickens.includes(nearbyChicken)) {\\n        chickens.push(nearbyChicken);\\n        return chickens.length === 3 ? chickens : null;\\n      }\\n      return null;\\n    });\\n  }\\n\\n  // Kill each chicken one by one\\n  for (const chicken of chickens) {\\n    await killMob(bot, chicken.name, 300);\\n  }\\n\\n  // Report the completion of the task\\n  bot.chat(\\\"3 chickens killed.\\\");\\n}\", \"description\": \"async function killThreeChickens(bot) {\\n    // The function is about killing 3 chickens. First, it equips a sword to kill the chickens, and if there is no sword, it uses bare hands. Then, it explores the environment to find 3 chickens within a 32 block radius. Once 3 chickens are found, it kills each chicken one by one using the equipped weapon. Finally, it reports the completion of the task by sending a chat message.\\n}\"}, \"killThreeSheep\": {\"code\": \"async function killThreeSheep(bot) {\\n  // Equip a weapon (preferably a sword) to kill the sheep\\n  const sword = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"stone_sword\\\"].id) || bot.inventory.findInventoryItem(mcData.itemsByName[\\\"wooden_sword\\\"].id);\\n  if (sword) {\\n    await bot.equip(sword, \\\"hand\\\");\\n  } else {\\n    bot.chat(\\\"No sword found, using bare hands.\\\");\\n  }\\n\\n  // Explore the area to find 3 sheep\\n  let sheep = [];\\n  while (sheep.length < 3) {\\n    await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n      const nearbySheep = bot.nearestEntity(entity => {\\n        return entity.name === \\\"sheep\\\" && entity.position.distanceTo(bot.entity.position) < 32;\\n      });\\n      if (nearbySheep && !sheep.includes(nearbySheep)) {\\n        sheep.push(nearbySheep);\\n        return sheep.length === 3 ? sheep : null;\\n      }\\n      return null;\\n    });\\n  }\\n\\n  // Kill each sheep one by one\\n  for (const singleSheep of sheep) {\\n    await killMob(bot, singleSheep.name, 300);\\n  }\\n\\n  // Report the completion of the task\\n  bot.chat(\\\"3 sheep killed.\\\");\\n}\", \"description\": \"async function killThreeSheep(bot) {\\n    // The function is about killing 3 sheep. First, it equips a weapon (preferably a sword) to kill the sheep. Then, it explores the environment to find 3 sheep. Once 3 sheep are found, it kills each sheep one by one. Finally, it reports the completion of the task by sending a chat message.\\n}\"}, \"craftStoneAxe\": {\"code\": \"async function craftStoneAxe(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 3) {\\n    bot.chat(\\\"Not enough cobblestones to craft a stone axe.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone axe using cobblestones and sticks with the crafting table\\n  await craftItem(bot, \\\"stone_axe\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone axe crafted.\\\");\\n}\", \"description\": \"async function craftStoneAxe(bot) {\\n    // The function crafts a stone axe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone axe using the cobblestones and sticks with the crafting table. Finally, it sends a chat message indicating that the stone axe has been crafted.\\n}\"}, \"cookThreeRawChicken\": {\"code\": \"async function cookThreeRawChicken(bot) {\\n  // Find a suitable location to place the furnace\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n\\n  // Place the furnace\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt 3 raw chicken using coal as fuel\\n  await smeltItem(bot, \\\"chicken\\\", \\\"coal\\\", 3);\\n  bot.chat(\\\"3 raw chicken cooked.\\\");\\n}\", \"description\": \"async function cookThreeRawChicken(bot) {\\n    // The function is about cooking 3 raw chicken using a furnace and coal as fuel. First, it finds a suitable location to place the furnace. Then, it places the furnace at that location. Finally, it smelts 3 raw chicken using coal as fuel and sends a chat message indicating that the chicken has been cooked.\\n}\"}, \"craftStoneTools\": {\"code\": \"async function craftStoneTools(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 6) {\\n    // Mine more cobblestones\\n    await mineBlock(bot, \\\"stone\\\", 6 - cobblestones);\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 5) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 5 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone sword, a stone axe, and a stone shovel using the crafting table\\n  await craftItem(bot, \\\"stone_sword\\\", 1, craftingTablePosition);\\n  await craftItem(bot, \\\"stone_axe\\\", 1, craftingTablePosition);\\n  await craftItem(bot, \\\"stone_shovel\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone sword, stone axe, and stone shovel crafted.\\\");\\n}\", \"description\": \"async function craftStoneTools(bot) {\\n    // The function crafts stone tools (sword, axe, and shovel) using a crafting table. It checks if there are enough cobblestones and sticks in the inventory, and mines more cobblestones or crafts more sticks if necessary. Then, it places a crafting table near the player and crafts the stone tools using the crafting table. Finally, it sends a chat message indicating that the tools have been crafted.\\n}\"}, \"cookRawMutton\": {\"code\": \"async function cookRawMutton(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"furnace\\\"].id);\\n\\n  // If there is no furnace, craft one using cobblestone\\n  if (!furnace) {\\n    await craftItem(bot, \\\"furnace\\\", 1);\\n  }\\n\\n  // Place the furnace near the player\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt the 4 raw mutton using coal as fuel in the furnace\\n  await smeltItem(bot, \\\"mutton\\\", \\\"coal\\\", 4);\\n\\n  // Collect the cooked mutton\\n  bot.chat(\\\"4 raw mutton cooked.\\\");\\n}\", \"description\": \"async function cookRawMutton(bot) {\\n    // The function is about cooking 4 raw mutton using a furnace and coal as fuel. If there is no furnace in the inventory, the bot will craft one using cobblestone. Then, the bot will place the furnace near the player and smelt the 4 raw mutton using coal as fuel. Finally, the bot will collect the cooked mutton and print a message in the chat.\\n}\"}, \"plantOakSapling\": {\"code\": \"async function plantOakSapling(bot) {\\n  // Find a suitable location to plant the oak sapling\\n  const targetBlock = bot.findBlock({\\n    matching: block => {\\n      return block.name === \\\"grass_block\\\" || block.name === \\\"dirt\\\";\\n    },\\n    maxDistance: 32\\n  });\\n  if (!targetBlock) {\\n    bot.chat(\\\"Could not find a suitable location to plant the oak sapling.\\\");\\n    return;\\n  }\\n\\n  // Go to the location\\n  await bot.pathfinder.goto(new GoalBlock(targetBlock.position.x, targetBlock.position.y, targetBlock.position.z));\\n\\n  // Equip the oak sapling in the bot's hand\\n  const oakSapling = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"oak_sapling\\\"].id);\\n  await bot.equip(oakSapling, \\\"hand\\\");\\n\\n  // Right-click on the ground to plant the oak sapling\\n  await bot.activateBlock(targetBlock);\\n\\n  // Send a chat message to indicate the oak sapling has been planted\\n  bot.chat(\\\"Oak sapling planted.\\\");\\n}\", \"description\": \"async function plantOakSapling(bot) {\\n    // The function is about finding a suitable location to plant an oak sapling, going to that location, equipping the oak sapling in the bot's hand, right-clicking on the ground to plant the oak sapling, and sending a chat message to indicate the oak sapling has been planted. If a suitable location cannot be found, the function will return without planting the oak sapling.\\n}\"}, \"craftStoneHoe\": {\"code\": \"async function craftStoneHoe(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 2) {\\n    bot.chat(\\\"Not enough cobblestones to craft a stone hoe.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 2) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 2 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a stone hoe using cobblestones and sticks with the crafting table\\n  await craftItem(bot, \\\"stone_hoe\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Stone hoe crafted.\\\");\\n}\", \"description\": \"async function craftStoneHoe(bot) {\\n    // The function crafts a stone hoe using cobblestones and sticks. It first checks if there are enough cobblestones and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts a stone hoe using the cobblestones and sticks with the crafting table. Finally, it sends a chat message indicating that the stone hoe has been crafted.\\n}\"}, \"craftTenCobblestoneWalls\": {\"code\": \"async function craftTenCobblestoneWalls(bot) {\\n  // Check if there are enough cobblestones in the inventory\\n  const cobblestones = bot.inventory.count(mcData.itemsByName[\\\"cobblestone\\\"].id);\\n  if (cobblestones < 32) {\\n    bot.chat(\\\"Not enough cobblestones to craft 10 cobblestone walls.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft 6 cobblestone walls using the crafting table\\n  await craftItem(bot, \\\"cobblestone_wall\\\", 1, craftingTablePosition);\\n\\n  // Craft 6 more cobblestone walls using the crafting table\\n  await craftItem(bot, \\\"cobblestone_wall\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"10 cobblestone walls crafted.\\\");\\n}\", \"description\": \"async function craftTenCobblestoneWalls(bot) {\\n    // The function crafts 10 cobblestone walls using a crafting table. It first checks if there are enough cobblestones in the inventory, and if not, it returns. Then, it places a crafting table near the player and crafts 6 cobblestone walls using the crafting table. It repeats the process to craft 6 more cobblestone walls and outputs a message when the process is complete.\\n}\"}, \"openChestAndCheckContents\": {\"code\": \"async function openChestAndCheckContents(bot) {\\n  const targetChestPosition = new Vec3(5, 61, 134);\\n\\n  // Find the chest at the specified position\\n  const chestPosition = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const chest = bot.findBlock({\\n      matching: mcData.blocksByName[\\\"chest\\\"].id,\\n      maxDistance: 32,\\n      position: targetChestPosition\\n    });\\n    return chest ? chest.position : null;\\n  });\\n\\n  // Check the contents of the chest\\n  await checkItemInsideChest(bot, chestPosition);\\n  bot.chat(\\\"Chest at (5, 61, 134) opened and contents checked.\\\");\\n}\", \"description\": \"async function openChestAndCheckContents(bot) {\\n    // The function is about finding a chest at a specified position, opening it, and checking its contents. It uses the `exploreUntil` helper function to find the chest and the `checkItemInsideChest` helper function to check the contents of the chest. The position of the chest is specified by `targetChestPosition`. Once the chest is found, the function checks its contents and sends a chat message indicating that the chest has been opened and its contents have been checked.\\n}\"}, \"mineTenCobbledDeepslateBelowY0\": {\"code\": \"async function mineTenCobbledDeepslateBelowY0(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_pickaxe\\\"].id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find cobbled_deepslate blocks below Y=0\\n  const cobbledDeepslateBlocks = await exploreUntil(bot, new Vec3(1, -1, 1), 60, () => {\\n    const cobbledDeepslate = bot.findBlock({\\n      matching: mcData.blocksByName[\\\"cobbled_deepslate\\\"].id,\\n      maxDistance: 32,\\n      position: pos => pos.y < 0\\n    });\\n    return cobbledDeepslate;\\n  });\\n\\n  // Mine 10 cobbled_deepslate blocks\\n  await mineBlock(bot, \\\"cobbled_deepslate\\\", 10);\\n  bot.chat(\\\"10 cobbled_deepslate mined below Y=0.\\\");\\n}\", \"description\": \"async function mineTenCobbledDeepslateBelowY0(bot) {\\n    // The function is about mining 10 cobbled_deepslate blocks below Y=0 using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding a cobbled_deepslate block below Y=0. Once 10 cobbled_deepslate blocks are found, mine them using the iron pickaxe. Finally, a message is sent to the chat indicating that 10 cobbled_deepslate blocks have been mined below Y=0.\\n}\"}, \"mineDeepslateOres\": {\"code\": \"async function mineDeepslateOres(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_pickaxe\\\"].id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find and mine 1 deepslate_redstone_ore\\n  await mineBlock(bot, \\\"deepslate_redstone_ore\\\", 1);\\n  bot.chat(\\\"1 deepslate_redstone_ore mined.\\\");\\n\\n  // Find and mine 1 deepslate_gold_ore\\n  await mineBlock(bot, \\\"deepslate_gold_ore\\\", 1);\\n  bot.chat(\\\"1 deepslate_gold_ore mined.\\\");\\n}\", \"description\": \"async function mineDeepslateOres(bot) {\\n    // The function is about mining 1 deepslate_redstone_ore and 1 deepslate_gold_ore using an iron pickaxe. The function first equips the iron pickaxe in the hand. Then, it finds and mines 1 deepslate_redstone_ore and 1 deepslate_gold_ore using the mineBlock function. Finally, it sends a chat message indicating the number of ores mined.\\n}\"}, \"craftChest\": {\"code\": \"async function craftChest(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\\\"oak_planks\\\"].id);\\n  if (oakPlanks < 8) {\\n    // Mine more oak logs\\n    await mineBlock(bot, \\\"oak_log\\\", 8 - oakPlanks);\\n    // Craft oak planks using oak logs\\n    await craftItem(bot, \\\"oak_planks\\\", 8 - oakPlanks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a chest using oak planks with the crafting table\\n  await craftItem(bot, \\\"chest\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Chest crafted.\\\");\\n}\", \"description\": \"async function craftChest(bot) {\\n    // The function crafts a chest using oak planks. It checks if there are enough oak planks in the inventory, and if not, it mines oak logs and crafts oak planks. It then places a crafting table near the player and crafts a chest using oak planks with the crafting table. Finally, it sends a chat message indicating that the chest has been crafted.\\n}\"}, \"smeltFiveRawGold\": {\"code\": \"async function smeltFiveRawGold(bot) {\\n  // Check if there is a furnace in the inventory\\n  const furnace = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"furnace\\\"].id);\\n\\n  // If there is no furnace, craft one using cobblestone\\n  if (!furnace) {\\n    await craftItem(bot, \\\"furnace\\\", 1);\\n  }\\n\\n  // Place the furnace near the player\\n  const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n  // Smelt the 5 raw gold using coal as fuel in the furnace\\n  await smeltItem(bot, \\\"raw_gold\\\", \\\"coal\\\", 5);\\n\\n  // Collect the smelted gold ingots\\n  bot.chat(\\\"5 raw gold smelted.\\\");\\n}\", \"description\": \"async function smeltFiveRawGold(bot) {\\n    // The function is about smelting 5 raw gold into gold ingots using a furnace and coal as fuel. If there is no furnace in the inventory, the bot will craft one using cobblestone. Then, the bot will place the furnace near the player and smelt the 5 raw gold using coal as fuel. Finally, the bot will collect the smelted gold ingots and print a message in the chat.\\n}\"}, \"craftClock\": {\"code\": \"async function craftClock(bot) {\\n  // Check if there is a crafting table in the inventory\\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"crafting_table\\\"].id);\\n\\n  // If there is no crafting table, craft one using oak planks\\n  if (!craftingTable) {\\n    await craftItem(bot, \\\"crafting_table\\\", 1);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a clock using 4 gold ingots and 1 redstone dust with the crafting table\\n  await craftItem(bot, \\\"clock\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Clock crafted.\\\");\\n}\", \"description\": \"async function craftClock(bot) {\\n    // The function crafts a clock using 4 gold ingots and 1 redstone dust. It first checks if there is a crafting table in the inventory, and if not, crafts one using oak planks. Then, it places the crafting table near the player. Finally, it crafts a clock using the crafting table and saves the event of crafting a clock.\\n}\"}, \"craftIronSword\": {\"code\": \"async function craftIronSword(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 2) {\\n    bot.chat(\\\"Not enough iron ingots to craft an iron sword.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 1) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 1 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron sword using iron ingots and sticks with the crafting table\\n  await craftItem(bot, \\\"iron_sword\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Iron sword crafted.\\\");\\n}\", \"description\": \"async function craftIronSword(bot) {\\n    // The function crafts an iron sword using iron ingots and sticks. It first checks if there are enough iron ingots and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and crafts an iron sword using the crafting table. Finally, it sends a chat message indicating that the iron sword has been crafted.\\n}\"}, \"obtainBirchLogs\": {\"code\": \"async function obtainBirchLogs(bot) {\\n  // Check if there are enough birch logs in the inventory\\n  const birchLogs = bot.inventory.count(mcData.itemsByName[\\\"birch_log\\\"].id);\\n  const logsNeeded = 5 - birchLogs;\\n  if (logsNeeded > 0) {\\n    // Mine the required number of birch logs\\n    await mineBlock(bot, \\\"birch_log\\\", logsNeeded);\\n    bot.chat(\\\"5 birch logs obtained.\\\");\\n  } else {\\n    bot.chat(\\\"Already have 5 birch logs in the inventory.\\\");\\n  }\\n}\", \"description\": \"async function obtainBirchLogs(bot) {\\n    // The function is about obtaining 5 birch logs. It checks if there are enough birch logs in the inventory and mines the required number of birch logs if necessary. Once 5 birch logs are obtained, it sends a chat message. If there are already 5 birch logs in the inventory, it sends a different chat message.\\n}\"}, \"mineFiveCoalOre\": {\"code\": \"async function mineFiveCoalOre(bot) {\\n  // Equip the iron pickaxe\\n  const ironPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_pickaxe\\\"].id);\\n  await bot.equip(ironPickaxe, \\\"hand\\\");\\n\\n  // Find 5 coal ore blocks\\n  const coalOres = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\\n    const coalOres = bot.findBlocks({\\n      matching: mcData.blocksByName[\\\"coal_ore\\\"].id,\\n      maxDistance: 32,\\n      count: 5\\n    });\\n    return coalOres.length >= 5 ? coalOres : null;\\n  });\\n\\n  // Mine the 5 coal ore blocks\\n  await mineBlock(bot, \\\"coal_ore\\\", 5);\\n  bot.chat(\\\"5 coal ore mined.\\\");\\n}\", \"description\": \"async function mineFiveCoalOre(bot) {\\n    // The function is about mining 5 coal ore blocks using an iron pickaxe. First, equip the iron pickaxe in the hand. Next, explore the environment until finding 5 coal ore blocks. Once 5 coal ore blocks are found, mine them using the iron pickaxe and save the event of mining 5 coal ore blocks.\\n}\"}, \"craftShield\": {\"code\": \"async function craftShield(bot) {\\n  // Check if there are enough oak planks in the inventory\\n  const oakPlanks = bot.inventory.count(mcData.itemsByName[\\\"oak_planks\\\"].id);\\n  if (oakPlanks < 6) {\\n    // Craft more oak planks using oak logs\\n    await craftItem(bot, \\\"oak_planks\\\", 6 - oakPlanks);\\n  }\\n\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 1) {\\n    bot.chat(\\\"Not enough iron ingots to craft a shield.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a shield using oak planks and iron ingots with the crafting table\\n  await craftItem(bot, \\\"shield\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Shield crafted.\\\");\\n}\", \"description\": \"async function craftShield(bot) {\\n    // The function crafts a shield using oak planks and iron ingots. It checks if there are enough oak planks and iron ingots in the inventory, and crafts more oak planks if necessary. If there are not enough iron ingots, it returns. It then places a crafting table near the player and crafts a shield using the crafting table. Finally, it sends a chat message indicating that the shield has been crafted.\\n}\"}, \"craftDiamondSword\": {\"code\": \"async function craftDiamondSword(bot) {\\n  // Check if there are enough diamonds in the inventory\\n  const diamonds = bot.inventory.count(mcData.itemsByName[\\\"diamond\\\"].id);\\n  if (diamonds < 2) {\\n    bot.chat(\\\"Not enough diamonds to craft a diamond sword.\\\");\\n    return;\\n  }\\n\\n  // Check if there are enough sticks in the inventory\\n  const sticks = bot.inventory.count(mcData.itemsByName[\\\"stick\\\"].id);\\n  if (sticks < 1) {\\n    // Craft more sticks using oak planks\\n    await craftItem(bot, \\\"stick\\\", 1 - sticks);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a diamond sword using diamonds and sticks with the crafting table\\n  await craftItem(bot, \\\"diamond_sword\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Diamond sword crafted.\\\");\\n}\", \"description\": \"async function craftDiamondSword(bot) {\\n    // The function crafts a diamond sword using diamonds and sticks. It first checks if there are enough diamonds and sticks in the inventory. If there are not enough sticks, it crafts more using oak planks. Then, it places a crafting table near the player and uses it to craft a diamond sword. Finally, it sends a chat message indicating that the diamond sword has been crafted.\\n}\"}, \"craftIronHelmet\": {\"code\": \"async function craftIronHelmet(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 5) {\\n    // Mine iron ores\\n    await mineBlock(bot, \\\"iron_ore\\\", 5 - ironIngots);\\n\\n    // Place a furnace near the player\\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n    // Smelt iron ores into iron ingots\\n    for (let i = 0; i < 5 - ironIngots; i++) {\\n      await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\");\\n    }\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft an iron helmet using iron ingots and the crafting table\\n  await craftItem(bot, \\\"iron_helmet\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Iron helmet crafted.\\\");\\n}\", \"description\": \"async function craftIronHelmet(bot) {\\n    // The function crafts an iron helmet using iron ingots and a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores, places a furnace, and smelts the ores into ingots. Then it places a crafting table near the player and crafts an iron helmet using the ingots and the crafting table. Finally, it sends a chat message indicating that the iron helmet has been crafted.\\n}\"}, \"equipIronHelmet\": {\"code\": \"async function equipIronHelmet(bot) {\\n  // Find the iron helmet in the bot's inventory\\n  const ironHelmet = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_helmet\\\"].id);\\n\\n  // Equip the iron helmet in the head slot\\n  await bot.equip(ironHelmet, \\\"head\\\");\\n  bot.chat(\\\"Iron helmet equipped.\\\");\\n}\", \"description\": \"async function equipIronHelmet(bot) {\\n    // The function is about equipping an iron helmet in the head slot of the bot's inventory. It first finds the iron helmet in the bot's inventory and then equips it in the head slot. Finally, it sends a chat message confirming that the iron helmet has been equipped.\\n}\"}, \"craftIronChestplate\": {\"code\": \"async function craftIronChestplate(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 8) {\\n    // Mine iron ores\\n    await mineBlock(bot, \\\"iron_ore\\\", 8 - ironIngots);\\n\\n    // Place a furnace near the player\\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n    // Smelt iron ores into iron ingots\\n    for (let i = 0; i < 8 - ironIngots; i++) {\\n      await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\");\\n    }\\n  }\\n\\n  // Check if there is a crafting table in the inventory\\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"crafting_table\\\"].id);\\n  if (!craftingTable) {\\n    // Craft a crafting table\\n    await craftItem(bot, \\\"crafting_table\\\", 1);\\n  }\\n\\n  // Try to place the crafting table near the player at different positions until it is successfully placed\\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\\n  let craftingTablePosition = null;\\n  for (const offset of offsets) {\\n    try {\\n      craftingTablePosition = bot.entity.position.offset(offset.x, offset.y, offset.z);\\n      await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n      break;\\n    } catch (error) {\\n      console.log(\\\"Error placing crafting_table:\\\", error.message);\\n    }\\n  }\\n  if (!craftingTablePosition) {\\n    bot.chat(\\\"Failed to place crafting table. Please try again.\\\");\\n    return;\\n  }\\n\\n  // Craft an iron chestplate using iron ingots and the crafting table\\n  await craftItem(bot, \\\"iron_chestplate\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Iron chestplate crafted.\\\");\\n}\", \"description\": \"async function craftIronChestplate(bot) {\\n    // The function crafts an iron chestplate using iron ingots and a crafting table. It first checks if there are enough iron ingots in the inventory, and if not, it mines iron ores, places a furnace, and smelts the ores into ingots. Then it checks if there is a crafting table in the inventory, and if not, it crafts one. Next, it tries to place the crafting table near the player at different positions until it is successfully placed. Finally, it crafts an iron chestplate using the iron ingots and the crafting table.\\n}\"}, \"equipShield\": {\"code\": \"async function equipShield(bot) {\\n  // Find the shield in the bot's inventory\\n  const shield = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"shield\\\"].id);\\n\\n  // Equip the shield in the off-hand slot\\n  await bot.equip(shield, \\\"off-hand\\\");\\n  bot.chat(\\\"Shield equipped.\\\");\\n}\", \"description\": \"async function equipShield(bot) {\\n    // The function equips a shield in the off-hand slot of the bot's inventory. It first finds the shield in the bot's inventory and then equips it in the off-hand slot. Finally, it sends a chat message confirming that the shield has been equipped.\\n}\"}, \"equipIronChestplate\": {\"code\": \"async function equipIronChestplate(bot) {\\n  // Find the iron chestplate in the bot's inventory\\n  const ironChestplate = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_chestplate\\\"].id);\\n\\n  // Equip the iron chestplate in the torso slot\\n  await bot.equip(ironChestplate, \\\"torso\\\");\\n  bot.chat(\\\"Iron chestplate equipped.\\\");\\n}\", \"description\": \"async function equipIronChestplate(bot) {\\n    // The function equips an iron chestplate in the torso slot of the bot's armor. It first finds the iron chestplate in the bot's inventory and then equips it using the `bot.equip` function. Finally, it sends a chat message confirming that the iron chestplate has been equipped.\\n}\"}, \"craftIronLeggingsAndBoots\": {\"code\": \"async function craftIronLeggingsAndBoots(bot) {\\n  // Check if there are enough iron ingots in the inventory\\n  const ironIngots = bot.inventory.count(mcData.itemsByName[\\\"iron_ingot\\\"].id);\\n  if (ironIngots < 11) {\\n    // Mine iron ores\\n    await mineBlock(bot, \\\"iron_ore\\\", 11 - ironIngots);\\n\\n    // Check if there are enough coal in the inventory\\n    const coalCount = bot.inventory.count(mcData.itemsByName[\\\"coal\\\"].id);\\n    if (coalCount < 11 - ironIngots) {\\n      // Mine coal\\n      await mineBlock(bot, \\\"coal_ore\\\", 11 - ironIngots - coalCount);\\n    }\\n\\n    // Place a furnace near the player\\n    const furnacePosition = bot.entity.position.offset(1, 0, 0);\\n    await placeItem(bot, \\\"furnace\\\", furnacePosition);\\n\\n    // Smelt iron ores into iron ingots\\n    for (let i = 0; i < 11 - ironIngots; i++) {\\n      await smeltItem(bot, \\\"raw_iron\\\", \\\"coal\\\");\\n    }\\n  }\\n\\n  // Check if there is a crafting table in the inventory\\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"crafting_table\\\"].id);\\n  if (!craftingTable) {\\n    // Craft a crafting table\\n    await craftItem(bot, \\\"crafting_table\\\", 1);\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft iron leggings using the crafting table\\n  await craftItem(bot, \\\"iron_leggings\\\", 1);\\n\\n  // Craft iron boots using the crafting table\\n  await craftItem(bot, \\\"iron_boots\\\", 1);\\n  bot.chat(\\\"Iron leggings and iron boots crafted.\\\");\\n}\", \"description\": \"async function craftIronLeggingsAndBoots(bot) {\\n    // The function crafts iron leggings and boots. It checks if there are enough iron ingots in the inventory, and if not, it mines iron ores and coal to smelt them into iron ingots. It then checks if there is a crafting table in the inventory, and if not, it crafts one. The function places the crafting table and a furnace near the player, and uses the furnace to smelt the iron ores. Finally, it crafts iron leggings and boots using the crafting table.\\n}\"}, \"equipIronLeggingsAndBoots\": {\"code\": \"async function equipIronLeggingsAndBoots(bot) {\\n  // Find the iron leggings and iron boots in the bot's inventory\\n  const ironLeggings = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_leggings\\\"].id);\\n  const ironBoots = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"iron_boots\\\"].id);\\n\\n  // Check if the bot has iron leggings and iron boots\\n  if (ironLeggings && ironBoots) {\\n    // Equip the iron leggings in the legs slot\\n    await bot.equip(ironLeggings, \\\"legs\\\");\\n\\n    // Equip the iron boots in the feet slot\\n    await bot.equip(ironBoots, \\\"feet\\\");\\n\\n    // Send a chat message to indicate that the iron leggings and iron boots have been equipped\\n    bot.chat(\\\"Iron leggings and iron boots equipped.\\\");\\n  } else {\\n    bot.chat(\\\"Iron leggings and/or iron boots not found in inventory.\\\");\\n  }\\n}\", \"description\": \"async function equipIronLeggingsAndBoots(bot) {\\n    // The function equips the bot with iron leggings and iron boots if they are available in the inventory, and sends a chat message indicating that they have been equipped. If the items are not found in the inventory, it sends a chat message indicating that they were not found.\\n}\"}, \"waitAndEatCookedMutton\": {\"code\": \"async function waitAndEatCookedMutton(bot) {\\n  // Wait until the bot's hunger is less than 20\\n  while (bot.food >= 20) {\\n    await bot.waitForTicks(20);\\n  }\\n\\n  // Equip a cooked mutton in the bot's hand\\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"cooked_mutton\\\"].id);\\n  await bot.equip(cookedMutton, \\\"hand\\\");\\n\\n  // Consume the cooked mutton\\n  await bot.consume();\\n  bot.chat(\\\"1 cooked mutton eaten.\\\");\\n}\", \"description\": \"async function waitAndEatCookedMutton(bot) {\\n    // The function waits until the bot's hunger is less than 20, equips a cooked mutton in the bot's hand, consumes it, and then sends a chat message indicating that 1 cooked mutton has been eaten.\\n}\"}, \"eatCookedMuttonIfHungry\": {\"code\": \"async function eatCookedMuttonIfHungry(bot) {\\n  // Check if the bot's hunger is less than 20\\n  if (bot.food < 20) {\\n    // Equip the cooked mutton in the bot's hand\\n    const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"cooked_mutton\\\"].id);\\n    await bot.equip(cookedMutton, \\\"hand\\\");\\n\\n    // Consume the cooked mutton\\n    await bot.consume();\\n    bot.chat(\\\"1 cooked mutton eaten.\\\");\\n  } else {\\n    bot.chat(\\\"Hunger is full, no need to eat cooked mutton.\\\");\\n  }\\n}\", \"description\": \"async function eatCookedMuttonIfHungry(bot) {\\n    // The function checks if the bot's hunger is less than 20, and if so, equips and consumes a cooked mutton to restore hunger. If the hunger is already full, it will not eat the cooked mutton.\\n}\"}, \"eatCookedMutton\": {\"code\": \"async function eatCookedMutton(bot) {\\n  // Equip a cooked mutton in the bot's hand\\n  const cookedMutton = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"cooked_mutton\\\"].id);\\n  await bot.equip(cookedMutton, \\\"hand\\\");\\n\\n  // Consume the cooked mutton\\n  await bot.consume();\\n  bot.chat(\\\"1 cooked mutton eaten.\\\");\\n}\", \"description\": \"async function eatCookedMutton(bot) {\\n    // The function is about making the bot eat a cooked mutton. First, it equips a cooked mutton in the bot's hand. Then, it consumes the cooked mutton and sends a chat message indicating that 1 cooked mutton has been eaten.\\n}\"}, \"craftBirchBoat\": {\"code\": \"async function findSuitablePosition(bot) {\\n  const offsets = [new Vec3(1, 0, 0), new Vec3(-1, 0, 0), new Vec3(0, 0, 1), new Vec3(0, 0, -1)];\\n  for (const offset of offsets) {\\n    const position = bot.entity.position.offset(offset.x, offset.y, offset.z);\\n    const blockBelow = bot.blockAt(position.offset(0, -1, 0));\\n    if (blockBelow && blockBelow.name !== \\\"air\\\") {\\n      return position;\\n    }\\n  }\\n  return null;\\n}\\n\\nasync function craftBirchBoat(bot) {\\n  // Check if there are enough birch logs in the inventory\\n  const birchLogs = bot.inventory.count(mcData.itemsByName[\\\"birch_log\\\"].id);\\n  if (birchLogs < 5) {\\n    // Mine more birch logs\\n    await mineBlock(bot, \\\"birch_log\\\", 5 - birchLogs);\\n  }\\n\\n  // Craft birch planks using birch logs\\n  await craftItem(bot, \\\"birch_planks\\\", 5);\\n\\n  // Check if there is a crafting table in the inventory\\n  const craftingTable = bot.inventory.findInventoryItem(mcData.itemsByName[\\\"crafting_table\\\"].id);\\n  if (!craftingTable) {\\n    // Craft a crafting table\\n    await craftItem(bot, \\\"crafting_table\\\", 1);\\n  }\\n\\n  // Find a suitable position to place the crafting table\\n  const craftingTablePosition = await findSuitablePosition(bot);\\n  if (!craftingTablePosition) {\\n    bot.chat(\\\"Failed to find a suitable position to place the crafting table. Please try again.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table at the suitable position\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft a birch boat using birch planks and the crafting table\\n  await craftItem(bot, \\\"birch_boat\\\", 1, craftingTablePosition);\\n  bot.chat(\\\"Birch boat crafted.\\\");\\n}\", \"description\": \"async function craftBirchBoat(bot) {\\n    // The function crafts a birch boat using birch logs and a crafting table. It first checks if there are enough birch logs in the inventory, and if not, mines more. Then, it crafts birch planks using the birch logs. If there is no crafting table in the inventory, it crafts one. It finds a suitable position to place the crafting table and places it there. Finally, it crafts a birch boat using the birch planks and the crafting table.\\n}\"}, \"craftBoneMeal\": {\"code\": \"async function craftBoneMeal(bot) {\\n  // Check if there are enough bones in the inventory\\n  const bones = bot.inventory.count(mcData.itemsByName[\\\"bone\\\"].id);\\n  if (bones < 2) {\\n    bot.chat(\\\"Not enough bones to craft 4 bone meal.\\\");\\n    return;\\n  }\\n\\n  // Place the crafting table near the player\\n  const craftingTablePosition = bot.entity.position.offset(1, 0, 0);\\n  await placeItem(bot, \\\"crafting_table\\\", craftingTablePosition);\\n\\n  // Craft 4 bone meal using 2 bones and the crafting table\\n  await craftItem(bot, \\\"bone_meal\\\", 2, craftingTablePosition);\\n  bot.chat(\\\"4 bone meal crafted.\\\");\\n}\", \"description\": \"async function craftBoneMeal(bot) {\\n    // The function is about crafting 4 bone meal using 2 bones and a crafting table. It first checks if there are enough bones in the inventory, and if not, it returns. Then, it places a crafting table near the player using the `placeItem` helper function. Finally, it crafts 4 bone meal using 2 bones and the crafting table, and sends a chat message indicating that the bone meal has been crafted.\\n}\"}}"
  },
  {
    "path": "voyager/__init__.py",
    "content": "from .voyager import Voyager\n"
  },
  {
    "path": "voyager/agents/__init__.py",
    "content": "from .action import ActionAgent\nfrom .critic import CriticAgent\nfrom .curriculum import CurriculumAgent\nfrom .skill import SkillManager\n"
  },
  {
    "path": "voyager/agents/action.py",
    "content": "import re\nimport time\n\nimport voyager.utils as U\nfrom javascript import require\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts import SystemMessagePromptTemplate\nfrom langchain.schema import AIMessage, HumanMessage, SystemMessage\n\nfrom voyager.prompts import load_prompt\nfrom voyager.control_primitives_context import load_control_primitives_context\n\n\nclass ActionAgent:\n    def __init__(\n        self,\n        model_name=\"gpt-3.5-turbo\",\n        temperature=0,\n        request_timout=120,\n        ckpt_dir=\"ckpt\",\n        resume=False,\n        chat_log=True,\n        execution_error=True,\n    ):\n        self.ckpt_dir = ckpt_dir\n        self.chat_log = chat_log\n        self.execution_error = execution_error\n        U.f_mkdir(f\"{ckpt_dir}/action\")\n        if resume:\n            print(f\"\\033[32mLoading Action Agent from {ckpt_dir}/action\\033[0m\")\n            self.chest_memory = U.load_json(f\"{ckpt_dir}/action/chest_memory.json\")\n        else:\n            self.chest_memory = {}\n        self.llm = ChatOpenAI(\n            model_name=model_name,\n            temperature=temperature,\n            request_timeout=request_timout,\n        )\n\n    def update_chest_memory(self, chests):\n        for position, chest in chests.items():\n            if position in self.chest_memory:\n                if isinstance(chest, dict):\n                    self.chest_memory[position] = chest\n                if chest == \"Invalid\":\n                    print(\n                        f\"\\033[32mAction Agent removing chest {position}: {chest}\\033[0m\"\n                    )\n                    self.chest_memory.pop(position)\n            else:\n                if chest != \"Invalid\":\n                    print(f\"\\033[32mAction Agent saving chest {position}: {chest}\\033[0m\")\n                    self.chest_memory[position] = chest\n        U.dump_json(self.chest_memory, f\"{self.ckpt_dir}/action/chest_memory.json\")\n\n    def render_chest_observation(self):\n        chests = []\n        for chest_position, chest in self.chest_memory.items():\n            if isinstance(chest, dict) and len(chest) > 0:\n                chests.append(f\"{chest_position}: {chest}\")\n        for chest_position, chest in self.chest_memory.items():\n            if isinstance(chest, dict) and len(chest) == 0:\n                chests.append(f\"{chest_position}: Empty\")\n        for chest_position, chest in self.chest_memory.items():\n            if isinstance(chest, str):\n                assert chest == \"Unknown\"\n                chests.append(f\"{chest_position}: Unknown items inside\")\n        assert len(chests) == len(self.chest_memory)\n        if chests:\n            chests = \"\\n\".join(chests)\n            return f\"Chests:\\n{chests}\\n\\n\"\n        else:\n            return f\"Chests: None\\n\\n\"\n\n    def render_system_message(self, skills=[]):\n        system_template = load_prompt(\"action_template\")\n        # FIXME: Hardcoded control_primitives\n        base_skills = [\n            \"exploreUntil\",\n            \"mineBlock\",\n            \"craftItem\",\n            \"placeItem\",\n            \"smeltItem\",\n            \"killMob\",\n        ]\n        if not self.llm.model_name == \"gpt-3.5-turbo\":\n            base_skills += [\n                \"useChest\",\n                \"mineflayer\",\n            ]\n        programs = \"\\n\\n\".join(load_control_primitives_context(base_skills) + skills)\n        response_format = load_prompt(\"action_response_format\")\n        system_message_prompt = SystemMessagePromptTemplate.from_template(\n            system_template\n        )\n        system_message = system_message_prompt.format(\n            programs=programs, response_format=response_format\n        )\n        assert isinstance(system_message, SystemMessage)\n        return system_message\n\n    def render_human_message(\n        self, *, events, code=\"\", task=\"\", context=\"\", critique=\"\"\n    ):\n        chat_messages = []\n        error_messages = []\n        # FIXME: damage_messages is not used\n        damage_messages = []\n        assert events[-1][0] == \"observe\", \"Last event must be observe\"\n        for i, (event_type, event) in enumerate(events):\n            if event_type == \"onChat\":\n                chat_messages.append(event[\"onChat\"])\n            elif event_type == \"onError\":\n                error_messages.append(event[\"onError\"])\n            elif event_type == \"onDamage\":\n                damage_messages.append(event[\"onDamage\"])\n            elif event_type == \"observe\":\n                biome = event[\"status\"][\"biome\"]\n                time_of_day = event[\"status\"][\"timeOfDay\"]\n                voxels = event[\"voxels\"]\n                entities = event[\"status\"][\"entities\"]\n                health = event[\"status\"][\"health\"]\n                hunger = event[\"status\"][\"food\"]\n                position = event[\"status\"][\"position\"]\n                equipment = event[\"status\"][\"equipment\"]\n                inventory_used = event[\"status\"][\"inventoryUsed\"]\n                inventory = event[\"inventory\"]\n                assert i == len(events) - 1, \"observe must be the last event\"\n\n        observation = \"\"\n\n        if code:\n            observation += f\"Code from the last round:\\n{code}\\n\\n\"\n        else:\n            observation += f\"Code from the last round: No code in the first round\\n\\n\"\n\n        if self.execution_error:\n            if error_messages:\n                error = \"\\n\".join(error_messages)\n                observation += f\"Execution error:\\n{error}\\n\\n\"\n            else:\n                observation += f\"Execution error: No error\\n\\n\"\n\n        if self.chat_log:\n            if chat_messages:\n                chat_log = \"\\n\".join(chat_messages)\n                observation += f\"Chat log: {chat_log}\\n\\n\"\n            else:\n                observation += f\"Chat log: None\\n\\n\"\n\n        observation += f\"Biome: {biome}\\n\\n\"\n\n        observation += f\"Time: {time_of_day}\\n\\n\"\n\n        if voxels:\n            observation += f\"Nearby blocks: {', '.join(voxels)}\\n\\n\"\n        else:\n            observation += f\"Nearby blocks: None\\n\\n\"\n\n        if entities:\n            nearby_entities = [\n                k for k, v in sorted(entities.items(), key=lambda x: x[1])\n            ]\n            observation += f\"Nearby entities (nearest to farthest): {', '.join(nearby_entities)}\\n\\n\"\n        else:\n            observation += f\"Nearby entities (nearest to farthest): None\\n\\n\"\n\n        observation += f\"Health: {health:.1f}/20\\n\\n\"\n\n        observation += f\"Hunger: {hunger:.1f}/20\\n\\n\"\n\n        observation += f\"Position: x={position['x']:.1f}, y={position['y']:.1f}, z={position['z']:.1f}\\n\\n\"\n\n        observation += f\"Equipment: {equipment}\\n\\n\"\n\n        if inventory:\n            observation += f\"Inventory ({inventory_used}/36): {inventory}\\n\\n\"\n        else:\n            observation += f\"Inventory ({inventory_used}/36): Empty\\n\\n\"\n\n        if not (\n            task == \"Place and deposit useless items into a chest\"\n            or task.startswith(\"Deposit useless items into the chest at\")\n        ):\n            observation += self.render_chest_observation()\n\n        observation += f\"Task: {task}\\n\\n\"\n\n        if context:\n            observation += f\"Context: {context}\\n\\n\"\n        else:\n            observation += f\"Context: None\\n\\n\"\n\n        if critique:\n            observation += f\"Critique: {critique}\\n\\n\"\n        else:\n            observation += f\"Critique: None\\n\\n\"\n\n        return HumanMessage(content=observation)\n\n    def process_ai_message(self, message):\n        assert isinstance(message, AIMessage)\n\n        retry = 3\n        error = None\n        while retry > 0:\n            try:\n                babel = require(\"@babel/core\")\n                babel_generator = require(\"@babel/generator\").default\n\n                code_pattern = re.compile(r\"```(?:javascript|js)(.*?)```\", re.DOTALL)\n                code = \"\\n\".join(code_pattern.findall(message.content))\n                parsed = babel.parse(code)\n                functions = []\n                assert len(list(parsed.program.body)) > 0, \"No functions found\"\n                for i, node in enumerate(parsed.program.body):\n                    if node.type != \"FunctionDeclaration\":\n                        continue\n                    node_type = (\n                        \"AsyncFunctionDeclaration\"\n                        if node[\"async\"]\n                        else \"FunctionDeclaration\"\n                    )\n                    functions.append(\n                        {\n                            \"name\": node.id.name,\n                            \"type\": node_type,\n                            \"body\": babel_generator(node).code,\n                            \"params\": list(node[\"params\"]),\n                        }\n                    )\n                # find the last async function\n                main_function = None\n                for function in reversed(functions):\n                    if function[\"type\"] == \"AsyncFunctionDeclaration\":\n                        main_function = function\n                        break\n                assert (\n                    main_function is not None\n                ), \"No async function found. Your main function must be async.\"\n                assert (\n                    len(main_function[\"params\"]) == 1\n                    and main_function[\"params\"][0].name == \"bot\"\n                ), f\"Main function {main_function['name']} must take a single argument named 'bot'\"\n                program_code = \"\\n\\n\".join(function[\"body\"] for function in functions)\n                exec_code = f\"await {main_function['name']}(bot);\"\n                return {\n                    \"program_code\": program_code,\n                    \"program_name\": main_function[\"name\"],\n                    \"exec_code\": exec_code,\n                }\n            except Exception as e:\n                retry -= 1\n                error = e\n                time.sleep(1)\n        return f\"Error parsing action response (before program execution): {error}\"\n\n    def summarize_chatlog(self, events):\n        def filter_item(message: str):\n            craft_pattern = r\"I cannot make \\w+ because I need: (.*)\"\n            craft_pattern2 = (\n                r\"I cannot make \\w+ because there is no crafting table nearby\"\n            )\n            mine_pattern = r\"I need at least a (.*) to mine \\w+!\"\n            if re.match(craft_pattern, message):\n                return re.match(craft_pattern, message).groups()[0]\n            elif re.match(craft_pattern2, message):\n                return \"a nearby crafting table\"\n            elif re.match(mine_pattern, message):\n                return re.match(mine_pattern, message).groups()[0]\n            else:\n                return \"\"\n\n        chatlog = set()\n        for event_type, event in events:\n            if event_type == \"onChat\":\n                item = filter_item(event[\"onChat\"])\n                if item:\n                    chatlog.add(item)\n        return \"I also need \" + \", \".join(chatlog) + \".\" if chatlog else \"\"\n"
  },
  {
    "path": "voyager/agents/critic.py",
    "content": "from voyager.prompts import load_prompt\nfrom voyager.utils.json_utils import fix_and_parse_json\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.schema import HumanMessage, SystemMessage\n\n\nclass CriticAgent:\n    def __init__(\n        self,\n        model_name=\"gpt-3.5-turbo\",\n        temperature=0,\n        request_timout=120,\n        mode=\"auto\",\n    ):\n        self.llm = ChatOpenAI(\n            model_name=model_name,\n            temperature=temperature,\n            request_timeout=request_timout,\n        )\n        assert mode in [\"auto\", \"manual\"]\n        self.mode = mode\n\n    def render_system_message(self):\n        system_message = SystemMessage(content=load_prompt(\"critic\"))\n        return system_message\n\n    def render_human_message(self, *, events, task, context, chest_observation):\n        assert events[-1][0] == \"observe\", \"Last event must be observe\"\n        biome = events[-1][1][\"status\"][\"biome\"]\n        time_of_day = events[-1][1][\"status\"][\"timeOfDay\"]\n        voxels = events[-1][1][\"voxels\"]\n        health = events[-1][1][\"status\"][\"health\"]\n        hunger = events[-1][1][\"status\"][\"food\"]\n        position = events[-1][1][\"status\"][\"position\"]\n        equipment = events[-1][1][\"status\"][\"equipment\"]\n        inventory_used = events[-1][1][\"status\"][\"inventoryUsed\"]\n        inventory = events[-1][1][\"inventory\"]\n\n        for i, (event_type, event) in enumerate(events):\n            if event_type == \"onError\":\n                print(f\"\\033[31mCritic Agent: Error occurs {event['onError']}\\033[0m\")\n                return None\n\n        observation = \"\"\n\n        observation += f\"Biome: {biome}\\n\\n\"\n\n        observation += f\"Time: {time_of_day}\\n\\n\"\n\n        if voxels:\n            observation += f\"Nearby blocks: {', '.join(voxels)}\\n\\n\"\n        else:\n            observation += f\"Nearby blocks: None\\n\\n\"\n\n        observation += f\"Health: {health:.1f}/20\\n\\n\"\n        observation += f\"Hunger: {hunger:.1f}/20\\n\\n\"\n\n        observation += f\"Position: x={position['x']:.1f}, y={position['y']:.1f}, z={position['z']:.1f}\\n\\n\"\n\n        observation += f\"Equipment: {equipment}\\n\\n\"\n\n        if inventory:\n            observation += f\"Inventory ({inventory_used}/36): {inventory}\\n\\n\"\n        else:\n            observation += f\"Inventory ({inventory_used}/36): Empty\\n\\n\"\n\n        observation += chest_observation\n\n        observation += f\"Task: {task}\\n\\n\"\n\n        if context:\n            observation += f\"Context: {context}\\n\\n\"\n        else:\n            observation += f\"Context: None\\n\\n\"\n\n        print(f\"\\033[31m****Critic Agent human message****\\n{observation}\\033[0m\")\n        return HumanMessage(content=observation)\n\n    def human_check_task_success(self):\n        confirmed = False\n        success = False\n        critique = \"\"\n        while not confirmed:\n            success = input(\"Success? (y/n)\")\n            success = success.lower() == \"y\"\n            critique = input(\"Enter your critique:\")\n            print(f\"Success: {success}\\nCritique: {critique}\")\n            confirmed = input(\"Confirm? (y/n)\") in [\"y\", \"\"]\n        return success, critique\n\n    def ai_check_task_success(self, messages, max_retries=5):\n        if max_retries == 0:\n            print(\n                \"\\033[31mFailed to parse Critic Agent response. Consider updating your prompt.\\033[0m\"\n            )\n            return False, \"\"\n\n        if messages[1] is None:\n            return False, \"\"\n\n        critic = self.llm(messages).content\n        print(f\"\\033[31m****Critic Agent ai message****\\n{critic}\\033[0m\")\n        try:\n            response = fix_and_parse_json(critic)\n            assert response[\"success\"] in [True, False]\n            if \"critique\" not in response:\n                response[\"critique\"] = \"\"\n            return response[\"success\"], response[\"critique\"]\n        except Exception as e:\n            print(f\"\\033[31mError parsing critic response: {e} Trying again!\\033[0m\")\n            return self.ai_check_task_success(\n                messages=messages,\n                max_retries=max_retries - 1,\n            )\n\n    def check_task_success(\n        self, *, events, task, context, chest_observation, max_retries=5\n    ):\n        human_message = self.render_human_message(\n            events=events,\n            task=task,\n            context=context,\n            chest_observation=chest_observation,\n        )\n\n        messages = [\n            self.render_system_message(),\n            human_message,\n        ]\n\n        if self.mode == \"manual\":\n            return self.human_check_task_success()\n        elif self.mode == \"auto\":\n            return self.ai_check_task_success(\n                messages=messages, max_retries=max_retries\n            )\n        else:\n            raise ValueError(f\"Invalid critic agent mode: {self.mode}\")\n"
  },
  {
    "path": "voyager/agents/curriculum.py",
    "content": "from __future__ import annotations\n\nimport random\nimport re\n\nimport voyager.utils as U\nfrom voyager.prompts import load_prompt\nfrom voyager.utils.json_utils import fix_and_parse_json\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.embeddings.openai import OpenAIEmbeddings\nfrom langchain.schema import HumanMessage, SystemMessage\nfrom langchain.vectorstores import Chroma\n\n\nclass CurriculumAgent:\n    def __init__(\n        self,\n        model_name=\"gpt-3.5-turbo\",\n        temperature=0,\n        qa_model_name=\"gpt-3.5-turbo\",\n        qa_temperature=0,\n        request_timout=120,\n        ckpt_dir=\"ckpt\",\n        resume=False,\n        mode=\"auto\",\n        warm_up=None,\n        core_inventory_items: str | None = None,\n    ):\n        self.llm = ChatOpenAI(\n            model_name=model_name,\n            temperature=temperature,\n            request_timeout=request_timout,\n        )\n        self.qa_llm = ChatOpenAI(\n            model_name=qa_model_name,\n            temperature=qa_temperature,\n            request_timeout=request_timout,\n        )\n        assert mode in [\n            \"auto\",\n            \"manual\",\n        ], f\"mode {mode} not supported\"\n        self.mode = mode\n        self.ckpt_dir = ckpt_dir\n        U.f_mkdir(f\"{ckpt_dir}/curriculum/vectordb\")\n        if resume:\n            print(f\"\\033[35mLoading Curriculum Agent from {ckpt_dir}/curriculum\\033[0m\")\n            self.completed_tasks = U.load_json(\n                f\"{ckpt_dir}/curriculum/completed_tasks.json\"\n            )\n            self.failed_tasks = U.load_json(f\"{ckpt_dir}/curriculum/failed_tasks.json\")\n            self.qa_cache = U.load_json(f\"{ckpt_dir}/curriculum/qa_cache.json\")\n        else:\n            self.completed_tasks = []\n            self.failed_tasks = []\n            self.qa_cache = {}\n        # vectordb for qa cache\n        self.qa_cache_questions_vectordb = Chroma(\n            collection_name=\"qa_cache_questions_vectordb\",\n            embedding_function=OpenAIEmbeddings(),\n            persist_directory=f\"{ckpt_dir}/curriculum/vectordb\",\n        )\n        assert self.qa_cache_questions_vectordb._collection.count() == len(\n            self.qa_cache\n        ), (\n            f\"Curriculum Agent's qa cache question vectordb is not synced with qa_cache.json.\\n\"\n            f\"There are {self.qa_cache_questions_vectordb._collection.count()} questions in vectordb \"\n            f\"but {len(self.qa_cache)} questions in qa_cache.json.\\n\"\n            f\"Did you set resume=False when initializing the agent?\\n\"\n            f\"You may need to manually delete the qa cache question vectordb directory for running from scratch.\\n\"\n        )\n        # if warm up not defined, initialize it as a dict, else, initialize all the missing value as a default value\n        if not warm_up:\n            warm_up = self.default_warmup\n        self.warm_up = {}\n        if \"optional_inventory_items\" in warm_up:\n            assert core_inventory_items is not None\n            self._core_inv_items_regex = re.compile(core_inventory_items)\n            self.warm_up[\"optional_inventory_items\"] = warm_up[\n                \"optional_inventory_items\"\n            ]\n        else:\n            self.warm_up[\"optional_inventory_items\"] = 0\n        for key in self.curriculum_observations:\n            self.warm_up[key] = warm_up.get(key, self.default_warmup[key])\n        self.warm_up[\"nearby_blocks\"] = 0\n        self.warm_up[\"inventory\"] = 0\n        self.warm_up[\"completed_tasks\"] = 0\n        self.warm_up[\"failed_tasks\"] = 0\n\n    @property\n    def default_warmup(self):\n        return {\n            \"context\": 15,\n            \"biome\": 10,\n            \"time\": 15,\n            \"nearby_blocks\": 0,\n            \"other_blocks\": 10,\n            \"nearby_entities\": 5,\n            \"health\": 15,\n            \"hunger\": 15,\n            \"position\": 0,\n            \"equipment\": 0,\n            \"inventory\": 0,\n            \"optional_inventory_items\": 7,\n            \"chests\": 0,\n            \"completed_tasks\": 0,\n            \"failed_tasks\": 0,\n        }\n\n    @property\n    def curriculum_observations(self):\n        return [\n            \"context\",\n            \"biome\",\n            \"time\",\n            \"nearby_blocks\",\n            \"other_blocks\",\n            \"nearby_entities\",\n            \"health\",\n            \"hunger\",\n            \"position\",\n            \"equipment\",\n            \"inventory\",\n            \"chests\",\n            \"completed_tasks\",\n            \"failed_tasks\",\n        ]\n\n    @property\n    def progress(self):\n        return len(self.completed_tasks)\n\n    def render_system_message(self):\n        system_message = SystemMessage(content=load_prompt(\"curriculum\"))\n        assert isinstance(system_message, SystemMessage)\n        return system_message\n\n    def render_observation(self, *, events, chest_observation):\n        assert events[-1][0] == \"observe\", \"Last event must be observe\"\n        event = events[-1][1]\n        biome = event[\"status\"][\"biome\"]\n        time_of_day = event[\"status\"][\"timeOfDay\"]\n        voxels = event[\"voxels\"]\n        block_records = event[\"blockRecords\"]\n        entities = event[\"status\"][\"entities\"]\n        health = event[\"status\"][\"health\"]\n        hunger = event[\"status\"][\"food\"]\n        position = event[\"status\"][\"position\"]\n        equipment = event[\"status\"][\"equipment\"]\n        inventory_used = event[\"status\"][\"inventoryUsed\"]\n        inventory = event[\"inventory\"]\n\n        if not any(\n            \"dirt\" in block\n            or \"log\" in block\n            or \"grass\" in block\n            or \"sand\" in block\n            or \"snow\" in block\n            for block in voxels\n        ):\n            biome = \"underground\"\n\n        other_blocks = \", \".join(\n            list(\n                set(block_records).difference(set(voxels).union(set(inventory.keys())))\n            )\n        )\n\n        other_blocks = other_blocks if other_blocks else \"None\"\n\n        nearby_entities = (\n            \", \".join([k for k, v in sorted(entities.items(), key=lambda x: x[1])])\n            if entities\n            else \"None\"\n        )\n\n        completed_tasks = (\n            \", \".join(self.completed_tasks) if self.completed_tasks else \"None\"\n        )\n        failed_tasks = \", \".join(self.failed_tasks) if self.failed_tasks else \"None\"\n\n        # filter out optional inventory items if required\n        if self.progress < self.warm_up[\"optional_inventory_items\"]:\n            inventory = {\n                k: v\n                for k, v in inventory.items()\n                if self._core_inv_items_regex.search(k) is not None\n            }\n\n        observation = {\n            \"context\": \"\",\n            \"biome\": f\"Biome: {biome}\\n\\n\",\n            \"time\": f\"Time: {time_of_day}\\n\\n\",\n            \"nearby_blocks\": f\"Nearby blocks: {', '.join(voxels) if voxels else 'None'}\\n\\n\",\n            \"other_blocks\": f\"Other blocks that are recently seen: {other_blocks}\\n\\n\",\n            \"nearby_entities\": f\"Nearby entities: {nearby_entities}\\n\\n\",\n            \"health\": f\"Health: {health:.1f}/20\\n\\n\",\n            \"hunger\": f\"Hunger: {hunger:.1f}/20\\n\\n\",\n            \"position\": f\"Position: x={position['x']:.1f}, y={position['y']:.1f}, z={position['z']:.1f}\\n\\n\",\n            \"equipment\": f\"Equipment: {equipment}\\n\\n\",\n            \"inventory\": f\"Inventory ({inventory_used}/36): {inventory if inventory else 'Empty'}\\n\\n\",\n            \"chests\": chest_observation,\n            \"completed_tasks\": f\"Completed tasks so far: {completed_tasks}\\n\\n\",\n            \"failed_tasks\": f\"Failed tasks that are too hard: {failed_tasks}\\n\\n\",\n        }\n        return observation\n\n    def render_human_message(self, *, events, chest_observation):\n        content = \"\"\n        observation = self.render_observation(\n            events=events, chest_observation=chest_observation\n        )\n        if self.progress >= self.warm_up[\"context\"]:\n            questions, answers = self.run_qa(\n                events=events, chest_observation=chest_observation\n            )\n            i = 1\n            for question, answer in zip(questions, answers):\n                if \"Answer: Unknown\" in answer or \"language model\" in answer:\n                    continue\n                observation[\"context\"] += f\"Question {i}: {question}\\n\"\n                observation[\"context\"] += f\"{answer}\\n\\n\"\n                i += 1\n                if i > 5:\n                    break\n\n        for key in self.curriculum_observations:\n            if self.progress >= self.warm_up[key]:\n                if self.warm_up[key] != 0:\n                    should_include = random.random() < 0.8\n                else:\n                    should_include = True\n                if should_include:\n                    content += observation[key]\n\n        print(f\"\\033[35m****Curriculum Agent human message****\\n{content}\\033[0m\")\n        return HumanMessage(content=content)\n\n    def propose_next_task(self, *, events, chest_observation, max_retries=5):\n        if self.progress == 0 and self.mode == \"auto\":\n            task = \"Mine 1 wood log\"\n            context = \"You can mine one of oak, birch, spruce, jungle, acacia, dark oak, or mangrove logs.\"\n            return task, context\n\n        # hard code task when inventory is almost full\n        inventoryUsed = events[-1][1][\"status\"][\"inventoryUsed\"]\n        if inventoryUsed >= 33:\n            if chest_observation != \"Chests: None\\n\\n\":\n                chests = chest_observation[8:-2].split(\"\\n\")\n                for chest in chests:\n                    content = chest.split(\":\")[1]\n                    if content == \" Unknown items inside\" or content == \" Empty\":\n                        position = chest.split(\":\")[0]\n                        task = f\"Deposit useless items into the chest at {position}\"\n                        context = (\n                            f\"Your inventory have {inventoryUsed} occupied slots before depositing. \"\n                            \"After depositing, your inventory should only have 20 occupied slots. \"\n                            \"You should deposit useless items such as andesite, dirt, cobblestone, etc. \"\n                            \"Also, you can deposit low-level tools, \"\n                            \"For example, if you have a stone pickaxe, you can deposit a wooden pickaxe. \"\n                            \"Make sure the list of useless items are in your inventory \"\n                            \"(do not list items already in the chest), \"\n                            \"You can use bot.inventoryUsed() to check how many inventory slots are used.\"\n                        )\n                        return task, context\n            if \"chest\" in events[-1][1][\"inventory\"]:\n                task = \"Place a chest\"\n                context = (\n                    f\"You have a chest in inventory, place it around you. \"\n                    f\"If chests is not None, or nearby blocks contains chest, this task is success.\"\n                )\n            else:\n                task = \"Craft 1 chest\"\n                context = \"Craft 1 chest with 8 planks of any kind of wood.\"\n            return task, context\n\n        messages = [\n            self.render_system_message(),\n            self.render_human_message(\n                events=events, chest_observation=chest_observation\n            ),\n        ]\n\n        if self.mode == \"auto\":\n            return self.propose_next_ai_task(messages=messages, max_retries=max_retries)\n        elif self.mode == \"manual\":\n            return self.propose_next_manual_task()\n        else:\n            raise ValueError(f\"Invalid curriculum agent mode: {self.mode}\")\n\n    def propose_next_ai_task(self, *, messages, max_retries=5):\n        if max_retries == 0:\n            raise RuntimeError(\"Max retries reached, failed to propose ai task.\")\n        curriculum = self.llm(messages).content\n        print(f\"\\033[31m****Curriculum Agent ai message****\\n{curriculum}\\033[0m\")\n        try:\n            response = self.parse_ai_message(curriculum)\n            assert \"next_task\" in response\n            context = self.get_task_context(response[\"next_task\"])\n            return response[\"next_task\"], context\n        except Exception as e:\n            print(\n                f\"\\033[35mError parsing curriculum response: {e}. Trying again!\\033[0m\"\n            )\n            return self.propose_next_ai_task(\n                messages=messages,\n                max_retries=max_retries - 1,\n            )\n\n    def parse_ai_message(self, message):\n        task = \"\"\n        for line in message.split(\"\\n\"):\n            if line.startswith(\"Task:\"):\n                task = line[5:].replace(\".\", \"\").strip()\n        assert task, \"Task not found in Curriculum Agent response\"\n        return {\"next_task\": task}\n\n    def propose_next_manual_task(self):\n        confirmed = False\n        task, context = \"\", \"\"\n        while not confirmed:\n            task = input(\"Enter task: \")\n            context = input(\"Enter context: \")\n            print(f\"Task: {task}\\nContext: {context}\")\n            confirmed = input(\"Confirm? (y/n)\").lower() in [\"y\", \"\"]\n        return task, context\n\n    def update_exploration_progress(self, info):\n        task = info[\"task\"]\n        if task.startswith(\"Deposit useless items into the chest at\"):\n            # No need to record the deposit task\n            return\n        if info[\"success\"]:\n            print(f\"\\033[35mCompleted task {task}.\\033[0m\")\n            self.completed_tasks.append(task)\n        else:\n            print(\n                f\"\\033[35mFailed to complete task {task}. Skipping to next task.\\033[0m\"\n            )\n            self.failed_tasks.append(task)\n\n        # clean up tasks and dump to disk\n        self.clean_up_tasks()\n\n    def clean_up_tasks(self):\n        updated_completed_tasks = []\n        # record repeated failed tasks\n        updated_failed_tasks = self.failed_tasks\n        # dedup but keep order\n        for task in self.completed_tasks:\n            if task not in updated_completed_tasks:\n                updated_completed_tasks.append(task)\n\n        # remove completed tasks from failed tasks\n        for task in updated_completed_tasks:\n            while task in updated_failed_tasks:\n                updated_failed_tasks.remove(task)\n\n        self.completed_tasks = updated_completed_tasks\n        self.failed_tasks = updated_failed_tasks\n\n        # dump to json\n        U.dump_json(\n            self.completed_tasks, f\"{self.ckpt_dir}/curriculum/completed_tasks.json\"\n        )\n        U.dump_json(self.failed_tasks, f\"{self.ckpt_dir}/curriculum/failed_tasks.json\")\n\n    def decompose_task(self, task, events):\n        messages = [\n            SystemMessage(\n                content=load_prompt(\"curriculum_task_decomposition\"),\n            ),\n            self.render_human_message(events=events, chest_observation=\"\"),\n            HumanMessage(content=f\"Final task: {task}\"),\n        ]\n        print(\n            f\"\\033[31m****Curriculum Agent task decomposition****\\nFinal task: {task}\\033[0m\"\n        )\n        response = self.llm(messages).content\n        print(f\"\\033[31m****Curriculum Agent task decomposition****\\n{response}\\033[0m\")\n        return fix_and_parse_json(response)\n\n    def run_qa(self, *, events, chest_observation):\n        questions_new, _ = self.run_qa_step1_ask_questions(\n            events=events, chest_observation=chest_observation\n        )\n        questions = []\n        answers = []\n        for question in questions_new:\n            if self.qa_cache_questions_vectordb._collection.count() > 0:\n                docs_and_scores = (\n                    self.qa_cache_questions_vectordb.similarity_search_with_score(\n                        question, k=1\n                    )\n                )\n                if docs_and_scores and docs_and_scores[0][1] < 0.05:\n                    question_cached = docs_and_scores[0][0].page_content\n                    assert question_cached in self.qa_cache\n                    answer_cached = self.qa_cache[question_cached]\n                    questions.append(question_cached)\n                    answers.append(answer_cached)\n                    continue\n            answer = self.run_qa_step2_answer_questions(question=question)\n            assert question not in self.qa_cache\n            self.qa_cache[question] = answer\n            self.qa_cache_questions_vectordb.add_texts(\n                texts=[question],\n            )\n            U.dump_json(self.qa_cache, f\"{self.ckpt_dir}/curriculum/qa_cache.json\")\n            self.qa_cache_questions_vectordb.persist()\n            questions.append(question)\n            answers.append(answer)\n        assert len(questions_new) == len(questions) == len(answers)\n        return questions, answers\n\n    def get_task_context(self, task):\n        # if include ore in question, gpt will try to use tool with skill touch enhancement to mine\n        question = (\n            f\"How to {task.replace('_', ' ').replace(' ore', '').replace(' ores', '').replace('.', '').strip().lower()}\"\n            f\" in Minecraft?\"\n        )\n        if question in self.qa_cache:\n            answer = self.qa_cache[question]\n        else:\n            answer = self.run_qa_step2_answer_questions(question=question)\n            self.qa_cache[question] = answer\n            self.qa_cache_questions_vectordb.add_texts(\n                texts=[question],\n            )\n            U.dump_json(self.qa_cache, f\"{self.ckpt_dir}/curriculum/qa_cache.json\")\n            self.qa_cache_questions_vectordb.persist()\n        context = f\"Question: {question}\\n{answer}\"\n        return context\n\n    def render_system_message_qa_step1_ask_questions(self):\n        return SystemMessage(content=load_prompt(\"curriculum_qa_step1_ask_questions\"))\n\n    def render_human_message_qa_step1_ask_questions(self, *, events, chest_observation):\n        observation = self.render_observation(\n            events=events, chest_observation=chest_observation\n        )\n        content = \"\"\n        for key in self.curriculum_observations:\n            content += observation[key]\n        return HumanMessage(content=content)\n\n    def run_qa_step1_ask_questions(self, *, events, chest_observation):\n        biome = events[-1][1][\"status\"][\"biome\"].replace(\"_\", \" \")\n        questions = [\n            f\"What are the blocks that I can find in the {biome} in Minecraft?\",\n            f\"What are the items that I can find in the {biome} in Minecraft?\",\n            f\"What are the mobs that I can find in the {biome} in Minecraft?\",\n        ]\n        concepts = [biome, biome, biome]\n        messages = [\n            self.render_system_message_qa_step1_ask_questions(),\n            self.render_human_message_qa_step1_ask_questions(\n                events=events, chest_observation=chest_observation\n            ),\n        ]\n        qa_response = self.qa_llm(messages).content\n        try:\n            # Regex pattern to extract question and concept pairs\n            pattern = r\"Question \\d+: (.+)\\nConcept \\d+: (.+)\"\n            # Extracting all question and concept pairs from the text\n            pairs = re.findall(pattern, qa_response)\n            # Storing each question and concept in separate lists\n            questions_new = [pair[0] for pair in pairs]\n            concepts_new = [pair[1] for pair in pairs]\n            assert len(questions_new) == len(concepts_new)\n            questions.extend(questions_new)\n            concepts.extend(concepts_new)\n        except Exception as e:\n            print(\n                f\"\\033[35mError parsing curriculum response for \"\n                f\"QA step 1 ask questions: {e}.\\033[0m\"\n            )\n        return questions, concepts\n\n    def render_system_message_qa_step2_answer_questions(self):\n        return SystemMessage(\n            content=load_prompt(\"curriculum_qa_step2_answer_questions\")\n        )\n\n    def render_human_message_qa_step2_answer_questions(self, question):\n        content = f\"Question: {question}\"\n        return HumanMessage(content=content)\n\n    def run_qa_step2_answer_questions(self, question):\n        messages = [\n            self.render_system_message_qa_step2_answer_questions(),\n            self.render_human_message_qa_step2_answer_questions(question=question),\n        ]\n        print(f\"\\033[35mCurriculum Agent Question: {question}\\033[0m\")\n        qa_answer = self.qa_llm(messages).content\n        print(f\"\\033[31mCurriculum Agent {qa_answer}\\033[0m\")\n        return qa_answer\n"
  },
  {
    "path": "voyager/agents/skill.py",
    "content": "import os\n\nimport voyager.utils as U\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.embeddings.openai import OpenAIEmbeddings\nfrom langchain.schema import HumanMessage, SystemMessage\nfrom langchain.vectorstores import Chroma\n\nfrom voyager.prompts import load_prompt\nfrom voyager.control_primitives import load_control_primitives\n\n\nclass SkillManager:\n    def __init__(\n        self,\n        model_name=\"gpt-3.5-turbo\",\n        temperature=0,\n        retrieval_top_k=5,\n        request_timout=120,\n        ckpt_dir=\"ckpt\",\n        resume=False,\n    ):\n        self.llm = ChatOpenAI(\n            model_name=model_name,\n            temperature=temperature,\n            request_timeout=request_timout,\n        )\n        U.f_mkdir(f\"{ckpt_dir}/skill/code\")\n        U.f_mkdir(f\"{ckpt_dir}/skill/description\")\n        U.f_mkdir(f\"{ckpt_dir}/skill/vectordb\")\n        # programs for env execution\n        self.control_primitives = load_control_primitives()\n        if resume:\n            print(f\"\\033[33mLoading Skill Manager from {ckpt_dir}/skill\\033[0m\")\n            self.skills = U.load_json(f\"{ckpt_dir}/skill/skills.json\")\n        else:\n            self.skills = {}\n        self.retrieval_top_k = retrieval_top_k\n        self.ckpt_dir = ckpt_dir\n        self.vectordb = Chroma(\n            collection_name=\"skill_vectordb\",\n            embedding_function=OpenAIEmbeddings(),\n            persist_directory=f\"{ckpt_dir}/skill/vectordb\",\n        )\n        assert self.vectordb._collection.count() == len(self.skills), (\n            f\"Skill Manager's vectordb is not synced with skills.json.\\n\"\n            f\"There are {self.vectordb._collection.count()} skills in vectordb but {len(self.skills)} skills in skills.json.\\n\"\n            f\"Did you set resume=False when initializing the manager?\\n\"\n            f\"You may need to manually delete the vectordb directory for running from scratch.\"\n        )\n\n    @property\n    def programs(self):\n        programs = \"\"\n        for skill_name, entry in self.skills.items():\n            programs += f\"{entry['code']}\\n\\n\"\n        for primitives in self.control_primitives:\n            programs += f\"{primitives}\\n\\n\"\n        return programs\n\n    def add_new_skill(self, info):\n        if info[\"task\"].startswith(\"Deposit useless items into the chest at\"):\n            # No need to reuse the deposit skill\n            return\n        program_name = info[\"program_name\"]\n        program_code = info[\"program_code\"]\n        skill_description = self.generate_skill_description(program_name, program_code)\n        print(\n            f\"\\033[33mSkill Manager generated description for {program_name}:\\n{skill_description}\\033[0m\"\n        )\n        if program_name in self.skills:\n            print(f\"\\033[33mSkill {program_name} already exists. Rewriting!\\033[0m\")\n            self.vectordb._collection.delete(ids=[program_name])\n            i = 2\n            while f\"{program_name}V{i}.js\" in os.listdir(f\"{self.ckpt_dir}/skill/code\"):\n                i += 1\n            dumped_program_name = f\"{program_name}V{i}\"\n        else:\n            dumped_program_name = program_name\n        self.vectordb.add_texts(\n            texts=[skill_description],\n            ids=[program_name],\n            metadatas=[{\"name\": program_name}],\n        )\n        self.skills[program_name] = {\n            \"code\": program_code,\n            \"description\": skill_description,\n        }\n        assert self.vectordb._collection.count() == len(\n            self.skills\n        ), \"vectordb is not synced with skills.json\"\n        U.dump_text(\n            program_code, f\"{self.ckpt_dir}/skill/code/{dumped_program_name}.js\"\n        )\n        U.dump_text(\n            skill_description,\n            f\"{self.ckpt_dir}/skill/description/{dumped_program_name}.txt\",\n        )\n        U.dump_json(self.skills, f\"{self.ckpt_dir}/skill/skills.json\")\n        self.vectordb.persist()\n\n    def generate_skill_description(self, program_name, program_code):\n        messages = [\n            SystemMessage(content=load_prompt(\"skill\")),\n            HumanMessage(\n                content=program_code\n                + \"\\n\\n\"\n                + f\"The main function is `{program_name}`.\"\n            ),\n        ]\n        skill_description = f\"    // { self.llm(messages).content}\"\n        return f\"async function {program_name}(bot) {{\\n{skill_description}\\n}}\"\n\n    def retrieve_skills(self, query):\n        k = min(self.vectordb._collection.count(), self.retrieval_top_k)\n        if k == 0:\n            return []\n        print(f\"\\033[33mSkill Manager retrieving for {k} skills\\033[0m\")\n        docs_and_scores = self.vectordb.similarity_search_with_score(query, k=k)\n        print(\n            f\"\\033[33mSkill Manager retrieved skills: \"\n            f\"{', '.join([doc.metadata['name'] for doc, _ in docs_and_scores])}\\033[0m\"\n        )\n        skills = []\n        for doc, _ in docs_and_scores:\n            skills.append(self.skills[doc.metadata[\"name\"]][\"code\"])\n        return skills\n"
  },
  {
    "path": "voyager/control_primitives/.prettierrc.json",
    "content": "{\n    \"tabWidth\": 4\n}\n"
  },
  {
    "path": "voyager/control_primitives/__init__.py",
    "content": "import pkg_resources\nimport os\nimport voyager.utils as U\n\n\ndef load_control_primitives(primitive_names=None):\n    package_path = pkg_resources.resource_filename(\"voyager\", \"\")\n    if primitive_names is None:\n        primitive_names = [\n            primitives[:-3]\n            for primitives in os.listdir(f\"{package_path}/control_primitives\")\n            if primitives.endswith(\".js\")\n        ]\n    primitives = [\n        U.load_text(f\"{package_path}/control_primitives/{primitive_name}.js\")\n        for primitive_name in primitive_names\n    ]\n    return primitives\n"
  },
  {
    "path": "voyager/control_primitives/craftHelper.js",
    "content": "function failedCraftFeedback(bot, name, item, craftingTable) {\n    const recipes = bot.recipesAll(item.id, null, craftingTable);\n    if (!recipes.length) {\n        throw new Error(`No crafting table nearby`);\n    } else {\n        const recipes = bot.recipesAll(\n            item.id,\n            null,\n            mcData.blocksByName.crafting_table.id\n        );\n        // find the recipe with the fewest missing ingredients\n        var min = 999;\n        var min_recipe = null;\n        for (const recipe of recipes) {\n            const delta = recipe.delta;\n            var missing = 0;\n            for (const delta_item of delta) {\n                if (delta_item.count < 0) {\n                    const inventory_item = bot.inventory.findInventoryItem(\n                        mcData.items[delta_item.id].name,\n                        null\n                    );\n                    if (!inventory_item) {\n                        missing += -delta_item.count;\n                    } else {\n                        missing += Math.max(\n                            -delta_item.count - inventory_item.count,\n                            0\n                        );\n                    }\n                }\n            }\n            if (missing < min) {\n                min = missing;\n                min_recipe = recipe;\n            }\n        }\n        const delta = min_recipe.delta;\n        let message = \"\";\n        for (const delta_item of delta) {\n            if (delta_item.count < 0) {\n                const inventory_item = bot.inventory.findInventoryItem(\n                    mcData.items[delta_item.id].name,\n                    null\n                );\n                if (!inventory_item) {\n                    message += ` ${-delta_item.count} more ${\n                        mcData.items[delta_item.id].name\n                    }, `;\n                } else {\n                    if (inventory_item.count < -delta_item.count) {\n                        message += `${\n                            -delta_item.count - inventory_item.count\n                        } more ${mcData.items[delta_item.id].name}`;\n                    }\n                }\n            }\n        }\n        bot.chat(`I cannot make ${name} because I need: ${message}`);\n    }\n}\n"
  },
  {
    "path": "voyager/control_primitives/craftItem.js",
    "content": "async function craftItem(bot, name, count = 1) {\n    // return if name is not string\n    if (typeof name !== \"string\") {\n        throw new Error(\"name for craftItem must be a string\");\n    }\n    // return if count is not number\n    if (typeof count !== \"number\") {\n        throw new Error(\"count for craftItem must be a number\");\n    }\n    const itemByName = mcData.itemsByName[name];\n    if (!itemByName) {\n        throw new Error(`No item named ${name}`);\n    }\n    const craftingTable = bot.findBlock({\n        matching: mcData.blocksByName.crafting_table.id,\n        maxDistance: 32,\n    });\n    if (!craftingTable) {\n        bot.chat(\"Craft without a crafting table\");\n    } else {\n        await bot.pathfinder.goto(\n            new GoalLookAtBlock(craftingTable.position, bot.world)\n        );\n    }\n    const recipe = bot.recipesFor(itemByName.id, null, 1, craftingTable)[0];\n    if (recipe) {\n        bot.chat(`I can make ${name}`);\n        try {\n            await bot.craft(recipe, count, craftingTable);\n            bot.chat(`I did the recipe for ${name} ${count} times`);\n        } catch (err) {\n            bot.chat(`I cannot do the recipe for ${name} ${count} times`);\n        }\n    } else {\n        failedCraftFeedback(bot, name, itemByName, craftingTable);\n        _craftItemFailCount++;\n        if (_craftItemFailCount > 10) {\n            throw new Error(\n                \"craftItem failed too many times, check chat log to see what happened\"\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "voyager/control_primitives/exploreUntil.js",
    "content": "// Explore downward for 60 seconds: exploreUntil(bot, new Vec3(0, -1, 0), 60);\nasync function exploreUntil(\n    bot,\n    direction,\n    maxTime = 60,\n    callback = () => {\n        return false;\n    }\n) {\n    if (typeof maxTime !== \"number\") {\n        throw new Error(\"maxTime must be a number\");\n    }\n    if (typeof callback !== \"function\") {\n        throw new Error(\"callback must be a function\");\n    }\n    const test = callback();\n    if (test) {\n        bot.chat(\"Explore success.\");\n        return Promise.resolve(test);\n    }\n    if (direction.x === 0 && direction.y === 0 && direction.z === 0) {\n        throw new Error(\"direction cannot be 0, 0, 0\");\n    }\n    if (\n        !(\n            (direction.x === 0 || direction.x === 1 || direction.x === -1) &&\n            (direction.y === 0 || direction.y === 1 || direction.y === -1) &&\n            (direction.z === 0 || direction.z === 1 || direction.z === -1)\n        )\n    ) {\n        throw new Error(\n            \"direction must be a Vec3 only with value of -1, 0 or 1\"\n        );\n    }\n    maxTime = Math.min(maxTime, 1200);\n    return new Promise((resolve, reject) => {\n        const dx = direction.x;\n        const dy = direction.y;\n        const dz = direction.z;\n\n        let explorationInterval;\n        let maxTimeTimeout;\n\n        const cleanUp = () => {\n            clearInterval(explorationInterval);\n            clearTimeout(maxTimeTimeout);\n            bot.pathfinder.setGoal(null);\n        };\n\n        const explore = () => {\n            const x =\n                bot.entity.position.x +\n                Math.floor(Math.random() * 20 + 10) * dx;\n            const y =\n                bot.entity.position.y +\n                Math.floor(Math.random() * 20 + 10) * dy;\n            const z =\n                bot.entity.position.z +\n                Math.floor(Math.random() * 20 + 10) * dz;\n            let goal = new GoalNear(x, y, z);\n            if (dy === 0) {\n                goal = new GoalNearXZ(x, z);\n            }\n            bot.pathfinder.setGoal(goal);\n\n            try {\n                const result = callback();\n                if (result) {\n                    cleanUp();\n                    bot.chat(\"Explore success.\");\n                    resolve(result);\n                }\n            } catch (err) {\n                cleanUp();\n                reject(err);\n            }\n        };\n\n        explorationInterval = setInterval(explore, 2000);\n\n        maxTimeTimeout = setTimeout(() => {\n            cleanUp();\n            bot.chat(\"Max exploration time reached\");\n            resolve(null);\n        }, maxTime * 1000);\n    });\n}\n"
  },
  {
    "path": "voyager/control_primitives/givePlacedItemBack.js",
    "content": "async function givePlacedItemBack(bot, name, position) {\n    await bot.chat(\"/gamerule doTileDrops false\");\n    // iterate name and position\n    const history = [];\n    for (let i = 0; i < name.length; i++) {\n        await givePlacedItemBackSingle(bot, name[i], position[i]);\n    }\n    await bot.chat(\"/gamerule doTileDrops true\");\n\n    async function givePlacedItemBackSingle(bot, name, position) {\n        bot.chat(`/give bot ${name} 1`);\n        const x = Math.floor(position.x);\n        const y = Math.floor(position.y);\n        const z = Math.floor(position.z);\n        // loop through 125 blocks around the block\n        const size = 3;\n        for (let dx = -size; dx <= size; dx++) {\n            for (let dy = -size; dy <= size; dy++) {\n                for (let dz = -size; dz <= size; dz++) {\n                    const block = bot.blockAt(new Vec3(x + dx, y + dy, z + dz));\n                    if (\n                        block?.name === name &&\n                        !history.includes(block.position)\n                    ) {\n                        await bot.chat(\n                            `/setblock ${x + dx} ${y + dy} ${\n                                z + dz\n                            } air destroy`\n                        );\n                        history.push(block.position);\n                        await bot.waitForTicks(20);\n                        return;\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "voyager/control_primitives/killMob.js",
    "content": "async function killMob(bot, mobName, timeout = 300) {\n    // return if mobName is not string\n    if (typeof mobName !== \"string\") {\n        throw new Error(`mobName for killMob must be a string`);\n    }\n    // return if timeout is not number\n    if (typeof timeout !== \"number\") {\n        throw new Error(`timeout for killMob must be a number`);\n    }\n\n    const weaponsForShooting = [\n        \"bow\",\n        \"crossbow\",\n        \"snowball\",\n        \"ender_pearl\",\n        \"egg\",\n        \"splash_potion\",\n        \"trident\",\n    ];\n    const mainHandItem = bot.inventory.slots[bot.getEquipmentDestSlot(\"hand\")];\n\n    const entity = bot.nearestEntity(\n        (entity) =>\n            entity.name === mobName &&\n            // kill mob distance should be slightly bigger than explore distance\n            entity.position.distanceTo(bot.entity.position) < 48\n    );\n    if (!entity) {\n        bot.chat(`No ${mobName} nearby, please explore first`);\n        _killMobFailCount++;\n        if (_killMobFailCount > 10) {\n            throw new Error(\n                `killMob failed too many times, make sure you explore before calling killMob`\n            );\n        }\n        return;\n    }\n\n    let droppedItem;\n    if (mainHandItem && weaponsForShooting.includes(mainHandItem.name)) {\n        bot.hawkEye.autoAttack(entity, mainHandItem.name);\n        droppedItem = await waitForMobShot(bot, entity, timeout);\n    } else {\n        await bot.pvp.attack(entity);\n        droppedItem = await waitForMobRemoved(bot, entity, timeout);\n    }\n    if (droppedItem) {\n        await bot.collectBlock.collect(droppedItem, { ignoreNoPath: true });\n    }\n    bot.save(`${mobName}_killed`);\n}\n"
  },
  {
    "path": "voyager/control_primitives/mineBlock.js",
    "content": "async function mineBlock(bot, name, count = 1) {\n    // return if name is not string\n    if (typeof name !== \"string\") {\n        throw new Error(`name for mineBlock must be a string`);\n    }\n    if (typeof count !== \"number\") {\n        throw new Error(`count for mineBlock must be a number`);\n    }\n    const blockByName = mcData.blocksByName[name];\n    if (!blockByName) {\n        throw new Error(`No block named ${name}`);\n    }\n    const blocks = bot.findBlocks({\n        matching: [blockByName.id],\n        maxDistance: 32,\n        count: 1024,\n    });\n    if (blocks.length === 0) {\n        bot.chat(`No ${name} nearby, please explore first`);\n        _mineBlockFailCount++;\n        if (_mineBlockFailCount > 10) {\n            throw new Error(\n                \"mineBlock failed too many times, make sure you explore before calling mineBlock\"\n            );\n        }\n        return;\n    }\n    const targets = [];\n    for (let i = 0; i < blocks.length; i++) {\n        targets.push(bot.blockAt(blocks[i]));\n    }\n    await bot.collectBlock.collect(targets, {\n        ignoreNoPath: true,\n        count: count,\n    });\n    bot.save(`${name}_mined`);\n}\n"
  },
  {
    "path": "voyager/control_primitives/placeItem.js",
    "content": "async function placeItem(bot, name, position) {\n    // return if name is not string\n    if (typeof name !== \"string\") {\n        throw new Error(`name for placeItem must be a string`);\n    }\n    // return if position is not Vec3\n    if (!(position instanceof Vec3)) {\n        throw new Error(`position for placeItem must be a Vec3`);\n    }\n    const itemByName = mcData.itemsByName[name];\n    if (!itemByName) {\n        throw new Error(`No item named ${name}`);\n    }\n    const item = bot.inventory.findInventoryItem(itemByName.id);\n    if (!item) {\n        bot.chat(`No ${name} in inventory`);\n        return;\n    }\n    const item_count = item.count;\n    // find a reference block\n    const faceVectors = [\n        new Vec3(0, 1, 0),\n        new Vec3(0, -1, 0),\n        new Vec3(1, 0, 0),\n        new Vec3(-1, 0, 0),\n        new Vec3(0, 0, 1),\n        new Vec3(0, 0, -1),\n    ];\n    let referenceBlock = null;\n    let faceVector = null;\n    for (const vector of faceVectors) {\n        const block = bot.blockAt(position.minus(vector));\n        if (block?.name !== \"air\") {\n            referenceBlock = block;\n            faceVector = vector;\n            bot.chat(`Placing ${name} on ${block.name} at ${block.position}`);\n            break;\n        }\n    }\n    if (!referenceBlock) {\n        bot.chat(\n            `No block to place ${name} on. You cannot place a floating block.`\n        );\n        _placeItemFailCount++;\n        if (_placeItemFailCount > 10) {\n            throw new Error(\n                `placeItem failed too many times. You cannot place a floating block.`\n            );\n        }\n        return;\n    }\n\n    // You must use try catch to placeBlock\n    try {\n        // You must first go to the block position you want to place\n        await bot.pathfinder.goto(new GoalPlaceBlock(position, bot.world, {}));\n        // You must equip the item right before calling placeBlock\n        await bot.equip(item, \"hand\");\n        await bot.placeBlock(referenceBlock, faceVector);\n        bot.chat(`Placed ${name}`);\n        bot.save(`${name}_placed`);\n    } catch (err) {\n        const item = bot.inventory.findInventoryItem(itemByName.id);\n        if (item?.count === item_count) {\n            bot.chat(\n                `Error placing ${name}: ${err.message}, please find another position to place`\n            );\n            _placeItemFailCount++;\n            if (_placeItemFailCount > 10) {\n                throw new Error(\n                    `placeItem failed too many times, please find another position to place.`\n                );\n            }\n        } else {\n            bot.chat(`Placed ${name}`);\n            bot.save(`${name}_placed`);\n        }\n    }\n}\n"
  },
  {
    "path": "voyager/control_primitives/shoot.js",
    "content": "// shoot 1 pig with a bow: shoot(bot, \"bow\", \"pig\");\nasync function shoot(bot, weapon, target) {\n    const validWeapons = [\n        \"bow\",\n        \"crossbow\",\n        \"snowball\",\n        \"ender_pearl\",\n        \"egg\",\n        \"splash_potion\",\n        \"trident\",\n    ];\n    if (!validWeapons.includes(weapon)) {\n        bot.chat(`${weapon} is not a valid weapon for shooting`);\n        return;\n    }\n\n    const weaponItem = mcData.itemsByName[weapon];\n    if (!bot.inventory.findInventoryItem(weaponItem.id, null)) {\n        bot.chat(`No ${weapon} in inventory for shooting`);\n        return;\n    }\n\n    const targetEntity = bot.nearestEntity(\n        (entity) =>\n            entity.name === target\n    );\n    if (!targetEntity) {\n        bot.chat(`No ${target} nearby`);\n        return;\n    }\n    bot.hawkEye.autoAttack(targetEntity, \"bow\");\n    bot.on('auto_shot_stopped', (target) => {\n    })\n}\n"
  },
  {
    "path": "voyager/control_primitives/smeltItem.js",
    "content": "async function smeltItem(bot, itemName, fuelName, count = 1) {\n    // return if itemName or fuelName is not string\n    if (typeof itemName !== \"string\" || typeof fuelName !== \"string\") {\n        throw new Error(\"itemName or fuelName for smeltItem must be a string\");\n    }\n    // return if count is not a number\n    if (typeof count !== \"number\") {\n        throw new Error(\"count for smeltItem must be a number\");\n    }\n    const item = mcData.itemsByName[itemName];\n    const fuel = mcData.itemsByName[fuelName];\n    if (!item) {\n        throw new Error(`No item named ${itemName}`);\n    }\n    if (!fuel) {\n        throw new Error(`No item named ${fuelName}`);\n    }\n    const furnaceBlock = bot.findBlock({\n        matching: mcData.blocksByName.furnace.id,\n        maxDistance: 32,\n    });\n    if (!furnaceBlock) {\n        throw new Error(\"No furnace nearby\");\n    } else {\n        await bot.pathfinder.goto(\n            new GoalLookAtBlock(furnaceBlock.position, bot.world)\n        );\n    }\n    const furnace = await bot.openFurnace(furnaceBlock);\n    let success_count = 0;\n    for (let i = 0; i < count; i++) {\n        if (!bot.inventory.findInventoryItem(item.id, null)) {\n            bot.chat(`No ${itemName} to smelt in inventory`);\n            break;\n        }\n        if (furnace.fuelSeconds < 15 && furnace.fuelItem()?.name !== fuelName) {\n            if (!bot.inventory.findInventoryItem(fuel.id, null)) {\n                bot.chat(`No ${fuelName} as fuel in inventory`);\n                break;\n            }\n            await furnace.putFuel(fuel.id, null, 1);\n            await bot.waitForTicks(20);\n            if (!furnace.fuel && furnace.fuelItem()?.name !== fuelName) {\n                throw new Error(`${fuelName} is not a valid fuel`);\n            }\n        }\n        await furnace.putInput(item.id, null, 1);\n        await bot.waitForTicks(12 * 20);\n        if (!furnace.outputItem()) {\n            throw new Error(`${itemName} is not a valid input`);\n        }\n        await furnace.takeOutput();\n        success_count++;\n    }\n    furnace.close();\n    if (success_count > 0) bot.chat(`Smelted ${success_count} ${itemName}.`);\n    else {\n        bot.chat(\n            `Failed to smelt ${itemName}, please check the fuel and input.`\n        );\n        _smeltItemFailCount++;\n        if (_smeltItemFailCount > 10) {\n            throw new Error(\n                `smeltItem failed too many times, please check the fuel and input.`\n            );\n        }\n    }\n}\n"
  },
  {
    "path": "voyager/control_primitives/useChest.js",
    "content": "async function getItemFromChest(bot, chestPosition, itemsToGet) {\n    // return if chestPosition is not Vec3\n    if (!(chestPosition instanceof Vec3)) {\n        bot.chat(\"chestPosition for getItemFromChest must be a Vec3\");\n        return;\n    }\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    const chest = await bot.openContainer(chestBlock);\n    for (const name in itemsToGet) {\n        const itemByName = mcData.itemsByName[name];\n        if (!itemByName) {\n            bot.chat(`No item named ${name}`);\n            continue;\n        }\n\n        const item = chest.findContainerItem(itemByName.id);\n        if (!item) {\n            bot.chat(`I don't see ${name} in this chest`);\n            continue;\n        }\n        try {\n            await chest.withdraw(item.type, null, itemsToGet[name]);\n        } catch (err) {\n            bot.chat(`Not enough ${name} in chest.`);\n        }\n    }\n    await closeChest(bot, chestBlock);\n}\n\nasync function depositItemIntoChest(bot, chestPosition, itemsToDeposit) {\n    // return if chestPosition is not Vec3\n    if (!(chestPosition instanceof Vec3)) {\n        throw new Error(\n            \"chestPosition for depositItemIntoChest must be a Vec3\"\n        );\n    }\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    const chest = await bot.openContainer(chestBlock);\n    for (const name in itemsToDeposit) {\n        const itemByName = mcData.itemsByName[name];\n        if (!itemByName) {\n            bot.chat(`No item named ${name}`);\n            continue;\n        }\n        const item = bot.inventory.findInventoryItem(itemByName.id);\n        if (!item) {\n            bot.chat(`No ${name} in inventory`);\n            continue;\n        }\n        try {\n            await chest.deposit(item.type, null, itemsToDeposit[name]);\n        } catch (err) {\n            bot.chat(`Not enough ${name} in inventory.`);\n        }\n    }\n    await closeChest(bot, chestBlock);\n}\n\nasync function checkItemInsideChest(bot, chestPosition) {\n    // return if chestPosition is not Vec3\n    if (!(chestPosition instanceof Vec3)) {\n        throw new Error(\n            \"chestPosition for depositItemIntoChest must be a Vec3\"\n        );\n    }\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    await bot.openContainer(chestBlock);\n    await closeChest(bot, chestBlock);\n}\n\nasync function moveToChest(bot, chestPosition) {\n    if (!(chestPosition instanceof Vec3)) {\n        throw new Error(\n            \"chestPosition for depositItemIntoChest must be a Vec3\"\n        );\n    }\n    if (chestPosition.distanceTo(bot.entity.position) > 32) {\n        bot.chat(\n            `/tp ${chestPosition.x} ${chestPosition.y} ${chestPosition.z}`\n        );\n        await bot.waitForTicks(20);\n    }\n    const chestBlock = bot.blockAt(chestPosition);\n    if (chestBlock.name !== \"chest\") {\n        bot.emit(\"removeChest\", chestPosition);\n        throw new Error(\n            `No chest at ${chestPosition}, it is ${chestBlock.name}`\n        );\n    }\n    await bot.pathfinder.goto(\n        new GoalLookAtBlock(chestBlock.position, bot.world, {})\n    );\n    return chestBlock;\n}\n\nasync function listItemsInChest(bot, chestBlock) {\n    const chest = await bot.openContainer(chestBlock);\n    const items = chest.containerItems();\n    if (items.length > 0) {\n        const itemNames = items.reduce((acc, obj) => {\n            if (acc[obj.name]) {\n                acc[obj.name] += obj.count;\n            } else {\n                acc[obj.name] = obj.count;\n            }\n            return acc;\n        }, {});\n        bot.emit(\"closeChest\", itemNames, chestBlock.position);\n    } else {\n        bot.emit(\"closeChest\", {}, chestBlock.position);\n    }\n    return chest;\n}\n\nasync function closeChest(bot, chestBlock) {\n    try {\n        const chest = await listItemsInChest(bot, chestBlock);\n        await chest.close();\n    } catch (err) {\n        await bot.closeWindow(chestBlock);\n    }\n}\n\nfunction itemByName(items, name) {\n    for (let i = 0; i < items.length; ++i) {\n        const item = items[i];\n        if (item && item.name === name) return item;\n    }\n    return null;\n}\n"
  },
  {
    "path": "voyager/control_primitives/waitForMobRemoved.js",
    "content": "function waitForMobRemoved(bot, entity, timeout = 300) {\n    return new Promise((resolve, reject) => {\n        let success = false;\n        let droppedItem = null;\n        // Set up timeout\n        const timeoutId = setTimeout(() => {\n            success = false;\n            bot.pvp.stop();\n        }, timeout * 1000);\n\n        // Function to handle entityRemoved event\n        function onEntityGone(e) {\n            if (e === entity) {\n                success = true;\n                clearTimeout(timeoutId);\n                bot.chat(`Killed ${entity.name}!`);\n                bot.pvp.stop();\n            }\n        }\n\n        function onItemDrop(item) {\n            if (entity.position.distanceTo(item.position) <= 1) {\n                droppedItem = item;\n            }\n        }\n\n        function onStoppedAttacking() {\n            clearTimeout(timeoutId);\n            bot.removeListener(\"entityGone\", onEntityGone);\n            bot.removeListener(\"stoppedAttacking\", onStoppedAttacking);\n            bot.removeListener(\"itemDrop\", onItemDrop);\n            if (!success) reject(new Error(`Failed to kill ${entity.name}.`));\n            else resolve(droppedItem);\n        }\n\n        // Listen for entityRemoved event\n        bot.on(\"entityGone\", onEntityGone);\n        bot.on(\"stoppedAttacking\", onStoppedAttacking);\n        bot.on(\"itemDrop\", onItemDrop);\n    });\n}\n\n\nfunction waitForMobShot(bot, entity, timeout = 300) {\n    return new Promise((resolve, reject) => {\n        let success = false;\n        let droppedItem = null;\n        // Set up timeout\n        const timeoutId = setTimeout(() => {\n            success = false;\n            bot.hawkEye.stop();\n        }, timeout * 1000);\n\n        // Function to handle entityRemoved event\n        function onEntityGone(e) {\n            if (e === entity) {\n                success = true;\n                clearTimeout(timeoutId);\n                bot.chat(`Shot ${entity.name}!`);\n                bot.hawkEye.stop();\n            }\n        }\n\n        function onItemDrop(item) {\n            if (entity.position.distanceTo(item.position) <= 1) {\n                droppedItem = item;\n            }\n        }\n\n        function onAutoShotStopped() {\n            clearTimeout(timeoutId);\n            bot.removeListener(\"entityGone\", onEntityGone);\n            bot.removeListener(\"auto_shot_stopped\", onAutoShotStopped);\n            bot.removeListener(\"itemDrop\", onItemDrop);\n            if (!success) reject(new Error(`Failed to shoot ${entity.name}.`));\n            else resolve(droppedItem);\n        }\n\n        // Listen for entityRemoved event\n        bot.on(\"entityGone\", onEntityGone);\n        bot.on(\"auto_shot_stopped\", onAutoShotStopped);\n        bot.on(\"itemDrop\", onItemDrop);\n    });\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/.prettierrc.json",
    "content": "{\n    \"tabWidth\": 4\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/__init__.py",
    "content": "import pkg_resources\nimport os\nimport voyager.utils as U\n\n\ndef load_control_primitives_context(primitive_names=None):\n    package_path = pkg_resources.resource_filename(\"voyager\", \"\")\n    if primitive_names is None:\n        primitive_names = [\n            primitive[:-3]\n            for primitive in os.listdir(f\"{package_path}/control_primitives_context\")\n            if primitive.endswith(\".js\")\n        ]\n    primitives = [\n        U.load_text(f\"{package_path}/control_primitives_context/{primitive_name}.js\")\n        for primitive_name in primitive_names\n    ]\n    return primitives\n"
  },
  {
    "path": "voyager/control_primitives_context/craftItem.js",
    "content": "// Craft 8 oak_planks from 2 oak_log (do the recipe 2 times): craftItem(bot, \"oak_planks\", 2);\n// You must place a crafting table before calling this function\nasync function craftItem(bot, name, count = 1) {\n    const item = mcData.itemsByName[name];\n    const craftingTable = bot.findBlock({\n        matching: mcData.blocksByName.crafting_table.id,\n        maxDistance: 32,\n    });\n    await bot.pathfinder.goto(\n        new GoalLookAtBlock(craftingTable.position, bot.world)\n    );\n    const recipe = bot.recipesFor(item.id, null, 1, craftingTable)[0];\n    await bot.craft(recipe, count, craftingTable);\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/exploreUntil.js",
    "content": "/*\nExplore until find an iron_ore, use Vec3(0, -1, 0) because iron ores are usually underground\nawait exploreUntil(bot, new Vec3(0, -1, 0), 60, () => {\n    const iron_ore = bot.findBlock({\n        matching: mcData.blocksByName[\"iron_ore\"].id,\n        maxDistance: 32,\n    });\n    return iron_ore;\n});\n\nExplore until find a pig, use Vec3(1, 0, 1) because pigs are usually on the surface\nlet pig = await exploreUntil(bot, new Vec3(1, 0, 1), 60, () => {\n    const pig = bot.nearestEntity((entity) => {\n        return (\n            entity.name === \"pig\" &&\n            entity.position.distanceTo(bot.entity.position) < 32\n        );\n    });\n    return pig;\n});\n*/\nasync function exploreUntil(bot, direction, maxTime = 60, callback) {\n    /*\n    Implementation of this function is omitted.\n    direction: Vec3, can only contain value of -1, 0 or 1\n    maxTime: number, the max time for exploration\n    callback: function, early stop condition, will be called each second, exploration will stop if return value is not null\n\n    Return: null if explore timeout, otherwise return the return value of callback\n    */\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/killMob.js",
    "content": "// Kill a pig and collect the dropped item: killMob(bot, \"pig\", 300);\nasync function killMob(bot, mobName, timeout = 300) {\n    const entity = bot.nearestEntity(\n        (entity) =>\n            entity.name === mobName &&\n            entity.position.distanceTo(bot.entity.position) < 32\n    );\n    await bot.pvp.attack(entity);\n    await bot.pathfinder.goto(\n        new GoalBlock(entity.position.x, entity.position.y, entity.position.z)\n    );\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/mineBlock.js",
    "content": "// Mine 3 cobblestone: mineBlock(bot, \"stone\", 3);\nasync function mineBlock(bot, name, count = 1) {\n    const blocks = bot.findBlocks({\n        matching: (block) => {\n            return block.name === name;\n        },\n        maxDistance: 32,\n        count: count,\n    });\n    const targets = [];\n    for (let i = 0; i < Math.min(blocks.length, count); i++) {\n        targets.push(bot.blockAt(blocks[i]));\n    }\n    await bot.collectBlock.collect(targets, { ignoreNoPath: true });\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/mineflayer.js",
    "content": "await bot.pathfinder.goto(goal); // A very useful function. This function may change your main-hand equipment.\n// Following are some Goals you can use:\nnew 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`\nnew GoalXZ(x, z); // Useful for long-range goals that don't have a specific Y level. `x` and `z` are `number`\nnew 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`\nnew GoalFollow(entity, range); // Follow the specified entity within the specified range. `entity` is `Entity`, `range` is `number`\nnew GoalPlaceBlock(position, bot.world, {}); // Position the bot in order to place a block. `position` is `Vec3`\nnew GoalLookAtBlock(position, bot.world, {}); // Path into a position where a blockface of the block at position is visible. `position` is `Vec3`\n\n// These are other Mineflayer functions you can use:\nbot.isABed(bedBlock); // Return true if `bedBlock` is a bed\nbot.blockAt(position); // Return the block at `position`. `position` is `Vec3`\n\n// These are other Mineflayer async functions you can use:\nawait 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\"\nawait 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.\nawait 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\nawait bot.sleep(bedBlock); // Sleep until sunrise. You must get to a bed block first\nawait 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\nawait 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`\nawait 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\nawait 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\n"
  },
  {
    "path": "voyager/control_primitives_context/placeItem.js",
    "content": "// 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));\nasync function placeItem(bot, name, position) {\n    const item = bot.inventory.findInventoryItem(mcData.itemsByName[name].id);\n    // find a reference block\n    const faceVectors = [\n        new Vec3(0, 1, 0),\n        new Vec3(0, -1, 0),\n        new Vec3(1, 0, 0),\n        new Vec3(-1, 0, 0),\n        new Vec3(0, 0, 1),\n        new Vec3(0, 0, -1),\n    ];\n    let referenceBlock = null;\n    let faceVector = null;\n    for (const vector of faceVectors) {\n        const block = bot.blockAt(position.minus(vector));\n        if (block?.name !== \"air\") {\n            referenceBlock = block;\n            faceVector = vector;\n            break;\n        }\n    }\n    // You must first go to the block position you want to place\n    await bot.pathfinder.goto(new GoalPlaceBlock(position, bot.world, {}));\n    // You must equip the item right before calling placeBlock\n    await bot.equip(item, \"hand\");\n    await bot.placeBlock(referenceBlock, faceVector);\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/smeltItem.js",
    "content": "// Smelt 1 raw_iron into 1 iron_ingot using 1 oak_planks as fuel: smeltItem(bot, \"raw_iron\", \"oak_planks\");\n// You must place a furnace before calling this function\nasync function smeltItem(bot, itemName, fuelName, count = 1) {\n    const item = mcData.itemsByName[itemName];\n    const fuel = mcData.itemsByName[fuelName];\n    const furnaceBlock = bot.findBlock({\n        matching: mcData.blocksByName.furnace.id,\n        maxDistance: 32,\n    });\n    await bot.pathfinder.goto(\n        new GoalLookAtBlock(furnaceBlock.position, bot.world)\n    );\n    const furnace = await bot.openFurnace(furnaceBlock);\n    for (let i = 0; i < count; i++) {\n        await furnace.putFuel(fuel.id, null, 1);\n        await furnace.putInput(item.id, null, 1);\n        // Wait 12 seconds for the furnace to smelt the item\n        await bot.waitForTicks(12 * 20);\n        await furnace.takeOutput();\n    }\n    await furnace.close();\n}\n"
  },
  {
    "path": "voyager/control_primitives_context/useChest.js",
    "content": "// Get a torch from chest at (30, 65, 100): getItemFromChest(bot, new Vec3(30, 65, 100), {\"torch\": 1});\n// This function will work no matter how far the bot is from the chest.\nasync function getItemFromChest(bot, chestPosition, itemsToGet) {\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    const chest = await bot.openContainer(chestBlock);\n    for (const name in itemsToGet) {\n        const itemByName = mcData.itemsByName[name];\n        const item = chest.findContainerItem(itemByName.id);\n        await chest.withdraw(item.type, null, itemsToGet[name]);\n    }\n    await closeChest(bot, chestBlock);\n}\n// Deposit a torch into chest at (30, 65, 100): depositItemIntoChest(bot, new Vec3(30, 65, 100), {\"torch\": 1});\n// This function will work no matter how far the bot is from the chest.\nasync function depositItemIntoChest(bot, chestPosition, itemsToDeposit) {\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    const chest = await bot.openContainer(chestBlock);\n    for (const name in itemsToDeposit) {\n        const itemByName = mcData.itemsByName[name];\n        const item = bot.inventory.findInventoryItem(itemByName.id);\n        await chest.deposit(item.type, null, itemsToDeposit[name]);\n    }\n    await closeChest(bot, chestBlock);\n}\n// Check the items inside the chest at (30, 65, 100): checkItemInsideChest(bot, new Vec3(30, 65, 100));\n// You only need to call this function once without any action to finish task of checking items inside the chest.\nasync function checkItemInsideChest(bot, chestPosition) {\n    await moveToChest(bot, chestPosition);\n    const chestBlock = bot.blockAt(chestPosition);\n    await bot.openContainer(chestBlock);\n    // You must close the chest after opening it if you are asked to open a chest\n    await closeChest(bot, chestBlock);\n}\n"
  },
  {
    "path": "voyager/prompts/__init__.py",
    "content": "import pkg_resources\nimport voyager.utils as U\n\n\ndef load_prompt(prompt):\n    package_path = pkg_resources.resource_filename(\"voyager\", \"\")\n    return U.load_text(f\"{package_path}/prompts/{prompt}.txt\")\n"
  },
  {
    "path": "voyager/prompts/action_response_format.txt",
    "content": "Explain: ...\nPlan:\n1) ...\n2) ...\n3) ...\n...\nCode:\n```javascript\n// helper functions (only if needed, try to avoid them)\n...\n// main function after the helper functions\nasync function yourMainFunctionName(bot) {\n  // ...\n}\n```"
  },
  {
    "path": "voyager/prompts/action_template.txt",
    "content": "You are a helpful assistant that writes Mineflayer javascript code to complete any Minecraft task specified by me.\n\nHere are some useful programs written with Mineflayer APIs.\n\n{programs}\n\n\nAt each round of conversation, I will give you\nCode from the last round: ...\nExecution error: ...\nChat log: ...\nBiome: ...\nTime: ...\nNearby blocks: ...\nNearby entities (nearest to farthest):\nHealth: ...\nHunger: ...\nPosition: ...\nEquipment: ...\nInventory (xx/36): ...\nChests: ...\nTask: ...\nContext: ...\nCritique: ...\n\nYou should then respond to me with\nExplain (if applicable): Are there any steps missing in your plan? Why does the code not complete the task? What does the chat log and execution error imply?\nPlan: How to complete the task step by step. You should pay attention to Inventory since it tells what you have. The task completeness check is also based on your final inventory.\nCode:\n    1) Write an async function taking the bot as the only argument.\n    2) Reuse the above useful programs as much as possible.\n        - Use `mineBlock(bot, name, count)` to collect blocks. Do not use `bot.dig` directly.\n        - Use `craftItem(bot, name, count)` to craft items. Do not use `bot.craft` or `bot.recipesFor` directly.\n        - Use `smeltItem(bot, name count)` to smelt items. Do not use `bot.openFurnace` directly.\n        - Use `placeItem(bot, name, position)` to place blocks. Do not use `bot.placeBlock` directly.\n        - Use `killMob(bot, name, timeout)` to kill mobs. Do not use `bot.attack` directly.\n    3) Your function will be reused for building more complex functions. Therefore, you should make it generic and reusable. You should not make strong assumption about the inventory (as it may be changed at a later time), and therefore you should always check whether you have the required items before using them. If not, you should first collect the required items and reuse the above useful programs.\n    4) Functions in the \"Code from the last round\" section will not be saved or executed. Do not reuse functions listed there.\n    5) Anything defined outside a function will be ignored, define all your variables inside your functions.\n    6) Call `bot.chat` to show the intermediate progress.\n    7) Use `exploreUntil(bot, direction, maxDistance, callback)` when you cannot find something. You should frequently call this before mining blocks or killing mobs. You should select a direction at random every time instead of constantly using (1, 0, 1).\n    8) `maxDistance` should always be 32 for `bot.findBlocks` and `bot.findBlock`. Do not cheat.\n    9) Do not write infinite loops or recursive functions.\n    10) Do not use `bot.on` or `bot.once` to register event listeners. You definitely do not need them.\n    11) Name your function in a meaningful way (can infer the task from the name).\n\nYou should only respond in the format as described below:\nRESPONSE FORMAT:\n{response_format}\n"
  },
  {
    "path": "voyager/prompts/critic.txt",
    "content": "You are an assistant that assesses my progress of playing Minecraft and provides useful guidance.\n\nYou are required to evaluate if I have met the task requirements. Exceeding the task requirements is also considered a success while failing to meet them requires you to provide critique to help me improve.\n\nI will give you the following information:\n\nBiome: The biome after the task execution.\nTime: The current time.\nNearby blocks: The surrounding blocks. These blocks are not collected yet. However, this is useful for some placing or planting tasks.\nHealth: My current health.\nHunger: My current hunger level. For eating task, if my hunger level is 20.0, then I successfully ate the food.\nPosition: My current position.\nEquipment: My final equipment. For crafting tasks, I sometimes equip the crafted item.\nInventory (xx/36): My final inventory. For mining and smelting tasks, you only need to check inventory.\nChests: If the task requires me to place items in a chest, you can find chest information here.\nTask: The objective I need to accomplish.\nContext: The context of the task.\n\nYou should only respond in JSON format as described below:\n{\n    \"reasoning\": \"reasoning\",\n    \"success\": boolean,\n    \"critique\": \"critique\",\n}\nEnsure the response can be parsed by Python `json.loads`, e.g.: no trailing commas, no single quotes, etc.\n\nHere are some examples:\nINPUT:\nInventory (2/36): {'oak_log':2, 'spruce_log':2}\n\nTask: Mine 3 wood logs\n\nRESPONSE:\n{\n    \"reasoning\": \"You need to mine 3 wood logs. You have 2 oak logs and 2 spruce logs, which add up to 4 wood logs.\",\n    \"success\": true,\n    \"critique\": \"\"\n}\n\nINPUT:\nInventory (3/36): {'crafting_table': 1, 'spruce_planks': 6, 'stick': 4}\n\nTask: Craft a wooden pickaxe\n\nRESPONSE:\n{\n    \"reasoning\": \"You have enough materials to craft a wooden pickaxe, but you didn't craft it.\",\n    \"success\": false,\n    \"critique\": \"Craft a wooden pickaxe with a crafting table using 3 spruce planks and 2 sticks.\"\n}\n\nINPUT:\nInventory (2/36): {'raw_iron': 5, 'stone_pickaxe': 1}\n\nTask: Mine 5 iron_ore\n\nRESPONSE:\n{\n    \"reasoning\": \"Mining iron_ore in Minecraft will get raw_iron. You have 5 raw_iron in your inventory.\",\n    \"success\": true,\n    \"critique\": \"\"\n}\n\nINPUT:\nBiome: plains\n\nNearby blocks: stone, dirt, grass_block, grass, farmland, wheat\n\nInventory (26/36): ...\n\nTask:  Plant 1 wheat seed.\n\nRESPONSE:\n{\n    \"reasoning\": \"For planting tasks, inventory information is useless. In nearby blocks, there is farmland and wheat, which means you succeed to plant the wheat seed.\",\n    \"success\": true,\n    \"critique\": \"\"\n}\n\nINPUT:\nInventory (11/36): {... ,'rotten_flesh': 1}\n\nTask: Kill 1 zombie\n\nContext: ...\n\nRESPONSE\n{\n    \"reasoning\": \"You have rotten flesh in your inventory, which means you successfully killed one zombie.\",\n    \"success\": true,\n    \"critique\": \"\"\n}\n\nINPUT:\nHunger: 20.0/20.0\n\nInventory (11/36): ...\n\nTask: Eat 1 ...\n\nContext: ...\n\nRESPONSE\n{\n    \"reasoning\": \"For all eating task, if the player's hunger is 20.0, then the player successfully ate the food.\",\n    \"success\": true,\n    \"critique\": \"\"\n}\n\nINPUT:\nNearby blocks: chest\n\nInventory (28/36): {'rail': 1, 'coal': 2, 'oak_planks': 13, 'copper_block': 1, 'diorite': 7, 'cooked_beef': 4, 'granite': 22, 'cobbled_deepslate': 23, 'feather': 4, 'leather': 2, 'cooked_chicken': 3, 'white_wool': 2, 'stick': 3, 'black_wool': 1, 'stone_sword': 2, 'stone_hoe': 1, 'stone_axe': 2, 'stone_shovel': 2, 'cooked_mutton': 4, 'cobblestone_wall': 18, 'crafting_table': 1, 'furnace': 1, 'iron_pickaxe': 1, 'stone_pickaxe': 1, 'raw_copper': 12}\n\nChests:\n(81, 131, 16): {'andesite': 2, 'dirt': 2, 'cobblestone': 75, 'wooden_pickaxe': 1, 'wooden_sword': 1}\n\nTask: Deposit useless items into the chest at (81, 131, 16)\n\nContext: ...\n\nRESPONSE\n{\n    \"reasoning\": \"You have 28 items in your inventory after depositing, which is more than 20. You need to deposit more items from your inventory to the chest.\",\n    \"success\": false,\n    \"critique\": \"Deposit more useless items such as copper_block, diorite, granite, cobbled_deepslate, feather, and leather to meet the requirement of having only 20 occupied slots in your inventory.\"\n}"
  },
  {
    "path": "voyager/prompts/curriculum.txt",
    "content": "You are a helpful assistant that tells me the next immediate task to do in Minecraft. My ultimate goal is to discover as many diverse things as possible, accomplish as many diverse tasks as possible and become the best Minecraft player in the world.\n\nI will give you the following information:\nQuestion 1: ...\nAnswer: ...\nQuestion 2: ...\nAnswer: ...\nQuestion 3: ...\nAnswer: ...\n...\nBiome: ...\nTime: ...\nNearby blocks: ...\nOther blocks that are recently seen: ...\nNearby entities (nearest to farthest): ...\nHealth: Higher than 15 means I'm healthy.\nHunger: Higher than 15 means I'm not hungry.\nPosition: ...\nEquipment: If I have better armor in my inventory, you should ask me to equip it.\nInventory (xx/36): ...\nChests: You can ask me to deposit or take items from these chests. There also might be some unknown chest, you should ask me to open and check items inside the unknown chest.\nCompleted tasks so far: ...\nFailed tasks that are too hard: ...\n\nYou must follow the following criteria:\n1) You should act as a mentor and guide me to the next task based on my current learning progress.\n2) Please be very specific about what resources I need to collect, what I need to craft, or what mobs I need to kill.\n3) The next task should follow a concise format, such as \"Mine [quantity] [block]\", \"Craft [quantity] [item]\", \"Smelt [quantity] [item]\", \"Kill [quantity] [mob]\", \"Cook [quantity] [food]\", \"Equip [item]\" etc. It should be a single phrase. Do not propose multiple tasks at the same time. Do not mention anything else.\n4) The next task should not be too hard since I may not have the necessary resources or have learned enough skills to complete it yet.\n5) The next task should be novel and interesting. I should look for rare resources, upgrade my equipment and tools using better materials, and discover new things. I should not be doing the same thing over and over again.\n6) I may sometimes need to repeat some tasks if I need to collect more resources to complete more difficult tasks. Only repeat tasks if necessary.\n7) Do not ask me to build or dig shelter even if it's at night. I want to explore the world and discover new things. I don't want to stay in one place.\n8) Tasks that require information beyond the player's status to verify should be avoided. For instance, \"Placing 4 torches\" and \"Dig a 2x1x2 hole\" are not ideal since they require visual confirmation from the screen. All the placing, building, planting, and trading tasks should be avoided. Do not propose task starting with these keywords.\n\nYou should only respond in the format as described below:\nRESPONSE FORMAT:\nReasoning: Based on the information I listed above, do reasoning about what the next task should be.\nTask: The next task.\n\nHere's an example response:\nReasoning: The inventory is empty now, chop down a tree to get some wood.\nTask: Obtain a wood log."
  },
  {
    "path": "voyager/prompts/curriculum_qa_step1_ask_questions.txt",
    "content": "You are a helpful assistant that asks questions to help me decide the next immediate task to do in Minecraft. My ultimate goal is to discover as many things as possible, accomplish as many tasks as possible and become the best Minecraft player in the world.\n\nI will give you the following information:\nBiome: ...\nTime: ...\nNearby blocks: ...\nOther blocks that are recently seen: ...\nNearby entities (nearest to farthest): ...\nHealth: ...\nHunger: ...\nPosition: ...\nEquipment: ...\nInventory (xx/36): ...\nChests: ...\nCompleted tasks so far: ...\nFailed tasks that are too hard: ...\n\nYou must follow the following criteria:\n1) You should ask at least 5 questions (but no more than 10 questions) to help me decide the next immediate task to do. Each question should be followed by the concept that the question is about.\n2) Your question should be specific to a concept in Minecraft.\n  Bad example (the question is too general):\n    Question: What is the best way to play Minecraft?\n    Concept: unknown\n  Bad example (axe is still general, you should specify the type of axe such as wooden axe):\n    What are the benefits of using an axe to gather resources?\n    Concept: axe\n  Good example:\n    Question: How to make a wooden pickaxe?\n    Concept: wooden pickaxe\n3) Your questions should be self-contained and not require any context.\n  Bad example (the question requires the context of my current biome):\n    Question: What are the blocks that I can find in my current biome?\n    Concept: unknown\n  Bad example (the question requires the context of my current inventory):\n    Question: What are the resources you need the most currently?\n    Concept: unknown\n  Bad example (the question requires the context of my current inventory):\n    Question: Do you have any gold or emerald resources?\n    Concept: gold\n  Bad example (the question requires the context of my nearby entities):\n    Question: Can you see any animals nearby that you can kill for food?\n    Concept: food\n  Bad example (the question requires the context of my nearby blocks):\n    Question: Is there any water source nearby?\n    Concept: water\n  Good example:\n    Question: What are the blocks that I can find in the sparse jungle?\n    Concept: sparse jungle\n4) Do not ask questions about building tasks (such as building a shelter) since they are too hard for me to do.\n\nLet's say your current biome is sparse jungle. You can ask questions like:\nQuestion: What are the items that I can find in the sparse jungle?\nConcept: sparse jungle\nQuestion: What are the mobs that I can find in the sparse jungle?\nConcept: sparse jungle\n\nLet's say you see a creeper nearby, and you have not defeated a creeper before. You can ask a question like:\nQuestion: How to defeat the creeper?\nConcept: creeper\n\nLet's say your last completed task is \"Craft a wooden pickaxe\". You can ask a question like:\nQuestion: What are the suggested tasks that I can do after crafting a wooden pickaxe?\nConcept: wooden pickaxe\n\nHere are some more question and concept examples:\nQuestion: What are the ores that I can find in the sparse jungle?\nConcept: sparse jungle\n(the above concept should not be \"ore\" because I need to look up the page of \"sparse jungle\" to find out what ores I can find in the sparse jungle)\nQuestion: How can you obtain food in the sparse jungle?\nConcept: sparse jungle\n(the above concept should not be \"food\" because I need to look up the page of \"sparse jungle\" to find out what food I can obtain in the sparse jungle)\nQuestion: How can you use the furnace to upgrade your equipment and make useful items?\nConcept: furnace\nQuestion: How to obtain a diamond ore?\nConcept: diamond ore\nQuestion: What are the benefits of using a stone pickaxe over a wooden pickaxe?\nConcept: stone pickaxe\nQuestion: What are the tools that you can craft using wood planks and sticks?\nConcept: wood planks\n\nYou should only respond in the format as described below:\nRESPONSE FORMAT:\nReasoning: ...\nQuestion 1: ...\nConcept 1: ...\nQuestion 2: ...\nConcept 2: ...\nQuestion 3: ...\nConcept 3: ...\nQuestion 4: ...\nConcept 4: ...\nQuestion 5: ...\nConcept 5: ...\n...\n"
  },
  {
    "path": "voyager/prompts/curriculum_qa_step2_answer_questions.txt",
    "content": "You are a helpful assistant that answer my question about Minecraft.\n\nI will give you the following information:\nQuestion: ...\n\nYou will answer the question based on the context (only if available and helpful) and your own knowledge of Minecraft.\n1) Start your answer with \"Answer: \".\n2) Answer \"Answer: Unknown\" if you don't know the answer."
  },
  {
    "path": "voyager/prompts/curriculum_task_decomposition.txt",
    "content": "You are a helpful assistant that generates a curriculum of subgoals to complete any Minecraft task specified by me.\n\nI'll give you a final task and my current inventory, you need to decompose the task into a list of subgoals based on my inventory.\n\nYou must follow the following criteria:\n1) Return a Python list of subgoals that can be completed in order to complete the specified task.\n2) Each subgoal should follow a concise format, such as \"Mine [quantity] [block]\", \"Craft [quantity] [item]\", \"Smelt [quantity] [item]\", \"Kill [quantity] [mob]\", \"Cook [quantity] [food]\", \"Equip [item]\".\n3) Include each level of necessary tools as a subgoal, such as wooden, stone, iron, diamond, etc.\n\nYou should only respond in JSON format as described below:\n[\"subgoal1\", \"subgoal2\", \"subgoal3\", ...]\nEnsure the response can be parsed by Python `json.loads`, e.g.: no trailing commas, no single quotes, etc."
  },
  {
    "path": "voyager/prompts/skill.txt",
    "content": "You are a helpful assistant that writes a description of the given function written in Mineflayer javascript code.\n\n1) Do not mention the function name.\n2) Do not mention anything about `bot.chat` or helper functions.\n3) There might be some helper functions before the main function, but you only need to describe the main function.\n4) Try to summarize the function in no more than 6 sentences.\n5) Your response should be a single line of text.\n\nFor example, if the function is:\n\nasync function mineCobblestone(bot) {\n  // Check if the wooden pickaxe is in the inventory, if not, craft one\n  let woodenPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_pickaxe\"].id);\n  if (!woodenPickaxe) {\n    bot.chat(\"Crafting a wooden pickaxe.\");\n    await craftWoodenPickaxe(bot);\n    woodenPickaxe = bot.inventory.findInventoryItem(mcData.itemsByName[\"wooden_pickaxe\"].id);\n  }\n\n  // Equip the wooden pickaxe if it exists\n  if (woodenPickaxe) {\n    await bot.equip(woodenPickaxe, \"hand\");\n\n    // Explore until we find a stone block\n    await exploreUntil(bot, new Vec3(1, -1, 1), 60, () => {\n      const stone = bot.findBlock({\n        matching: mcData.blocksByName[\"stone\"].id,\n        maxDistance: 32\n      });\n      if (stone) {\n        return true;\n      }\n    });\n\n    // Mine 8 cobblestone blocks using the wooden pickaxe\n    bot.chat(\"Found a stone block. Mining 8 cobblestone blocks.\");\n    await mineBlock(bot, \"stone\", 8);\n    bot.chat(\"Successfully mined 8 cobblestone blocks.\");\n\n    // Save the event of mining 8 cobblestone\n    bot.save(\"cobblestone_mined\");\n  } else {\n    bot.chat(\"Failed to craft a wooden pickaxe. Cannot mine cobblestone.\");\n  }\n}\n\nThe main function is `mineCobblestone`.\n\nThen you would write:\n\nThe function is about mining 8 cobblestones using a wooden pickaxe. First check if a wooden pickaxe is in the inventory. If not, craft one. If the wooden pickaxe is available, equip the wooden pickaxe in the hand. Next, explore the environment until finding a stone block. Once a stone block is found, mine a total of 8 cobblestone blocks using the wooden pickaxe."
  },
  {
    "path": "voyager/utils/__init__.py",
    "content": "from .file_utils import *\nfrom .json_utils import *\nfrom .record_utils import EventRecorder\n"
  },
  {
    "path": "voyager/utils/file_utils.py",
    "content": "\"\"\"\nFile system utils.\n\"\"\"\nimport collections\nimport os\nimport pickle\nimport sys\nimport errno\nimport shutil\nimport glob\n\n# import pwd\nimport codecs\nimport hashlib\nimport tarfile\nimport fnmatch\nimport tempfile\nfrom datetime import datetime\nfrom socket import gethostname\nimport logging\n\n\nf_ext = os.path.splitext\n\nf_size = os.path.getsize\n\nis_file = os.path.isfile\n\nis_dir = os.path.isdir\n\nget_dir = os.path.dirname\n\n\ndef host_name():\n    \"Get host name, alias with ``socket.gethostname()``\"\n    return gethostname()\n\n\ndef host_id():\n    \"\"\"\n    Returns: first part of hostname up to '.'\n    \"\"\"\n    return host_name().split(\".\")[0]\n\n\ndef utf_open(fname, mode):\n    \"\"\"\n    Wrapper for codecs.open\n    \"\"\"\n    return codecs.open(fname, mode=mode, encoding=\"utf-8\")\n\n\ndef is_sequence(obj):\n    \"\"\"\n    Returns:\n      True if the sequence is a collections.Sequence and not a string.\n    \"\"\"\n    return isinstance(obj, collections.abc.Sequence) and not isinstance(obj, str)\n\n\ndef pack_varargs(args):\n    \"\"\"\n    Pack *args or a single list arg as list\n\n    def f(*args):\n        arg_list = pack_varargs(args)\n        # arg_list is now packed as a list\n    \"\"\"\n    assert isinstance(args, tuple), \"please input the tuple `args` as in *args\"\n    if len(args) == 1 and is_sequence(args[0]):\n        return args[0]\n    else:\n        return args\n\n\ndef f_not_empty(*fpaths):\n    \"\"\"\n    Returns:\n        True if and only if the file exists and file size > 0\n          if fpath is a dir, if and only if dir exists and has at least 1 file\n    \"\"\"\n    fpath = f_join(*fpaths)\n    if not os.path.exists(fpath):\n        return False\n\n    if os.path.isdir(fpath):\n        return len(os.listdir(fpath)) > 0\n    else:\n        return os.path.getsize(fpath) > 0\n\n\ndef f_expand(fpath):\n    return os.path.expandvars(os.path.expanduser(fpath))\n\n\ndef f_exists(*fpaths):\n    return os.path.exists(f_join(*fpaths))\n\n\ndef f_join(*fpaths):\n    \"\"\"\n    join file paths and expand special symbols like `~` for home dir\n    \"\"\"\n    fpaths = pack_varargs(fpaths)\n    fpath = f_expand(os.path.join(*fpaths))\n    if isinstance(fpath, str):\n        fpath = fpath.strip()\n    return fpath\n\n\ndef f_listdir(\n    *fpaths,\n    filter_ext=None,\n    filter=None,\n    sort=True,\n    full_path=False,\n    nonexist_ok=True,\n    recursive=False,\n):\n    \"\"\"\n    Args:\n        full_path: True to return full paths to the dir contents\n        filter: function that takes in file name and returns True to include\n        nonexist_ok: True to return [] if the dir is non-existent, False to raise\n        sort: sort the file names by alphabetical\n        recursive: True to use os.walk to recursively list files. Note that `filter`\n            will be applied to the relative path string to the root dir.\n            e.g. filter will take \"a/data1.txt\" and \"a/b/data3.txt\" as input, instead of\n            just the base file names \"data1.txt\" and \"data3.txt\".\n            if False, will simply call os.listdir()\n    \"\"\"\n    assert not (filter_ext and filter), \"filter_ext and filter are mutually exclusive\"\n    dir_path = f_join(*fpaths)\n    if not os.path.exists(dir_path) and nonexist_ok:\n        return []\n    if recursive:\n        files = [\n            os.path.join(os.path.relpath(root, dir_path), file)\n            for root, _, files in os.walk(dir_path)\n            for file in files\n        ]\n    else:\n        files = os.listdir(dir_path)\n    if filter is not None:\n        files = [f for f in files if filter(f)]\n    elif filter_ext is not None:\n        files = [f for f in files if f.endswith(filter_ext)]\n    if sort:\n        files.sort()\n    if full_path:\n        return [os.path.join(dir_path, f) for f in files]\n    else:\n        return files\n\n\ndef f_mkdir(*fpaths):\n    \"\"\"\n    Recursively creates all the subdirs\n    If exist, do nothing.\n    \"\"\"\n    fpath = f_join(*fpaths)\n    os.makedirs(fpath, exist_ok=True)\n    return fpath\n\n\ndef f_mkdir_in_path(*fpaths):\n    \"\"\"\n    fpath is a file,\n    recursively creates all the parent dirs that lead to the file\n    If exist, do nothing.\n    \"\"\"\n    os.makedirs(get_dir(f_join(*fpaths)), exist_ok=True)\n\n\ndef last_part_in_path(fpath):\n    \"\"\"\n    https://stackoverflow.com/questions/3925096/how-to-get-only-the-last-part-of-a-path-in-python\n    \"\"\"\n    return os.path.basename(os.path.normpath(f_expand(fpath)))\n\n\ndef is_abs_path(*fpath):\n    return os.path.isabs(f_join(*fpath))\n\n\ndef is_relative_path(*fpath):\n    return not is_abs_path(f_join(*fpath))\n\n\ndef f_time(*fpath):\n    \"File modification time\"\n    return str(os.path.getctime(f_join(*fpath)))\n\n\ndef f_append_before_ext(fpath, suffix):\n    \"\"\"\n    Append a suffix to file name and retain its extension\n    \"\"\"\n    name, ext = f_ext(fpath)\n    return name + suffix + ext\n\n\ndef f_add_ext(fpath, ext):\n    \"\"\"\n    Append an extension if not already there\n    Args:\n      ext: will add a preceding `.` if doesn't exist\n    \"\"\"\n    if not ext.startswith(\".\"):\n        ext = \".\" + ext\n    if fpath.endswith(ext):\n        return fpath\n    else:\n        return fpath + ext\n\n\ndef f_has_ext(fpath, ext):\n    \"Test if file path is a text file\"\n    _, actual_ext = f_ext(fpath)\n    return actual_ext == \".\" + ext.lstrip(\".\")\n\n\ndef f_glob(*fpath):\n    return glob.glob(f_join(*fpath), recursive=True)\n\n\ndef f_remove(*fpath, verbose=False, dry_run=False):\n    \"\"\"\n    If exist, remove. Supports both dir and file. Supports glob wildcard.\n    \"\"\"\n    assert isinstance(verbose, bool)\n    fpath = f_join(fpath)\n    if dry_run:\n        print(\"Dry run, delete:\", fpath)\n        return\n    for f in glob.glob(fpath):\n        try:\n            shutil.rmtree(f)\n        except OSError as e:\n            if e.errno == errno.ENOTDIR:\n                try:\n                    os.remove(f)\n                except:  # final resort safeguard\n                    pass\n    if verbose:\n        print(f'Deleted \"{fpath}\"')\n\n\ndef f_copy(fsrc, fdst, ignore=None, include=None, exists_ok=True, verbose=False):\n    \"\"\"\n    Supports both dir and file. Supports glob wildcard.\n    \"\"\"\n    fsrc, fdst = f_expand(fsrc), f_expand(fdst)\n    for f in glob.glob(fsrc):\n        try:\n            f_copytree(f, fdst, ignore=ignore, include=include, exist_ok=exists_ok)\n        except OSError as e:\n            if e.errno == errno.ENOTDIR:\n                shutil.copy(f, fdst)\n            else:\n                raise\n    if verbose:\n        print(f'Copied \"{fsrc}\" to \"{fdst}\"')\n\n\ndef _f_copytree(\n    src,\n    dst,\n    symlinks=False,\n    ignore=None,\n    exist_ok=True,\n    copy_function=shutil.copy2,\n    ignore_dangling_symlinks=False,\n):\n    \"\"\"Copied from python standard lib shutil.copytree\n    except that we allow exist_ok\n    Use f_copytree as entry\n    \"\"\"\n    names = os.listdir(src)\n    if ignore is not None:\n        ignored_names = ignore(src, names)\n    else:\n        ignored_names = set()\n\n    os.makedirs(dst, exist_ok=exist_ok)\n    errors = []\n    for name in names:\n        if name in ignored_names:\n            continue\n        srcname = os.path.join(src, name)\n        dstname = os.path.join(dst, name)\n        try:\n            if os.path.islink(srcname):\n                linkto = os.readlink(srcname)\n                if symlinks:\n                    # We can't just leave it to `copy_function` because legacy\n                    # code with a custom `copy_function` may rely on copytree\n                    # doing the right thing.\n                    os.symlink(linkto, dstname)\n                    shutil.copystat(srcname, dstname, follow_symlinks=not symlinks)\n                else:\n                    # ignore dangling symlink if the flag is on\n                    if not os.path.exists(linkto) and ignore_dangling_symlinks:\n                        continue\n                    # otherwise let the copy occurs. copy2 will raise an error\n                    if os.path.isdir(srcname):\n                        _f_copytree(\n                            srcname, dstname, symlinks, ignore, exist_ok, copy_function\n                        )\n                    else:\n                        copy_function(srcname, dstname)\n            elif os.path.isdir(srcname):\n                _f_copytree(srcname, dstname, symlinks, ignore, exist_ok, copy_function)\n            else:\n                # Will raise a SpecialFileError for unsupported file types\n                copy_function(srcname, dstname)\n        # catch the Error from the recursive copytree so that we can\n        # continue with other files\n        except shutil.Error as err:\n            errors.extend(err.args[0])\n        except OSError as why:\n            errors.append((srcname, dstname, str(why)))\n    try:\n        shutil.copystat(src, dst)\n    except OSError as why:\n        # Copying file access times may fail on Windows\n        if getattr(why, \"winerror\", None) is None:\n            errors.append((src, dst, str(why)))\n    if errors:\n        raise shutil.Error(errors)\n    return dst\n\n\ndef _include_patterns(*patterns):\n    \"\"\"Factory function that can be used with copytree() ignore parameter.\n\n    Arguments define a sequence of glob-style patterns\n    that are used to specify what files to NOT ignore.\n    Creates and returns a function that determines this for each directory\n    in the file hierarchy rooted at the source directory when used with\n    shutil.copytree().\n    \"\"\"\n\n    def _ignore_patterns(path, names):\n        keep = set(\n            name for pattern in patterns for name in fnmatch.filter(names, pattern)\n        )\n        ignore = set(\n            name\n            for name in names\n            if name not in keep and not os.path.isdir(os.path.join(path, name))\n        )\n        return ignore\n\n    return _ignore_patterns\n\n\ndef f_copytree(fsrc, fdst, symlinks=False, ignore=None, include=None, exist_ok=True):\n    fsrc, fdst = f_expand(fsrc), f_expand(fdst)\n    assert (ignore is None) or (\n        include is None\n    ), \"ignore= and include= are mutually exclusive\"\n    if ignore:\n        ignore = shutil.ignore_patterns(*ignore)\n    elif include:\n        ignore = _include_patterns(*include)\n    _f_copytree(fsrc, fdst, ignore=ignore, symlinks=symlinks, exist_ok=exist_ok)\n\n\ndef f_move(fsrc, fdst):\n    fsrc, fdst = f_expand(fsrc), f_expand(fdst)\n    for f in glob.glob(fsrc):\n        shutil.move(f, fdst)\n\n\ndef f_split_path(fpath, normpath=True):\n    \"\"\"\n    Splits path into a list of its component folders\n\n    Args:\n        normpath: call os.path.normpath to remove redundant '/' and\n            up-level references like \"..\"\n    \"\"\"\n    if normpath:\n        fpath = os.path.normpath(fpath)\n    allparts = []\n    while 1:\n        parts = os.path.split(fpath)\n        if parts[0] == fpath:  # sentinel for absolute paths\n            allparts.insert(0, parts[0])\n            break\n        elif parts[1] == fpath:  # sentinel for relative paths\n            allparts.insert(0, parts[1])\n            break\n        else:\n            fpath = parts[0]\n            allparts.insert(0, parts[1])\n    return allparts\n\n\ndef get_script_dir():\n    \"\"\"\n    Returns: the dir of current script\n    \"\"\"\n    return os.path.dirname(os.path.realpath(sys.argv[0]))\n\n\ndef get_script_file_name():\n    \"\"\"\n    Returns: the dir of current script\n    \"\"\"\n    return os.path.basename(sys.argv[0])\n\n\ndef get_script_self_path():\n    \"\"\"\n    Returns: the dir of current script\n    \"\"\"\n    return os.path.realpath(sys.argv[0])\n\n\ndef get_parent_dir(location, abspath=False):\n    \"\"\"\n    Args:\n      location: current directory or file\n\n    Returns:\n        parent directory absolute or relative path\n    \"\"\"\n    _path = os.path.abspath if abspath else os.path.relpath\n    return _path(f_join(location, os.pardir))\n\n\ndef md5_checksum(*fpath):\n    \"\"\"\n    File md5 signature\n    \"\"\"\n    hash_md5 = hashlib.md5()\n    with open(f_join(*fpath), \"rb\") as f:\n        for chunk in iter(lambda: f.read(65536), b\"\"):\n            hash_md5.update(chunk)\n    return hash_md5.hexdigest()\n\n\ndef create_tar(fsrc, output_tarball, include=None, ignore=None, compress_mode=\"gz\"):\n    \"\"\"\n    Args:\n        fsrc: source file or folder\n        output_tarball: output tar file name\n        compress_mode: \"gz\", \"bz2\", \"xz\" or \"\" (empty for uncompressed write)\n        include: include pattern, will trigger copy to temp directory\n        ignore: ignore pattern, will trigger copy to temp directory\n    \"\"\"\n    fsrc, output_tarball = f_expand(fsrc), f_expand(output_tarball)\n    assert compress_mode in [\"gz\", \"bz2\", \"xz\", \"\"]\n    src_base = os.path.basename(fsrc)\n\n    tempdir = None\n    if include or ignore:\n        tempdir = tempfile.mkdtemp()\n        tempdest = f_join(tempdir, src_base)\n        f_copy(fsrc, tempdest, include=include, ignore=ignore)\n        fsrc = tempdest\n\n    with tarfile.open(output_tarball, \"w:\" + compress_mode) as tar:\n        tar.add(fsrc, arcname=src_base)\n\n    if tempdir:\n        f_remove(tempdir)\n\n\ndef extract_tar(source_tarball, output_dir=\".\", members=None):\n    \"\"\"\n    Args:\n        source_tarball: extract members from archive\n        output_dir: default to current working dir\n        members: must be a subset of the list returned by getmembers()\n    \"\"\"\n    source_tarball, output_dir = f_expand(source_tarball), f_expand(output_dir)\n    with tarfile.open(source_tarball, \"r:*\") as tar:\n        tar.extractall(output_dir, members=members)\n\n\ndef move_with_backup(*fpath, suffix=\".bak\"):\n    \"\"\"\n    Ensures that a path is not occupied. If there is a file, rename it by\n    adding @suffix. Resursively backs up everything.\n\n    Args:\n        fpath: file path to clear\n        suffix: Add to backed up files (default: {'.bak'})\n    \"\"\"\n    fpath = str(f_join(*fpath))\n    if os.path.exists(fpath):\n        move_with_backup(fpath + suffix)\n        shutil.move(fpath, fpath + suffix)\n\n\ndef insert_before_ext(name, insert):\n    \"\"\"\n    log.txt -> log.ep50.txt\n    \"\"\"\n    name, ext = os.path.splitext(name)\n    return name + insert + ext\n\n\ndef timestamp_file_name(fname):\n    timestr = datetime.now().strftime(\"_%H-%M-%S_%m-%d-%y\")\n    return insert_before_ext(fname, timestr)\n\n\ndef get_file_lock(*fpath, timeout: int = 15, logging_level=\"critical\"):\n    \"\"\"\n    NFS-safe filesystem-backed lock. `pip install flufl.lock`\n    https://flufllock.readthedocs.io/en/stable/apiref.html\n\n    Args:\n        fpath: should be a path on NFS so that every process can see it\n        timeout: seconds\n    \"\"\"\n    from flufl.lock import Lock\n\n    logging.getLogger(\"flufl.lock\").setLevel(logging_level.upper())\n    return Lock(f_join(*fpath), lifetime=timeout)\n\n\ndef load_pickle(*fpaths):\n    with open(f_join(*fpaths), \"rb\") as fp:\n        return pickle.load(fp)\n\n\ndef dump_pickle(data, *fpaths):\n    with open(f_join(*fpaths), \"wb\") as fp:\n        pickle.dump(data, fp)\n\n\ndef load_text(*fpaths, by_lines=False):\n    with open(f_join(*fpaths), \"r\") as fp:\n        if by_lines:\n            return fp.readlines()\n        else:\n            return fp.read()\n\n\ndef load_text_lines(*fpaths):\n    return load_text(*fpaths, by_lines=True)\n\n\ndef dump_text(s, *fpaths):\n    with open(f_join(*fpaths), \"w\") as fp:\n        fp.write(s)\n\n\ndef dump_text_lines(lines: list[str], *fpaths, add_newline=True):\n    with open(f_join(*fpaths), \"w\") as fp:\n        for line in lines:\n            print(line, file=fp, end=\"\\n\" if add_newline else \"\")\n\n\n# aliases to be consistent with other load_* and dump_*\npickle_load = load_pickle\npickle_dump = dump_pickle\ntext_load = load_text\nread_text = load_text\nread_text_lines = load_text_lines\nwrite_text = dump_text\nwrite_text_lines = dump_text_lines\ntext_dump = dump_text\n"
  },
  {
    "path": "voyager/utils/json_utils.py",
    "content": "import json\nimport re\nfrom typing import Any, Dict, Union\nfrom .file_utils import f_join\n\n\ndef json_load(*file_path, **kwargs):\n    file_path = f_join(file_path)\n    with open(file_path, \"r\") as fp:\n        return json.load(fp, **kwargs)\n\n\ndef json_loads(string, **kwargs):\n    return json.loads(string, **kwargs)\n\n\ndef json_dump(data, *file_path, **kwargs):\n    file_path = f_join(file_path)\n    with open(file_path, \"w\") as fp:\n        json.dump(data, fp, **kwargs)\n\n\ndef json_dumps(data, **kwargs):\n    \"\"\"\n    Returns: string\n    \"\"\"\n    return json.dumps(data, **kwargs)\n\n\n# ---------------- Aliases -----------------\n# add aliases where verb goes first, json_load -> load_json\nload_json = json_load\nloads_json = json_loads\ndump_json = json_dump\ndumps_json = json_dumps\n\n\ndef extract_char_position(error_message: str) -> int:\n    \"\"\"Extract the character position from the JSONDecodeError message.\n    Args:\n        error_message (str): The error message from the JSONDecodeError\n          exception.\n    Returns:\n        int: The character position.\n    \"\"\"\n    import re\n\n    char_pattern = re.compile(r\"\\(char (\\d+)\\)\")\n    if match := char_pattern.search(error_message):\n        return int(match[1])\n    else:\n        raise ValueError(\"Character position not found in the error message.\")\n\n\ndef add_quotes_to_property_names(json_string: str) -> str:\n    \"\"\"\n    Add quotes to property names in a JSON string.\n    Args:\n        json_string (str): The JSON string.\n    Returns:\n        str: The JSON string with quotes added to property names.\n    \"\"\"\n\n    def replace_func(match):\n        return f'\"{match.group(1)}\":'\n\n    property_name_pattern = re.compile(r\"(\\w+):\")\n    corrected_json_string = property_name_pattern.sub(replace_func, json_string)\n\n    try:\n        json.loads(corrected_json_string)\n        return corrected_json_string\n    except json.JSONDecodeError as e:\n        raise e\n\n\ndef balance_braces(json_string: str) -> str:\n    \"\"\"\n    Balance the braces in a JSON string.\n    Args:\n        json_string (str): The JSON string.\n    Returns:\n        str: The JSON string with braces balanced.\n    \"\"\"\n\n    open_braces_count = json_string.count(\"{\")\n    close_braces_count = json_string.count(\"}\")\n\n    while open_braces_count > close_braces_count:\n        json_string += \"}\"\n        close_braces_count += 1\n\n    while close_braces_count > open_braces_count:\n        json_string = json_string.rstrip(\"}\")\n        close_braces_count -= 1\n\n    try:\n        json.loads(json_string)\n        return json_string\n    except json.JSONDecodeError as e:\n        raise e\n\n\ndef fix_invalid_escape(json_str: str, error_message: str) -> str:\n    while error_message.startswith(\"Invalid \\\\escape\"):\n        bad_escape_location = extract_char_position(error_message)\n        json_str = json_str[:bad_escape_location] + json_str[bad_escape_location + 1 :]\n        try:\n            json.loads(json_str)\n            return json_str\n        except json.JSONDecodeError as e:\n            error_message = str(e)\n    return json_str\n\n\ndef correct_json(json_str: str) -> str:\n    \"\"\"\n    Correct common JSON errors.\n    Args:\n        json_str (str): The JSON string.\n    \"\"\"\n\n    try:\n        json.loads(json_str)\n        return json_str\n    except json.JSONDecodeError as e:\n        error_message = str(e)\n        if error_message.startswith(\"Invalid \\\\escape\"):\n            json_str = fix_invalid_escape(json_str, error_message)\n        if error_message.startswith(\n            \"Expecting property name enclosed in double quotes\"\n        ):\n            json_str = add_quotes_to_property_names(json_str)\n            try:\n                json.loads(json_str)\n                return json_str\n            except json.JSONDecodeError as e:\n                error_message = str(e)\n        if balanced_str := balance_braces(json_str):\n            return balanced_str\n    return json_str\n\n\ndef fix_and_parse_json(\n    json_str: str, try_to_fix_with_gpt: bool = True\n) -> Union[str, Dict[Any, Any]]:\n    \"\"\"Fix and parse JSON string\"\"\"\n    try:\n        json_str = json_str.replace(\"\\t\", \"\")\n        return json.loads(json_str)\n    except json.JSONDecodeError as _:  # noqa: F841\n        json_str = correct_json(json_str)\n        try:\n            return json.loads(json_str)\n        except json.JSONDecodeError as _:  # noqa: F841\n            pass\n    # Let's do something manually:\n    # sometimes GPT responds with something BEFORE the braces:\n    # \"I'm sorry, I don't understand. Please try again.\"\n    # {\"text\": \"I'm sorry, I don't understand. Please try again.\",\n    #  \"confidence\": 0.0}\n    # So let's try to find the first brace and then parse the rest\n    #  of the string\n    try:\n        brace_index = json_str.index(\"{\")\n        json_str = json_str[brace_index:]\n        last_brace_index = json_str.rindex(\"}\")\n        json_str = json_str[: last_brace_index + 1]\n        return json.loads(json_str)\n    except json.JSONDecodeError as e:  # noqa: F841\n        # if try_to_fix_with_gpt:\n        #     print(\n        #         \"Warning: Failed to parse AI output, attempting to fix.\"\n        #         \"\\n If you see this warning frequently, it's likely that\"\n        #         \" your prompt is confusing the AI. Try changing it up\"\n        #         \" slightly.\"\n        #     )\n        #     # Now try to fix this up using the ai_functions\n        #     ai_fixed_json = fix_json(json_str, JSON_SCHEMA)\n        #\n        #     if ai_fixed_json != \"failed\":\n        #         return json.loads(ai_fixed_json)\n        #     else:\n        #         # This allows the AI to react to the error message,\n        #         #   which usually results in it correcting its ways.\n        #         print(\"Failed to fix ai output, telling the AI.\")\n        #         return json_str\n        # else:\n        raise e\n\n\n# def fix_json(json_str: str, schema: str) -> str:\n#     \"\"\"Fix the given JSON string to make it parseable and fully complient with the provided schema.\"\"\"\n#\n#     # Try to fix the JSON using gpt:\n#     function_string = \"def fix_json(json_str: str, schema:str=None) -> str:\"\n#     args = [f\"'''{json_str}'''\", f\"'''{schema}'''\"]\n#     description_string = (\n#         \"Fixes the provided JSON string to make it parseable\"\n#         \" and fully complient with the provided schema.\\n If an object or\"\n#         \" field specified in the schema isn't contained within the correct\"\n#         \" JSON, it is ommited.\\n This function is brilliant at guessing\"\n#         \" when the format is incorrect.\"\n#     )\n#\n#     # If it doesn't already start with a \"`\", add one:\n#     if not json_str.startswith(\"`\"):\n#         json_str = \"```json\\n\" + json_str + \"\\n```\"\n#     result_string = call_ai_function(\n#         function_string, args, description_string, model=cfg.fast_llm_model\n#     )\n#     if cfg.debug:\n#         print(\"------------ JSON FIX ATTEMPT ---------------\")\n#         print(f\"Original JSON: {json_str}\")\n#         print(\"-----------\")\n#         print(f\"Fixed JSON: {result_string}\")\n#         print(\"----------- END OF FIX ATTEMPT ----------------\")\n#\n#     try:\n#         json.loads(result_string)  # just check the validity\n#         return result_string\n#     except:  # noqa: E722\n#         # Get the call stack:\n#         # import traceback\n#         # call_stack = traceback.format_exc()\n#         # print(f\"Failed to fix JSON: '{json_str}' \"+call_stack)\n#         return \"failed\"\n"
  },
  {
    "path": "voyager/utils/record_utils.py",
    "content": "import time\n\nfrom .file_utils import *\nfrom .json_utils import *\n\n\nclass EventRecorder:\n    def __init__(\n        self,\n        ckpt_dir=\"ckpt\",\n        resume=False,\n        init_position=None,\n    ):\n        self.ckpt_dir = ckpt_dir\n        self.item_history = set()\n        self.item_vs_time = {}\n        self.item_vs_iter = {}\n        self.biome_history = set()\n        self.init_position = init_position\n        self.position_history = [[0, 0]]\n        self.elapsed_time = 0\n        self.iteration = 0\n        f_mkdir(self.ckpt_dir, \"events\")\n        if resume:\n            self.resume()\n\n    def record(self, events, task):\n        task = re.sub(r'[\\\\/:\"*?<>| ]', \"_\", task)\n        task = task.replace(\" \", \"_\") + time.strftime(\n            \"_%Y%m%d_%H%M%S\", time.localtime()\n        )\n        self.iteration += 1\n        if not self.init_position:\n            self.init_position = [\n                events[0][1][\"status\"][\"position\"][\"x\"],\n                events[0][1][\"status\"][\"position\"][\"z\"],\n            ]\n        for event_type, event in events:\n            self.update_items(event)\n            if event_type == \"observe\":\n                self.update_elapsed_time(event)\n        print(\n            f\"\\033[96m****Recorder message: {self.elapsed_time} ticks have elapsed****\\033[0m\\n\"\n            f\"\\033[96m****Recorder message: {self.iteration} iteration passed****\\033[0m\"\n        )\n        dump_json(events, f_join(self.ckpt_dir, \"events\", task))\n\n    def resume(self, cutoff=None):\n        self.item_history = set()\n        self.item_vs_time = {}\n        self.item_vs_iter = {}\n        self.elapsed_time = 0\n        self.position_history = [[0, 0]]\n\n        def get_timestamp(string):\n            timestamp = \"_\".join(string.split(\"_\")[-2:])\n            return time.mktime(time.strptime(timestamp, \"%Y%m%d_%H%M%S\"))\n\n        records = f_listdir(self.ckpt_dir, \"events\")\n        sorted_records = sorted(records, key=get_timestamp)\n        for record in sorted_records:\n            self.iteration += 1\n            if cutoff and self.iteration > cutoff:\n                break\n            events = load_json(f_join(self.ckpt_dir, \"events\", record))\n            if not self.init_position:\n                self.init_position = (\n                    events[0][1][\"status\"][\"position\"][\"x\"],\n                    events[0][1][\"status\"][\"position\"][\"z\"],\n                )\n            for event_type, event in events:\n                self.update_items(event)\n                self.update_position(event)\n                if event_type == \"observe\":\n                    self.update_elapsed_time(event)\n\n    def update_items(self, event):\n        inventory = event[\"inventory\"]\n        elapsed_time = event[\"status\"][\"elapsedTime\"]\n        biome = event[\"status\"][\"biome\"]\n        items = set(inventory.keys())\n        new_items = items - self.item_history\n        self.item_history.update(items)\n        self.biome_history.add(biome)\n        if new_items:\n            if self.elapsed_time + elapsed_time not in self.item_vs_time:\n                self.item_vs_time[self.elapsed_time + elapsed_time] = []\n            self.item_vs_time[self.elapsed_time + elapsed_time].extend(new_items)\n            if self.iteration not in self.item_vs_iter:\n                self.item_vs_iter[self.iteration] = []\n            self.item_vs_iter[self.iteration].extend(new_items)\n\n    def update_elapsed_time(self, event):\n        self.elapsed_time += event[\"status\"][\"elapsedTime\"]\n\n    def update_position(self, event):\n        position = [\n            event[\"status\"][\"position\"][\"x\"] - self.init_position[0],\n            event[\"status\"][\"position\"][\"z\"] - self.init_position[1],\n        ]\n        if self.position_history[-1] != position:\n            self.position_history.append(position)\n"
  },
  {
    "path": "voyager/voyager.py",
    "content": "import copy\nimport json\nimport os\nimport time\nfrom typing import Dict\n\nimport voyager.utils as U\nfrom .env import VoyagerEnv\n\nfrom .agents import ActionAgent\nfrom .agents import CriticAgent\nfrom .agents import CurriculumAgent\nfrom .agents import SkillManager\n\n\n# TODO: remove event memory\nclass Voyager:\n    def __init__(\n        self,\n        mc_port: int = None,\n        azure_login: Dict[str, str] = None,\n        server_port: int = 3000,\n        openai_api_key: str = None,\n        env_wait_ticks: int = 20,\n        env_request_timeout: int = 600,\n        max_iterations: int = 160,\n        reset_placed_if_failed: bool = False,\n        action_agent_model_name: str = \"gpt-4\",\n        action_agent_temperature: float = 0,\n        action_agent_task_max_retries: int = 4,\n        action_agent_show_chat_log: bool = True,\n        action_agent_show_execution_error: bool = True,\n        curriculum_agent_model_name: str = \"gpt-4\",\n        curriculum_agent_temperature: float = 0,\n        curriculum_agent_qa_model_name: str = \"gpt-3.5-turbo\",\n        curriculum_agent_qa_temperature: float = 0,\n        curriculum_agent_warm_up: Dict[str, int] = None,\n        curriculum_agent_core_inventory_items: str = r\".*_log|.*_planks|stick|crafting_table|furnace\"\n        r\"|cobblestone|dirt|coal|.*_pickaxe|.*_sword|.*_axe\",\n        curriculum_agent_mode: str = \"auto\",\n        critic_agent_model_name: str = \"gpt-4\",\n        critic_agent_temperature: float = 0,\n        critic_agent_mode: str = \"auto\",\n        skill_manager_model_name: str = \"gpt-3.5-turbo\",\n        skill_manager_temperature: float = 0,\n        skill_manager_retrieval_top_k: int = 5,\n        openai_api_request_timeout: int = 240,\n        ckpt_dir: str = \"ckpt\",\n        skill_library_dir: str = None,\n        resume: bool = False,\n    ):\n        \"\"\"\n        The main class for Voyager.\n        Action agent is the iterative prompting mechanism in paper.\n        Curriculum agent is the automatic curriculum in paper.\n        Critic agent is the self-verification in paper.\n        Skill manager is the skill library in paper.\n        :param mc_port: minecraft in-game port\n        :param azure_login: minecraft login config\n        :param server_port: mineflayer port\n        :param openai_api_key: openai api key\n        :param env_wait_ticks: how many ticks at the end each step will wait, if you found some chat log missing,\n        you should increase this value\n        :param env_request_timeout: how many seconds to wait for each step, if the code execution exceeds this time,\n        python side will terminate the connection and need to be resumed\n        :param reset_placed_if_failed: whether to reset placed blocks if failed, useful for building task\n        :param action_agent_model_name: action agent model name\n        :param action_agent_temperature: action agent temperature\n        :param action_agent_task_max_retries: how many times to retry if failed\n        :param curriculum_agent_model_name: curriculum agent model name\n        :param curriculum_agent_temperature: curriculum agent temperature\n        :param curriculum_agent_qa_model_name: curriculum agent qa model name\n        :param curriculum_agent_qa_temperature: curriculum agent qa temperature\n        :param curriculum_agent_warm_up: info will show in curriculum human message\n        if completed task larger than the value in dict, available keys are:\n        {\n            \"context\": int,\n            \"biome\": int,\n            \"time\": int,\n            \"other_blocks\": int,\n            \"nearby_entities\": int,\n            \"health\": int,\n            \"hunger\": int,\n            \"position\": int,\n            \"equipment\": int,\n            \"chests\": int,\n            \"optional_inventory_items\": int,\n        }\n        :param curriculum_agent_core_inventory_items: only show these items in inventory before optional_inventory_items\n        reached in warm up\n        :param curriculum_agent_mode: \"auto\" for automatic curriculum, \"manual\" for human curriculum\n        :param critic_agent_model_name: critic agent model name\n        :param critic_agent_temperature: critic agent temperature\n        :param critic_agent_mode: \"auto\" for automatic critic ,\"manual\" for human critic\n        :param skill_manager_model_name: skill manager model name\n        :param skill_manager_temperature: skill manager temperature\n        :param skill_manager_retrieval_top_k: how many skills to retrieve for each task\n        :param openai_api_request_timeout: how many seconds to wait for openai api\n        :param ckpt_dir: checkpoint dir\n        :param skill_library_dir: skill library dir\n        :param resume: whether to resume from checkpoint\n        \"\"\"\n        # init env\n        self.env = VoyagerEnv(\n            mc_port=mc_port,\n            azure_login=azure_login,\n            server_port=server_port,\n            request_timeout=env_request_timeout,\n        )\n        self.env_wait_ticks = env_wait_ticks\n        self.reset_placed_if_failed = reset_placed_if_failed\n        self.max_iterations = max_iterations\n\n        # set openai api key\n        os.environ[\"OPENAI_API_KEY\"] = openai_api_key\n\n        # init agents\n        self.action_agent = ActionAgent(\n            model_name=action_agent_model_name,\n            temperature=action_agent_temperature,\n            request_timout=openai_api_request_timeout,\n            ckpt_dir=ckpt_dir,\n            resume=resume,\n            chat_log=action_agent_show_chat_log,\n            execution_error=action_agent_show_execution_error,\n        )\n        self.action_agent_task_max_retries = action_agent_task_max_retries\n        self.curriculum_agent = CurriculumAgent(\n            model_name=curriculum_agent_model_name,\n            temperature=curriculum_agent_temperature,\n            qa_model_name=curriculum_agent_qa_model_name,\n            qa_temperature=curriculum_agent_qa_temperature,\n            request_timout=openai_api_request_timeout,\n            ckpt_dir=ckpt_dir,\n            resume=resume,\n            mode=curriculum_agent_mode,\n            warm_up=curriculum_agent_warm_up,\n            core_inventory_items=curriculum_agent_core_inventory_items,\n        )\n        self.critic_agent = CriticAgent(\n            model_name=critic_agent_model_name,\n            temperature=critic_agent_temperature,\n            request_timout=openai_api_request_timeout,\n            mode=critic_agent_mode,\n        )\n        self.skill_manager = SkillManager(\n            model_name=skill_manager_model_name,\n            temperature=skill_manager_temperature,\n            retrieval_top_k=skill_manager_retrieval_top_k,\n            request_timout=openai_api_request_timeout,\n            ckpt_dir=skill_library_dir if skill_library_dir else ckpt_dir,\n            resume=True if resume or skill_library_dir else False,\n        )\n        self.recorder = U.EventRecorder(ckpt_dir=ckpt_dir, resume=resume)\n        self.resume = resume\n\n        # init variables for rollout\n        self.action_agent_rollout_num_iter = -1\n        self.task = None\n        self.context = \"\"\n        self.messages = None\n        self.conversations = []\n        self.last_events = None\n\n    def reset(self, task, context=\"\", reset_env=True):\n        self.action_agent_rollout_num_iter = 0\n        self.task = task\n        self.context = context\n        if reset_env:\n            self.env.reset(\n                options={\n                    \"mode\": \"soft\",\n                    \"wait_ticks\": self.env_wait_ticks,\n                }\n            )\n        difficulty = (\n            \"easy\" if len(self.curriculum_agent.completed_tasks) > 15 else \"peaceful\"\n        )\n        # step to peek an observation\n        events = self.env.step(\n            \"bot.chat(`/time set ${getNextTime()}`);\\n\"\n            + f\"bot.chat('/difficulty {difficulty}');\"\n        )\n        skills = self.skill_manager.retrieve_skills(query=self.context)\n        print(\n            f\"\\033[33mRender Action Agent system message with {len(skills)} skills\\033[0m\"\n        )\n        system_message = self.action_agent.render_system_message(skills=skills)\n        human_message = self.action_agent.render_human_message(\n            events=events, code=\"\", task=self.task, context=context, critique=\"\"\n        )\n        self.messages = [system_message, human_message]\n        print(\n            f\"\\033[32m****Action Agent human message****\\n{human_message.content}\\033[0m\"\n        )\n        assert len(self.messages) == 2\n        self.conversations = []\n        return self.messages\n\n    def close(self):\n        self.env.close()\n\n    def step(self):\n        if self.action_agent_rollout_num_iter < 0:\n            raise ValueError(\"Agent must be reset before stepping\")\n        ai_message = self.action_agent.llm(self.messages)\n        print(f\"\\033[34m****Action Agent ai message****\\n{ai_message.content}\\033[0m\")\n        self.conversations.append(\n            (self.messages[0].content, self.messages[1].content, ai_message.content)\n        )\n        parsed_result = self.action_agent.process_ai_message(message=ai_message)\n        success = False\n        if isinstance(parsed_result, dict):\n            code = parsed_result[\"program_code\"] + \"\\n\" + parsed_result[\"exec_code\"]\n            events = self.env.step(\n                code,\n                programs=self.skill_manager.programs,\n            )\n            self.recorder.record(events, self.task)\n            self.action_agent.update_chest_memory(events[-1][1][\"nearbyChests\"])\n            success, critique = self.critic_agent.check_task_success(\n                events=events,\n                task=self.task,\n                context=self.context,\n                chest_observation=self.action_agent.render_chest_observation(),\n                max_retries=5,\n            )\n\n            if self.reset_placed_if_failed and not success:\n                # revert all the placing event in the last step\n                blocks = []\n                positions = []\n                for event_type, event in events:\n                    if event_type == \"onSave\" and event[\"onSave\"].endswith(\"_placed\"):\n                        block = event[\"onSave\"].split(\"_placed\")[0]\n                        position = event[\"status\"][\"position\"]\n                        blocks.append(block)\n                        positions.append(position)\n                new_events = self.env.step(\n                    f\"await givePlacedItemBack(bot, {U.json_dumps(blocks)}, {U.json_dumps(positions)})\",\n                    programs=self.skill_manager.programs,\n                )\n                events[-1][1][\"inventory\"] = new_events[-1][1][\"inventory\"]\n                events[-1][1][\"voxels\"] = new_events[-1][1][\"voxels\"]\n            new_skills = self.skill_manager.retrieve_skills(\n                query=self.context\n                + \"\\n\\n\"\n                + self.action_agent.summarize_chatlog(events)\n            )\n            system_message = self.action_agent.render_system_message(skills=new_skills)\n            human_message = self.action_agent.render_human_message(\n                events=events,\n                code=parsed_result[\"program_code\"],\n                task=self.task,\n                context=self.context,\n                critique=critique,\n            )\n            self.last_events = copy.deepcopy(events)\n            self.messages = [system_message, human_message]\n        else:\n            assert isinstance(parsed_result, str)\n            self.recorder.record([], self.task)\n            print(f\"\\033[34m{parsed_result} Trying again!\\033[0m\")\n        assert len(self.messages) == 2\n        self.action_agent_rollout_num_iter += 1\n        done = (\n            self.action_agent_rollout_num_iter >= self.action_agent_task_max_retries\n            or success\n        )\n        info = {\n            \"task\": self.task,\n            \"success\": success,\n            \"conversations\": self.conversations,\n        }\n        if success:\n            assert (\n                \"program_code\" in parsed_result and \"program_name\" in parsed_result\n            ), \"program and program_name must be returned when success\"\n            info[\"program_code\"] = parsed_result[\"program_code\"]\n            info[\"program_name\"] = parsed_result[\"program_name\"]\n        else:\n            print(\n                f\"\\033[32m****Action Agent human message****\\n{self.messages[-1].content}\\033[0m\"\n            )\n        return self.messages, 0, done, info\n\n    def rollout(self, *, task, context, reset_env=True):\n        self.reset(task=task, context=context, reset_env=reset_env)\n        while True:\n            messages, reward, done, info = self.step()\n            if done:\n                break\n        return messages, reward, done, info\n\n    def learn(self, reset_env=True):\n        if self.resume:\n            # keep the inventory\n            self.env.reset(\n                options={\n                    \"mode\": \"soft\",\n                    \"wait_ticks\": self.env_wait_ticks,\n                }\n            )\n        else:\n            # clear the inventory\n            self.env.reset(\n                options={\n                    \"mode\": \"hard\",\n                    \"wait_ticks\": self.env_wait_ticks,\n                }\n            )\n            self.resume = True\n        self.last_events = self.env.step(\"\")\n\n        while True:\n            if self.recorder.iteration > self.max_iterations:\n                print(\"Iteration limit reached\")\n                break\n            task, context = self.curriculum_agent.propose_next_task(\n                events=self.last_events,\n                chest_observation=self.action_agent.render_chest_observation(),\n                max_retries=5,\n            )\n            print(\n                f\"\\033[35mStarting task {task} for at most {self.action_agent_task_max_retries} times\\033[0m\"\n            )\n            try:\n                messages, reward, done, info = self.rollout(\n                    task=task,\n                    context=context,\n                    reset_env=reset_env,\n                )\n            except Exception as e:\n                time.sleep(3)  # wait for mineflayer to exit\n                info = {\n                    \"task\": task,\n                    \"success\": False,\n                }\n                # reset bot status here\n                self.last_events = self.env.reset(\n                    options={\n                        \"mode\": \"hard\",\n                        \"wait_ticks\": self.env_wait_ticks,\n                        \"inventory\": self.last_events[-1][1][\"inventory\"],\n                        \"equipment\": self.last_events[-1][1][\"status\"][\"equipment\"],\n                        \"position\": self.last_events[-1][1][\"status\"][\"position\"],\n                    }\n                )\n                # use red color background to print the error\n                print(\"Your last round rollout terminated due to error:\")\n                print(f\"\\033[41m{e}\\033[0m\")\n\n            if info[\"success\"]:\n                self.skill_manager.add_new_skill(info)\n\n            self.curriculum_agent.update_exploration_progress(info)\n            print(\n                f\"\\033[35mCompleted tasks: {', '.join(self.curriculum_agent.completed_tasks)}\\033[0m\"\n            )\n            print(\n                f\"\\033[35mFailed tasks: {', '.join(self.curriculum_agent.failed_tasks)}\\033[0m\"\n            )\n\n        return {\n            \"completed_tasks\": self.curriculum_agent.completed_tasks,\n            \"failed_tasks\": self.curriculum_agent.failed_tasks,\n            \"skills\": self.skill_manager.skills,\n        }\n\n    def decompose_task(self, task):\n        if not self.last_events:\n            self.last_events = self.env.reset(\n                options={\n                    \"mode\": \"hard\",\n                    \"wait_ticks\": self.env_wait_ticks,\n                }\n            )\n        return self.curriculum_agent.decompose_task(task, self.last_events)\n\n    def inference(self, task=None, sub_goals=[], reset_mode=\"hard\", reset_env=True):\n        if not task and not sub_goals:\n            raise ValueError(\"Either task or sub_goals must be provided\")\n        if not sub_goals:\n            sub_goals = self.decompose_task(task)\n        self.env.reset(\n            options={\n                \"mode\": reset_mode,\n                \"wait_ticks\": self.env_wait_ticks,\n            }\n        )\n        self.curriculum_agent.completed_tasks = []\n        self.curriculum_agent.failed_tasks = []\n        self.last_events = self.env.step(\"\")\n        while self.curriculum_agent.progress < len(sub_goals):\n            next_task = sub_goals[self.curriculum_agent.progress]\n            context = self.curriculum_agent.get_task_context(next_task)\n            print(\n                f\"\\033[35mStarting task {next_task} for at most {self.action_agent_task_max_retries} times\\033[0m\"\n            )\n            messages, reward, done, info = self.rollout(\n                task=next_task,\n                context=context,\n                reset_env=reset_env,\n            )\n            self.curriculum_agent.update_exploration_progress(info)\n            print(\n                f\"\\033[35mCompleted tasks: {', '.join(self.curriculum_agent.completed_tasks)}\\033[0m\"\n            )\n            print(\n                f\"\\033[35mFailed tasks: {', '.join(self.curriculum_agent.failed_tasks)}\\033[0m\"\n            )\n"
  }
]