├── .gitattributes ├── .gitconfig ├── .gitignore ├── .travis.yml ├── AUTHORS ├── CONTRIBUTING.rst ├── LEGAL.md ├── LICENSE ├── MANIFEST.in ├── README.rst ├── dev-requirements.txt ├── docs ├── Makefile ├── authors.rst ├── conf.py ├── contributing.rst ├── getting-started.rst ├── index.rst ├── installation.rst ├── license.rst ├── modules │ ├── index.rst │ ├── modules.rst │ ├── spockbot.mcdata.biomes.rst │ ├── spockbot.mcdata.blocks.rst │ ├── spockbot.mcdata.constants.rst │ ├── spockbot.mcdata.items.rst │ ├── spockbot.mcdata.materials.rst │ ├── spockbot.mcdata.recipes.rst │ ├── spockbot.mcdata.rst │ ├── spockbot.mcdata.utils.rst │ ├── spockbot.mcdata.windows.rst │ ├── spockbot.mcp.bbuff.rst │ ├── spockbot.mcp.datautils.rst │ ├── spockbot.mcp.mcdata.rst │ ├── spockbot.mcp.mcpacket.rst │ ├── spockbot.mcp.mcpacket_extensions.rst │ ├── spockbot.mcp.nbt.rst │ ├── spockbot.mcp.rst │ ├── spockbot.mcp.yggdrasil.rst │ ├── spockbot.plugins.base.rst │ ├── spockbot.plugins.core.auth.rst │ ├── spockbot.plugins.core.event.rst │ ├── spockbot.plugins.core.net.rst │ ├── spockbot.plugins.core.rst │ ├── spockbot.plugins.core.settings.rst │ ├── spockbot.plugins.core.taskmanager.rst │ ├── spockbot.plugins.core.ticker.rst │ ├── spockbot.plugins.core.timer.rst │ ├── spockbot.plugins.helpers.channels.rst │ ├── spockbot.plugins.helpers.chat.rst │ ├── spockbot.plugins.helpers.clientinfo.rst │ ├── spockbot.plugins.helpers.craft.rst │ ├── spockbot.plugins.helpers.entities.rst │ ├── spockbot.plugins.helpers.interact.rst │ ├── spockbot.plugins.helpers.inventory.rst │ ├── spockbot.plugins.helpers.keepalive.rst │ ├── spockbot.plugins.helpers.movement.rst │ ├── spockbot.plugins.helpers.pathfinding.rst │ ├── spockbot.plugins.helpers.physics.rst │ ├── spockbot.plugins.helpers.respawn.rst │ ├── spockbot.plugins.helpers.rst │ ├── spockbot.plugins.helpers.start.rst │ ├── spockbot.plugins.helpers.world.rst │ ├── spockbot.plugins.loader.rst │ ├── spockbot.plugins.rst │ ├── spockbot.plugins.tools.collision.rst │ ├── spockbot.plugins.tools.event.rst │ ├── spockbot.plugins.tools.inventory_async.rst │ ├── spockbot.plugins.tools.rst │ ├── spockbot.plugins.tools.smpmap.rst │ ├── spockbot.plugins.tools.task.rst │ ├── spockbot.rst │ └── spockbot.vector.rst └── plugins │ ├── core │ ├── auth.rst │ ├── event.rst │ ├── index.rst │ ├── net.rst │ ├── settings.rst │ ├── taskmanager.rst │ ├── ticker.rst │ └── timer.rst │ ├── helpers │ ├── channels.rst │ ├── chat.rst │ ├── clientinfo.rst │ ├── craft.rst │ ├── entities.rst │ ├── index.rst │ ├── interact.rst │ ├── inventory.rst │ ├── keepalive.rst │ ├── movement.rst │ ├── pathfinding.rst │ ├── physics.rst │ ├── respawn.rst │ ├── start.rst │ └── world.rst │ └── index.rst ├── examples └── basic │ ├── README.md │ ├── __init__.py │ ├── example.py │ └── example_plugin.py ├── setup.cfg ├── setup.py ├── spockbot ├── __init__.py ├── mcdata │ ├── __init__.py │ ├── biomes.py │ ├── blocks.py │ ├── constants.py │ ├── items.py │ ├── materials.py │ ├── recipes.py │ ├── utils.py │ └── windows.py ├── mcp │ ├── __init__.py │ ├── bbuff.py │ ├── datautils.py │ ├── extensions.py │ ├── mcpacket.py │ ├── nbt.py │ ├── proto.py │ └── yggdrasil.py ├── plugins │ ├── __init__.py │ ├── base.py │ ├── core │ │ ├── __init__.py │ │ ├── auth.py │ │ ├── event.py │ │ ├── net.py │ │ ├── select.py │ │ ├── settings.py │ │ ├── taskmanager.py │ │ ├── ticker.py │ │ └── timers.py │ ├── helpers │ │ ├── __init__.py │ │ ├── auxiliary.py │ │ ├── channels.py │ │ ├── chat.py │ │ ├── clientinfo.py │ │ ├── craft.py │ │ ├── entities.py │ │ ├── interact.py │ │ ├── inventory.py │ │ ├── movement.py │ │ ├── pathfinding.py │ │ ├── physics.py │ │ ├── start.py │ │ └── world.py │ ├── loader.py │ └── tools │ │ ├── __init__.py │ │ ├── collision.py │ │ ├── event.py │ │ ├── inventory_async.py │ │ ├── smpmap.py │ │ └── task.py └── vector.py ├── tests ├── __init__.py ├── mcp │ ├── __init__.py │ ├── test_datautils.py │ └── test_yggdrasil.py ├── plugins │ ├── __init__.py │ ├── core │ │ ├── __init__.py │ │ ├── test_auth.py │ │ └── test_taskmanager.py │ ├── helpers │ │ ├── __init__.py │ │ ├── test_chat.py │ │ └── test_interact.py │ └── test_base.py └── test_vector.py └── tox.ini /.gitattributes: -------------------------------------------------------------------------------- 1 | *.py filter=spabs 2 | -------------------------------------------------------------------------------- /.gitconfig: -------------------------------------------------------------------------------- 1 | [filter "spabs"] 2 | clean = expand --initial -t 4 3 | smudge = expand --initial -t 4 4 | required 5 | [merge] 6 | renormalize = true 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[doc] 2 | *.log 3 | *.swp 4 | .cache 5 | *~ 6 | __pycache__/ 7 | config.yaml 8 | login.py 9 | run.py 10 | contrib/ 11 | 12 | #generated files 13 | /dist/ 14 | /build/ 15 | /.tox/ 16 | *.egg-info/ 17 | xunit-*.xml 18 | .coverage 19 | /tags 20 | packetlog 21 | /htmlcov/ 22 | _build 23 | _templates 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: python 4 | 5 | python: 6 | - "2.7_with_system_site_packages" 7 | 8 | env: 9 | - TOX_ENV=py27 10 | - TOX_ENV=py33 11 | - TOX_ENV=py34 12 | - TOX_ENV=flake8 13 | 14 | install: 15 | - "pip install tox" 16 | 17 | script: 18 | - "tox -e $TOX_ENV" 19 | 20 | after_success: 21 | - "if [ `echo $TOX_ENV | grep -v flake8` ]; then pip install coveralls; coveralls; fi" 22 | 23 | # whitelist 24 | branches: 25 | only: 26 | - master 27 | 28 | notifications: 29 | irc: 30 | channels: 31 | - "irc.freenode.org#spockbot" 32 | template: 33 | - "%{repository_name}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}" 34 | - "Build details: %{build_url}" 35 | on_success: change 36 | on_failure: change 37 | use_notice: false 38 | skip_join: true 39 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | - Nicholas Gamberini 2 | - Morgan Creekmore 3 | - gjum 4 | - Jasper Bok 5 | - Javier Domingo 6 | - Joshua Aune 7 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Fork, Clone 2 | ----------- 3 | 4 | Fork the SpockBot repository, then clone your fork locally. 5 | 6 | Setup 7 | ----- 8 | 9 | Configure remote 10 | ~~~~~~~~~~~~~~~~ 11 | 12 | :: 13 | 14 | $ cd SpockBot 15 | $ git remote add upstream git://github.com/SpockBotMC/SpockBot 16 | 17 | Install development dependencies 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 20 | :: 21 | 22 | $ pip3 install -r dev-requirements.txt 23 | 24 | Install extra test interpreters 25 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 | 27 | Installing the extra interpreters allows tox to test against multiple 28 | versions of python. 29 | 30 | :: 31 | 32 | $ sudo apt-get install python2.7 python3.3 python3.4 33 | 34 | Development 35 | ----------- 36 | 37 | Create development branch 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | 40 | **Do not** work in the ``master`` branch, create a bug or feature branch 41 | and work from there. ``master`` should always be a mirror of upstream 42 | master. 43 | 44 | :: 45 | 46 | $ git checkout -b feature-tacocat 47 | 48 | Please use a more descriptive branch name than ``feature-tacocat`` 49 | 50 | Hack away at the code 51 | ~~~~~~~~~~~~~~~~~~~~~ 52 | 53 | Have fun! 54 | 55 | Docstrings 56 | ~~~~~~~~~~ 57 | 58 | We use Google Style Python Docstrings, an example can be found `here `__ 59 | 60 | Test your changes 61 | ~~~~~~~~~~~~~~~~~ 62 | 63 | Running ``tox`` will test that your changes pass all tests and follows 64 | the pep8 standard. 65 | 66 | :: 67 | 68 | $ tox 69 | 70 | Pull Request 71 | ~~~~~~~~~~~~ 72 | 73 | If ``tox`` comes back with a success you are ready for a pull request. 74 | Commit your changes to your feature branch, push them to your fork and 75 | create a pull request. 76 | 77 | Testing 78 | ------- 79 | 80 | We highly encourage writing tests, we use the pytest framework and you 81 | can run ``tox`` to test your newly written tests. 82 | -------------------------------------------------------------------------------- /LEGAL.md: -------------------------------------------------------------------------------- 1 | See LICENSE for SpockBot's license 2 | 3 | NBT 4 | === 5 | 6 | We use a slightly modified version of Thomas Woolford's NBT parser in 7 | spockbot/mcp/nbt.py, original can be found here: 8 | https://github.com/twoolie/NBT 9 | 10 | Copyright (c) 2010 Thomas Woolford 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a 13 | copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included 21 | in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 27 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 28 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 29 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | BarneyMC 32 | ======== 33 | 34 | The Minecraft protocol implementation found in spockbot/mcp is largely 35 | modeled after Barney Gale's implementation from barneymc and retains 36 | many of its naming conventions. However, much of the code has been 37 | rewritten following the massive Minecraft 1.7 networking update. 38 | Barney's original implementation can be found here: 39 | https://github.com/barneygale/barneymc 40 | 41 | Copyright (c) 2012 Barney Gale 42 | 43 | Permission is hereby granted, free of charge, to any person obtaining a 44 | copy of this software and associated documentation files (the 45 | "Software"), to deal in the Software without restriction, including 46 | without limitation the rights to use, copy, modify, merge, publish, 47 | distribute, sublicense, and/or sell copies of the Software, and to 48 | permit persons to whom the Software is furnished to do so, subject to 49 | the following conditions: 50 | 51 | The above copyright notice and this permission notice shall be included 52 | in all copies or substantial portions of the Software. 53 | 54 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 55 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 56 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 57 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 58 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 59 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 60 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2015 The SpockBot Project 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.md 2 | include *.rst 3 | include AUTHORS 4 | include LICENSE 5 | include MANIFEST.in 6 | include tox.ini 7 | include *.py 8 | include *.txt 9 | include .travis.yml 10 | recursive-include examples *.md 11 | recursive-include examples *.py 12 | recursive-include tests *.py 13 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | SpockBot 2 | ======== 3 | 4 | |Build Status| |Docs Status| |Coverage Status| 5 | 6 | SpockBot currently supports Minecraft 1.8.8 7 | 8 | Minecraft bot framework written in Python, currently under heavy development. 9 | 10 | - Protocol stuff lives in `spockbot/mcp `__ 11 | - Map stuff lives in `spockbot/mcmap `__ 12 | - Data stuff lives in `spockbot/mcdata `__ 13 | - Core client stuff lives in `spockbot/plugins/core `__ 14 | - Helpful client stuff lives in `spockbot/plugins/helpers `__ 15 | 16 | Client could loosely be called "event-driven". By default plugins 17 | register handler functions to handle events that may or may not be 18 | emitted by other plugins. Everything is a plugin in SpockBot, including 19 | the event loop/framework itself, so you can feel free to rip out the 20 | entire back end and replace it with your framework or paradigm of choice. 21 | As long as you provide the same simple APIs, other plugins won't know the 22 | difference. 23 | 24 | We're only just getting started with documentation so if you're uncomfortable 25 | reading source code this might not be the framework for you. Or, better yet, 26 | hop on IRC and help us write some docs! 27 | 28 | SpockBot officially supports Python 3.x and Python 2.7.x on \*nix operating 29 | systems and requires cryptography_. It also runs on Windows and under 30 | PyPy 2.6.x but that's not regularly tested and could be broken at any given 31 | moment. If you support one of those use cases and SpockBot breaks for you, 32 | submit an issue with a stack trace and we'll try to fix it. 33 | 34 | 35 | Features 36 | -------- 37 | 38 | - World Interaction (finding, placing, breaking) 39 | - Vanilla Physics 40 | - Pathfinding 41 | - Inventory (player, chests, etc) 42 | - Crafting 43 | - Entity Tracking 44 | 45 | 46 | Dependencies 47 | ------------ 48 | 49 | - Python 3.x or Python 2.7.x or PyPy 2.6.x 50 | - cryptography_ 0.9+ 51 | - minecraft_data_ 52 | - six 53 | 54 | Installation 55 | ------------ 56 | 57 | ``python3 setup.py install`` 58 | 59 | **Note:** 60 | The cryptography library has some extra dependencies to install, you can find detailed instructions `here `__. 61 | 62 | Documentation 63 | ------------- 64 | 65 | Current docs live here https://spockbot.readthedocs.org 66 | 67 | Examples 68 | -------- 69 | 70 | Refer to the `example bot `__ for instructions on how to 71 | write a bot and a plugin that provides some common functionality. 72 | 73 | Also see `Extra examples `__ 74 | and `Bat bot `__ 75 | for additional examples. 76 | 77 | Projects Using SpockBot 78 | ----------------------- 79 | 80 | - `Gjum/bat `__ - High level bot 81 | - `opencog/opencog-to-minecraft `__ - Interface linking Minecraft to OpenCog 82 | 83 | Support 84 | ------- 85 | 86 | | ``#spockbot`` on Freenode 87 | | gamingrobot or nickelpro in ``#mcdevs`` on Freenode 88 | 89 | Contributing 90 | ------------ 91 | 92 | Instructions for contributing to SpockBot can be found in `CONTRIBUTING `__ 93 | 94 | Credits 95 | ------- 96 | 97 | Inspired by `remyroy's 98 | COPS `__, 99 | a Minecraft client in Python. 100 | 101 | COPS was a service that tracked players on a minecraft server called Civcraft. It looked like `this `__ 102 | 103 | Protocol implementation based on `barneymc `__. 104 | 105 | Legal 106 | ----- 107 | 108 | This project is licensed under the MIT License which can be found in `LICENSE `__ 109 | 110 | The NBT parser and the original protocol implementation came from other projects, relevant legal information and attribution can be found in `LEGAL `__ 111 | 112 | .. |Build Status| image:: https://travis-ci.org/SpockBotMC/SpockBot.svg 113 | :target: https://travis-ci.org/SpockBotMC/SpockBot 114 | .. |Coverage Status| image:: https://coveralls.io/repos/SpockBotMC/SpockBot/badge.svg?branch=master&service=github 115 | :target: https://coveralls.io/github/SpockBotMC/SpockBot?branch=master 116 | .. |Docs Status| image:: https://readthedocs.org/projects/spockbot/badge/?version=latest 117 | :target: http://spockbot.readthedocs.org/en/latest/?badge=latest 118 | .. _cryptography: https://cryptography.io/ 119 | .. _minecraft_data: https://pypi.python.org/pypi/minecraft_data 120 | -------------------------------------------------------------------------------- /dev-requirements.txt: -------------------------------------------------------------------------------- 1 | # Check code style, errors, etc. 2 | flake8 3 | flake8-import-order 4 | pep8-naming 5 | 6 | # Test runners 7 | pytest 8 | pytest-capturelog 9 | pytest-cov 10 | pytest-xdist 11 | tox 12 | mock 13 | 14 | # Check all files in git are in MANIFEST.in 15 | check-manifest 16 | 17 | # Build documentation 18 | sphinx 19 | sphinx_rtd_theme 20 | sphinxcontrib-spelling 21 | 22 | # To make wheel packages 23 | wheel 24 | 25 | # Securely upload packages to PyPI 26 | twine 27 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " applehelp to make an Apple Help Book" 34 | @echo " devhelp to make HTML files and a Devhelp project" 35 | @echo " epub to make an epub" 36 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 37 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 38 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 39 | @echo " text to make text files" 40 | @echo " man to make manual pages" 41 | @echo " texinfo to make Texinfo files" 42 | @echo " info to make Texinfo files and run them through makeinfo" 43 | @echo " gettext to make PO message catalogs" 44 | @echo " changes to make an overview of all changed/added/deprecated items" 45 | @echo " xml to make Docutils-native XML files" 46 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 47 | @echo " linkcheck to check all external links for integrity" 48 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 49 | @echo " coverage to run coverage check of the documentation (if enabled)" 50 | 51 | clean: 52 | rm -rf $(BUILDDIR)/* 53 | 54 | html: 55 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 56 | @echo 57 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 58 | 59 | dirhtml: 60 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 61 | @echo 62 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 63 | 64 | singlehtml: 65 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 66 | @echo 67 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 68 | 69 | pickle: 70 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 71 | @echo 72 | @echo "Build finished; now you can process the pickle files." 73 | 74 | json: 75 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 76 | @echo 77 | @echo "Build finished; now you can process the JSON files." 78 | 79 | htmlhelp: 80 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 81 | @echo 82 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 83 | ".hhp project file in $(BUILDDIR)/htmlhelp." 84 | 85 | qthelp: 86 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 87 | @echo 88 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 89 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 90 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SpockBot.qhcp" 91 | @echo "To view the help file:" 92 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SpockBot.qhc" 93 | 94 | applehelp: 95 | $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp 96 | @echo 97 | @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." 98 | @echo "N.B. You won't be able to view it unless you put it in" \ 99 | "~/Library/Documentation/Help or install it in your application" \ 100 | "bundle." 101 | 102 | devhelp: 103 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 104 | @echo 105 | @echo "Build finished." 106 | @echo "To view the help file:" 107 | @echo "# mkdir -p $$HOME/.local/share/devhelp/SpockBot" 108 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SpockBot" 109 | @echo "# devhelp" 110 | 111 | epub: 112 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 113 | @echo 114 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 115 | 116 | latex: 117 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 118 | @echo 119 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 120 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 121 | "(use \`make latexpdf' here to do that automatically)." 122 | 123 | latexpdf: 124 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 125 | @echo "Running LaTeX files through pdflatex..." 126 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 127 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 128 | 129 | latexpdfja: 130 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 131 | @echo "Running LaTeX files through platex and dvipdfmx..." 132 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 133 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 134 | 135 | text: 136 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 137 | @echo 138 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 139 | 140 | man: 141 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 142 | @echo 143 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 144 | 145 | texinfo: 146 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 147 | @echo 148 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 149 | @echo "Run \`make' in that directory to run these through makeinfo" \ 150 | "(use \`make info' here to do that automatically)." 151 | 152 | info: 153 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 154 | @echo "Running Texinfo files through makeinfo..." 155 | make -C $(BUILDDIR)/texinfo info 156 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 157 | 158 | gettext: 159 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 160 | @echo 161 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 162 | 163 | changes: 164 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 165 | @echo 166 | @echo "The overview file is in $(BUILDDIR)/changes." 167 | 168 | linkcheck: 169 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 170 | @echo 171 | @echo "Link check complete; look for any errors in the above output " \ 172 | "or in $(BUILDDIR)/linkcheck/output.txt." 173 | 174 | doctest: 175 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 176 | @echo "Testing of doctests in the sources finished, look at the " \ 177 | "results in $(BUILDDIR)/doctest/output.txt." 178 | 179 | coverage: 180 | $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage 181 | @echo "Testing of coverage in the sources finished, look at the " \ 182 | "results in $(BUILDDIR)/coverage/python.txt." 183 | 184 | xml: 185 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 186 | @echo 187 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 188 | 189 | pseudoxml: 190 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 191 | @echo 192 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 193 | -------------------------------------------------------------------------------- /docs/authors.rst: -------------------------------------------------------------------------------- 1 | .. _authors: 2 | 3 | ******* 4 | Authors 5 | ******* 6 | 7 | The following persons have contributed to SpockBot. The list is in the order of 8 | first contribution. For details on who contributed what, please refer to 9 | our Git repository. 10 | 11 | .. include:: ../AUTHORS 12 | 13 | -------------------------------------------------------------------------------- /docs/contributing.rst: -------------------------------------------------------------------------------- 1 | .. _contributing: 2 | 3 | ************ 4 | Contributing 5 | ************ 6 | 7 | .. include:: ../CONTRIBUTING.rst 8 | 9 | -------------------------------------------------------------------------------- /docs/getting-started.rst: -------------------------------------------------------------------------------- 1 | .. _getting-started: 2 | 3 | *************** 4 | Getting Started 5 | *************** 6 | 7 | See the `Basic Example Bot `__ for basic usage of SpockBot. 8 | 9 | Also see the `Extra Repository `__ for some more plugin examples. 10 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | ******** 2 | SpockBot 3 | ******** 4 | 5 | Welcome to SpockBot's documentation! 6 | ==================================== 7 | 8 | .. toctree:: 9 | :caption: Usage 10 | :maxdepth: 1 11 | 12 | installation 13 | getting-started 14 | 15 | .. toctree:: 16 | :caption: Reference 17 | :maxdepth: 2 18 | 19 | plugins/index 20 | modules/index 21 | 22 | .. toctree:: 23 | :caption: Development 24 | :maxdepth: 1 25 | 26 | contributing 27 | 28 | .. toctree:: 29 | :caption: About 30 | :maxdepth: 1 31 | 32 | authors 33 | license 34 | 35 | 36 | Indices and tables 37 | ================== 38 | 39 | * :ref:`genindex` 40 | * :ref:`modindex` 41 | 42 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. _installation: 2 | 3 | ************ 4 | Installation 5 | ************ 6 | 7 | If you are looking to contribute to SpockBot please follow the instructions :ref:`here `. 8 | 9 | #. Install cryptography first, instructions for that are `here `__ 10 | 11 | #. Clone the repository locally:: 12 | 13 | git clone https://github.com/SpockBotMC/SpockBot.git 14 | 15 | #. Install SpockBot:: 16 | 17 | cd SpockBot 18 | python3 setup.py install 19 | 20 | -------------------------------------------------------------------------------- /docs/license.rst: -------------------------------------------------------------------------------- 1 | .. _license: 2 | 3 | ******* 4 | License 5 | ******* 6 | 7 | .. include:: ../LICENSE 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/modules/index.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | spockbot 8 | -------------------------------------------------------------------------------- /docs/modules/modules.rst: -------------------------------------------------------------------------------- 1 | spockbot 2 | ======== 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | spockbot 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.biomes.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.biomes module 2 | ============================= 3 | 4 | .. automodule:: spockbot.mcdata.biomes 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.blocks.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.blocks module 2 | ============================= 3 | 4 | .. automodule:: spockbot.mcdata.blocks 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.constants.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.constants module 2 | ================================ 3 | 4 | .. automodule:: spockbot.mcdata.constants 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.items.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.items module 2 | ============================ 3 | 4 | .. automodule:: spockbot.mcdata.items 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.materials.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.materials module 2 | ================================ 3 | 4 | .. automodule:: spockbot.mcdata.materials 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.recipes.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.recipes module 2 | ============================== 3 | 4 | .. automodule:: spockbot.mcdata.recipes 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata package 2 | ======================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.mcdata.biomes 10 | spockbot.mcdata.blocks 11 | spockbot.mcdata.constants 12 | spockbot.mcdata.items 13 | spockbot.mcdata.materials 14 | spockbot.mcdata.recipes 15 | spockbot.mcdata.utils 16 | spockbot.mcdata.windows 17 | 18 | Module contents 19 | --------------- 20 | 21 | .. automodule:: spockbot.mcdata 22 | :members: 23 | :undoc-members: 24 | :show-inheritance: 25 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.utils.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.utils module 2 | ============================ 3 | 4 | .. automodule:: spockbot.mcdata.utils 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcdata.windows.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcdata.windows module 2 | ============================== 3 | 4 | .. automodule:: spockbot.mcdata.windows 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.bbuff.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.bbuff module 2 | ========================= 3 | 4 | .. automodule:: spockbot.mcp.bbuff 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.datautils.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.datautils module 2 | ============================= 3 | 4 | .. automodule:: spockbot.mcp.datautils 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.mcdata.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.mcdata module 2 | ========================== 3 | 4 | .. automodule:: spockbot.mcp.mcdata 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.mcpacket.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.mcpacket module 2 | ============================ 3 | 4 | .. automodule:: spockbot.mcp.mcpacket 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.mcpacket_extensions.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.mcpacket_extensions module 2 | ======================================= 3 | 4 | .. automodule:: spockbot.mcp.mcpacket_extensions 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.nbt.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.nbt module 2 | ======================= 3 | 4 | .. automodule:: spockbot.mcp.nbt 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp package 2 | ==================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.mcp.bbuff 10 | spockbot.mcp.datautils 11 | spockbot.mcp.mcdata 12 | spockbot.mcp.mcpacket 13 | spockbot.mcp.mcpacket_extensions 14 | spockbot.mcp.nbt 15 | spockbot.mcp.yggdrasil 16 | 17 | Module contents 18 | --------------- 19 | 20 | .. automodule:: spockbot.mcp 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | -------------------------------------------------------------------------------- /docs/modules/spockbot.mcp.yggdrasil.rst: -------------------------------------------------------------------------------- 1 | spockbot.mcp.yggdrasil module 2 | ============================= 3 | 4 | .. automodule:: spockbot.mcp.yggdrasil 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.base.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.base module 2 | ============================ 3 | 4 | .. automodule:: spockbot.plugins.base 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.auth.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.auth module 2 | ================================= 3 | 4 | .. automodule:: spockbot.plugins.core.auth 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.event.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.event module 2 | ================================== 3 | 4 | .. automodule:: spockbot.plugins.core.event 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.net.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.net module 2 | ================================ 3 | 4 | .. automodule:: spockbot.plugins.core.net 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core package 2 | ============================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.plugins.core.auth 10 | spockbot.plugins.core.event 11 | spockbot.plugins.core.net 12 | spockbot.plugins.core.settings 13 | spockbot.plugins.core.taskmanager 14 | spockbot.plugins.core.ticker 15 | spockbot.plugins.core.timer 16 | 17 | Module contents 18 | --------------- 19 | 20 | .. automodule:: spockbot.plugins.core 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.settings.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.settings module 2 | ===================================== 3 | 4 | .. automodule:: spockbot.plugins.core.settings 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.taskmanager.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.taskmanager module 2 | ======================================== 3 | 4 | .. automodule:: spockbot.plugins.core.taskmanager 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.ticker.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.ticker module 2 | =================================== 3 | 4 | .. automodule:: spockbot.plugins.core.ticker 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.core.timer.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.core.timer module 2 | ================================== 3 | 4 | .. automodule:: spockbot.plugins.core.timer 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.channels.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.channels module 2 | ======================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.channels 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.chat.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.chat module 2 | ==================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.chat 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.clientinfo.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.clientinfo module 2 | ========================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.clientinfo 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.craft.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.craft module 2 | ===================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.craft 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.entities.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.entities module 2 | ======================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.entities 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.interact.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.interact module 2 | ======================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.interact 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.inventory.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.inventory module 2 | ========================================= 3 | 4 | .. automodule:: spockbot.plugins.helpers.inventory 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.keepalive.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.keepalive module 2 | ========================================= 3 | 4 | .. automodule:: spockbot.plugins.helpers.keepalive 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.movement.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.movement module 2 | ======================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.movement 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.pathfinding.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.pathfinding module 2 | =========================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.pathfinding 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.physics.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.physics module 2 | ======================================= 3 | 4 | .. automodule:: spockbot.plugins.helpers.physics 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.respawn.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.respawn module 2 | ======================================= 3 | 4 | .. automodule:: spockbot.plugins.helpers.respawn 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers package 2 | ================================ 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.plugins.helpers.channels 10 | spockbot.plugins.helpers.chat 11 | spockbot.plugins.helpers.clientinfo 12 | spockbot.plugins.helpers.craft 13 | spockbot.plugins.helpers.entities 14 | spockbot.plugins.helpers.interact 15 | spockbot.plugins.helpers.inventory 16 | spockbot.plugins.helpers.keepalive 17 | spockbot.plugins.helpers.movement 18 | spockbot.plugins.helpers.pathfinding 19 | spockbot.plugins.helpers.physics 20 | spockbot.plugins.helpers.respawn 21 | spockbot.plugins.helpers.start 22 | spockbot.plugins.helpers.world 23 | 24 | Module contents 25 | --------------- 26 | 27 | .. automodule:: spockbot.plugins.helpers 28 | :members: 29 | :undoc-members: 30 | :show-inheritance: 31 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.start.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.start module 2 | ===================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.start 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.helpers.world.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.helpers.world module 2 | ===================================== 3 | 4 | .. automodule:: spockbot.plugins.helpers.world 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.loader.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.loader module 2 | ============================== 3 | 4 | .. automodule:: spockbot.plugins.loader 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins package 2 | ======================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.plugins.core 10 | spockbot.plugins.helpers 11 | spockbot.plugins.tools 12 | 13 | Submodules 14 | ---------- 15 | 16 | .. toctree:: 17 | 18 | spockbot.plugins.base 19 | spockbot.plugins.loader 20 | 21 | Module contents 22 | --------------- 23 | 24 | .. automodule:: spockbot.plugins 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.collision.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools.collision module 2 | ======================================= 3 | 4 | .. automodule:: spockbot.plugins.tools.collision 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.event.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools.event module 2 | =================================== 3 | 4 | .. automodule:: spockbot.plugins.tools.event 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.inventory_async.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools.inventory_async module 2 | ============================================= 3 | 4 | .. automodule:: spockbot.plugins.tools.inventory_async 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools package 2 | ============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.plugins.tools.collision 10 | spockbot.plugins.tools.event 11 | spockbot.plugins.tools.inventory_async 12 | spockbot.plugins.tools.smpmap 13 | spockbot.plugins.tools.task 14 | 15 | Module contents 16 | --------------- 17 | 18 | .. automodule:: spockbot.plugins.tools 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.smpmap.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools.smpmap module 2 | ==================================== 3 | 4 | .. automodule:: spockbot.plugins.tools.smpmap 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.plugins.tools.task.rst: -------------------------------------------------------------------------------- 1 | spockbot.plugins.tools.task module 2 | ================================== 3 | 4 | .. automodule:: spockbot.plugins.tools.task 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/modules/spockbot.rst: -------------------------------------------------------------------------------- 1 | spockbot package 2 | ================ 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | 9 | spockbot.mcdata 10 | spockbot.mcp 11 | spockbot.plugins 12 | 13 | Submodules 14 | ---------- 15 | 16 | .. toctree:: 17 | 18 | spockbot.vector 19 | 20 | Module contents 21 | --------------- 22 | 23 | .. automodule:: spockbot 24 | :members: 25 | :undoc-members: 26 | :show-inheritance: 27 | -------------------------------------------------------------------------------- /docs/modules/spockbot.vector.rst: -------------------------------------------------------------------------------- 1 | spockbot.vector module 2 | ====================== 3 | 4 | .. automodule:: spockbot.vector 5 | :members: 6 | :undoc-members: 7 | :show-inheritance: 8 | -------------------------------------------------------------------------------- /docs/plugins/core/auth.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-auth: 2 | 3 | **** 4 | Auth 5 | **** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.auth 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: AuthCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/core/event.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-event: 2 | 3 | ***** 4 | Event 5 | ***** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.event 10 | 11 | Events 12 | ====== 13 | .. object:: event_start 14 | 15 | Fired before the first iteration of the event loop. The default 16 | StartPlugin depends on this event. 17 | 18 | .. object:: event_tick 19 | 20 | Fired at the beginning of every iteration of the event loop. The default 21 | NetPlugin depends on this event. 22 | 23 | .. object:: event_kill 24 | 25 | Fired after the last iteration of the event loop. Many plugins depend on 26 | this event for environment clean up purposes. 27 | 28 | Methods and Attributes 29 | ====================== 30 | .. autoclass:: EventCore 31 | :members: 32 | :undoc-members: 33 | -------------------------------------------------------------------------------- /docs/plugins/core/index.rst: -------------------------------------------------------------------------------- 1 | Core Plugins 2 | ============ 3 | 4 | .. toctree:: 5 | :hidden: 6 | 7 | auth 8 | event 9 | net 10 | settings 11 | taskmanager 12 | ticker 13 | timer 14 | 15 | 16 | - :ref:`plugin-auth` - Handling Minecraft account authentication 17 | - :ref:`plugin-event` - Provides an event system 18 | - :ref:`plugin-net` - Handles packets 19 | - :ref:`plugin-settings` - Allows custom settings handlers 20 | - :ref:`plugin-taskmanager` - Create state machine tasks 21 | - :ref:`plugin-ticker` - Ticks 20 times a second 22 | - :ref:`plugin-timer` - Create timers to do stuff later 23 | 24 | -------------------------------------------------------------------------------- /docs/plugins/core/net.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-net: 2 | 3 | *** 4 | Net 5 | *** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.net 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: NetCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/core/settings.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-settings: 2 | 3 | ******** 4 | Settings 5 | ******** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.settings 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | Undocumented 18 | -------------------------------------------------------------------------------- /docs/plugins/core/taskmanager.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-taskmanager: 2 | 3 | ************ 4 | Task Manager 5 | ************ 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.taskmanager 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | Undocumented 18 | -------------------------------------------------------------------------------- /docs/plugins/core/ticker.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-ticker: 2 | 3 | ****** 4 | Ticker 5 | ****** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.ticker 10 | 11 | Events 12 | ====== 13 | .. object:: action_tick 14 | 15 | This tick is for scheduling physical actions for the client, specifically 16 | those related to movement. Any plugin that wishes to move the client 17 | should schedule those movements by hooking into `action_tick` and calling 18 | the appropriate pathfinding or movement methods. 19 | 20 | .. object:: physics_tick 21 | 22 | This tick fires immediately after `action_tick` and signals that all 23 | movement actions have been scheduled and the client is ready to process 24 | the movement actions as well as world forces to resolve a position for 25 | the client. The default PhysicsPlugin depends on this event. 26 | 27 | .. object:: client_tick 28 | 29 | This tick fires immediately after `physics_tick` and signals that a new 30 | position has been resolved for the client and is ready to be sent to the 31 | server. The default MovementPlugin depends on this event. 32 | -------------------------------------------------------------------------------- /docs/plugins/core/timer.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-timer: 2 | 3 | ***** 4 | Timer 5 | ***** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.core.timer 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: TimerCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/channels.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-channels: 2 | 3 | ******** 4 | Channels 5 | ******** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.channels 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: ChannelsCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/chat.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-chat: 2 | 3 | **** 4 | Chat 5 | **** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.chat 10 | 11 | Events 12 | ====== 13 | .. object:: chat 14 | 15 | Chat event was recieved 16 | 17 | **Playload** :: 18 | 19 | {'position': position, 'raw': json_data, 'text': text, 'type': chat_type, 'message': msg, 'name': name, 'uuid': uuid} 20 | 21 | .. object:: position 22 | 23 | *int* 24 | 25 | Where the text should be displayed 26 | 27 | .. object:: raw 28 | 29 | *dict* 30 | 31 | Raw json data from the chat message 32 | 33 | .. object:: text 34 | 35 | *string* 36 | 37 | The text of the chat message 38 | 39 | .. object:: type 40 | 41 | *string* 42 | 43 | The type of message (achievement, admin, announcement, emote, incoming, outgoing, text) 44 | 45 | .. object:: message 46 | 47 | *string* 48 | 49 | message 50 | 51 | .. object:: uuid 52 | 53 | *string* 54 | 55 | UUID of the player who sent the message 56 | 57 | 58 | Methods and Attributes 59 | ====================== 60 | .. autoclass:: ChatCore 61 | :members: 62 | :undoc-members: 63 | 64 | 65 | -------------------------------------------------------------------------------- /docs/plugins/helpers/clientinfo.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-clientinfo: 2 | 3 | *********** 4 | ClientInfo 5 | *********** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.clientinfo 10 | 11 | Events 12 | ====== 13 | .. object:: client_login_success 14 | 15 | Client Info is done processing the Login Success packet 16 | 17 | .. object:: client_join_game 18 | 19 | Client Info is done processing the Join Game packet 20 | 21 | **Payload** :: 22 | 23 | GameInfo() 24 | 25 | .. object:: client_spawn_update 26 | 27 | Client Info is done processing the Spawn Position packet 28 | 29 | **Payload** :: 30 | 31 | Position() 32 | 33 | .. object:: client_health_update 34 | 35 | When the players health changes 36 | 37 | **Payload** :: 38 | 39 | PlayerHealth() 40 | 41 | .. object:: client_death 42 | 43 | When the player health becomes 0.0 44 | 45 | **Payload** :: 46 | 47 | PlayerHealth() 48 | 49 | .. object:: client_position_update 50 | 51 | When the player is moved by the server 52 | 53 | **Payload** :: 54 | 55 | PlayerPosition() 56 | 57 | .. object:: client_add_player 58 | 59 | Player added to the player list 60 | 61 | **Payload** :: 62 | 63 | PlayerListItem() 64 | 65 | .. object:: client_update_player 66 | 67 | Player info is updated on the player list 68 | 69 | **Payload** :: 70 | 71 | PlayerListItem() 72 | 73 | .. object:: client_remove_player 74 | 75 | Player removed from the player list 76 | 77 | **Payload** :: 78 | 79 | PlayerListItem() 80 | 81 | Methods and Attributes 82 | ====================== 83 | .. autoclass:: ClientInfo 84 | :members: 85 | :undoc-members: 86 | -------------------------------------------------------------------------------- /docs/plugins/helpers/craft.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-craft: 2 | 3 | ***** 4 | Craft 5 | ***** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.craft 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: CraftPlugin 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/entities.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-entities: 2 | 3 | ******** 4 | Entities 5 | ******** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.entities 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: EntitiesCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/index.rst: -------------------------------------------------------------------------------- 1 | Helper Plugins 2 | ============== 3 | 4 | .. toctree:: 5 | :hidden: 6 | 7 | channels 8 | chat 9 | clientinfo 10 | craft 11 | entities 12 | interact 13 | inventory 14 | keepalive 15 | movement 16 | pathfinding 17 | physics 18 | respawn 19 | start 20 | world 21 | 22 | - :ref:`plugin-channels` - Process Plugin Channels 23 | - :ref:`plugin-chat` - Process chat into simple events 24 | - :ref:`plugin-clientinfo` - Keep track of information about the client/player 25 | - :ref:`plugin-craft` - Craft items 26 | - :ref:`plugin-entities` - Keep track of entities 27 | - :ref:`plugin-interact` - Interact with the world 28 | - :ref:`plugin-inventory` - Interact with inventories in Minecraft 29 | - :ref:`plugin-keepalive` - Keep sending the keep alive packet 30 | - :ref:`plugin-movement` - Basic movement around the world 31 | - :ref:`plugin-pathfinding` - Pathfinding 32 | - :ref:`plugin-physics` - Reimplmentation of the Vanilla physics 33 | - :ref:`plugin-respawn` - Auto respawn the player on death 34 | - :ref:`plugin-start` - Helper start system for doing handshake and login 35 | - :ref:`plugin-world` - Keep track of world data 36 | 37 | -------------------------------------------------------------------------------- /docs/plugins/helpers/interact.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-interact: 2 | 3 | ******** 4 | Interact 5 | ******** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.interact 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: InteractPlugin 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/inventory.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-inventory: 2 | 3 | ********* 4 | Inventory 5 | ********* 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.inventory 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: InventoryCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/keepalive.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-keepalive: 2 | 3 | ********** 4 | Keep Alive 5 | ********** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.keepalive 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | Undocumented 18 | 19 | -------------------------------------------------------------------------------- /docs/plugins/helpers/movement.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-movement: 2 | 3 | ******** 4 | Movement 5 | ******** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.movement 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: MovementCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/pathfinding.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-pathfinding: 2 | 3 | *********** 4 | Pathfinding 5 | *********** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.pathfinding 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: PathfindingCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/physics.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-physics: 2 | 3 | ******* 4 | Physics 5 | ******* 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.physics 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: PhysicsCore 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/helpers/respawn.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-respawn: 2 | 3 | ******* 4 | Respawn 5 | ******* 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.respawn 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | Undocumented 18 | 19 | -------------------------------------------------------------------------------- /docs/plugins/helpers/start.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-start: 2 | 3 | ***** 4 | Start 5 | ***** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.start 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | Undocumented 18 | 19 | -------------------------------------------------------------------------------- /docs/plugins/helpers/world.rst: -------------------------------------------------------------------------------- 1 | .. _plugin-world: 2 | 3 | ***** 4 | World 5 | ***** 6 | 7 | Description 8 | =========== 9 | .. automodule:: spockbot.plugins.helpers.world 10 | 11 | Events 12 | ====== 13 | Undocumented 14 | 15 | Methods and Attributes 16 | ====================== 17 | .. autoclass:: WorldData 18 | :members: 19 | :undoc-members: 20 | 21 | -------------------------------------------------------------------------------- /docs/plugins/index.rst: -------------------------------------------------------------------------------- 1 | .. _plugins: 2 | 3 | ******* 4 | Plugins 5 | ******* 6 | 7 | .. toctree:: 8 | 9 | core/index 10 | helpers/index 11 | 12 | 13 | -------------------------------------------------------------------------------- /examples/basic/README.md: -------------------------------------------------------------------------------- 1 | # Example usage of SpockBotMC 2 | 3 | ## Functionality 4 | - Connecting to the server 5 | - Creating a plugin 6 | - Receiving chat messages 7 | - Sending chat commands 8 | - Using inventory 9 | - Moving to location 10 | - Triggering a periodic event using a timer 11 | - Registering for an event upon startup 12 | - Placing blocks 13 | - Reading blocks 14 | 15 | ## Usage 16 | - Add your credentials and server information to ```example.py``` 17 | - Review the layout and methods in ```example_plugin.py``` 18 | - Run ```python example.py``` to test the client and plugin 19 | -------------------------------------------------------------------------------- /examples/basic/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpockBotMC/SpockBot/f89911551f18357720034fbaa52837a0d09f66ea/examples/basic/__init__.py -------------------------------------------------------------------------------- /examples/basic/example.py: -------------------------------------------------------------------------------- 1 | """ 2 | Basic example of how to use spockbot 3 | 4 | Instructions: 5 | - Enter the e-mail for your Minecraft account in the USERNAME field below 6 | and enter your password in the PASSWORD field. 7 | 8 | - Update the SERVER to the appropriate value for your Minecraft server. 9 | 10 | - See the example plugin that is loaded in example_plugin.py and update it 11 | according to your desired functionality. 12 | """ 13 | from __future__ import absolute_import 14 | 15 | import logging 16 | 17 | # Import the plugins you have created 18 | from example_plugin import ExamplePlugin 19 | 20 | from spockbot import Client 21 | from spockbot.plugins import default_plugins 22 | 23 | __author__ = 'Cosmo Harrigan' 24 | 25 | # Change default log level to DEBUG so we can see extra messages 26 | logger = logging.getLogger('spockbot') 27 | logger.setLevel(logging.DEBUG) 28 | 29 | # Set the following values: 30 | USERNAME = 'spockbot' 31 | PASSWORD = '' 32 | SERVER = 'localhost' 33 | 34 | # Enter your credentials and the server information 35 | settings = { 36 | 'start': { 37 | 'username': USERNAME, 38 | 'password': PASSWORD, 39 | }, 40 | } 41 | 42 | # Load the plugins. 43 | # Any functionality that you want to implement must be called from a plugin. 44 | # You can define new plugins that listen for arbitrary events from the game. 45 | # Furthermore, events can even be periodic timers that trigger a method. 46 | plugins = default_plugins 47 | plugins.append(('example', ExamplePlugin)) 48 | 49 | # Instantiate and start the client, which will then 50 | # run and wait for events to occur. 51 | client = Client(plugins=plugins, settings=settings) 52 | client.start(SERVER, 25565) 53 | -------------------------------------------------------------------------------- /examples/basic/example_plugin.py: -------------------------------------------------------------------------------- 1 | """ 2 | An example plugin for spockbot 3 | 4 | Demonstrates the following functionality: 5 | - Receiving chat messages 6 | - Sending chat commands 7 | - Using inventory 8 | - Moving to location 9 | - Triggering a periodic event using a timer 10 | - Registering for an event upon startup 11 | - Placing blocks 12 | - Reading blocks 13 | """ 14 | import logging 15 | 16 | # Import any modules that you need in your plugin 17 | from spockbot.mcdata import blocks 18 | from spockbot.plugins.base import PluginBase, pl_announce 19 | from spockbot.plugins.tools.event import EVENT_UNREGISTER 20 | from spockbot.vector import Vector3 21 | 22 | __author__ = 'Cosmo Harrigan, Morgan Creekmore' 23 | 24 | logger = logging.getLogger('spockbot') 25 | 26 | # The bot will walk to this starting position. Set it to a sensible 27 | # location for your world file. The format is: (x, y, z) 28 | TARGET_COORDINATES = Vector3(10, 2, 10) 29 | 30 | 31 | # Required class decorator 32 | @pl_announce('ExamplePlugin') 33 | class ExamplePlugin(PluginBase): 34 | # Require other plugins that you want use later in the plugin 35 | requires = ('Movement', 'Timers', 'World', 'ClientInfo', 'Inventory', 36 | 'Interact', 'Chat') 37 | # Example of registering an event handler 38 | # Packet event types are enumerated here: 39 | # https://github.com/SpockBotMC/SpockBot/blob/master/spockbot/mcp 40 | # /mcdata.py#L213 41 | # There are other events that can be used that are emitted by other plugins 42 | events = { 43 | # This event will be triggered when a chat message is received 44 | # from the server 45 | 'PLAY= 0.9', 18 | 'minecraft_data == 0.4.0', 19 | 'six', 20 | ], 21 | keywords=['minecraft'], 22 | classifiers=[ 23 | 'License :: OSI Approved :: MIT License', 24 | ] 25 | ) 26 | -------------------------------------------------------------------------------- /spockbot/__init__.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from spockbot.plugins.loader import PluginLoader as Client # noqa 4 | 5 | logger = logging.getLogger('spockbot') 6 | logger.setLevel(logging.INFO) 7 | default_handler = logging.StreamHandler() 8 | formatter = logging.Formatter('[%(levelname)s]: %(message)s') 9 | default_handler.setFormatter(formatter) 10 | logger.addHandler(default_handler) 11 | -------------------------------------------------------------------------------- /spockbot/mcdata/__init__.py: -------------------------------------------------------------------------------- 1 | from spockbot.mcdata import blocks 2 | from spockbot.mcdata import items 3 | from spockbot.mcdata.utils import find_by 4 | 5 | 6 | def get_item_or_block(find, meta=0, init=True): 7 | ret = None 8 | if isinstance(find, int): # by id 9 | ret = find_by(find, items.items, blocks.blocks) 10 | else: # by name 11 | ret = find_by(find, items.items_name, blocks.blocks_name) 12 | if init and ret is not None: 13 | return ret(meta) 14 | return ret 15 | -------------------------------------------------------------------------------- /spockbot/mcdata/biomes.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from collections import namedtuple 4 | 5 | from minecraft_data.v1_8 import biomes_list 6 | 7 | from spockbot.mcdata.utils import camel_case, find_by, snake_case 8 | 9 | biomes = {} 10 | biomes_name = {} 11 | 12 | 13 | def get_biome(biome): 14 | if isinstance(biome, int): # by id 15 | return find_by(biome, biomes) 16 | else: # by name 17 | return find_by(biome, biomes_name) 18 | 19 | 20 | def _make_biome(biome_dict): 21 | name = biome_dict['name'].replace("+", " Plus") # Extreme Hills+ 22 | nt_name = '%sBiome' % camel_case(str(name)) 23 | # Convert dict to a namedtuple 24 | nt = namedtuple(nt_name, biome_dict.keys())(**biome_dict) 25 | assert not hasattr(sys.modules[__name__], nt_name), \ 26 | 'Biome "%s" already registered at %s' % (nt_name, __name__) 27 | setattr(sys.modules[__name__], nt_name, nt) 28 | return nt 29 | 30 | 31 | def _create_biomes(): 32 | for biome in biomes_list: 33 | nt = _make_biome(biome) 34 | biomes[nt.id] = nt 35 | biomes_name[snake_case(nt.name)] = nt 36 | 37 | _create_biomes() 38 | -------------------------------------------------------------------------------- /spockbot/mcdata/blocks.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from minecraft_data.v1_8 import blocks_list 4 | 5 | from spockbot.mcdata import constants as const, materials 6 | from spockbot.mcdata.utils import BoundingBox 7 | from spockbot.mcdata.utils import camel_case, find_by 8 | 9 | 10 | blocks = {} 11 | blocks_name = {} 12 | 13 | # Used for extra logic outside of minecraft_data 14 | _block_exts = {} 15 | 16 | 17 | def get_block(block, meta=0, init=True): 18 | ret = None 19 | if isinstance(block, int): # by id 20 | ret = find_by(block, blocks) 21 | else: # by name 22 | ret = find_by(block, blocks_name) 23 | if init and ret is not None: 24 | return ret(meta) 25 | return ret 26 | 27 | 28 | class Block(object): 29 | id = -1 30 | display_name = 'Block' 31 | name = 'block' 32 | hardness = 0.0 33 | stack_size = 0 34 | diggable = True 35 | bounding_box = None 36 | material = None 37 | slipperiness = 0.6 38 | harvest_tools = [] 39 | variations = {} 40 | drops = [] 41 | 42 | def __init__(self, meta=None): 43 | if meta is None: 44 | return 45 | self.metadata = meta 46 | # Set data off variations 47 | if self.metadata in self.variations: 48 | # TODO: apply other all possible variations 49 | self.display_name = self.variations[self.metadata]["display_name"] 50 | # Set data based off block extentions 51 | if self.id in _block_exts: 52 | _block_exts[self.id](self) 53 | 54 | def __str__(self): 55 | return '%s %i:%i' % (self.display_name, self.id, 56 | getattr(self, 'metadata', 0)) 57 | 58 | 59 | def _convert_boundingbox(bb): 60 | if bb == 'block': 61 | return BoundingBox(1, 1) 62 | else: # empty or unknown 63 | return None 64 | 65 | 66 | def _make_block(block_dict): 67 | cls_name = '%sBlock' % camel_case(str(block_dict['name'])) 68 | bases = (Block,) 69 | harvest_tools = [] 70 | if "harvestTools" in block_dict: 71 | for tool in block_dict['harvestTools'].keys(): 72 | harvest_tools.append(int(tool)) 73 | variations = {} 74 | if "variations" in block_dict: 75 | for var in block_dict['variations']: 76 | variations[var['metadata']] = {"display_name": var['displayName']} 77 | mat = None 78 | if "material" in block_dict: 79 | mat = materials.get_material(block_dict['material']) 80 | bounding_box = _convert_boundingbox(block_dict['boundingBox']) 81 | attrs = { 82 | '__module__': sys.modules[__name__], 83 | 'id': block_dict['id'], 84 | 'display_name': block_dict['displayName'], 85 | 'name': block_dict['name'], 86 | 'hardness': block_dict['hardness'], 87 | 'stack_size': block_dict['stackSize'], 88 | 'diggable': block_dict['diggable'], 89 | 'bounding_box': bounding_box, 90 | 'material': mat, 91 | 'harvest_tools': harvest_tools, 92 | 'variations': variations, 93 | 'drops': block_dict['drops'], 94 | } 95 | 96 | cls = type(cls_name, bases, attrs) 97 | assert not hasattr(sys.modules[__name__], cls_name), \ 98 | 'Block "%s" already registered at %s' % (cls_name, __name__) 99 | setattr(sys.modules[__name__], cls_name, cls) 100 | return cls 101 | 102 | 103 | def _create_blocks(): 104 | for block in blocks_list: 105 | cls = _make_block(block) 106 | blocks[cls.id] = cls 107 | blocks_name[cls.name] = cls 108 | 109 | _create_blocks() 110 | 111 | 112 | def block_ext(*block_ids): 113 | def inner(fn): 114 | for bid in block_ids: 115 | _block_exts[bid] = fn 116 | return fn 117 | 118 | return inner 119 | 120 | 121 | @block_ext(85, 113, 188, 189, 190, 191, 192) 122 | def _fence_ext(block): 123 | block.bounding_box = BoundingBox(1, 1.5) 124 | 125 | 126 | @block_ext(107, 183, 184, 185, 186, 187) 127 | def _gate_ext(block): 128 | block.direction = block.metadata & 0x03 129 | block.open = (block.metadata >> 2) & 0x01 == const.BLOCK_GATE_OPEN 130 | block.powered = block.metadata >> 3 == const.BLOCK_GATE_POWERED 131 | if block.open: 132 | block.bounding_box = None 133 | else: 134 | block.bounding_box = BoundingBox(1, 1.5) 135 | 136 | 137 | @block_ext(64, 71, 193, 194, 195, 196, 197) 138 | def _door_ext(block): 139 | block.section = (block.metadata >> 3) & 0x1 140 | if block.section == const.BLOCK_DOOR_LOWER: 141 | block.open = (block.metadata >> 2) & 0x01 == const.BLOCK_DOOR_OPEN 142 | block.direction = block.metadata & 0x03 143 | if not block.open: 144 | block.bounding_box = BoundingBox(1, 2) 145 | else: 146 | block.bounding_box = None 147 | elif block.section == const.BLOCK_DOOR_UPPER: 148 | block.hinge = block.metadata & 0x01 149 | block.bounding_box = None 150 | 151 | 152 | @block_ext(44, 126, 182) 153 | def _slab_ext(block): 154 | block.orientation = (block.metadata >> 3) & 0x1 155 | 156 | 157 | @block_ext(96, 167) 158 | def _trapdoor_ext(block): 159 | block.direction = block.metadata & 0x03 160 | block.open = (block.metadata >> 2) & 0x01 == const.BLOCK_TRAPDOOR_OPEN 161 | block.orientation = (block.metadata >> 3) & 0x1 162 | if block.open == const.BLOCK_TRAPDOOR_OPEN: 163 | block.bounding_box = None 164 | elif block.orientation == const.BLOCK_TRAPDOOR_UPPER: 165 | block.bounding_box = BoundingBox(1, 1) 166 | elif block.orientation == const.BLOCK_TRAPDOOR_LOWER: 167 | block.bounding_box = BoundingBox(1, 0.4) 168 | 169 | 170 | @block_ext(111) 171 | def _lillypad_ext(block): 172 | block.bounding_box = BoundingBox(1, 0.0, 1) 173 | -------------------------------------------------------------------------------- /spockbot/mcdata/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | These constants are used in some plugins, but do not belong there. 3 | Some of them can later be extracted from minecraft-data 4 | """ 5 | 6 | ########### 7 | # Physics # 8 | ########### 9 | 10 | CLIENT_TICK_RATE = 0.05 11 | PLAYER_EYE_HEIGHT = 1.62 12 | PLAYER_HEIGHT = 1.80 13 | PLAYER_WIDTH = 0.6 14 | 15 | # These values are strictly for player and maybe mob physics, different types 16 | # of entities have different drag coefficients and gravitational accelerations 17 | # Someone who isn't nickelpro can go do all the other possible values if they 18 | # want 19 | 20 | PHY_GAV_ACC = 0.08 21 | PHY_WLK_ACC = 0.10 22 | PHY_FLY_ACC = 0.05 23 | PHY_JMP_ACC = 0.02 24 | 25 | PHY_JMP_ABS = 0.42 26 | 27 | PHY_SOULSAND = 0.40 28 | PHY_BASE_DRG = 0.98 29 | 30 | PHY_DRG_MUL = 0.91 31 | PHY_SPR_MUL = 1.30 32 | PHY_JMP_MUL = 0.2 33 | 34 | # Slipperiness value for normal materials 35 | BASE_GND_SLIP = 0.6 36 | 37 | ############ 38 | # Interact # 39 | ############ 40 | 41 | INTERACT_ENTITY = 0 42 | ATTACK_ENTITY = 1 43 | INTERACT_ENTITY_AT = 2 44 | 45 | ENTITY_ACTION_SNEAK = 0 46 | ENTITY_ACTION_UNSNEAK = 1 47 | ENTITY_ACTION_LEAVE_BED = 2 48 | ENTITY_ACTION_START_SPRINT = 3 49 | ENTITY_ACTION_STOP_SPRINT = 4 50 | ENTITY_ACTION_JUMP_HORSE = 5 51 | ENTITY_ACTION_OPEN_INVENTORY = 6 52 | 53 | # the six faces of a block 54 | FACE_BOTTOM = 0 55 | FACE_TOP = 1 56 | FACE_Y_NEG = 0 57 | FACE_Y_POS = 1 58 | FACE_Z_NEG = 2 59 | FACE_Z_POS = 3 60 | FACE_X_NEG = 4 61 | FACE_X_POS = 5 62 | 63 | DIG_START = 0 64 | DIG_CANCEL = 1 65 | DIG_FINISH = 2 66 | DIG_DROP_STACK = 3 67 | DIG_DROP_ITEM = 4 68 | DIG_DEACTIVATE_ITEM = 5 69 | 70 | CHAT_POS_CHAT = 0 71 | CHAT_POS_SYSTEM_MESSAGE = 1 72 | CHAT_POS_ABOVE_HOTBAR = 2 73 | 74 | BOOK_MAXPAGES = 50 75 | BOOK_CHARS_PER_PAGE = 266 76 | 77 | ############# 78 | # Inventory # 79 | ############# 80 | 81 | # the button codes used in send_click 82 | INV_BUTTON_LEFT = 0 83 | INV_BUTTON_RIGHT = 1 84 | INV_BUTTON_MIDDLE = 2 85 | 86 | INV_OUTSIDE_WINDOW = -999 87 | INV_SLOT_NR_CURSOR = -1 88 | INV_WINID_CURSOR = -1 # the slot that follows the cursor 89 | # player inventory window ID/type, not opened but updated by server 90 | INV_WINID_PLAYER = 0 91 | INV_ITEMID_EMPTY = -1 92 | 93 | INV_SLOTS_PLAYER = 9 # crafting and armor 94 | INV_SLOTS_INVENTORY = 9 * 3 # above hotbar 95 | INV_SLOTS_HOTBAR = 9 96 | # always accessible 97 | INV_SLOTS_PERSISTENT = INV_SLOTS_INVENTORY + INV_SLOTS_HOTBAR 98 | 99 | ############## 100 | # ClientInfo # 101 | ############## 102 | 103 | GM_SURVIVAL = 0x00 104 | GM_CREATIVE = 0x01 105 | GM_ADVENTURE = 0x02 106 | GM_SPECTATOR = 0x03 107 | 108 | FLG_XPOS_REL = 0x01 109 | FLG_YPOS_REL = 0x02 110 | FLG_ZPOS_REL = 0x04 111 | FLG_YROT_REL = 0x08 112 | FLG_XROT_REL = 0x10 113 | 114 | ######### 115 | # World # 116 | ######### 117 | 118 | SMP_NETHER = -0x01 119 | SMP_OVERWORLD = 0x00 120 | SMP_END = 0x01 121 | 122 | ########## 123 | # Blocks # 124 | ########## 125 | 126 | # Gate 127 | BLOCK_GATE_SOUTH = 0x00 128 | BLOCK_GATE_WEST = 0x01 129 | BLOCK_GATE_NORTH = 0x02 130 | BLOCK_GATE_EAST = 0x03 131 | 132 | BLOCK_GATE_CLOSE = 0x00 133 | BLOCK_GATE_OPEN = 0x01 134 | 135 | BLOCK_GATE_UNPOWERED = 0x00 136 | BLOCK_GATE_POWERED = 0x01 137 | 138 | # Door 139 | BLOCK_DOOR_WEST = 0x00 140 | BLOCK_DOOR_NORTH = 0x01 141 | BLOCK_DOOR_EAST = 0x02 142 | BLOCK_DOOR_SOUTH = 0x03 143 | 144 | BLOCK_DOOR_CLOSE = 0x00 145 | BLOCK_DOOR_OPEN = 0x01 146 | 147 | BLOCK_DOOR_LOWER = 0x00 148 | BLOCK_DOOR_UPPER = 0x01 149 | 150 | BLOCK_DOOR_HINGE_LEFT = 0x00 151 | BLOCK_DOOR_HINGE_RIGHT = 0x01 152 | 153 | 154 | # Trapdoor 155 | BLOCK_TRAPDOOR_WEST = 0x00 156 | BLOCK_TRAPDOOR_NORTH = 0x01 157 | BLOCK_TRAPDOOR_EAST = 0x02 158 | BLOCK_TRAPDOOR_SOUTH = 0x03 159 | 160 | BLOCK_TRAPDOOR_CLOSE = 0x00 161 | BLOCK_TRAPDOOR_OPEN = 0x01 162 | 163 | BLOCK_TRAPDOOR_LOWER = 0x00 164 | BLOCK_TRAPDOOR_UPPER = 0x01 165 | 166 | # Slab 167 | BLOCK_SLAB_LOWER = 0x00 168 | BLOCK_SLAB_UPPER = 0x01 169 | 170 | ############ 171 | # Protocol # 172 | ############ 173 | 174 | # Clientbound 0x38 Player List Item 175 | PL_ADD_PLAYER = 0x00 176 | PL_UPDATE_GAMEMODE = 0x01 177 | PL_UPDATE_LATENCY = 0x02 178 | PL_UPDATE_DISPLAY = 0x03 179 | PL_REMOVE_PLAYER = 0x04 180 | 181 | # Clientbound 0x3B Scoreboard Objective 182 | SO_CREATE_BOARD = 0x00 183 | SO_REMOVE_BOARD = 0x01 184 | SO_UPDATE_BOARD = 0x02 185 | 186 | # Clientbound 0x3C Update Score 187 | US_UPDATE_SCORE = 0x00 188 | US_REMOVE_SCORE = 0x01 189 | 190 | # Clientbound 0x3E Teams 191 | TE_CREATE_TEAM = 0x00 192 | TE_REMOVE_TEAM = 0x01 193 | TE_UPDATE_TEAM = 0x02 194 | TE_ADDPLY_TEAM = 0x03 195 | TE_REMPLY_TEAM = 0x04 196 | 197 | # Clientbound 0x42 Combat Event 198 | CE_ENTER_COMBAT = 0x00 199 | CE_END_COMBAT = 0x01 200 | CE_ENTITY_DEAD = 0x02 201 | 202 | # Clientbound 0x44 World Border 203 | WB_SET_SIZE = 0x00 204 | WB_LERP_SIZE = 0x01 205 | WB_SET_CENTER = 0x02 206 | WB_INITIALIZE = 0x03 207 | WB_SET_WARN_TIME = 0x04 208 | WB_SET_WARN_BLOCKS = 0x05 209 | 210 | # Clientbound 0x45 Title 211 | TL_TITLE = 0x00 212 | TL_SUBTITLE = 0x01 213 | TL_TIMES = 0x02 214 | TL_CLEAR = 0x03 215 | TL_RESET = 0x04 216 | 217 | # Serverbound 0x16 Client Status 218 | CL_STATUS_RESPAWN = 0x00 219 | CL_STATUS_STATS = 0x01 220 | CL_STATUS_INV = 0x02 221 | 222 | # Clientbound 0x2B Change Game State 223 | GS_INVALID_BED = 0x00 224 | GS_END_RAIN = 0x01 225 | GS_START_RAIN = 0x02 226 | GS_GAMEMODE = 0x03 227 | GS_CREDITS = 0x04 228 | GS_DEMO_MESSAGE = 0x05 229 | GS_ARROW = 0x06 230 | GS_FADE_VALUE = 0x07 231 | GS_FADE_TIME = 0x08 232 | -------------------------------------------------------------------------------- /spockbot/mcdata/items.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | from minecraft_data.v1_8 import items_list 4 | 5 | from spockbot.mcdata.utils import camel_case, find_by 6 | 7 | items = {} 8 | items_name = {} 9 | 10 | 11 | def get_item(item, meta=0, init=True): 12 | ret = None 13 | if isinstance(item, int): # by id 14 | ret = find_by(item, items) 15 | else: # by name 16 | ret = find_by(item, items_name) 17 | if init and ret is not None: 18 | return ret(meta) 19 | return ret 20 | 21 | 22 | class Item(object): 23 | id = -1 24 | display_name = "Item" 25 | stack_size = 0 26 | name = "item" 27 | variations = {} 28 | 29 | def __init__(self, meta=None): 30 | if meta is None: 31 | return 32 | self.metadata = meta 33 | if self.metadata in self.variations: 34 | # TODO: apply other all possible variations 35 | self.display_name = self.variations[self.metadata]["display_name"] 36 | 37 | def __str__(self): 38 | return '%s %i:%i' % (self.display_name, self.id, 39 | getattr(self, 'metadata', 0)) 40 | 41 | 42 | def _make_item(item_dict): 43 | cls_name = '%sItem' % camel_case(str(item_dict['name'])) 44 | bases = (Item,) 45 | variations = {} 46 | if "variations" in item_dict: 47 | for var in item_dict['variations']: 48 | variations[var['metadata']] = {"display_name": var['displayName']} 49 | attrs = { 50 | '__module__': sys.modules[__name__], 51 | 'id': item_dict['id'], 52 | 'name': item_dict['name'], 53 | 'display_name': item_dict['displayName'], 54 | 'stack_size': item_dict['stackSize'], 55 | 'variations': variations, 56 | } 57 | 58 | cls = type(cls_name, bases, attrs) 59 | assert not hasattr(sys.modules[__name__], cls_name), \ 60 | 'Item "%s" already registered at %s' % (cls_name, __name__) 61 | setattr(sys.modules[__name__], cls_name, cls) 62 | return cls 63 | 64 | 65 | def _create_items(): 66 | for item in items_list: 67 | cls = _make_item(item) 68 | items[cls.id] = cls 69 | items_name[cls.name] = cls 70 | 71 | _create_items() 72 | -------------------------------------------------------------------------------- /spockbot/mcdata/materials.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from collections import defaultdict, namedtuple 3 | 4 | from minecraft_data.v1_8 import materials as materials_by_name 5 | 6 | from spockbot.mcdata.utils import camel_case, find_by 7 | 8 | materials = {} 9 | 10 | 11 | def get_material(name): 12 | return find_by(name, materials) 13 | 14 | 15 | def _make_material(name, material_dict): 16 | eff = {int(k): float(v) for k, v in material_dict.items()} 17 | eff = defaultdict(lambda: 1.0, eff) 18 | nt_name = '%sMaterial' % camel_case(str(name)) 19 | # Convert dict to a namedtuple 20 | nt_class = namedtuple(nt_name, ['name', 'tool_effectiveness']) 21 | nt = nt_class(name=name, tool_effectiveness=eff) 22 | assert not hasattr(sys.modules[__name__], nt_name), \ 23 | 'Material "%s" already registered at %s' % (nt_name, __name__) 24 | setattr(sys.modules[__name__], nt_name, nt) 25 | return nt 26 | 27 | 28 | def _create_materials(): 29 | for name, data in materials_by_name.items(): 30 | nt = _make_material(name, data) 31 | materials[nt.name] = nt 32 | 33 | _create_materials() 34 | -------------------------------------------------------------------------------- /spockbot/mcdata/recipes.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict, namedtuple 2 | 3 | from minecraft_data.v1_8 import recipes as raw_recipes 4 | 5 | 6 | RecipeItem = namedtuple('RecipeItem', 'id meta amount') 7 | 8 | 9 | class Recipe(object): 10 | def __init__(self, raw): 11 | self.result = reformat_item(raw['result'], None) 12 | if 'ingredients' in raw: 13 | self.ingredients = [reformat_item(item, 0) 14 | for item in raw['ingredients']] 15 | self.in_shape = None 16 | self.out_shape = None 17 | else: 18 | self.in_shape = reformat_shape(raw['inShape']) 19 | self.out_shape = reformat_shape(raw['outShape']) \ 20 | if 'outShape' in raw else None 21 | self.ingredients = [item for row in self.in_shape for item in row] 22 | 23 | @property 24 | def total_ingredient_amounts(self): 25 | """ 26 | Returns: 27 | dict: In the form { (item_id, metadata) -> amount } 28 | """ 29 | totals = defaultdict(int) 30 | for id, meta, amount in self.ingredients: 31 | totals[(id, meta)] += amount 32 | return totals 33 | 34 | @property 35 | def ingredient_positions(self): 36 | """ 37 | Returns: 38 | dict: In the form { (item_id, metadata) -> [(x, y, amount), ...] } 39 | """ 40 | positions = defaultdict(list) 41 | for y, row in enumerate(self.in_shape): 42 | for x, (item_id, metadata, amount) in enumerate(row): 43 | positions[(item_id, metadata)].append((x, y, amount)) 44 | return positions 45 | 46 | 47 | def reformat_item(raw, default_meta=None): 48 | if isinstance(raw, dict): 49 | raw = raw.copy() # do not modify arg 50 | if 'metadata' not in raw: 51 | raw['metadata'] = default_meta 52 | if 'count' not in raw: 53 | raw['count'] = 1 54 | return RecipeItem(raw['id'], raw['metadata'], raw['count']) 55 | elif isinstance(raw, list): 56 | return RecipeItem(raw[0], raw[1], 1) 57 | else: # single ID or None 58 | return RecipeItem(raw or None, default_meta, 1) 59 | 60 | 61 | def reformat_shape(shape): 62 | return [[reformat_item(item, None) for item in row] for row in shape] 63 | 64 | 65 | def iter_recipes(item_id, meta=None): 66 | item_id = str(item_id) 67 | meta = meta and int(meta) 68 | try: 69 | recipes_for_item = raw_recipes[item_id] 70 | except KeyError: 71 | return # no recipe found, do not yield anything 72 | else: 73 | for raw in recipes_for_item: 74 | recipe = Recipe(raw) 75 | if meta is None or meta == recipe.result.meta: 76 | yield recipe 77 | 78 | 79 | def get_any_recipe(item, meta=None): 80 | # TODO return small recipes if present 81 | for matching in iter_recipes(item, meta): 82 | return matching 83 | return None 84 | -------------------------------------------------------------------------------- /spockbot/mcdata/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from spockbot.vector import Vector3 4 | 5 | 6 | class BoundingBox(Vector3): 7 | def __init__(self, w, h, d=None): 8 | d = w if d is None else d 9 | super(BoundingBox, self).__init__(w, h, d) 10 | self.w = self.x 11 | self.h = self.y 12 | self.d = self.z 13 | 14 | 15 | class Info(object): 16 | def set_dict(self, data): 17 | for key in data: 18 | if hasattr(self, key): 19 | setattr(self, key, data[key]) 20 | 21 | def get_dict(self): 22 | return self.__dict__ 23 | 24 | def __repr__(self): 25 | return repr(self.get_dict()).replace('dict', self.__class__.__name__) 26 | 27 | def __str__(self): 28 | return str(self.get_dict()) 29 | 30 | 31 | def find_by(key, *args): 32 | for arg in args: 33 | if key in arg: 34 | return arg[key] 35 | return None 36 | 37 | 38 | # from http://stackoverflow.com/a/12867228 39 | re_spaced_caps = re.compile(r'((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))') 40 | 41 | # from http://stackoverflow.com/a/3303361 42 | # Remove invalid characters 43 | re_invalid_var = re.compile(r'[^0-9a-zA-Z_]') 44 | 45 | # Remove leading characters until we find a letter or underscore 46 | re_invalid_start = re.compile(r'^[^a-zA-Z_]+') 47 | 48 | 49 | def split_words(text): # TODO lacking a better name 50 | if '_' in text: 51 | return [w.lower() for w in text.split('_')] 52 | if ' ' not in text: 53 | text = re_spaced_caps.sub(r' \1', text) 54 | return [w.lower() for w in text.split(' ')] 55 | 56 | 57 | def snake_case(text): 58 | return '_'.join(split_words(text)) 59 | 60 | 61 | def camel_case(text): 62 | return ''.join(map(str.capitalize, split_words(text))) 63 | 64 | 65 | def clean_var(text): 66 | """Turn text into a valid python classname or variable""" 67 | text = re_invalid_var.sub('', text) 68 | text = re_invalid_start.sub('', text) 69 | return text 70 | -------------------------------------------------------------------------------- /spockbot/mcp/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpockBotMC/SpockBot/f89911551f18357720034fbaa52837a0d09f66ea/spockbot/mcp/__init__.py -------------------------------------------------------------------------------- /spockbot/mcp/bbuff.py: -------------------------------------------------------------------------------- 1 | class BufferUnderflowException(Exception): 2 | pass 3 | 4 | 5 | class BoundBuffer(object): 6 | buff = b'' 7 | cursor = 0 8 | 9 | def __init__(self, data=b""): 10 | self.write(data) 11 | 12 | def read(self, length): 13 | if length > len(self): 14 | raise BufferUnderflowException() 15 | 16 | out = self.buff[self.cursor:self.cursor+length] 17 | self.cursor += length 18 | return out 19 | 20 | def write(self, data): 21 | self.buff += data 22 | 23 | def flush(self): 24 | return self.read(len(self)) 25 | 26 | def save(self): 27 | self.buff = self.buff[self.cursor:] 28 | self.cursor = 0 29 | 30 | def revert(self): 31 | self.cursor = 0 32 | 33 | def tell(self): 34 | return self.cursor 35 | 36 | def __len__(self): 37 | return len(self.buff) - self.cursor 38 | 39 | def __repr__(self): 40 | return "" % repr(self.buff[self.cursor:]) 41 | 42 | recv = read 43 | append = write 44 | -------------------------------------------------------------------------------- /spockbot/mcp/mcpacket.py: -------------------------------------------------------------------------------- 1 | try: 2 | basestring 3 | except NameError: 4 | basestring = str 5 | 6 | import copy 7 | import logging 8 | import zlib 9 | from time import gmtime, strftime 10 | 11 | from spockbot.mcp import datautils, proto 12 | from spockbot.mcp.bbuff import BoundBuffer, BufferUnderflowException 13 | from spockbot.mcp.extensions import hashed_extensions 14 | from spockbot.mcp.proto import MC_VARINT 15 | 16 | 17 | logger = logging.getLogger('spockbot') 18 | 19 | 20 | class PacketDecodeFailure(Exception): 21 | def __init__(self, packet, pbuff, underflow=False): 22 | self.packet = packet 23 | self.pbuff = pbuff 24 | self.underflow = underflow 25 | 26 | 27 | class Packet(object): 28 | def __init__(self, 29 | ident=[proto.HANDSHAKE_STATE, proto.CLIENT_TO_SERVER, 0x00], 30 | data=None 31 | ): 32 | if isinstance(ident, basestring): 33 | ident = proto.packet_str2ident[ident] 34 | self.__ident = list(ident) 35 | # Quick hack to fake default ident 36 | if len(self.__ident) == 2: 37 | self.__ident.append(0x00) 38 | self.ident = tuple(self.__ident) 39 | self.str_ident = proto.packet_ident2str[self.ident] 40 | self.data = data if data else {} 41 | 42 | def clone(self): 43 | return Packet(self.ident, copy.deepcopy(self.data)) 44 | 45 | def new_ident(self, ident): 46 | self.__init__(ident, self.data) 47 | 48 | def decode(self, bbuff, proto_comp_state): 49 | self.data = {} 50 | packet_length = datautils.unpack(MC_VARINT, bbuff) 51 | packet_data = bbuff.recv(packet_length) 52 | pbuff = BoundBuffer(packet_data) 53 | if proto_comp_state == proto.PROTO_COMP_ON: 54 | body_length = datautils.unpack(MC_VARINT, pbuff) 55 | if body_length: 56 | body_data = zlib.decompress(pbuff.flush(), zlib.MAX_WBITS) 57 | pbuff.write(body_data) 58 | pbuff.save() 59 | 60 | try: 61 | # Ident 62 | self.__ident[2] = datautils.unpack(MC_VARINT, pbuff) 63 | self.ident = tuple(self.__ident) 64 | self.str_ident = proto.packet_ident2str[self.ident] 65 | # Payload 66 | for dtype, name in proto.hashed_structs[self.ident]: 67 | self.data[name] = datautils.unpack(dtype, pbuff) 68 | # Extension 69 | if self.ident in hashed_extensions: 70 | hashed_extensions[self.ident].decode_extra(self, pbuff) 71 | if pbuff: 72 | raise PacketDecodeFailure(self, pbuff) 73 | except BufferUnderflowException: 74 | raise PacketDecodeFailure(self, pbuff, True) 75 | return self 76 | 77 | def encode(self, proto_comp_state, proto_comp_threshold, comp_level=6): 78 | # Ident 79 | o = datautils.pack(MC_VARINT, self.ident[2]) 80 | # Payload 81 | for dtype, name in proto.hashed_structs[self.ident]: 82 | o += datautils.pack(dtype, self.data[name]) 83 | # Extension 84 | if self.ident in hashed_extensions: 85 | o += hashed_extensions[self.ident].encode_extra(self) 86 | 87 | if proto_comp_state == proto.PROTO_COMP_ON: 88 | uncompressed_len = len(o) 89 | if uncompressed_len < proto_comp_threshold: 90 | header = datautils.pack(MC_VARINT, uncompressed_len + 1) 91 | header += datautils.pack(MC_VARINT, 0) 92 | else: 93 | o = zlib.compress(o, comp_level) 94 | ulen_varint = datautils.pack(MC_VARINT, uncompressed_len) 95 | header = datautils.pack(MC_VARINT, 96 | len(o) + len(ulen_varint)) 97 | header += ulen_varint 98 | return header + o 99 | elif proto_comp_state == proto.PROTO_COMP_OFF: 100 | return datautils.pack(MC_VARINT, len(o)) + o 101 | else: 102 | return None 103 | 104 | def __repr__(self): 105 | s = ('<<<', '>>>')[self.ident[1]] 106 | f = "[%s] %s (0x%02X, 0x%02X): %-" + str( 107 | max([len(i) for i in proto.hashed_names.values()]) + 1) + "s%s" 108 | return f % ( 109 | strftime("%H:%M:%S", gmtime()), s, self.ident[0], self.ident[2], 110 | proto.hashed_names[self.ident], 111 | str(self.data) 112 | ) 113 | -------------------------------------------------------------------------------- /spockbot/mcp/yggdrasil.py: -------------------------------------------------------------------------------- 1 | from __future__ import unicode_literals 2 | 3 | import logging 4 | 5 | try: 6 | import simplejson as json 7 | except ImportError: 8 | import json 9 | from six.moves.urllib.error import HTTPError 10 | from six.moves.urllib.request import Request, urlopen 11 | 12 | logger = logging.getLogger() 13 | 14 | 15 | class YggdrasilCore(object): 16 | ygg_version = 1 17 | ygg_url = 'https://authserver.mojang.com' 18 | 19 | def __init__(self, username='', password='', client_token='', 20 | access_token=''): 21 | self.username = username 22 | self.password = password 23 | self.client_token = client_token 24 | self.access_token = access_token 25 | self.available_profiles = [] 26 | self.selected_profile = {} 27 | 28 | def login(self): 29 | if self.access_token and self.validate(): 30 | return True 31 | if self.access_token and self.client_token and self.refresh(): 32 | return True 33 | return self.username and self.password and self.authenticate() 34 | 35 | def logout(self): 36 | return self.access_token and self.client_token and self.invalidate() 37 | 38 | def _ygg_req(self, endpoint, payload): 39 | try: 40 | resp = urlopen(Request( 41 | url=self.ygg_url + endpoint, 42 | data=json.dumps(payload).encode('utf-8'), 43 | headers={'Content-Type': 'application/json'}) 44 | ) 45 | except HTTPError as e: 46 | resp = e 47 | data = resp.read().decode('utf-8') 48 | return json.loads(data) if data else dict() 49 | 50 | def authenticate(self): 51 | """ 52 | Generate an access token using an username and password. Any existing 53 | client token is invalidated if not provided. 54 | 55 | Returns: 56 | dict: Response or error dict 57 | """ 58 | endpoint = '/authenticate' 59 | 60 | payload = { 61 | 'agent': { 62 | 'name': 'Minecraft', 63 | 'version': self.ygg_version, 64 | }, 65 | 'username': self.username, 66 | 'password': self.password, 67 | 'clientToken': self.client_token, 68 | } 69 | rep = self._ygg_req(endpoint, payload) 70 | if not rep or 'error' in rep: 71 | return False 72 | self.access_token = rep['accessToken'] 73 | self.client_token = rep['clientToken'] 74 | self.available_profiles = rep['availableProfiles'] 75 | self.selected_profile = rep['selectedProfile'] 76 | return True 77 | 78 | def refresh(self): 79 | """ 80 | Generate an access token with a client/access token pair. Used 81 | access token is invalidated. 82 | 83 | Returns: 84 | dict: Response or error dict 85 | """ 86 | endpoint = '/refresh' 87 | 88 | payload = { 89 | 'accessToken': self.access_token, 90 | 'clientToken': self.client_token, 91 | } 92 | rep = self._ygg_req(endpoint, payload) 93 | if not rep or 'error' in rep: 94 | return False 95 | 96 | self.access_token = rep['accessToken'] 97 | self.client_token = rep['clientToken'] 98 | self.selected_profile = rep['selectedProfile'] 99 | return True 100 | 101 | def signout(self): 102 | """ 103 | Invalidate access tokens with a username and password. 104 | 105 | Returns: 106 | dict: Empty or error dict 107 | """ 108 | endpoint = '/signout' 109 | 110 | payload = { 111 | 'username': self.username, 112 | 'password': self.password, 113 | } 114 | rep = self._ygg_req(endpoint, payload) 115 | if not rep or 'error' in rep: 116 | return False 117 | self.client_token = '' 118 | self.access_token = '' 119 | self.available_profiles = [] 120 | self.selected_profile = {} 121 | return True 122 | 123 | def invalidate(self): 124 | """ 125 | Invalidate access tokens with a client/access token pair 126 | 127 | Returns: 128 | dict: Empty or error dict 129 | """ 130 | endpoint = '/invalidate' 131 | 132 | payload = { 133 | 'accessToken': self.access_token, 134 | 'clientToken': self.client_token, 135 | } 136 | self._ygg_req(endpoint, payload) 137 | self.client_token = '' 138 | self.access_token = '' 139 | self.available_profiles = [] 140 | self.selected_profile = {} 141 | return True 142 | 143 | def validate(self): 144 | """ 145 | Check if an access token is valid 146 | 147 | Returns: 148 | dict: Empty or error dict 149 | """ 150 | endpoint = '/validate' 151 | 152 | payload = dict(accessToken=self.access_token) 153 | rep = self._ygg_req(endpoint, payload) 154 | return not bool(rep) 155 | -------------------------------------------------------------------------------- /spockbot/plugins/__init__.py: -------------------------------------------------------------------------------- 1 | from spockbot.plugins.core import auth, event, net, select, \ 2 | taskmanager, ticker, timers 3 | from spockbot.plugins.helpers import auxiliary, channels, chat, clientinfo, \ 4 | craft, entities, interact, inventory, movement, \ 5 | pathfinding, physics, start, world 6 | 7 | core_plugins = [ 8 | ('auth', auth.AuthPlugin), 9 | ('event', event.EventPlugin), 10 | ('net', net.NetPlugin), 11 | ('select', select.SelectPlugin), 12 | ('taskmanager', taskmanager.TaskManager), 13 | ('ticker', ticker.TickerPlugin), 14 | ('timers', timers.TimersPlugin), 15 | ] 16 | helper_plugins = [ 17 | ('auxiliary', auxiliary.AuxiliaryPlugin), 18 | ('channels', channels.ChannelsPlugin), 19 | ('chat', chat.ChatPlugin), 20 | ('clientinfo', clientinfo.ClientInfoPlugin), 21 | ('craft', craft.CraftPlugin), 22 | ('entities', entities.EntitiesPlugin), 23 | ('interact', interact.InteractPlugin), 24 | ('inventory', inventory.InventoryPlugin), 25 | ('movement', movement.MovementPlugin), 26 | ('pathfinding', pathfinding.PathfindingPlugin), 27 | ('physics', physics.PhysicsPlugin), 28 | ('start', start.StartPlugin), 29 | ('world', world.WorldPlugin), 30 | ] 31 | default_plugins = core_plugins + helper_plugins 32 | -------------------------------------------------------------------------------- /spockbot/plugins/base.py: -------------------------------------------------------------------------------- 1 | import copy 2 | 3 | from six import string_types 4 | 5 | 6 | def get_settings(defaults, settings): 7 | return dict(copy.deepcopy(defaults), **settings) 8 | 9 | 10 | def pl_announce(*args): 11 | def inner(cl): 12 | cl.pl_announce = args 13 | return cl 14 | 15 | return inner 16 | 17 | 18 | def pl_event(*args): 19 | def inner(cl): 20 | cl.pl_event = args 21 | return cl 22 | 23 | return inner 24 | 25 | 26 | class PluginBase(object): 27 | """A base class for cleaner plugin code. 28 | 29 | Extending from PluginBase allows you to declare any requirements, default 30 | settings, and event listeners in a declarative way. Define the appropriate 31 | attributes on your subclass and enjoy cleaner code. 32 | """ 33 | requires = () 34 | defaults = {} 35 | events = {} 36 | 37 | def __init__(self, ploader, settings): 38 | # Load the plugin's settings. 39 | self.settings = get_settings(self.defaults, settings) 40 | 41 | # Load all the plugin's dependencies. 42 | if isinstance(self.requires, string_types): 43 | setattr(self, self.requires.lower(), 44 | ploader.requires(self.requires)) 45 | else: 46 | for requirement in self.requires: 47 | setattr(self, requirement.lower(), 48 | ploader.requires(requirement)) 49 | 50 | # Setup the plugin's event handlers. 51 | for event in self.events.keys(): 52 | if hasattr(self, self.events[event]): 53 | ploader.reg_event_handler(event, 54 | getattr(self, self.events[event])) 55 | else: 56 | raise AttributeError("'%s' object has no attribute '%s'" 57 | % (self.__class__.__name__, 58 | self.events[event])) 59 | -------------------------------------------------------------------------------- /spockbot/plugins/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpockBotMC/SpockBot/f89911551f18357720034fbaa52837a0d09f66ea/spockbot/plugins/core/__init__.py -------------------------------------------------------------------------------- /spockbot/plugins/core/auth.py: -------------------------------------------------------------------------------- 1 | """ 2 | Provides authorization functions for Mojang's login and session servers 3 | """ 4 | 5 | import hashlib 6 | import json 7 | # This is for python2 compatibility 8 | try: 9 | import urllib.request as request 10 | from urllib.error import URLError 11 | except ImportError: 12 | import urllib2 as request 13 | from urllib2 import URLError 14 | import logging 15 | import os 16 | 17 | from spockbot.mcp.yggdrasil import YggdrasilCore 18 | from spockbot.plugins.base import PluginBase, pl_announce 19 | 20 | logger = logging.getLogger('spockbot') 21 | 22 | 23 | # This function courtesy of barneygale 24 | def java_hex_digest(digest): 25 | d = int(digest.hexdigest(), 16) 26 | if d >> 39 * 4 & 0x8: 27 | d = "-%x" % ((-d) & (2 ** (40 * 4) - 1)) 28 | else: 29 | d = "%x" % d 30 | return d 31 | 32 | 33 | class AuthCore(object): 34 | def __init__(self, event, online_mode, auth_timeout): 35 | self.online_mode = online_mode 36 | self.auth_timeout = auth_timeout 37 | self.__event = event 38 | self.ygg = YggdrasilCore() 39 | self._shared_secret = None 40 | self._username = None 41 | 42 | def get_username(self): 43 | return self._username 44 | 45 | def set_username(self, username): 46 | self.ygg.username = username 47 | 48 | username = property(get_username, set_username) 49 | 50 | def set_password(self, password): 51 | if password and not self.online_mode: 52 | logger.warning("PASSWORD PROVIDED WITH ONLINE_MODE == FALSE") 53 | logger.warning("YOU PROBABLY DIDN'T WANT TO DO THAT") 54 | self.ygg.password = password 55 | 56 | password = property(lambda x: bool(x.ygg.password), set_password) 57 | 58 | def set_client_token(self, client_token): 59 | if not self.online_mode: 60 | logger.warning("CLIENT TOKEN PROVIDED WITH ONLINE_MODE == FALSE") 61 | logger.warning("YOU PROBABLY DIDN'T WANT TO DO THAT") 62 | self.ygg.client_token = client_token 63 | 64 | client_token = property( 65 | lambda x: bool(x.ygg.client_token), set_client_token 66 | ) 67 | 68 | def set_auth_token(self, auth_token): 69 | if not self.online_mode: 70 | logger.warning("AUTH TOKEN PROVIDED WITH ONLINE_MODE == FALSE") 71 | logger.warning("YOU PROBABLY DIDN'T WANT TO DO THAT") 72 | self.ygg.auth_token = auth_token 73 | 74 | auth_token = property( 75 | lambda x: bool(x.ygg.auth_token), set_auth_token 76 | ) 77 | 78 | def get_shared_secret(self): 79 | self._shared_secret = self._shared_secret or os.urandom(16) 80 | return self._shared_secret 81 | 82 | shared_secret = property(get_shared_secret) 83 | 84 | def start_session(self): 85 | if not self.online_mode: 86 | self._username = self.ygg.username 87 | return True 88 | if self.ygg.login(): 89 | self._username = self.ygg.selected_profile['name'] 90 | return True 91 | self.__event.emit('auth_session_error') 92 | return False 93 | 94 | def send_session_auth(self, pubkey_raw, server_id_raw): 95 | server_id = java_hex_digest(hashlib.sha1( 96 | server_id_raw.encode('ascii') + self.shared_secret + pubkey_raw 97 | )) 98 | logger.info('Attempting to authenticate with Mojang session server') 99 | url = "https://sessionserver.mojang.com/session/minecraft/join" 100 | data = json.dumps({ 101 | 'accessToken': self.ygg.access_token, 102 | 'selectedProfile': self.ygg.selected_profile, 103 | 'serverId': server_id, 104 | }).encode('utf-8') 105 | headers = {'Content-Type': 'application/json'} 106 | req = request.Request(url, data, headers) 107 | try: 108 | rep = request.urlopen( 109 | req, timeout=self.auth_timeout 110 | ).read().decode('ascii') 111 | except URLError: 112 | rep = "Couldn't connect to sessionserver.mojang.com" 113 | if rep: 114 | logger.warning('Mojang session auth response: %s', rep) 115 | logger.info('Session authentication successful') 116 | 117 | 118 | @pl_announce('Auth') 119 | class AuthPlugin(PluginBase): 120 | requires = 'Event' 121 | defaults = { 122 | 'online_mode': True, 123 | 'auth_timeout': 3, # No idea how long this should be, 3s seems good 124 | 'auth_quit': True, 125 | 'sess_quit': True, 126 | } 127 | events = { 128 | 'auth_login_error': 'handle_auth_error', 129 | 'auth_session_error': 'handle_session_error', 130 | } 131 | 132 | def __init__(self, ploader, settings): 133 | super(AuthPlugin, self).__init__(ploader, settings) 134 | self.sess_quit = self.settings['sess_quit'] 135 | self.auth_quit = self.settings['auth_quit'] 136 | ploader.provides('Auth', AuthCore( 137 | self.event, 138 | self.settings['online_mode'], 139 | self.settings['auth_timeout'] 140 | )) 141 | 142 | def handle_auth_error(self, name, data): 143 | if self.auth_quit: 144 | logger.error('AUTH: Session authentication error, calling kill') 145 | self.event.kill() 146 | 147 | def handle_session_error(self, name, data): 148 | if self.sess_quit: 149 | logger.error('AUTH: Session start error, calling kill') 150 | self.event.kill() 151 | -------------------------------------------------------------------------------- /spockbot/plugins/core/event.py: -------------------------------------------------------------------------------- 1 | """ 2 | Provides the core event loop 3 | """ 4 | import logging 5 | import signal 6 | from collections import defaultdict 7 | from copy import deepcopy 8 | 9 | from spockbot.plugins.base import pl_announce 10 | from spockbot.plugins.tools.event import EVENT_UNREGISTER 11 | 12 | logger = logging.getLogger('spockbot') 13 | 14 | 15 | @pl_announce('Event') 16 | class EventPlugin(object): 17 | def __init__(self, ploader, settings): 18 | ploader.provides('Event', self) 19 | self.has_run = False 20 | self.kill_event = False 21 | self.event_handlers = defaultdict(list) 22 | signal.signal(signal.SIGINT, self.kill) 23 | signal.signal(signal.SIGTERM, self.kill) 24 | 25 | def event_loop(self, once=False): 26 | if once: 27 | self.run_once() 28 | else: 29 | self.run_continuous() 30 | 31 | def run_continuous(self): 32 | if not self.has_run and not self.kill_event: 33 | self.has_run = True 34 | self.emit('event_start') 35 | while not self.kill_event: 36 | self.emit('event_tick') 37 | logger.debug('EVENTCORE: Kill called, shutting down') 38 | self.emit('event_kill') 39 | 40 | def run_once(self): 41 | if not self.has_run and not self.kill_event: 42 | self.has_run = True 43 | self.emit('event_start') 44 | if not self.kill_event: 45 | self.emit('event_tick') 46 | else: 47 | logger.debug('EVENTCORE: Kill called, shutting down') 48 | self.emit('event_kill') 49 | 50 | def reg_event_handler(self, event, handler): 51 | self.event_handlers[event].append(handler) 52 | 53 | def unreg_event_handler(self, event, handler): 54 | self.event_handlers[event].remove(handler) 55 | 56 | def emit(self, event, data=None): 57 | # the handler list of this event can change during handler execution, 58 | # so we loop over a copy 59 | try: 60 | for handler in self.event_handlers[event][:]: 61 | d = data.clone() if hasattr(data, 'clone') else deepcopy(data) 62 | if handler(event, d) == EVENT_UNREGISTER: 63 | self.event_handlers[event].remove(handler) 64 | except: 65 | logger.debug('EVENTCORE: Exception while emitting %s %s', 66 | event, data) 67 | raise 68 | 69 | def kill(self, *args): 70 | self.kill_event = True 71 | -------------------------------------------------------------------------------- /spockbot/plugins/core/select.py: -------------------------------------------------------------------------------- 1 | """ 2 | Provides an asynchronous multi-socket selector with a poll method 3 | built on top of select.select for cross-platform compatibility. 4 | 5 | After polling select, two events are emitted for each socket and kind-of-ready, 6 | ``select_`` and ``select__``, where 7 | ```` is one of ``recv, send, err``. 8 | 9 | The event payload is always the fileno of the corresponding socket. 10 | (The event plugin deep-copies the payload, but sockets are not serializable) 11 | 12 | Note that the event loop is stopped during selecting. This is good in that 13 | the loop does not consume 100% CPU, but it means you have to register 14 | at least a slow timer if you do stuff on ``event_tick`` and 15 | expect it to be emitted frequently. 16 | """ 17 | 18 | from __future__ import absolute_import 19 | 20 | import logging 21 | import select 22 | 23 | from spockbot.plugins.base import PluginBase, pl_announce 24 | 25 | logger = logging.getLogger('spockbot') 26 | 27 | 28 | @pl_announce('Select') 29 | class SelectPlugin(PluginBase): 30 | requires = ('Event', 'Timers') 31 | 32 | def __init__(self, ploader, settings): 33 | super(SelectPlugin, self).__init__(ploader, settings) 34 | self.sockets = set() 35 | self.sending = set() 36 | ploader.provides('Select', self) 37 | 38 | def register_socket(self, sock): 39 | """``poll()``ing will emit events when this socket is ready.""" 40 | self.sockets.add(sock) 41 | 42 | def unregister_socket(self, sock): 43 | self.sockets.remove(sock) 44 | 45 | def schedule_sending(self, sock): 46 | """Emit one event the next time this socket is ready to send.""" 47 | self.sending.add(sock) 48 | 49 | def poll(self): 50 | timeout = self.timers.get_timeout() 51 | if timeout < 0: 52 | timeout = 5 # do not hang 53 | 54 | select_args = [ 55 | tuple(self.sockets), 56 | tuple(self.sending), 57 | tuple(self.sockets), 58 | timeout, 59 | ] 60 | self.sending.clear() 61 | 62 | try: 63 | ready_lists = select.select(*select_args) 64 | except select.error as e: 65 | logger.error('SELECTSOCKET: Socket Error: "%s" %s', str(e), e.args) 66 | return 67 | 68 | for ready_socks, kind in zip(ready_lists, ('recv', 'send', 'err')): 69 | for sock in ready_socks: 70 | self.event.emit('select_%s' % kind, sock.fileno()) 71 | self.event.emit('select_%s_%s' % (kind, sock.fileno()), 72 | sock.fileno()) 73 | -------------------------------------------------------------------------------- /spockbot/plugins/core/settings.py: -------------------------------------------------------------------------------- 1 | from spockbot.plugins import default_plugins 2 | from spockbot.plugins.base import get_settings, pl_announce 3 | 4 | 5 | class PloaderFetch(object): 6 | def __init__(self, plugins, plugin_settings): 7 | self.plugins = plugins 8 | self.plugin_settings = plugin_settings 9 | 10 | def get_plugins(self): 11 | return self.plugins 12 | 13 | def get_plugin_settings(self, plugin): 14 | return self.plugin_settings.get(plugin, {}) 15 | 16 | 17 | @pl_announce('PloaderFetch') 18 | class SettingsPlugin(object): 19 | def __init__(self, ploader, kwargs): 20 | settings = get_settings(kwargs.get('settings', {}), kwargs) 21 | plugin_list = settings.get('plugins', default_plugins) 22 | plugins = [] 23 | plugin_settings = {} 24 | for plugin in plugin_list: 25 | plugins.append(plugin[1]) 26 | plugin_settings[plugin[1]] = settings.get(plugin[0], {}) 27 | ploader.provides('PloaderFetch', 28 | PloaderFetch(plugins, plugin_settings)) 29 | -------------------------------------------------------------------------------- /spockbot/plugins/core/taskmanager.py: -------------------------------------------------------------------------------- 1 | from spockbot.plugins.base import PluginBase, pl_announce 2 | from spockbot.plugins.tools.task import Task 3 | 4 | 5 | @pl_announce('TaskManager') 6 | class TaskManager(PluginBase): 7 | requires = 'Event' 8 | 9 | def __init__(self, ploader, settings): 10 | super(TaskManager, self).__init__(ploader, settings) 11 | ploader.provides('TaskManager', self) 12 | 13 | def run_task(self, task, parent=None, name=None): 14 | if not isinstance(task, Task): 15 | task = Task(task, parent, name) 16 | if parent: 17 | parent.last_child = task 18 | task.run(self) 19 | return task 20 | -------------------------------------------------------------------------------- /spockbot/plugins/core/ticker.py: -------------------------------------------------------------------------------- 1 | """ 2 | Registers timers to provide the necessary tick rates expected by MC servers 3 | """ 4 | from spockbot.mcdata.constants import CLIENT_TICK_RATE 5 | from spockbot.plugins.base import PluginBase 6 | 7 | 8 | class TickerPlugin(PluginBase): 9 | requires = ('Event', 'Timers') 10 | events = { 11 | 'PLAY 0 and not self.runs < 0: 33 | self.runs -= 1 34 | if self.runs: 35 | self.reset() 36 | 37 | def stop(self): 38 | self.runs = 0 39 | 40 | def reset(self): 41 | pass 42 | 43 | 44 | # Time based timer 45 | class EventTimer(BaseTimer): 46 | def __init__(self, wait_time, callback, runs=1): 47 | super(EventTimer, self).__init__(callback, runs) 48 | self.wait_time = wait_time 49 | self.end_time = time.time() + self.wait_time 50 | 51 | def countdown(self): 52 | count = self.end_time - time.time() 53 | return count if count > 0 else 0 54 | 55 | def check(self): 56 | if self.runs == 0: 57 | return False 58 | return self.end_time <= time.time() 59 | 60 | def reset(self): 61 | self.end_time = time.time() + self.wait_time 62 | 63 | 64 | # World tick based timer 65 | class TickTimer(BaseTimer): 66 | def __init__(self, world, wait_ticks, callback, runs=1): 67 | super(TickTimer, self).__init__(callback, runs) 68 | self.world = world 69 | self.wait_ticks = wait_ticks 70 | self.end_tick = self.world.age + self.wait_ticks 71 | 72 | def check(self): 73 | if self.runs == 0: 74 | return False 75 | return self.end_tick <= self.world.age 76 | 77 | def reset(self): 78 | self.end_tick = self.world.age + self.wait_ticks 79 | 80 | 81 | class TimersCore(object): 82 | def __init__(self, world): 83 | self.timers = [] 84 | self.persist_timers = [] 85 | self.world = world 86 | 87 | def reg_timer(self, timer, persist=False): 88 | if not persist: 89 | self.timers.append(timer) 90 | else: 91 | self.persist_timers.append(timer) 92 | 93 | def get_timeout(self): 94 | timeout = -1 95 | for timer in self.timers + self.persist_timers: 96 | if timeout > timer.countdown() or timeout == -1: 97 | timeout = timer.countdown() 98 | return timeout 99 | 100 | def reg_event_timer(self, wait_time, callback, runs=-1, persist=False): 101 | self.reg_timer(EventTimer(wait_time, callback, runs), persist) 102 | 103 | def reg_tick_timer(self, wait_ticks, callback, runs=-1, persist=False): 104 | self.reg_timer(TickTimer(self.world, wait_ticks, callback, runs), 105 | persist) 106 | 107 | 108 | class WorldTick(object): 109 | def __init__(self): 110 | self.age = 0 111 | 112 | 113 | @pl_announce('Timers') 114 | class TimersPlugin(PluginBase): 115 | requires = 'World' 116 | events = { 117 | 'event_tick': 'tick', 118 | 'net_disconnect': 'handle_disconnect', 119 | } 120 | 121 | def __init__(self, ploader, settings): 122 | super(TimersPlugin, self).__init__(ploader, settings) 123 | if not self.world: 124 | self.world = WorldTick() 125 | ploader.reg_event_handler('PLAY