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.

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.

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

 ✕ 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:

 ✕ < 

This extends the Wolfram Language with the following new commands:

 ✕ ?MinecraftLink*

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["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["Hello from the Wolfram Language"]

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

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[]

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

 ✕ 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:

 ✕ y=MinecraftGetHeight[{0,8}]

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

 ✕ pos={0,y,8}
 ✕ MinecraftGetBlock[pos]

And the block below it should be something solid:

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

Building

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

 ✕ MinecraftSetBlock[pos,"Wood"]

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

 ✕ MinecraftSetBlock[pos,"Air"]

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

 ✕ MinecraftSave[]

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

 ✕ MinecraftRestore[]

The list of the 156 available Minecraft block names is in the symbol $MinecraftBlockNames:  ✕ 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[pos,"GoldBlock","X"]

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

 ✕ 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:

 ✕ MinecraftSetBlock[pos,"GoldBlock","",RasterSize->50]
 ✕ 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]:

 ✕ MinecraftSetBlock[pos,"Dirt",Plot[Sin[x],{x,0,12},Axes->False],RasterSize->18]
 ✕ 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:

 ✕ MinecraftSetBlock[pos,"Wood",Sphere[],RasterSize->50]
 ✕ 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[{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:

 ✕ MinecraftSetCamera["Fixed"]; MinecraftSetCamera[{0,25,6}];
 ✕ 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[]

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[HitHistory[-1]["Position"]]

And we can clear the data with:

 ✕ 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[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[ 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...

I can remove the monitoring task with:

 ✕ 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.

RELATED POSTS

The Story of Spikey
December 28, 2018

 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
 “No paclet named MinecraftLink is available for download from any currently enabled paclet sites” Posted by PhillPot    July 6, 2018 at 12:40 am
 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  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  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
 Hi Brian. Thanks for reaching out. One of these two steps is failing for you as the package loads: data = Get["MinecraftLinkEntityStore`"] 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