Glasses in Front of Monitor

Minecraft Pi Edition is a version of the popular open world sandbox game for the Raspberry Pi. Based on the mobile version of the game, the Pi edition has the added feature that you can program it. It is free of charge and can be downloaded from the Minecraft Pi Edition page on the Minecraft website.

This currently only supports creative mode in a world of 256*256 blocks, just like the pocket edition. It comes with an Application Programming Interface ( API) for both Python and Java, but there is also a Ruby interface for download from the website. This tutorial will focus on the Python API. By accessing this API, you can change the world of Minecraft by placing blocks, adding your own logic, and making your own games in the world of Minecraft.

Installing Minecraft Pi Edition

You need to run Raspbian on your Pi to get started with Minecraft Pi Edition. To install Minecraft Pi Edition, follow the following instructions:

  1. Visit the Minecraft Pi Edition download page to download the game.
  2. Open LXTerminal by clicking the icon on your desktop or under Applications on the menu.
  3. Then run tar xzf minecraft-pi-0.1.1.tar.gz to extract the tar-gzip archive to your home directory.

If you then want to run the game you can do the following:

  1. cd mcpi to change to the Minecraft Pi Edition game directory
  2. Then run ./minecraft-pi

Programming Minecraft Pi Edition

Now I'm going to take you through some of the basics of programming Minecraft Pi Edition using the Python API.

Getting Started
The first thing you need to do is to launch Minecraft on your Raspberry Pi.

Once you've started the game, you need to choose "Start Game", followed by "Create New". This should take you to a randomly generated world that you can start modifying with code.

Now you need to open another terminal from which you can run your programs. To do this, you'll need to press escape to pause the game and allow the mouse to move out of the game window. Then you can start another terminal from your desktop. You may find it easier to use ssh to access the machine if you can, as you don't have to leave the game in a paused state while entering the code.

Once your terminal is launched, you need to go to the python api directory by running:

cd mcpi/api/python/mcpi

Now you can get a python prompt by typing "python" and pressing the return button. You should see your prompt go to >>>.

Hello Minecraft World

Now that you've got your python prompt, you 're ready to start programming. The first thing we need to do is import the library from Minecraft.

import minecraft

Now we need to initialise it which will create a connection to your game and allow you to start modifying the game world.

mc = minecraft.Minecraft.create()

You can now use the mc object you've created to control the world. Let's say hello to your world of Minecraft:

mc.postToChat("Hello Minecraft World!")

You should see your message appear in the chat window of your game. Feel free to change this message to whatever you want to do. You can use the postToChat method to post all kinds of information you want the player to see.

Placing Blocks

We have a programmable version of Minecraft, so just writing stuff to the chat window doesn't cut it anymore. Let's take a look at the placement of blocks in the world. Let's use the following to place a block:

import block
mc.setBlock(0, 10, 0, block.STONE)

The first line that imports "block" simply allows us to use block names when we place them. We could easily set up block. LAVA, block. MELON, or block. WATER. A full list can be found on the Minecraft Wiki Page.

The second line calls setBlock and passes in three numbers and the block type. These 3 numbers are the X , Y and Z coordinates of the game world. Just like you would find in math, this coordinate system , called Cartesian Coordinates, allows you to map your blocks in a 3D world. From the start position of your player, X is left and right, with numbers going down as you head left and up if you head right. The Y coordinates are up and down, increasing the number and decreasing the number. This leaves the Z axis forwards and backwards, increasing the number forwards and decreasing backwards. It's worth noting that declining numbers are going to a negative value.

Cartesian Coordinates Explained

Building Structures in Minecraft PI

Placing blocks individually in code to make structures can be time consuming, as well as making the code really big and bloated. The beauty of having a programmable interface into Minecraft means that we can get around this using for loops. Take the following code for instance:

import minecraft 
import block mc = minecraft.Minecraft.create() for x in xrange(0, 10): mc.setBlock(x, 10, 0, block.STONE)

This will produce a line of 10 blocks, 10 high on the Y axis and 0 on the Z.The x in xrange(0, 10) means that it will loop around 10 times starting at 0 (producing 0,1,2,3,4,5,6,7,8,9) and each pass increments x by 1. For instance, the first loop would produce 0, so our call to set block would actually be mc.setBlock(0, 10, 0, block.STONE), on the second pass it would be mc.setBlock(1, 10, 0, block.STONE), then mc.setBlock(2, 10, 0, block.STONE), and so on.

Building a Wall

If we take our code and build on it we can use it to build a wall. To do this we need to nest the loops. Let's take a look at the code:

for x in xrange(0, 10):
for y in xrange(0, 10):
mc.setBlock(x, y, 0, block.STONE)

So this has an extra for loop which gives us the y value of our coordinates. What is happening here is that the for loop calculating x is called and then immediately calls the for loop that calculates the y coordinate. The loop that calculates the y coordinate loops around its 10 times before it exits and goes back to the second iteration of the x loop. Let's simplify the loops a bit and break it down. Take the following code for instance:

for x in xrange(0, 3):
for y in xrange(0, 3):
mc.setBlock(x, y, 0, block.STONE)

These loops will loop around 3 times each, but the y loop will be called 3 times as it sits inside the x loop. This means it will actually do 9 iterations through the y loop in total. Let's see a break down of what it will actually do:

  1. The first call hist the x loop and x is set to 0.
  2. It then calls the y loop and y is set to 0.
  3. It then sets a block at (0,0,0)
  4. The Y loop then iterates around as it has not exhausted it's 3 iterations yet. This time y is 1.
  5. A block is set at (0,1,0)
  6. The y loop still has one more iteration and so goes around again, with y being 2 this time.
  7. A block is set at (0,2,0)
  8. The y loop has exhausted it's iterations on this call and so the scope falls back out the the x loop. X becomes 1 this time.
  9. The y loop is called again but this time it is from fresh as it is a new iteration of the x loop. Y is initialised to 0.
  10. A block is set at (1,0,0)
  11. The y loop goes back around and sets the y value to 1.
  12. A block is set to (1,1,0)
  13. Y is incremented again to 2.
  14. A block is set at (1,2,0).
  15. The Y loop is exhausted and the X loop comes round to it's final iteration. X is now 2.
  16. The Y loop is called again and starts fresh as it is a new iteration of the X loop. Y is 0.
  17. A block is set at (2,0,0)
  18. Y is incremented.
  19. A block is set to (2,1,0)
  20. Y is incremented.
  21. A block is set at (2,2,0)
  22. The Y loop has exhausted and so falls back to the X loop.
  23. The X loop has exhausted and so continues on with any code after.

Building a Cube

To build a solid Cube we simply need to add a third dimension to the last example. This time we need a z axis to give us out 3D Cube. To do this we simply add another nested loop like in the following:

for x in xrange(0, 10):
for y in xrange(0, 10):
for z in xrange(0, 10):
mc.setBlock(x, y, z, block.STONE)

Building a Hollow Cube

To build a hollow cube, we need to ensure that we only place a block if we are on the outer edge. Because our x, y and z coordinates are from 0 to 9, we only want to place a block if the value of x, y or z is at 0 or 9 (hence the first or last block). This is what the if statement does in the following code:

for x in xrange(0, 10):
for y in xrange(0, 10):
for z in xrange(0, 10):
if(x==0 or x==9 or y==0 or y==9 or z==0 or z==9):
mc.setBlock(x, y, z, block.STONE)

Building a Sphere

The following code will produce a sphere:

for x in range(-10, 10):
for y in xrange(-10,10):
for z in xrange(-10, 10):
if(x**2 + y**2 + z**2 < 10**2):
mc.setBlock(x,y,z,block.STONE)

We have 3 nested for loops to produce our x, y and z coordinates (to ensure the sphere is 3D) but we have this if statement in here. The ** in the calculations means to the power of. So what is actually happening is we are saying (x to the power 2) + (y to the power 2) + (z to the power 2) is less than (10 to the power 2).

Tracking your player in Minecraft PI

Getting the players position is made easy by the API. The following will get the players position and store it in the pos variable:

import minecraft
import block
                        
mc = minecraft.Minecraft.create()
                            
pos = mc.player.getTilePos()

You can then print this to the game chat using the following:

mc.postToChat(str(pos))

Building around your player

You can use the players position with an offset to build structures around the player in the world. Let's have a look at setting a block next to our player:

pos = mc.player.getTilePos()
mc.setBlock(pos.x + 1, pos.y + 1, pos.z, block.STONE)

In this example we assigned the players position, which is of type Vec3 and contains an x, y and z position, to pos. We then use this as the basis for the position of the stone block we are setting by adding 1 to the x and y coordinate. This then places the block to the side of the player at head hight. It's worth remembering that the player is 2 blocks high and the position you get is the coordinate for the players lower block, where as the camera site on the upper block.

Minecraft Place Block next to Player

The following is a more Python way of doing things. Either way is fine to use:

xpos,ypos,zpos = mc.player.getTilePos()
mc.setBlock(xpos+1, ypos+1, zpos, block.STONE)

Tracking the distance of your player

You might want to track the distance from another position in the Minecraft world like a structure or checkpoint. We can write a small function that allows us to pass in 2 sets of coordinates and returns us the distance in blocks. Take the following for instance:

import math
def getDistanceBetweenPoints(point1, point2):
    xDistance = point2.x - point1.x
    yDistance = point2.y - point1.y
    zDistance = point2.z - point1.z
    return math.sqrt((xDistance * xDistance) + (yDistance * yDistance) + (zDistance * zDistance))

We can call this function and pass in 2 point in the world and it will return the distance between them. The following will give us the distance between the player and the centre of the world and print it to the game chat:

startPos = minecraft.Vec3(0,0,0)
playerPos = mc.player.getPos()
distanceFromStart = getDistanceBetweenPoints(startPos, playerPos)
mc.postToChat("Distance " + str(int(distanceFromStart)))

Putting it all together

So if we wanted to keep the player updated with how far they are from the centre point then we need to add a bit of a loop to what we have. The following will keep printing the number of blocks between the player and the central position every 1 second.

import minecraft
import block
import math
import time #Returns the distance between 2 positions
def getDistanceBetweenPoints(point1, point2):
    xDistance = point2.x - point1.x
    yDistance = point2.y - point1.y
    zDistance = point2.z - point1.z
    return math.sqrt((xDistance * xDistance) + (yDistance * yDistance) + (zDistance * zDistance))                                                                                                                                   mc = minecraft.Minecraft.create() #Set the start position
startPos = minecraft.Vec3(0,0,0) while(True):
#Get the players position
playerPos = mc.player.getPos() #Calculate the distance to the start
distanceFromStart = getDistanceBetweenPoints(startPos, playerPos) #Print the distance on the game chat
mc.postToChat("Distance: " + str(int(distanceFromStart)) + " blocks") #Sleep for a second so that we don't just flood the game
time.sleep(1)

As you can see, we have barely modified the existing code to produce some regular output to the player which could lead them to the next position in a game.

Task

See if you can extend what is already there to make a Gold Finder game. Hide some gold around the world and get the player to go and find it. To do this you will need to generate a random position for the gold. You can use the random library for this. For instance:

import random
randomNumber = random.randrange(-100, 100)

This will produce a random number between -100 and 100, so you could use that as part of your coordinate. Give it a go.