Skip to content

Instantly share code, notes, and snippets.

@extremeheat
Created July 18, 2021 08:02
Show Gist options
  • Save extremeheat/65c34acb132ec097ea53247647609b5a to your computer and use it in GitHub Desktop.
Save extremeheat/65c34acb132ec097ea53247647609b5a to your computer and use it in GitHub Desktop.
mineflayer.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "mineflayer.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyM8AtSLPYrH5PrqIp20R7e8",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/extremeheat/65c34acb132ec097ea53247647609b5a/mineflayer.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2BAYqsdOgKNJ"
},
"source": [
"# Using mineflayer in Python\n",
"\n",
"This is a tutorial on how to use mineflayer in Python. This example will connect you to the PrismarineJS test server. You can join it with prismarine-viewer or your Minecraft client at server IP **95.111.249.143:10000**.\n",
"\n",
"If you're new to Jupyter Notebooks, you can press the \"Play\" button at the left of each code block to run it. "
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "qM2rVyxGf2Yv"
},
"source": [
"## Setup"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "K2ol06QOhL6s"
},
"source": [
"First, make sure you have Python version 3.7 and Node.js version 14 or newer installed"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "8zCSpx8Bif5m",
"outputId": "2be51f05-2099-4c15-8d38-ecf82ac227d3"
},
"source": [
"!python --version\n",
"!node --version"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"Python 3.7.11\n",
"v14.16.0\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "C7omnDs3lNaV"
},
"source": [
"Now, we can use pip to install the `javascript` Python package to access Node.js libraries from Python."
]
},
{
"cell_type": "code",
"metadata": {
"id": "DKnwzSZQ8Taf",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "d3035663-02e4-40ca-916c-78a9d0da92ca"
},
"source": [
" !pip install javascript"
],
"execution_count": 1,
"outputs": [
{
"output_type": "stream",
"text": [
"Collecting javascript\n",
" Downloading https://files.pythonhosted.org/packages/3c/fb/57d13463e6b975883747d8556449fc0a0b40dcc202b681b5f8df414f6115/javascript-1%210.2.5-py3-none-any.whl\n",
"Installing collected packages: javascript\n",
"Successfully installed javascript-1!0.2.5\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "_RAKlcScgKtV"
},
"source": [
"## Usage"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bxAdFbBfmdCd"
},
"source": [
"If all is well, we can import the `javascript` library. We can then import the `require` function which works similarly to the `require` function in Node.js, but does the dependency management for us.\n",
"\n",
"You may notice the extra imports : On, Once, off and AsyncTask. These will be discussed later on. \n",
"\n",
"\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "54Lnq3aH4Tee"
},
"source": [
"from javascript import require, On, Once, AsyncTask"
],
"execution_count": 2,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "cy7-0cWxdhU8"
},
"source": [
"We can now import Mineflayer"
]
},
{
"cell_type": "code",
"metadata": {
"id": "8jgkTVniDPUZ",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "bf37ddf5-6d23-4be4-ef7e-088c1a91e10f"
},
"source": [
"mineflayer = require('mineflayer')"
],
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"text": [
"\u001b[1m Installing 'mineflayer' version 'latest'... This will only happen once. \u001b[0m\n",
"\n",
"[JSE] npm notice created a lockfile as package-lock.json. You should commit this file.\n",
"[JSE] npm WARN js-modules@ No repository field.\n",
"[JSE] npm WARN js-modules@ No license field.\n",
"added 75 packages from 56 contributors and audited 75 packages in 4.47s\n",
"\n",
"\n",
"\n",
"4 packages are looking for funding\n",
"\n",
" run `npm fund` for details\n",
"\n",
"\n",
"\n",
"found 0 vulnerabilities\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\u001b[1m OK. \u001b[0m\n",
"\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WBAj5rSkgjKX"
},
"source": [
"Once we've done that, we can create a new `bot` instance, through the `createBot` function. You can see the docs for this function [here](https://github.com/PrismarineJS/mineflayer/blob/master/docs/api.md#bot). In the line below we specify a hostname and a port for the server, but do not pass any `auth` or `password` options, so it will connect to the server in offline mode.\n",
"\n",
"Below that, we also an event handlers, one that gets called on \"spawn\" event and sends a chat message."
]
},
{
"cell_type": "code",
"metadata": {
"id": "1gfZSAUCDVMg"
},
"source": [
"random_number = id([]) % 1000 # Give us a random number upto 1000\n",
"BOT_USERNAME = f'colab_{random_number}'\n",
"\n",
"bot = mineflayer.createBot({ 'host': '95.111.249.143', 'port': 10000, 'username': BOT_USERNAME, 'hideErrors': False })\n",
"\n",
"# The spawn event \n",
"@Once(bot, 'login')\n",
"def spawn(*a):\n",
" bot.chat('I spawned')"
],
"execution_count": 4,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "yvYZYbi0k8Za"
},
"source": [
"If your bot spawned, we can now take a look at the bot's position"
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "swMd1VvXYuKn",
"outputId": "3655292d-0495-40fd-f390-3cd3c1c3cc37"
},
"source": [
"bot.entity.position"
],
"execution_count": 5,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"Vec3 { \u001b[94mx\u001b[39m: \u001b[33m-152.5\u001b[39m, \u001b[94my\u001b[39m: \u001b[33m93\u001b[39m, \u001b[94mz\u001b[39m: \u001b[33m507.5\u001b[39m }"
]
},
"metadata": {
"tags": []
},
"execution_count": 5
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "EdSjlgmilZ3O"
},
"source": [
"### Listening to events"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "23FTp0XrioMg"
},
"source": [
"You can register an event handler with the `@On` or `@Once` decorator. This decorator takes two arguments, first it's the **Event Emitter** (the object that is sending events) and the second is the **event name**, what event you want to listen to. *Do not use the .on or .once methods on bot; use the decorators.*\n",
"\n",
"A decroator always has a function under it which is being decorated, which can have any name. The first parameter to any event emitter callback is the `this` argument. \n",
"\n",
"In the code below, we create an event emitter on `bot` that listens to `playerJoin` events, then print that out."
]
},
{
"cell_type": "code",
"metadata": {
"id": "s8QGmC4nHjnH"
},
"source": [
"@On(bot, 'playerJoin')\n",
"def end(this, player):\n",
" bot.chat('Someone joined!')"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "Onkn-TDsne9P"
},
"source": [
"In Python, you cannot leave any arguments for an event handler callback blank like in JavaScript. Instead, you can use the asterisk (`*`) operator in Python to capture all remaining arguments to the right, much like the `...` rest/spread operator in JavaScript. The parameter with the asterisk will be a tuple containing the captured arguments.\n",
"\n",
"You can stop listening for events through an event handler by using the imported `off` function. It takes three parameters: the emitter, event name, and a reference to the Python function.\n"
]
},
{
"cell_type": "code",
"metadata": {
"id": "S4y9qAe6oh8H"
},
"source": [
"@On(bot, 'chat')\n",
"def onChat(this, user, message, *rest):\n",
" print(f'{user} said \"{message}\"')\n",
"\n",
" # If the message contains stop, remove the event listener and stop logging.\n",
" if 'stop' in message:\n",
" off(bot, 'chat', onChat)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "OybQNxGAq4P2"
},
"source": [
"You need to `off` all the event listeners you listen to with `@On`, else the Python process won't exit until all of the active event emitters have been off'ed. If you only need to listen once, you can use the `@Once` decroator like in the example above."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "iOzZeWfHozeX"
},
"source": [
"## Asynchronous tasks\n",
"\n",
"By default, all the operations you do run on the main thread. This means you can only do one thing at a time. To multitask, you can use the `@AsyncTask` decroator to run a function in a new thread, while not obstructing the main thread."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xJUk8b21pOzg"
},
"source": [
"### Block breaking\n",
"\n",
"Take a look at the example below. Here we listen for a \"break\" trigger in a chat message, then we start digging the block underneath, while simultaneously sending a message that the bot has \"started digging\"."
]
},
{
"cell_type": "code",
"metadata": {
"id": "yhoAlhAhpSTL"
},
"source": [
"@On(bot, 'chat')\n",
"def breakListener(this, sender, message, *args):\n",
" if sender and (sender != BOT_USERNAME):\n",
" if 'break' in message:\n",
" pos = bot.entity.position.offset(0, -1, 0)\n",
" blockUnder = bot.blockAt(pos)\n",
" if bot.canDigBlock(blockUnder):\n",
" bot.chat(f\"I'm breaking the '{blockUnder.name}' block underneath {bot.canDigBlock(blockUnder)}\")\n",
" # The start=True parameter means to immediately invoke the function underneath\n",
" # If left blank, you can start it with the `start()` function later on.\n",
" try:\n",
" @AsyncTask(start=True)\n",
" def break_block(task):\n",
" bot.dig(blockUnder)\n",
" bot.chat('I started digging!')\n",
" except Exception as e:\n",
" bot.chat(f\"I had an error {e}\")\n",
" else:\n",
" bot.chat(f\"I can't break the '{blockUnder.name}' block underneath\")\n",
" if 'stop' in message:\n",
" off(bot, 'chat', breakListener)"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "JMgoMA-MriAt"
},
"source": [
"## Using mineflayer plugins\n",
"\n",
"Pick the plugin you want from the list [here](https://github.com/PrismarineJS/mineflayer#third-party-plugins), then `require()` it and register it to the bot. Some plugins have different ways to register to the bot, look at the plugin's README for usage steps."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "OVAJCyxcsfig"
},
"source": [
"### mineflayer-pathfinder\n",
"\n",
"`mineflayer-pathfinder` is a essential plugin that helps your bot move between places through A* pathfinding. Let's import it:"
]
},
{
"cell_type": "code",
"metadata": {
"id": "mH6eXm8TtTKh",
"colab": {
"base_uri": "https://localhost:8080/"
},
"outputId": "7c8f68ea-d8d8-4aae-f9b9-dcb26700e40f"
},
"source": [
"pathfinder = require('mineflayer-pathfinder')\n",
"bot.loadPlugin(pathfinder.pathfinder)\n",
"# Create a new minecraft-data instance with the bot's version\n",
"mcData = require('minecraft-data')(bot.version)\n",
"# Create a new movements class\n",
"movements = pathfinder.Movements(bot, mcData)\n",
"# How far to be fromt the goal\n",
"RANGE_GOAL = 1"
],
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": [
"\u001b[1m Installing 'mineflayer-pathfinder' version 'latest'... This will only happen once. \u001b[0m\n",
"\n",
"[JSE] npm WARN js-modules@ No repository field.\n",
"[JSE] npm WARN js-modules@ No license field.\n",
"added 1 package from 1 contributor and audited 76 packages in 1.172s\n",
"\n",
"\n",
"\n",
"4 packages are looking for funding\n",
"\n",
" run `npm fund` for details\n",
"\n",
"\n",
"\n",
"found 0 vulnerabilities\n",
"\n",
"\n",
"\n",
"\n",
"\n",
"\u001b[1m OK. \u001b[0m\n",
"\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Ju8MPkSauTBb"
},
"source": [
"Now let's have create a goal for the bot to move to where another player wants, based on a chat message."
]
},
{
"cell_type": "code",
"metadata": {
"id": "8jIp8bxnudDK"
},
"source": [
"bot.removeAllListeners('chat')\n",
"@On(bot, 'chat')\n",
"def handleMsg(this, sender, message, *args):\n",
" if sender and (sender != BOT_USERNAME):\n",
" bot.chat('Hi, you said ' + message)\n",
" if 'come' in message:\n",
" player = bot.players[sender]\n",
" target = player.entity\n",
" if not target:\n",
" bot.chat(\"I don't see you !\")\n",
" return\n",
" pos = target.position\n",
" bot.pathfinder.setMovements(movements)\n",
" bot.pathfinder.setGoal(pathfinder.goals.GoalNear(pos.x, pos.y, pos.z, RANGE_GOAL))\n",
" if 'stop' in message:\n",
" off(bot, 'chat', handleMsg)"
],
"execution_count": 15,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "K36XDP09k1aH"
},
"source": [
"## Analyzing the world"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "xK1Ww1ACmLZl"
},
"source": [
"You can also interact with mineflayer through any other Python package."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5QatUqxeW6b_"
},
"source": [
"Let's analyze some block frequencies..."
]
},
{
"cell_type": "code",
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 354
},
"id": "k2XyRgzi8otw",
"outputId": "028048ad-554f-4d8b-b3d0-6c1daa562902"
},
"source": [
"import matplotlib.pyplot as plt\n",
"figure = plt.figure()\n",
"axes = figure.add_axes([0,0,1,1])\n",
"Vec3 = require('vec3').Vec3\n",
"\n",
"columns = bot.world.getColumns()\n",
"block_freqs = {}\n",
"for c in range(0, 4): # iterate through some of the loaded chunk columns\n",
" cc = columns[c].column\n",
" for y in range(1, 40):\n",
" for x in range(1, 16):\n",
" for z in range(1, 16):\n",
" block = cc.getBlock(Vec3(x, y, z))\n",
" if block.name in block_freqs:\n",
" block_freqs[block.name] += 1\n",
" else:\n",
" block_freqs[block.name] = 1\n",
"\n",
"print(block_freqs)\n",
"axes.bar(block_freqs.keys(), block_freqs.values())\n",
"plt.show()"
],
"execution_count": null,
"outputs": [
{
"output_type": "stream",
"text": [
"{'stone': 32200, 'bedrock': 1807, 'dirt': 665, 'gravel': 340, 'lava': 56, 'coal_ore': 1, 'air': 30, 'torch': 1}\n"
],
"name": "stdout"
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "q2IkKpXZzRiP"
},
"source": [
"## Exiting the bot\n",
"\n",
"Once you're done, you can call `bot.quit()` or `bot.end()` to disconnect and stop the bot."
]
},
{
"cell_type": "code",
"metadata": {
"id": "1-NxvPk1YuGw"
},
"source": [
"bot.quit()"
],
"execution_count": 16,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "SpwlmlCBc90Q"
},
"source": [
"## Read more\n",
"\n",
"* **API** - https://github.com/PrismarineJS/mineflayer/blob/master/docs/api.md\n",
"* **Type Definitions** - https://github.com/PrismarineJS/mineflayer/blob/master/index.d.ts\n",
"* FAQ - https://github.com/PrismarineJS/mineflayer/blob/master/docs/FAQ.md\n",
"* JS tutorial - https://github.com/PrismarineJS/mineflayer/blob/master/docs/tutorial.md\n"
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment