This weekend Phillip and I have both been working on programs that required us to figure out where to put our blocks in 3d space (e.g. the x, y and z coordinates). We took two different approaches:

Phillip did a trial and error, writing/editing a line of python, running it and switching to minecraft to test it. He did this over several hours until he created what he wanted. I turned to graph paper, drawing out what I wanted and then writing down the coordinates I needed to add to my program.

I was unhappy with either approach and wanted a better solution – so I’ve created it with the “minescan.py” program. This program does a few things. First in it’s scanning mode:

When you run it, it will connect to a world using the MCPI API (e.g. Minecraft Pi Edition running on a Raspberry Pi, or a RaspberryJuice plugin on a bukkit server) It will then query every block id between two sets of x,y,z coordinates. (e.g. from 0,0,0 to 10,10,10 by default) It will then output a python program that recreates these objects. (It does not specify objects that are of type AIR — it assumes you’ll recreate the object on a clean map, such as using snowbound_flatmap.py)

I expect this script can be used for several purposes:

Learning — If you are just learning how to program MCPI using python, you can use this script to see how 3d objects are created. Designing — If you are developing a new program, you can create it interactively in minecraft — and then convert it to python to then further edit. Scraping — If you find a great object on an existing minecraft world, you can capture it and use it in one of your programs.

So I expect this to be very useful and now that I’ve written it, I’m using it already for my next script.

But the script has another mode and use as well. If you are Designing, you may find it useful to define the boundaries for your creation. So there are two modes:

the “-c” flag will create a glass container without erasing anything inside. This is particularly useful for the Scraping scenario (e.g. figure out the coordinates, generate a container to make sure you have the coordinates right, then scan it) the “-e” flag will create a class container with NOTHING inside (it replaces all interior blocks with AIR)

The tool is intended to be run from the command line like any good unix utility.

To get the script – you’ll find it on github as usual, here’s the link to minescan.py

To see how to use it, run the program with a -h flag like the following and it will tell you what the options are.

$ ./minescan.py -h usage: minescan [-hcevj] [-x num] [-y num] [-z num] [-X num] [-Y num] [-Z num] [-o outputfile] MineScan will connect to Minecraft PI Edition server or Bukkit Server using the RaspberryJuice plugin. It will by default scan a region and generate a python script which can be used to regenerate the blocks in that region. There is also an option to create a glass box around the region it will scan. This can be used to first define an area in which you will later create something in minecraft, then scan it. The options are as follows: -h: this Help message on how to use minescan -c: Create a glass container around the specified coordinates. Doesn't affect what's inside the container. -e: Creates a EMPTY glass container. This will annihilate anything inside the glass container. -v: Verbose output on the console, prints information on what's found... -j: If specified, scripts assumes it's running on RaspberryJuice which doesn't support the getBlockWithData command. As a result, some detail won't be scanned. MineScan needs to be told the xyz coordinates of where to scan and/or create the container and the how far to scan. This is done by specifying: -x num: The starting value of x. This can be positive or negative -y num: The starting value of y. This can be positive or negative -z num: The starting value of z. This can be positive or negative -X num: The starting value of X. This can be positive or negative -Y num: The starting value of Y. This can be positive or negative -Z num: The starting value of Z. This can be positive or negative The defaults are as follows: x = 0, y = 0, z = 0, X = 10, Y = 10, Z = 10 This means that the program will scan and/or create a container from 0,0,0 to 10,10,10. Note that when scanning the program must scan each block one by one, so in the above example 10 * 10 * 10 or 1000 blocks must be scanned. This takes some time. So if you increase these numbers significantly it will take some time to complete! Finally... -o filename: specifies what file to output, such as "scanned.py". If this file exists, it will be overwritten! The default is to create a filename with a prefix of "my-minescanned" with the date/time and a ".py". If not specified, this time the program would have output to %s -s address: Specifies the IP address/hostname of the Minecraft Server. Default is 127.0.0.1 (local machine)

So let’s walk through the different ways you can use this.

Creating a non-destructive container with default dimensions

$ ./minescan.py -c

Here’s an image showing what’s created. In this case I ran snowbound_flatmap.py first and you can see there is a glass floor under the sand — because -c is not destructive.

Creating a empty (destructive) container with default dimensions

$ ./minescan.py -e Here's another image showing what's created, because -e is destructive notice there is no sand inside the glass cube.

Scanning the object with default dimensions

So first let’s create an object in Minecraft. Fleap created a house for me and I scanned it…

I then run the script to scan minecraft and create the python program:

$ ./minescan.py 15:06:35 @ ~/Dropbox/python/mcpipy > ./minescan.py Output file is "my-minescanned-20130224-153149.py" [10/1000] 1% complete [20/1000] 2% complete [30/1000] 3% complete [40/1000] 4% complete [50/1000] 5% complete [60/1000] 6% complete [70/1000] 7% complete [80/1000] 8% complete [90/1000] 9% complete [100/1000] 10% complete [edited] [950/1000] 95% complete [960/1000] 96% complete [970/1000] 97% complete [980/1000] 98% complete [990/1000] 99% complete [1000/1000] 100% complete

And the above generates the following program with a auto generated default name.

The script generated was called “my-minescanned-20130224-153149.py” I added it to the github directory as scans/fleap_house.py

Here’s a picture of what it recreated:

And here’s an abbreviated version of the program it generated, so you can get a sense of what it creates…

#!/usr/bin/env python # generated by minescan.py from mcpipy.com import mcpi.minecraft as minecraft import mcpi.block as block import server mc = minecraft.Minecraft.create(server.address) mc.postToChat("Re-creating world") # The following was generated by minescan.py from mcpipy.com mc.setBlock(0,0,0,block.STONE_BRICK.id) mc.setBlock(0,0,1,block.STONE_BRICK.id) mc.setBlock(0,0,2,block.STONE_BRICK.id) mc.setBlock(0,0,3,block.STONE_BRICK.id) # Note this block is not supported in Minecraft Pi Edition v0.1.1 mc.setBlock(0,0,4,109) # Note this block is not supported in Minecraft Pi Edition v0.1.1 mc.setBlock(0,0,5,109) # Note this block is not supported in Minecraft Pi Edition v0.1.1 mc.setBlock(0,0,6,109) mc.setBlock(0,0,7,block.STONE_BRICK.id) mc.setBlock(0,0,8,block.STONE_BRICK.id) mc.setBlock(0,0,9,block.STONE_BRICK.id) mc.setBlock(0,0,10,block.STONE_BRICK.id) mc.setBlock(1,0,0,block.STONE_BRICK.id) mc.setBlock(1,0,1,block.STONE_BRICK.id) [... many more lines deleted for brevity sake ...] mc.setBlock(0,5,0,block.GLOWSTONE_BLOCK.id) mc.setBlock(0,5,10,block.GLOWSTONE_BLOCK.id) mc.setBlock(4,5,0,block.GLOWSTONE_BLOCK.id) mc.setBlock(4,5,10,block.GLOWSTONE_BLOCK.id) mc.setBlock(6,5,0,block.GLOWSTONE_BLOCK.id) mc.setBlock(6,5,10,block.GLOWSTONE_BLOCK.id) mc.setBlock(10,5,0,block.GLOWSTONE_BLOCK.id) mc.setBlock(10,5,4,block.GLOWSTONE_BLOCK.id) mc.setBlock(10,5,6,block.GLOWSTONE_BLOCK.id) mc.setBlock(10,5,10,block.GLOWSTONE_BLOCK.id) mc.postToChat('World Re-created!')

And that’s it!

Other Commands

As you can see from the -h help text above, there are other commands above. The most useful are the ability to set a custom start and end x, y and z.

Let’s say you want to create a non-destructive container from -5, -4, -15 to 14, 10, 30 and then scan the same coordinates.

The command you would use to create the container around these coordinates is:

./minescan.py -x -5 -y -4 -z -15 -X 14 -Y 10 -Z 30 -c

And the cmmand to scan these coordinates is:

./minescan.py -x -5 -y -4 -z -15 -X 14 -Y 10 -Z 30

That’s it!

Got an interesting scan?

If you have an interesting scan you’d like to share, contact us via the instructions on the above to submit your interesting object scan!

One last thing… using this with RaspberryJuice on a bukkit server

As I was developing this script I used a bukkit server as that was more convenient — and found that the RaspberryJuice plugin didn’t implement one of the APIs that the MCPI on Raspberry Pi Supports. Specifically getBlocksWithData. As a result, this script can capture more detail when run on a Raspberry Pi than against a bukkit server.

Anyway, to allow this script to work with both – I’ve added a “-j” option which should be set when you are running it against a bukkit server with the RaspberryJuice plug-in. If you forget to do this, the script will hang.

Hopefully the RaspberryJuice plugin will be updated with support for getBlocksWithData in the future so this will no longer be necessary…

Note: RaspberryJuice has since been updated to 1.2 and it includes support for getblocksWithData. If you are using this script with a bukkit server, then make sure you upgrade!