Tuesday, 9 April 2013

Minecraft: Pi Edition - API Tutorial

This tutorial started off as an article I wrote on Minecraft: Pi Edition for the Issue 11 of The Mag Pi, a magazine written by Raspberry Pi enthusiasts, and builds on my first post Raspberry Pi - Minecraft - API Basics, which describes the basics of how to use the API.  I highly recommend you give The Mag Pi a go, its always full of interesting and relevant articles.


Install Minecraft
If Minecraft: Pi edition isn't already installed on your Pi, head over to www.raspberrypi.org/documentation/usage/minecraft and follow the instructions.

The API
The API allows you to write programs which control, alter and interact with the minecraft world, unlocking a whole load of minecraft hacking.  How about creating massive structures at the click of a button or a bridge which automatically appears under your feet allowing you to walk across massive chasms or a game of minesweeper, a huge real time clock, a programmable directional cannonturn blocks into bombs or the game snake?




Minecraft is a world of cubes or blocks, all with a relative size of 1m x 1m x 1m, and every block has a position in the world of x, y, z; x and z being the horizontal positions and y being the vertical.


The API works by changing the ‘server’, which runs underneath the game, allowing you to interact with these blocks and the player, such as:

  • Get the player’s position
  • Change (or set) the player’s position
  • Get the type of block
  • Change a block
  • Change the camera angle
  • Post messages to the player

Libraries
You can interact with the server directly by sending a message to it, but the nice people at Mojang also provide libraries for python and java which simplify and standardise using the API.

The libraries are installed along with the game in the /opt/minecraft-pi/api/java and api/python directories.

The following example is written in Python and uses Mojang’s python api library.

API Example

Create Directory
We need to create a directory to put our program into.

mkdir ~/minecraft-magpi

Create program
Open the Python 2 editor Idle (or your favourite editor) and create a program file called minecraft-magpi.py in the ~/minecraft-magpi directory

We are going to need 3 modules, the minecraft.py and block.py modules from the minecraft directory containing the library we just copied and the standard time module so we can introduce delays into our program.

import mcpi.minecraft as minecraft
import mcpi.block as block
import time

Next, we need to use the Minecraft class in the python library to create a connection to the game’s server, this object will also be how we interact with the game and will provide access to all the functions.  When your program runs this statement, Minecraft will have to be running and you will need to be in a game, otherwise you will get errors.

mc = minecraft.Minecraft.create()

Using our minecraft object, mc, we can then interact with the game and send the player a message.  We will also put a delay in using the time.sleep() function otherwise the whole program will run too fast for us to see what’s going on.

mc.postToChat("Hello Minecraft World")
time.sleep(5)

Using the program built so far, you can test to make sure everything is working.  Load up minecraft and create a (or enter an existing) world then if you’re using Idle pick 'Run, Run Module'  from the menu.  If all has been setup correctly you will see the “Hello Minecraft World” message in the game.


Interacting with the player is done through the player class of the mc object allowing us to find the position and change the position of the player.  The next block of code finds the players position using the getPos() command, which returns an object of x,y and z coordinates, the setPos() command is then used to move the player 50 blocks up, by adding 50 to the player’s y coordinate.  We then add a delay, so there is enough time for your player to fall down to the ground!

playerPos = mc.player.getPos()
mc.player.setPos(playerPos.x, playerPos.y + 50, playerPos.z)
mc.postToChat("Dont look down")
time.sleep(5)

You can use the position of the player as a starting point for interacting blocks, this way you can find out what block the player is standing on or place blocks around the player, there is however a challenge, the x, y and z coordinates returned by the getPos() function are decimals (aka floats), as your player can be in the middle of a block, but to interact with blocks we need to use whole numbers (aka integers), so we need to use the function getTilePos(), which returns the block (or tile) he’s standing on.

The code below gets the players tile position, it then calls the minecraft API’s getBlock() function to find out the type of block the player is standing on (by minusing 1 from the y co-ordinate) before using setBlock() to create blocks of the same type the player is standing on around him.  So if your player is standing on DIRT, he will end up with DIRT surrounding him, however if he is standing on STONE, STONE will appear.

playerTilePos = mc.player.getTilePos()
blockBelowPlayerType = mc.getBlock(playerTilePos.x, playerTilePos.y - 1, playerTilePos.z)
mc.setBlock(playerTilePos.x + 1, playerTilePos.y + 1, playerTilePos.z, blockBelowPlayerType)
mc.setBlock(playerTilePos.x, playerTilePos.y + 1, playerTilePos.z + 1, blockBelowPlayerType)
mc.setBlock(playerTilePos.x - 1, playerTilePos.y + 1, playerTilePos.z, blockBelowPlayerType)
mc.setBlock(playerTilePos.x, playerTilePos.y + 1, playerTilePos.z - 1, blockBelowPlayerType)
mc.postToChat("Trapped you")
time.sleep(5)


We have now trapped our player within 4 blocks (providing he doesn’t break out!), in order to set him free we need to remove a block.  Removing blocks is done using setBlock(), but rather than making the block solid like WOOD or STONE we set it to AIR.

mc.setBlock(playerTilePos.x + 1, playerTilePos.y + 1, playerTilePos.z, block.AIR)
mc.postToChat("Be free")
time.sleep(5)

A full list of all the available blocks can be found in either the minecraft api specification or in the block.py module in the python api library ~/mcpi/api/python/mcpi/block.py.

The API also allows you to set many blocks at a time, allowing you to create cuboids very quickly using the setBlocks() command.  It works by specifying 2 sets of x,y,z coordinates which it then fills the gap between the 2 coordinates with a certain block you pass as the final parameter.  The code below will create a diamond floor underneath our player 50 blocks (across) x 1 block (up) x 50 blocks (along), with our player in the middle (i.e. 25 behind and to the left, 25 in front and to the right).

mc.setBlocks(playerTilePos.x - 25, playerTilePos.y - 1, playerTilePos.z - 25, playerTilePos.x + 25, playerTilePos.y -1, playerTilePos.z + 25, block.DIAMOND_BLOCK)
mc.postToChat("Now thats a big diamond floor!")


To recap on the functions covered in this article:
  • postToChat(message) - communicate with the player(s) in the game
  • getBlock(x, y, z) - get a block type for a specific position
  • setBlock(x, y, z, blockType, blockData) - set (change) a block to a specific blockType
  • setBlocks(x1, y1, z1, x2, y2, z2, blockType, blockData) - set lots of blocks all at the same time by providing 2 sets of co-ordinates (x, y, z) and fill the gap between with a blockType
  • player.getPos() - get the precise position of a player
  • player.setPos(x, y, z) - set (change) the players position
  • player.getTilePos() - get the position of the block where the player current is
There are a few other functions available in the api which should be explored but using only the small number discussed in this article, its possible, with some imagination and a small amount of programming knowledge to create some quite fantastic constructions, tools and utilities.

I love minecraft, its a tremendously creative game and with the Pi edition’s API it opens up new level of creativity and will hopefully encourage more people to try their hand at programming.

If you want to see more examples of what I have done with Minecraft: Pi edition (e.g. a massive analogue clock, the game of snake, an auto bridge which appears under your feet or the whole of Manhattan) head over to my Minecraft page.

60 comments:

  1. I love this blog!! I've always wanted to know how to mod Minecraft Pi. But can you make it a little clearer?

    ReplyDelete
    Replies
    1. What are you struggling with? Is there something specific you want clearer?

      Delete
    2. Well, I had trouble at first. I was thinking that maybe you can put in which files you are editing, etc.

      Delete
    3. I was thinking about modding the minecraft files so I can add in new blocks or change how the world generates
      Is this possible?

      Delete
    4. I would also love to know how to add new blocks on mcpi... if it is possible

      Delete
  2. WHAT IS mkdir ~/minecraft-magpi AND WHERE CAN I FIND IT??? I CHECKED THROUGH MY COMPUTER, PORPERTIES OF EVERUTHING... AND STILL COULDN'T FIND IT... WHEN YOU SAY; We need to create a directory to put our program and api library into mkdir ~/minecraft-magpi. I GET TOTALLY COFUSED BECAUSE I DON'T KNOW WHERE ALL THIS STUFF IS... :/

    AS I SAID BEFORE, I AM WORKING ON A PROJECT THAT WILL ME MASSIVE!!! SO PLEASE HELP AND REPLY FAST!

    PS: GREAT JOB WIHT CREATING THIS PROGRAM

    ReplyDelete
  3. Hi

    mkdir is the command to create a directory. mkdir ~/minecraft-magpi creates a directory called minecraft-magpi in the /home/pi directory. You would run these commands in the terminal.

    You mention your computer. Are you using a raspberry pi?

    Have you thought about starting with some linux usage tutorials before embarking on your big project, it would give you some useful knowledge.

    Best of luck

    Mart

    ReplyDelete
  4. yes, i meant my raspberry pi. i understand that the stuff should run in something, but where? i am new to raspberry pi and dont really know how it works... Thank you for the reply!

    ReplyDelete
    Replies
    1. If you are using the desktop. You can run this commands in a terminal, double click LX Terminal on the desktop to open up the command window.

      Delete
  5. THNX Martin!!! it is working great! you dont know where i could find a program like this one (that builds things for you) for computer?

    ReplyDelete
    Replies
    1. a program that builds stuff for you on minecraft.

      Delete
    2. I have built several programs that automatically build things in minecraft, check out my minecraft projects here - http://www.stuffaboutcode.com/p/minecraft.html

      Also take a look at my program which converts 3d models into minecraft, it might give you some inspiration. http://www.stuffaboutcode.com/2013/03/minecraft-pi-edition-create-massive-3d.html

      Delete
  6. Thanks! This got me started with the API so now I know roughly how to make something of my own!

    ReplyDelete
  7. ImportError: no module named connection

    ReplyDelete
    Replies
    1. Are you by any chance using Idle 3 (and therefore Python 3)? The API doesnt work with python 3 (without doing some fiddling).

      Delete
  8. I have an error, when I hit F5 this is what comes up in the Python Shell...

    Traceback (most recent call last):
    File "/home/pi/minecraft-magpi/minecraft-magpi.py", line 1, in
    import minecraft.minecraft as minecraft
    File "/home/pi/minecraft-magpi/minecraft/minecraft.py", line 1, in
    from connection import Connection
    Import Error: No module named connection

    Can you help me?

    ReplyDelete
    Replies
    1. Are you by chance using IDLE3 (and therefore Python 3?). If so switch to IDLE Python 2.x). The api modules arent python 3.

      Delete
    2. Um.. How would I do that? I'm not very good with the Pi.

      Delete
    3. When you double click on IDLE on the desktop, pick IDLE and not IDLE3

      Delete
  9. I'm of the C64 and Amiga generation (wonderful wonderful times for all of us fortunate enough), and now have the absolute privilege to meet people like yourself doing what we did for fun way back in the day.. It swells me with pride to see what you are doing, and now I can share the basics with my 13 yo son in his favourite game .. A truly magical time for us old guys to pass on... It is a privilege to meet you Martin, and continued good fortune to you for establishing this wonderful project

    ReplyDelete
    Replies
    1. Thanks a lot for the encouraging words... Im not quite so pleased with being an "old guy" tho ;)

      Delete
  10. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. when i run the.program it says
      importerror no module named minecraft
      please help

      Delete
    2. Did you copy the minecraft python library to your program's folder, this line:

      cp -r ~/mcpi/api/python/mcpi ~/minecraft-magpi/minecraft

      Delete
  11. Replies
    1. could i just copy the code from minecraft.py and block.py and just put it in there???

      Delete
    2. If its setup correctly you should have a folder called minecraft in the same folder as your minecraft-magpi.py program which has got all the api py files including minecraft.py, block.py, connection.py, vec3.py, etc

      Delete
  12. I got that /home/pi/minecraft-magpi/minecraft is not a directory

    ReplyDelete
    Replies
    1. Sorry its difficult to offer any advice other than start at the top and try again. You should have copied the minecraft python api library to the /home/pi/minecraft-magpi/minecraft directory when you did this step:

      cp -r ~/mcpi/api/python/mcpi ~/minecraft-magpi/minecraft

      Delete
  13. This comment has been removed by a blog administrator.

    ReplyDelete
  14. I had no trouble with the hello world one, but the next two are making this show up when I run them:

    Traceback (most recent call last):
    File "/home/pi/minecraft-magpi/TrappedYou.py", line 1, in
    playerTilePos = mc.player.getTilePos()
    NameError: name 'mc' is not defined

    Help???

    ReplyDelete
    Replies
    1. I think you have taken my code instructions to literally, the 2nd portion of code:

      playerPos = mc.player.getPos()
      mc.player.setPos(playerPos.x, playerPos.y + 50, playerPos.z)
      mc.postToChat("Dont look down")
      time.sleep(5)

      should be added to the bottom of the first code

      import minecraft.minecraft as minecraft
      import minecraft.block as block
      import time
      mc = minecraft.Minecraft.create()
      mc.postToChat("Hello Minecraft World")
      time.sleep(5)

      Through the tutorial you are meant to build up 1 program not many programs. I hope that makes sense.

      The reason you are getting the error is because your program is create "mc", because you program is missing the code

      mc = minecraft.Minecraft.create()

      Delete
  15. Thanks so much! Also, did you know that the current version of NOOBS (raspberrypi.org/downloads) has Minecraft Pi Edition pre installed? I didn't like it that way, because I Like going inside and changing the names of worlds and things like that. :) I went ahead and uninstalled the pre-installed package, then did it the way your tutorial shows, then I played around until I got a nice grass block icon for it on the desktop. Just wondering, if I follow your tutorial for making a Minecraft server on my Raspberrry Pi, does it run a PC Minecraft server, or a Pi Edition one? Keep up the good work!

    ReplyDelete
    Replies
    1. I did. I'll update the post at some point...

      Delete
  16. Hi, at the Raspberry Jam at PyConUK Coventry, Sept 2014, you handed out a neat four-page (4xA5) version of this article, which would be ideal for schools. Is that available as a freely distributable PDF, please, and if so from where? Looking forward to your book.

    ReplyDelete
  17. i am getting an error : cp -r ~/mcpi/api/python/mcpi ~/minecraft-magpi/minecraft
    when i do the: cp -r ~/mcpi/api/python/mcpi ~/minecraft-magpi/minecraft command in the LX terminal

    ReplyDelete
  18. hi I am new to the raspberry pi and I am using the IDLE to code. I have got an error coming up on the screen when I run it saying. in
    import minecraft.Minecraft ImportError: No module named. when you reply could you break it down so that I could understand the code a bit better. and what does it mean by module.

    ReplyDelete
    Replies
    1. Minecraft comes installed with raspbian as default now so my tutorial is a little out of date. Change your import to be import mcpi.minecraft as minecraft.

      Delete
    2. I have updated the tutorial to reflect the latest changes in Raspbian. Hopefully it should work for you now.

      Delete
  19. Hi.

    I wondered if you can help.

    I'm trying to set minecraft up as a coding tool for primary school kids.

    I've bought your book and followed your instructions, but the first program won't work.

    I've installed the AIMStarterKitPi.tar.gz onto the pi (minecraft Pi was already installed) and extracted this as per your instructions in the book.

    I've then followed you instructions and entered the code into IDLE (not IDLE3) and triple checked it for accuracy.

    But when I run it I get the following error in line 1 from connection import connection:

    ImportError: No module named connection.

    How do I fix this? I don't understand what's gone wrong?

    ReplyDelete
    Replies
    1. Hi,

      The usual problem if you get the "no module named connection" error is because the code is being run in python 3 not python 2. This might not be your issue because you seem pretty clear that you are using IDLE (and not IDLE 3), but I would double check that the python shell shows you are running Python 2.x.x.

      If you submit a post in the forum http://www.stuffaboutcode.com/p/adventures-in-minecraft-forum.html along with your code I will do my best to help you.

      You might also find the videos on the companion website, they take you through adventure 1 step by step.

      Mart

      Delete
  20. Hi mart,

    Thanks for the help!

    I feel a bit daft now, i'd opened both IDLE and IDLE3 by accident and ended up in the IDLE3 window so all is resolved now!

    Thanks again for your help!

    Chris

    ReplyDelete
    Replies
    1. No problem. We have all been there. Im glad you are up and running.

      Delete
  21. #!/bin/sh
    # /etc/init.d/tightvncserver
    # Set the VNCUSER variable to
    the name of the user to start
    tightvncserver under
    VNCUSER=’pi’
    case “$1” in
    start)
    su $VNCUSER -c ‘/usr/bin/
    tightvncserver :1’
    echo “Starting TightVNC
    server for $VNCUSER”
    ;;
    stop)
    pkill Xtightvnc
    echo “Tightvncserver stopped”
    ;;
    *)
    echo “Usage: /etc/init.d/
    tightvncserver
    {start|stop}”
    exit 1
    ;;
    esac
    exit 0

    ReplyDelete
    Replies
    1. Do you have a point to make?

      Delete
    2. ### BEGIN INIT INFO
      # Provides: vncboot
      # Required-Start: $remote_fs $syslog
      # Required-Stop: $remote_fs $syslog
      # Default-Start: 2 3 4 5
      # Default-Stop: 0 1 6
      # Short-Description: Start VNC Server at boot time
      # Description: Start VNC Server at boot time.
      ### END INIT INFO

      #! /bin/sh
      # /etc/init.d/vncboot

      USER=pi
      HOME=/home/pi

      export USER HOME

      case "$1" in
      start)
      echo "Starting VNC Server"
      #Insert your favoured settings for a VNC session
      su - pi -c "/usr/bin/vncserver :0 -geometry 1280x800 -depth 16 -pixelformat rgb565"
      ;;

      stop)
      echo "Stopping VNC Server"
      /usr/bin/vncserver -kill :0
      ;;

      *)
      echo "Usage: /etc/init.d/vncboot {start|stop}"
      exit 1
      ;;
      esac

      exit 0

      Delete
    3. Its an init.d script for starting a VNC server... Well done. Are you just posting obscure spam?

      Delete
  22. Good morning, I've got a question about interacting with multiple players. My son and I are doing some programming and connecting to the same world. While we can see the blocks each other is creating we are having problems with interacting with each other's programs. Specifically we created transporters and it leverages a while loop uses the getTilePos () to determine the location of a player but only seems to recognize the player associated to the computer the script is running on. Is there something I can do to make it functional for all players. Also is there a solution for renaming players? Thanks this blog is a huge help for my 9 year old programmer

    ReplyDelete
    Replies
    1. Hi Michael,

      In order to interact with multi players in the same game you need to use the 'entity' functions in the api. Have a look at "MInecraft Entity" in the Python API Reference http://www.stuffaboutcode.com/p/minecraft-api-reference.html

      For info - when you use mc.player.getTilePos() it only returns data for the 'host' player, you can use mc.entity.getTilePos(entityid) to return the position for any player.

      If you are running 2 programs on 2 different Pi's, you will need to use the IP address when creating the connection to the Pi which is hosting the Minecraft game. e.g. mc = minecraft.Minecraft.create("192.168.1.1")

      I hope this helps.

      Martin

      Delete
    2. Martin, thanks using entity worked like a charm. We have printed out your api reference it is awesome companion to the adventures book. Really let's us expand the options and complexity of the solutions. Tons of fun, thanks for putting that together.

      Quick follow up question do know how to change a players name or where that is stored?

      Delete
    3. Good news. Unfortunately the Pi edition doesn't allow you to change the players name.

      Delete
  23. Martin,
    I've got a Raspberry Pi with Minedraft installed with it and I have your 'Adventures in Minecraft' book, but I am stuck at adventure 1!
    I have written down all of the code to say "Hello Minecraft World" , (CAREFULLY(with no mistakes)) but when I press 'Run' it switches to Python Shell and says, "ImportError: No module named mcpi.minecraft"

    What should I do?!

    ReplyDelete
    Replies
    1. Have you downloaded the starter kit and saved your program to the 'MyAdventures' folder? The error is saying it can't find the minecraft api module which is in the MyAdventures/mcpi directory.

      Create a new post in our forum, it'll be easier to help you there, following the Adventures in Minecraft tab at the top of the page.

      Delete
    2. I don't have the starter pack,
      I didn't know where to get it.

      Delete
    3. From

      Wiley.com/go/adventuresinminecraft

      Follow Adventure 1 it'll talk you through download and install

      Delete
    4. This comment has been removed by the author.

      Delete
    5. I have downloaded the starter pack for my Pi and it came up with an Xarchiver window and it showed the API and just some Licenses.

      What do I do now? I tried the "Hello Minecraft World" command again but again it said, "ImportError: No module named mcpi.minecraft"!

      Delete
    6. Well that sounds positive. Did you extract the files to the /home/pi directory?

      There is a video on the wiley.com/go/adventuresinminecraft website which shows you how to setup your raspberry pi and get hello minecraft world working. Perhaps that might help?

      It would be great if you could create a post in the forum if you need more help, that way others can help and we can share links, pictures, videos, etc.

      Delete
    7. Thanks for your help Martin!

      I like the adventures you have made. :)

      Delete