Wolfram Blog
Jon McLoone

Programming Minecraft on the Raspberry Pi

July 5, 2018 — Jon McLoone, Director, Technical Communication & Strategy

The standard Raspbian software on the Raspberry Pi comes with a basic implementation of Minecraft and a full implementation of the Wolfram Language. Combining the two provides a fun playground for learning coding. If you are a gamer, you can use the richness of the Wolfram Language to programmatically generate all kinds of interesting structures in the game world, or to add new capabilities to the game. If you are a coder, then you can consider Minecraft just as a fun 3D rendering engine for the output of your code.

Minecraft

Installation

The first step is to make sure that you have all the right components. Make sure that you have the latest version of Raspbian and the Wolfram Language. You do this by connecting your Raspberry Pi to the network, opening the Terminal app and typing the following:

sudo apt-get update.
sudo apt-get dist-upgrade

Now open Mathematica on the Pi, or another computer, and type:

PacletInstall
&#10005

PacletInstall["MinecraftLink"] 

… followed by Shift + Return to evaluate it. If all went well, we are ready to start.

The MinecraftLink library adds a small set of new commands to the Wolfram Language for connecting to a running Raspberry Pi Minecraft game.

Start by launching Minecraft on the Raspberry Pi, and then start a fresh game or open an existing one. In the Wolfram Language, load the library by evaluating the following:

<<MinecraftLink`
&#10005

<

This extends the Wolfram Language with the following new commands:

?MinecraftLink`*
&#10005

?MinecraftLink`*

Wolfram Language commands

You can find documentation on these by evaluating MinecraftHelp[] after you have installed the link.

You can control a Minecraft game running on the Raspberry Pi from the Wolfram Language running on the same Raspberry Pi, or from any other computer that has a network connection to the Pi. If you’re connecting from a different computer, you must now tell the Wolfram Language the name or IP address of the Raspberry Pi where Minecraft is running...

MinecraftConnect
&#10005

MinecraftConnect["10.10.163.22"]

You don’t need to do this if both programs are on the same machine, but if you need to reset the connection, you can use MinecraftConnect or MinecraftConnect["localhost"].

Let’s test to see if that worked by evaluating the following code:

MinecraftChat
&#10005

MinecraftChat["Hello from the Wolfram Language"]

You should see the message appear briefly in the game chat area:

Hello from the Wolfram Language

We need to find out where we are in the Minecraft world. Minecraft uses a simple 
{x, y, z} coordinate system, where x and z are the horizontal directions (x is left/right if you have just started the game) and y is the vertical direction. If you have started a fresh game, you will be near to {0, 0, 0}. You can see the coordinates in the top-left corner of the screen, but to get them programmatically you can use:

MinecraftGetPosition
&#10005

MinecraftGetPosition[]

We can teleport the character to a new location (in this case, up in the air) with:

MinecraftSetPosition
&#10005

MinecraftSetPosition[{0,50,0}]

If we have just started a game, then 10 blocks in front of us is {0, 10, 0}. But depending on how mountainous the terrain is, that block might be above or below ground. We can find the surface level with:

&#10005

y=MinecraftGetHeight[{0,8}]

We can test that by looking at the block at that position. It should be Air.

pos={0,y,8}
&#10005

pos={0,y,8}

MinecraftGetBlock
&#10005

MinecraftGetBlock[pos]

And the block below it should be something solid:

MinecraftGetBlock
&#10005

MinecraftGetBlock[pos-{0,1,0}]

Building

Now we can start building. We can place blocks of any type—for example, "Wood":

MinecraftSetBlock, Wood
&#10005

MinecraftSetBlock[pos,"Wood"]

We remove them by just overwriting the block with something else, such as "Air":

MinecraftSetBlock, Air
&#10005

MinecraftSetBlock[pos,"Air"]

But if you want a full undo, you must precede your changes with:

MinecraftSave
&#10005

MinecraftSave[]

And then if you don’t like your changes, you can undo them with:

MinecraftRestore
&#10005

MinecraftRestore[]

The list of the 156 available Minecraft block names is in the symbol $MinecraftBlockNames:

$MinecraftBlockNames
&#10005

Short[$MinecraftBlockNames,5]

One reason to use the Wolfram Language for this is that it handles all kinds of interesting 2D and 3D objects, and I have set up the SetBlock command to handle these fairly automatically. For example, let’s paint a letter X in the sky in gold.

MinecraftSetBlock GoldBlock
&#10005

MinecraftSetBlock[pos,"GoldBlock","X"]

We can remove it again by replacing it with "Air":

MinecraftSetBlock, Air
&#10005

MinecraftSetBlock[pos,"Air","X"]

By default, rasterized content will be 12 blocks wide, so if you need more detail, you can increase that with an option:

RasterSize->50
&#10005

MinecraftSetBlock[pos,"GoldBlock","",RasterSize->50]

Air, RasterSize->50
&#10005

MinecraftSetBlock[pos,"Air","",RasterSize->50]

Anything you can create in the Wolfram Language can be made into blocks. Here is a plot of the function Sin[x]:

Dirt, RasterSize->18
&#10005

MinecraftSetBlock[pos,"Dirt",Plot[Sin[x],{x,0,12},Axes->False],RasterSize->18]

Air, RasterSize->18
&#10005

MinecraftSetBlock[pos,"Air",Plot[Sin[x],{x,0,12},Axes->False],RasterSize->18]

You can also control the orientation of rasterized images with an option Orientation.

If the content is a 3D geometry, then it will be rasterized in 3D:

Wood, RasterSize->50
&#10005

MinecraftSetBlock[pos,"Wood",Sphere[],RasterSize->50]

Air, RasterSize->50
&#10005

MinecraftSetBlock[pos,"Air",Sphere[],RasterSize->50]

There are lots of 3D geometry primitives, and they can be combined in many ways. Here are some cuboids, a pyramid and a sphere to make a house:

(*Main house frame*)MinecraftSetBlock
&#10005

(*Main house frame*)MinecraftSetBlock[{pos,pos+{8,3,8}},"Wood"];
(*Windows*)MinecraftSetBlock[{pos+{1,0,0},pos+{7,3,8}},"Glass"];
(*Make it hollow*)MinecraftSetBlock[{pos+{1,0,1},pos+{7,3,7}},"Air"];
(*Add a doorway*)MinecraftSetBlock[{pos+{4,0,0},pos+{4,1,0}},"Air"];
(*Add a roof*)
MinecraftSetBlock[pos+{0,4,0},"WoodPlanksSpruce",Pyramid[],RasterSize->12];
(*Decorate with gold ball*)
MinecraftSetBlock[pos+{3,8,2},"GoldBlock",Sphere[],RasterSize->5];)

OK, I’m not much of an architect! We can look at our creation from the air by controlling the camera:

Camera control

Camera
&#10005

MinecraftSetCamera["Fixed"];
MinecraftSetCamera[{0,25,6}];

Camera
&#10005

MinecraftSetCamera["Normal"]

Reacting to Events

Finally, we can interact with blocks that you hit using the right mouse button while holding a sword. The left mouse button just places and smashes blocks, but the right mouse button creates events that wait for us to read and act on them. You can read these with:

MinecraftHitHistory
&#10005

MinecraftHitHistory[]

This shows that since the game started, I have done two of these special hits, each time on the same block at {–1, 2, 2}, on face number 1 (the top of the block). I am player 1, but there could be multiple players. I can fetch these pieces of information by position and name. For example, HitHistory[–1] is the last hit, and we extract its "Position" information and use that coordinate in MinecraftGetBlock to discover the type of block that was most recently hit:

MinecraftGetBlock
&#10005

MinecraftGetBlock[HitHistory[-1]["Position"]]

And we can clear the data with:

MinecraftClearHits
&#10005

MinecraftClearHits[]

As a simple example, let’s monitor this list every second and create an explosive “super hit.” I will define the explosion first. It is a function that takes a position and places a large sphere of air at that position:

explosion
&#10005

explosion[event_]:=MinecraftSetBlock[event["Position"]-{2,2,2},"Air",Ball[],RasterSize->8];

Now I create a scheduled task to run every second, and apply that function to the hit history:

task=SessionSubmit
&#10005

task=SessionSubmit[
ScheduledTask[
Map[explosion,MinecraftHitHistory[]];MinecraftClearHits[],1]]

And now when I strike the ground in front of my house with my sword, using the right mouse button, a huge hole appears...

Hole

I can remove the monitoring task with:

TaskRemove
&#10005

TaskRemove[task]

There are a few more commands in the MinecraftLink package that you can read about in the documentation after you have installed the link.

As well as giving you a simple programming interface to Minecraft, similar to other languages, the Wolfram Language contains hundreds of high-level functions that let you develop much more exciting projects quickly; you might want to check out some of the 3D geometry, 3D image processing and built-in data sources as a starting point.

I will return soon with a few projects of my own.


Download this post as a Wolfram Notebook.

Leave a Comment

6 Comments


Lou

Really cool. And now I want it available on my Windows desktop . And (not done yet) I really would like an interface to Unity😊

Posted by Lou    July 5, 2018 at 4:25 pm
PhillPot

“No paclet named MinecraftLink is available for download from any currently enabled paclet sites”

Posted by PhillPot    July 6, 2018 at 12:40 am
    Wolfram Blog

    I just tested that is was still being served and it is but a temporary server failure could explain your issue.

    Are you on version 11.2 or greater? Seems like the most likely could be the issue.

    You should see:
    In[39]:= $PacletSite

    Out[39]= “http://pacletserver.wolfram.com”

    If that value is messed up for some reason, then that would cause this failure.

    Posted by Wolfram Blog    July 11, 2018 at 1:27 pm
Arjen

I wrote some software once that did things by manipulating the administrative console but obviously that had to be a special setup. (My software ran the minecraft process itself).

Posted by Arjen    July 8, 2018 at 10:14 pm
Brian

The block names aren’t populating for me:

In[8]:= $MinecraftBlockNames

Out[8]= Missing[UnknownType[Name], MinecraftBlock[Name]]

Posted by Brian    July 16, 2018 at 7:13 pm
    Wolfram Blog

    Hi Brian. Thanks for reaching out. One of these two steps is failing for you as the package loads:

    data = Get["MinecraftLink`EntityStore`"]

    EntityRegister[data]

    But not sure why either should.

    If you do succeed then the definition of that symbol is just

    $MinecraftBlockNames = #["Name"]&/@EntityList["MinecraftBlock"]

    Posted by Wolfram Blog    August 8, 2018 at 1:36 pm


Leave a comment in reply to PhillPot

Loading...

Or continue as a guest (your comment will be held for moderation):