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 you haven't done so already, head over to this post for how to Install Minecraft on the Raspberry Pi.

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 mcpi/api/java and mcpi/api/python directories.

The following example is written in Python and uses Mojang’s python api library, the first task is to create a directory for your API program and copy the python library to it.

API Example

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

mkdir ~/minecraft-magpi

Copy Python Library
We will be using the python api library supplied with the game and need to copy it into our directory.

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

Create program
Open 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 minecraft.minecraft as minecraft
import minecraft.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.

34 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