Monday, 2 March 2015

Minecraft - Star Wars

Myself and David Whale (my co-author on Adventures in Minecraft) were asked if we would do a talk on "Hacking Minecraft" at the Raspberry Pi 3rd Birthday Party. I wanted to do something fun to show you how you can do amazing things in Minecraft using the Pi API.

After coding the Solar System in Minecraft I had the idea of creating the Death Star which would be able to 'fire' at the planets and destroy them.  I ended up coding an animation of the Death Star destroying Alderaan right up to Luke flying down the trench and successfully bombing the exhaust port with a block of TNT.

If you want to try it out yourself, all the code in at To download the code and run it on your raspberry pi, follow these instructions.

Run Minecraft: Pi Edition and open a world.

Open LX Terminal, and run the following commands to download the program and run the program

cd ~
git clone
cd minecraft-starwars

The code relies heavily on the minecraftstuff module which is included in the mcpi directory of the repository, so if you copy the program anywhere else be sure to copy the mcpi directory too.

Saturday, 21 February 2015

Minecraft - Code a Solar System

Update - I took this further and created a DeathStar to blow up planets too, in a Minecraft Star Wars animation.

Every wondered how big the Sun is? Well check out the picture below.

If the Earth was the size of 1 block in Minecraft the Sun would have a diameter of 109 blocks and if the distance was to scale 11728 blocks away!

What about the size and distance of the other planets in blocks?


I didn't build this Solar System I coded it. I took information about the diameter and distance of the planets from Nasa's Planetary Fact Sheet and created a fairly simple program which created spheres of the right size based on a factor of Kilometers to Blocks.

The code is on github at or you can download the Minecraft world.

You can change the ratio of the sun and planets by changing the constant KMTOBLOCK, which is the number of kilometers per block - be careful though, the sun will be VERY big if the value is too low. You might have to increase the height of your Minecraft world too.

#Minecraft - Code a solar system
#Martin O'Hanlon

#import minecraft api library
import mcpi.minecraft as minecraft
import mcpi.block as block

# draw hollow sphere
def drawHollowSphere(mc, x1, y1, z1, radius, blockType, blockData=0):
    # create sphere
    for x in range(radius*-1,radius):
        for y in range(radius*-1, radius):
            for z in range(radius*-1,radius):
                if (x**2 + y**2 + z**2 < radius**2) and (x**2 + y**2 + z**2 > (radius**2 - (radius * 2))):
                    mc.setBlock(x1 + x, y1 + y, z1 +z, blockType, blockData)

# draw sphere
def drawSphere(mc, x1, y1, z1, radius, blockType, blockData=0):
    # create sphere
    for x in range(radius*-1,radius):
        for y in range(radius*-1, radius):
            for z in range(radius*-1,radius):
                if (x**2 + y**2 + z**2 < radius**2):
                    mc.setBlock(x1 + x, y1 + y, z1 +z, blockType, blockData)

#setup constants (all values in kilometers)
SUN = 1391684
#name, diameter, distance, blockId, blockData
PLANETS = (("mercury", 4879, 57900000,, 7),
           ("venus", 12104, 108200000,, 0),
           ("earth", 12756, 149600000,, 11),
           ("mars", 6792, 227900000,, 14),
           ("jupiter", 142984, 778600000,, 4),
           ("saturn", 120536, 1433500000,, 8),
           ("uranus", 51118, 2872500000,, 3),
           ("neptune", 49528, 4495100000,, 10),
           ("pluto", 2390, 5870000000,, 6))

#how many km's to a block
# change this value to have different sizes in the solar system
KMTOBLOCK = 12756.0

#middle of the minecraft sky, where the centre of the planets will be

print("Minecraft Planets")
print("1 block = {} kilometers".format(KMTOBLOCK))

#connect to minecraft
mc = minecraft.Minecraft.create()

#set the middle of the solar system
pos = minecraft.Vec3(0,MCMIDDLE,0)

#create the sun
sunDiameter = round(SUN / KMTOBLOCK, 2)
sunRadius = int(round(sunDiameter / 2))
print("Sun - Diameter = {} blocks".format(sunDiameter))
drawHollowSphere(mc, pos.x, pos.y, pos.z, sunRadius,, 1)
gapToLeave = (sunDiameter / 2) + 20
pos.z = pos.z + gapToLeave

#loop through the planets
for planet in PLANETS:
    name = planet[0]
    diameter = round(planet[1] / KMTOBLOCK, 2)
    radius = int(round(diameter / 2))
    distance = round(planet[2] / KMTOBLOCK, 2)
    print("{} - Diameter = {} blocks - Distance = {} blocks".format(name, diameter, distance))
    #if the diameter is less than 1.5 draw a single block
    if diameter < 1.5:
        mc.setBlock(pos.x, pos.y, pos.z, planet[3], planet[4])
        drawSphere(mc, pos.x, pos.y, pos.z, radius, planet[3], planet[4])
    gapToLeave = (diameter / 2) + 20
    pos.z = pos.z + gapToLeave

#move the player to the sun

Have fun.

Wednesday, 4 February 2015

Raspberry Pi 2 - Minecraft Server

The new Raspberry Pi 2 has got twice the RAM and a load more processing power, so will it make a better Minecraft server?  The old Pi made an adequate Minecraft server providing you only had a few players and you kept the view distance low.

I tried both the vanilla server and a spigot server, both similar results, both performed reasonably well, but Spigot seemed a little more stable (but this is only based on feeling).  I was only able to test with up to 3 players but it worked well under those conditions.

Setting up your own server is pretty simple.

You will need to download either the vanilla server from Mojang or build your own spigot server jar file.

Note - The instructions below, will take you through how to create a vanilla server, if you have built spigot the only difference will be the name of the 'jar file' you put into the file

1. Make a directory for your Minecraft server

mkdir ~/MinecraftServer
cd ~/MinecraftServer

2. Download the 1.8.1 vanilla Minecraft server jar file


3. Create a script to run the server jar file


Enter the following command which will run the server

java -Xmx1024M -Xms512M -jar minecraft_server.1.8.1.jar nogui

Ctrl X to exit & save

4. Make the script executable:

chmod +x

5. Run the server


You should receive a message asking you to accept the EULA.

6. Accept the EULA (end user license agreement), open eula.txt

nano eula.txt





Ctrl X to save and exit

7. Run the server


The first time the server runs it will take a while to start as it creates a new world.

Once you see the word "Done", the server is up and running and you should be able to connect to the server using Minecraft choosing Multiplayer, Direct Connect and entering the IP address of the Pi.

You can shutdown the server by typing the command "stop" in the command window .

If you find the server is slow, particularly when generating chunks (i.e. creating new bits of the world when you get to the edge), you could try reducing the view distance.  I reduced it from 10 to 7 and this seemed to make the server more responsive.

8. Edit view-distance in






Ctrl X to save and exit

Restart the server for the change to take effect.

Tuesday, 13 January 2015

Minecraft API - Player's Direction

One of the questions I get asked a lot about the Minecraft: Pi edition APi is "how can I get the direction the player is facing?" and I have always had to say "sorry you can't do that".

While I can't change the API for Minecraft: Pi edition I can change RaspberryJuice - so I decided to add functions to allow you to find out where the player is looking.  You can download the RaspberryJuice plugin Canarymod and Bukkit.

I have also created a new Adventures in Minecraft starterkit which includes the new version of RapsberryJuice and everything you need to use the new api functions.

The 3 new functions in the api are:
  • player.getRotation() - return the angle of rotation between 0 and 360
  • player.getPitch() - returns the angle of pitch between -90 and 90
  • player.getDirection() - returns a unit-vector of x,y,z pointing in the direction the player is facing
The functions also work with the entities as well so you can use entity.getRotation(), entity.getPitch() and entity.getDirection()

Here are the couple of code examples I demo in the video.

Get the players rotation and pitch angles:
#import the minecraft module
import mcpi.minecraft as minecraft

#create a connection to minecraft
mc = minecraft.Minecraft.create()

while True:
    #get the players rotational angle
    angle = mc.player.getRotation()
    #get the player up and down angle
    pitch = mc.player.getPitch()
    mc.postToChat(str(angle) + " : " + str(pitch))

Create a block in front of the player using getDirection():
import mcpi.minecraft as minecraft
import mcpi.block as block
import time

#how far in front of the player the block will be

mc = minecraft.Minecraft.create()

while True:
    #get the position
    pos = mc.player.getPos()
    #get the direction
    direction = mc.player.getDirection()
    #calc the position of the block in front of the player
    x = round(pos.x + (direction.x * BLOCKDISTANCE))
    y = round(pos.y + (direction.y * BLOCKDISTANCE) + 1)
    z = round(pos.z + (direction.z * BLOCKDISTANCE))

I hope you find the new api functions useful.

Tuesday, 30 December 2014

BBC iPlayer RSS Feeds - 4 million / day

When the BBC decided to turn off its iPlayer RSS feeds with no up front warning, I was annoyed, really annoyed, which isn't like me.

Why was I annoyed? I think it was the total arrogance of the "Yeah sorry you used to use them, we don't do that anymore, try this new thing", "but the new things not ready yet?", "Yeah sorry about that".

In short a fairly sizable group of people used these RSS feeds either directly or indirectly via 3rd party tools to access iPlayer content and it was the only reliable and open data method for getting information about iPlayer content.

I was interested, other than me, who else used these RSS feeds, so I made a freedom of information (FOI) request to the BBC and asked them.  It turns out for the 30 days prior to them being shutdown they were accessed 4,000,000 (yes 4 MILLION) times a day!  

The response from the BBC goes on to state that they suspect that a fair number of the downloads where from bots, yep probably, but those bots where doing so to deliver services to people and it could be that 1 bot download serviced many people.

The moral of the story is that you can't expect services to be provided forever regardless of who is providing them and how many people use them or assume that there will be a replacement.

Below is my request and subsequent response from the BBC.

Subject: FOI Request - BBC iPlayer RSS Feeds Usage
From: "Martin O'Hanlon" 

Dear Sir,

I am requesting information under the Freedom of Information act about the
usage of BBC iPlayer RSS feeds.

On (or around) the 29th October, access to the BBC iPlayer RSS Feeds was
removed (

Could you provide information relating to the use of the RSS Feeds prior to
them being removed.

By month, for the 12 months previous could you state the number of access
requests for the RSS feeds supplied under

If you are unable to provide 12 months of data by month, could you provide
the information for the last 30 days.

Kind regards

Martin O'Hanlon


From: FOI Enquiries <>
To: "'Martin O'Hanlon'" 
Subject: Response to your request for information - RFI20141782
Date: Fri, 28 Nov 2014 14:49:53 +0000

Dear Mr O'Hanlon

Please find attached the response to your request for information, referenc=
e RFI20141782.

Kind regards

BBC Information Policy and Compliance
BC2 B6, 201 Wood Lane, London W12 7TP

You can download the attached from here, or view the contents below:

Martin O'Hanlon
Via email:

28th November 2014

Dear Martin,

Freedom of Information Act 2000 – RFI20141782

Thank you for your request under the Freedom of Information Act (‘the Act’) of 30th
October 2014, seeking:

“I am requesting information under the Freedom of Information act about the usage of BBC iPlayer
RSS feeds.

On (or around) the 29th October, access to the BBC iPlayer RSS Feeds was removed

Could you provide information relating to the use of the RSS Feeds prior to them being removed.
By month, for the 12 months previous could you state the number of access requests for the RSS
feeds supplied under

If you are unable to provide 12 months of data by month, could you provide the information for the
last 30 days.”

I estimate that to deal with your request for 12 months’ worth of data, given the amount of
data this involves, would take more than two and a half days; under section 12 of the Act, we
are allowed to refuse to handle the request if it would exceed the appropriate limit. The
appropriate limit has been set by the Regulations (SI 2004/3244) as being £450 (equivalent to
two and a half days work, at an hourly rate of £25).

With regard to the 30 days’ worth information, the following is the total number of requests
for urls under which relates to iPlayer RSS feeds (date followed
by the total):

28/09/2014 - 4139102
29/09/2014 - 3969429
30/09/2014 - 3688324
01/10/2014 - 3884073
02/10/2014 - 3883081
03/10/2014 - 3925662
04/10/2014 - 4159130
05/10/2014 - 4222500
06/10/2014 - 4131642
07/10/2014 - 3985815
08/10/2014 - 4012385
09/10/2014 - 3915717
10/10/2014 - 3882014
11/10/2014 - 4048638
12/10/2014 - 4208782
13/10/2014 - 4116161
14/10/2014 - 3970894
15/10/2014 - 4140721
16/10/2014 - 3840215
17/10/2014 - 3929542
18/10/2014 - 4183741
19/10/2014 - 4298197
20/10/2014 - 4059930
21/10/2014 - 4046123
22/10/2014 - 3941945
23/10/2014 - 3922209
24/10/2014 - 3962244
25/10/2014 - 4070949
26/10/2014 - 4307425
27/10/2014 - 4074942
28/10/2014 - 4050387

Please note that the data above does not give any indication of what was making the request
i.e. whether human or bot (a software application which runs automated tasks over the
internet). The rather flat level probably indicates that there was a very large amount of
automated processing going on, so this should not be confused with actual users doing
something with the information in the feeds.

You may request an internal review of our decision that your request exceeds the
appropriate limit. Please contact us at the address above, explaining what you would like us to
review and including your reference number. If you are not satisfied with the internal review,
you can appeal to the Information Commissioner. The contact details are: Information
Commissioner's Office, Wycliffe House, Water Lane, Wilmslow, Cheshire, SK9 5AF, Tel:
0303 123 1113 (local rate) or 01625 545 745 (national rate) or see

Yours sincerely,

Kate Leece
Head of Legal and Business Affairs
BBC Future Media

Sunday, 21 December 2014

Minecraft - QR Codes

This isn't a particularly new idea and it has certainly been done before... but I like it.

Point your phone at this...

I saw a tweet from @ImmersiveMind (aka Stephen Reid) linking to a new blog post about creating qr codes in Minecraft as a way of showing how to link the real world with the digital.

That afternoon I had 30 minutes to wait before I was picked up to be taken out for festive activities - could I code a Minecraft QR generator in time? It turns out I could:

I used the fantastic python module qrcode to create the QR, which has a useful function, get_matrix(), to allow you to get the QR as a 2 dimensional list of True and False's.  I then used this matrix to create white and black wool - dead easy!

The qrcode module can be installed using pip and requires PIL (python imaging library) to work - the first step is to install pip and PIL and then use pip to install qrcode:
sudo apt-get install python-pip python-imaging
sudo pip install qrcode
You can get the code from github:
git clone
Run it:
python minecraft-qrcode/
The code:
from qrcode import *
from mcpi.minecraft import *
from mcpi.block import *

def getQR(inputString):
    qr = QRCode(version=1,
    return qr.get_matrix()

mc = Minecraft.create()
pos = mc.player.getTilePos()

qrMatrix = getQR("")

rowNo = 0
for row in qrMatrix:
    rowNo -= 1
    columnNo = 0
    for column in row:
        columnNo -= 1
        if column:
            blockColour = 15
            blockColour = 0

        mc.setBlock(pos.x + rowNo, pos.y + columnNo, pos.z,, blockColour)

Thursday, 18 December 2014

GPIO Xmas Tree Reaction Game

In order to bring a bit of Christmas based fun to the office (I am normally a bit of a 'bah humbug') I have created a reaction game using a Raspberry Pi and a GPIO Xmas Tree from pocketmoneytronics.

The game is pretty simple, random leds are lit up on the xmas tree, the player has to press the button when the green led on the top of the tree is lit up.  The quicker you are, the higher you score.

A random animation is played when the tree is waiting for the next player, you press the button to start, all the leds are lit up and then its time to play.  At the end the players position is displayed on the tree, with 1st place lighting up the top of the tree.

Have a go
You will need a Raspberry Pi, a GPIO Xmas Tree and a button:
  1. Plug the GPIO Xmas tree into the far left set of pins on the GPIO header
  2. Connect the button up between 3.3V and GPIO 4.

Update - 23/12/2014 - 2 player
The GPIO Xmas Tree Reaction game has gone 2 player...  You go head to head versus a friend, the quickest to the green led wins and an led on either the left or right of the tree is lit up to show you who won.

If you want to play head to head:
  1. Connect the button up between 3.3V and GPIO22
  2. Press the 2nd button to start the 2 player game, pressing the 1st button, still starts the 1 player game
Get the code
Download the code from and run the game - open a terminal and run:
git clone
cd GPIOXmasTreeGame/xmastreegame

How does it work
There was only 1 particular challenge to creating the game (other than my dodgy soldering which meant I ruined the first tree I brought)  - doing more than one thing at a time!

The libraries supplied by pocketmoneytronics are really good and there are some great examples, the problem I had is that when you tell the tree to "light up leds 1 & 4", that is all your program can do, it blocks because the tree uses Charlieplexing and the libraries don't support threading.

Charliewhat?  In summary, each gpio pin is actually controlling 2 leds and when you light up 2 leds on the tree the program is actually turning the leds on and off independently really quickly, so quickly that its tricking your eyes into thinking that both leds are actually turned on.

This is why you cant just "turn on led 1 and led 4", the tree doesn't work that way.

To get around this, I made a threaded version of the pocketmoneytronics module.

Using the original libraries, you would have used the following code to light up all the leds for 1 second:
#turn all the leds on for 1 second
#the program stops here and nothing can happen until the leds turns off
tree.leds_on_and_wait(ALL, 1)
Using my threaded class you would use:
#create the XmasTree object
tree = XmasTree()
#start the tree object
#turn all leds on
#the program can now do what it wants and the leds will stay on
The rest of the program was pretty easy to create, wait for a button to be pressed, light up led's randomly with a random delay in between, get the difference in time between turning on the yellow led and the button being pressed and hey presto, a Christmas themed game.

The code
All the code is here
import threading
import RPi.GPIO as GPIO
from time import sleep, time
from ThreadedTree import XmasTree
from random import getrandbits, randint
from os.path import isfile

L0 = 1
L1 = 2
L2 = 4
L3 = 8
L4 = 16
L5 = 32
L6 = 64
ALL = 1+2+4+8+16+32+64
#leds as a list
LEDS = [L0,L1,L2,L3,L4,L5,L6]
#leds as a list descending down the tree
LEDSDESC = [L0,L6,L5,L4,L2,L1,L3]
#gpio pin the game button is connected too
#gpio pin which will cause the game to stop if trigger

class TreeRandom(threading.Thread):
    def __init__(self, xmasTree):
        #setup threading
        #setup properties
        self.stopped = False
        self.running = False
        self.xmasTree = xmasTree
    def run(self):
        self.running = True
        while not self.stopped:
            ledsToLight = 0
            #loop through all the lights, randomly pick which ones to light
            for led in LEDS:
                if getrandbits(1) == 1:
                    ledsToLight = ledsToLight + led
            #turn the leds on
        #when its stopped turn the leds off
        self.running = False

    def stop(self):
        #stop the animation
        self.stopped = True
        #wait for it to stop running
        while self.running:

class TreeGame():
    def __init__(self, xmasTree, scoresFile):
        self.scoresFile = scoresFile
        self.scores = self._loadScores()
        #print self.scores

    def play(self):
        #turn on all leds
        #wait a bit
        #get a random number, which will be how many leds will be lit before the green one
        steps = randint(7,14)
        for step in range(0,steps):
            #light a random red led
            ledToLight = LEDS[randint(1,6)]
            #wait for a random time between 0.5 and 1 second
            timeToSleep = randint(5,10) / 10.0
        #light the green led
        #get the time
        startTime = time()
        #wait for button to be released (if its pressed)
        while(GPIO.input(NEWGAMEBUTTONPIN) == 1):
        #wait for the button to be pressed
        while(GPIO.input(NEWGAMEBUTTONPIN) == 0):
        #get the time
        endTime = time()
        timeDiff = endTime - startTime
        #put the score in the score list and find the position
        # loop through all the scores
        for score in range(0,len(self.scores)):
            # is this time less than the current score?
            if timeDiff < self.scores[score]:
                #record the players position
                position = score
        #save to the score file
        #flash the position

    def _displayPosition(self,position):
        #if there position was less than 6, flash it on the tree
        # else flash all the lights
        if position <= 6:
            ledToLight = LEDSDESC[position]
            ledToLight = ALL
        #flash the position
        for count in range(15):

    # load the scores files
    def _loadScores(self):
        scores = []
        #does the file exist?  If so open it
        if isfile(self.scoresFile):
            with open(self.scoresFile, "r") as file:
                for score in file:
            #no file so put an initial score which is massive

        return scores

    # save the scores file
    def _saveScores(self):
        with open(self.scoresFile, "w") as file:
            for score in self.scores:

#main program
if __name__ == "__main__":

    #setup GPIO

    #setup the new game button
    #setup the stop game button

    #create threaded tree object
    xmasTree = XmasTree()
    #start the xmas tree
    #create tree game oject
    treeGame = TreeGame(xmasTree, "scores.txt")

        stopGame = False
        #loop until the stop game pin is set
        while(not stopGame):
            #run the xmas tree random animation
            treeRandom = TreeRandom(xmasTree)
            #wait until a button is pressed to either start a new game or stop the game
            while(GPIO.input(NEWGAMEBUTTONPIN) == 0 and GPIO.input(STOPGAMEBUTTONPIN) == 0):
            #new game
            if GPIO.input(NEWGAMEBUTTONPIN) == 1:                
                #stop the animation
                #run the game
                #game over, start the animation again

            #stop game
            elif GPIO.input(STOPGAMEBUTTONPIN) == 1:
                stopGame = True
        #stop tree random animation
        #stop xmas tree
        #cleanup gpio