Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
42 changed files
with
9,738 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
Minecraft.Print() is a python library for converting defined regions of Minecraft levels to a 3D Printable format. | ||
|
||
Includes pymclevel. | ||
Requires numpy (https://github.com/numpy/numpy). | ||
|
||
In game: | ||
Before running Minecraft.Print() you will need to define the space you wish to print by placing two markers, in-game. The marker configuration is a diamond block, followed by a gold block, followed by an iron block in vertical order (ascending or descending). The coordinates of the diamond block will be used as the marker. | ||
|
||
Running Minecraft.Print(): | ||
Run "python run.py LEVEL_NAME OUTPUT_NAME" - replacing LEVEL_NAME and and OUTPUT_NAME with the level you wish to process and the desired output file name. The script will then run and save the STL file in the same directory. | ||
|
||
Viewing resulting file: | ||
There are many free programs for viewing STL files. One example: http://meshlab.sourceforge.net | ||
|
||
Printing: | ||
If you don't have a 3D Printer of your own, to print to, there are online services that will allow you to upload an STL file and order a print. Two random ones: cloudfab.com and shapeways.com | ||
|
||
Show off your creation: | ||
We figure you already know how to do this. | ||
|
||
Sharing: | ||
So here's the deal. We want to see what awesome stuff you guys are going to print. So drop us a line at hi@minecraftprint.com and let us know how it went. Also, if you have something really awesome, consider putting the model up on thingiverse.com for others to print. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,192 @@ | ||
import pymclevel.mclevel as mclevel | ||
import sys | ||
import os | ||
from pymclevel.box import BoundingBox | ||
import numpy | ||
from numpy import zeros, bincount | ||
import logging | ||
import itertools | ||
import traceback | ||
import shlex | ||
import operator | ||
import codecs | ||
|
||
from math import floor | ||
import readline | ||
|
||
class UsageError(RuntimeError): pass | ||
class BlockMatchError(RuntimeError): pass | ||
class PlayerNotFound(RuntimeError): pass | ||
|
||
class MinecraftPrint: | ||
|
||
def __init__(self, level, output): | ||
self.level_name = level | ||
self.output_name = output + '.stl' | ||
|
||
#The list of goodness and markers | ||
#Format: [[chunk_x, chunk_z, block_x, block_z, block_y]] | ||
self.markers = [] | ||
|
||
self.chunk_positions = [] | ||
self.num_chunks = 0 | ||
self.chunk_counter = 0 | ||
|
||
self.diamond_check = [] | ||
self.object_array = [] | ||
|
||
#Data value for each block type | ||
self.diamond = 57 | ||
self.gold = 41 | ||
self.iron = 42 | ||
|
||
def generate(self): | ||
self.find_marked_area() | ||
self.copy_marked_area() | ||
self.generate_stl() | ||
|
||
def find_marked_area(self): | ||
self.world = mclevel.loadWorld(self.level_name) | ||
|
||
#Load chunks and determine minimize indexes | ||
self.chunk_positions = list(self.world.allChunks) | ||
self.num_chunks = len(self.chunk_positions) | ||
|
||
#Just a little user feedback on the progress | ||
print "Processing level: " + self.level_name | ||
print "Scanning level for markers..." | ||
self.chunk_counter = 1 | ||
|
||
self.find_markers() | ||
|
||
print '100%' | ||
|
||
def find_markers(self): | ||
#Iterate through chunks, looking for block combination | ||
for x_pos, z_pos in self.chunk_positions: | ||
#User feedback | ||
if self.chunk_counter % 10 == 0: | ||
print str(self.chunk_counter/float(self.num_chunks)*100) + "%" | ||
self.chunk_counter += 1 | ||
|
||
chunk = self.world.getChunk(x_pos, z_pos) | ||
#Does this chunk have a diamond block? | ||
|
||
diamond_check = numpy.where(chunk.Blocks == self.diamond) | ||
if len(diamond_check[0]) > 0: | ||
for dx, dz, dy in zip(diamond_check[0], diamond_check[1], diamond_check[2]): | ||
|
||
#We found diamond, but is it a marker (diamond, gold, and iron in asc or desc vertical order) | ||
#If so, define the diamond block coordinates as the marker and remove the marker from the map | ||
if dy > 1 and chunk.Blocks[dx, dz, dy - 1] == self.gold and chunk.Blocks[dx, dz, dy - 2] == self.iron: | ||
self.markers.append([x_pos, z_pos, dx, dz, dy]) | ||
chunk.Blocks[dx, dz, dy] = 0 | ||
chunk.Blocks[dx, dz, dy - 1] = 0 | ||
chunk.Blocks[dx, dz, dy - 2] = 0 | ||
elif dy < 126 and chunk.Blocks[dx, dz, dy + 1] == self.gold and chunk.Blocks[dx, dz, dy + 2] == self.iron: | ||
self.markers.append([x_pos, z_pos, dx, dz, dy]) | ||
chunk.Blocks[dx, dz, dy] = 0 | ||
chunk.Blocks[dx, dz, dy + 1] = 0 | ||
chunk.Blocks[dx, dz, dy + 2] = 0 | ||
|
||
def copy_marked_area(self): | ||
#Now we have the markers. Time to get serious | ||
if len(self.markers) == 2: | ||
print "Congrats, looks like we have two markers" | ||
print "..." | ||
print "Capturing marked area... this may take a minute..." | ||
|
||
#Calculate x_min and x_max | ||
if self.markers[0][0] < self.markers[1][0]: | ||
x_min = [self.markers[0][0], self.markers[0][2]] | ||
x_max = [self.markers[1][0], self.markers[1][2]] | ||
elif self.markers[0][0] > self.markers[1][0]: | ||
x_min = [self.markers[1][0], self.markers[1][2]] | ||
x_max = [self.markers[0][0], self.markers[0][2]] | ||
else: | ||
x_min = [self.markers[0][0], min(self.markers[0][2], self.markers[1][2])] | ||
x_max = [self.markers[0][0], max(self.markers[0][2], self.markers[1][2])] | ||
|
||
#Calculate z_min and z_max | ||
if self.markers[0][1] < self.markers[1][1]: | ||
z_min = [self.markers[0][1], self.markers[0][3]] | ||
z_max = [self.markers[1][1], self.markers[1][3]] | ||
elif self.markers[0][1] > self.markers[1][1]: | ||
z_min = [self.markers[1][1], self.markers[1][3]] | ||
z_max = [self.markers[0][1], self.markers[0][3]] | ||
else: | ||
z_min = [self.markers[0][1], min(self.markers[0][3], self.markers[1][3])] | ||
z_max = [self.markers[0][1], max(self.markers[0][3], self.markers[1][3])] | ||
|
||
#Calculate y_min and y_max | ||
y_min = min(self.markers[0][4], self.markers[1][4]) | ||
y_max = max(self.markers[0][4], self.markers[1][4]) | ||
|
||
#Construct an array to fit the object | ||
self.object_array = [[[0 for z in xrange((z_max[0] - z_min[0] + 1) * 16)] for y in xrange(y_max - y_min + 1)] for x in xrange((x_max[0] - x_min[0] + 1) * 16)] | ||
|
||
#Copy marked blocks to object_array | ||
for x_pos in range(x_min[0], x_max[0] + 1): | ||
for z_pos in range(z_min[0], z_max[0] + 1): | ||
chunk = self.world.getChunk(x_pos, z_pos) | ||
for x in range(16): | ||
for z in range(16): | ||
for y in range(y_max - y_min + 1): | ||
if (x_pos == x_min[0] and x < x_min[1]) or (x_pos == x_max[0] and x > x_max[1]): | ||
block_type = 0 | ||
elif (z_pos == z_min[0] and z < z_min[1]) or (z_pos == z_max[0] and z > z_max[1]): | ||
block_type = 0 | ||
else: | ||
block_type = chunk.Blocks[x, z, y_min + y] | ||
#print str((16 * (x_pos + offsetx)) + x) + ", " + str(y) + ", " + str((16 * (z_pos + offsetz)) + z) | ||
self.object_array[(16 * (x_pos -x_min[0])) + x][y][(16 * (z_pos - z_min[0])) + z] = block_type | ||
|
||
else: | ||
print "Freak out! There are somehow more or less than 2 markers!" | ||
|
||
def generate_stl(self): | ||
"""Generate STL file""" | ||
filename = self.output_name | ||
|
||
width = len(self.object_array) | ||
height = len(self.object_array[0]) | ||
depth = len(self.object_array[0][0]) | ||
|
||
str_o = "solid Minecraft\n"; | ||
str_e = " endloop\n endfacet\n" | ||
str_s = " facet normal %d %d %d\n outer loop\n" | ||
str_v = " vertex %d %d %d\n" | ||
|
||
print "start" | ||
|
||
f=open(filename, 'w') | ||
f.write(str_o) | ||
for x in range(width): | ||
print str(x/float(width)*100) + "%" | ||
for y in range(height): | ||
for z in range(depth): | ||
if self.object_array[x][y][z] > 0: | ||
if x==0 or self.object_array[x-1][y][z]<=0: | ||
f.write("".join([str_s%(-1,0,0),str_v%(x,z+1,y), str_v%(x,z,y+1),str_v%(x,z+1,y+1),str_e])) | ||
f.write("".join([str_s%(-1,0,0),str_v%(x,z+1,y), str_v%(x,z,y),str_v%(x,z,y+1),str_e])) | ||
if x==width-1 or self.object_array[x+1][y][z]<=0: | ||
f.write("".join([str_s%(1,0,0),str_v%(x+1,z+1,y), str_v%(x+1,z+1,y+1),str_v%(x+1,z,y+1),str_e])) | ||
f.write("".join([str_s%(1,0,0),str_v%(x+1,z+1,y), str_v%(x+1,z,y+1),str_v%(x+1,z,y),str_e])) | ||
if (z==0) or self.object_array[x][y][z-1]<=0: | ||
f.write("".join([str_s%(0,0,-1),str_v%(x,z,y), str_v%(x+1,z,y+1),str_v%(x,z,y+1),str_e])) | ||
f.write("".join([str_s%(0,0,-1),str_v%(x,z,y), str_v%(x+1,z,y),str_v%(x+1,z,y+1),str_e])) | ||
if (z==depth-1) or self.object_array[x][y][z+1]<=0: | ||
f.write("".join([str_s%(0,0,1),str_v%(x,z+1,y), str_v%(x,z+1,y+1),str_v%(x+1,z+1,y+1),str_e])) | ||
f.write("".join([str_s%(0,0,1),str_v%(x,z+1,y), str_v%(x+1,z+1,y+1),str_v%(x+1,z+1,y),str_e])) | ||
if (y==0) or self.object_array[x][y-1][z]<=0: | ||
f.write("".join([str_s%(0,-1,0),str_v%(x+1,z,y), str_v%(x,z+1,y),str_v%(x+1,z+1,y),str_e])) | ||
f.write("".join([str_s%(0,-1,0),str_v%(x+1,z,y), str_v%(x,z,y),str_v%(x,z+1,y),str_e])) | ||
if (y==height-1) or self.object_array[x][y+1][z]<=0: | ||
f.write("".join([str_s%(0,1,0),str_v%(x+1,z,y+1), str_v%(x+1,z+1,y+1),str_v%(x,z+1,y+1),str_e])) | ||
f.write("".join([str_s%(0,1,0),str_v%(x+1,z,y+1), str_v%(x,z+1,y+1),str_v%(x,z,y+1),str_e])) | ||
|
||
f.write("endsolid Minecraft\n") | ||
print "100%" | ||
f.close() | ||
|
||
print "Done!" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# git-ls-files --others --exclude-from=.git/info/exclude | ||
# Lines that start with '#' are comments. | ||
# For a project mostly in C, the following would be a good set of | ||
# exclude patterns (uncomment them if you want to use them): | ||
# *.[oa] | ||
# *~ | ||
*.pyc | ||
*.pyo | ||
*~ | ||
|
||
.project | ||
.pydevproject | ||
|
||
#profiling/outputs | ||
*.log |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Copyright (c) 2010 David Rio Vierra | ||
|
||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted, provided that the above | ||
copyright notice and this permission notice appear in all copies. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
Python library for reading Minecraft levels. | ||
|
||
Can read Alpha levels, Indev levels, and Creative levels (with help). | ||
|
||
Includes a command-line client (mce.py) | ||
|
||
Requires numpy. | ||
|
||
Read mclevel.py to get started. | ||
|
||
See LICENSE.txt for licensing terms. | ||
|
||
|
||
|
||
mce.py is a command-line editor for SMP maps. It can be used interactively from a terminal, accept editing commands on standard input, or run a single editing command from the shell. | ||
|
||
Sample usage: | ||
|
||
$ python mce.py | ||
|
||
Usage: | ||
|
||
Block commands: | ||
clone <sourcePoint> <sourceSize> <destPoint> | ||
fill <blockType> [ <point> <size> ] | ||
replace <blockType> [with] <newBlockType> [ <point> <size> ] | ||
|
||
export <filename> <sourcePoint> <sourceSize> | ||
import <filename> <destPoint> | ||
|
||
analyze | ||
|
||
Player commands: | ||
player [ <player> [ <point> ] ] | ||
spawn [ <point> ] | ||
|
||
Entity commands: | ||
removeEntities [ <EntityID> ] | ||
|
||
Chunk commands: | ||
createChunks <point> <size> | ||
deleteChunks <point> <size> | ||
prune <point> <size> | ||
relight [ <point> <size> ] | ||
|
||
World commands: | ||
degrief | ||
|
||
Editor commands: | ||
save | ||
reload | ||
load <filename> | <world number> | ||
quit | ||
|
||
Informational: | ||
blocks [ <block name> | <block ID> ] | ||
help [ <command> ] | ||
|
||
Points and sizes are space-separated triplets of numbers ordered X Y Z. | ||
X is position north-south, increasing southward. | ||
Y is position up-down, increasing upward. | ||
Z is position east-west, increasing westward. | ||
|
||
A player's name can be used as a point - it will use the | ||
position of the player's head. Use the keyword 'delta' after | ||
the name to specify a point near the player. | ||
|
||
Example: | ||
codewarrior delta 0 5 0 | ||
|
||
This refers to a point 5 blocks above codewarrior's head. | ||
|
||
|
||
Please enter world number or path to world folder: 4 | ||
INFO:Identifying C:\Users\Rio\AppData\Roaming\.minecraft\saves\World4\level.dat | ||
INFO:Detected Infdev level.dat | ||
INFO:Saved 0 chunks | ||
INFO:Scanning for chunks... | ||
INFO:Found 6288 chunks. | ||
World4> fill 20 Player delta -10 0 -10 20 20 20 | ||
|
||
Filling with Glass | ||
Filled 8000 blocks. | ||
World4> player Player | ||
|
||
Player Player: [87.658381289724858, 54.620000004768372, 358.64257283335115] | ||
World4> player Player Player delta 0 25 0 | ||
|
||
Moved player Player to (87.658381289724858, 79.620000004768372, 358.642572833351 | ||
15) | ||
World4> save | ||
|
||
INFO:Asked to light 6 chunks | ||
INFO:Batch 1/1 | ||
INFO:Lighting 20 chunks | ||
INFO:Dispersing light... | ||
INFO:BlockLight Pass 0: 20 chunks | ||
INFO:BlockLight Pass 1: 2 chunks | ||
INFO:BlockLight Pass 2: 0 chunks | ||
INFO:BlockLight Pass 3: 0 chunks | ||
INFO:BlockLight Pass 4: 0 chunks | ||
INFO:BlockLight Pass 5: 0 chunks | ||
INFO:BlockLight Pass 6: 0 chunks | ||
INFO:BlockLight Pass 7: 0 chunks | ||
INFO:BlockLight Pass 8: 0 chunks | ||
INFO:BlockLight Pass 9: 0 chunks | ||
INFO:BlockLight Pass 10: 0 chunks | ||
INFO:BlockLight Pass 11: 0 chunks | ||
INFO:BlockLight Pass 12: 0 chunks | ||
INFO:BlockLight Pass 13: 0 chunks | ||
INFO:SkyLight Pass 0: 20 chunks | ||
INFO:SkyLight Pass 1: 22 chunks | ||
INFO:SkyLight Pass 2: 17 chunks | ||
INFO:SkyLight Pass 3: 9 chunks | ||
INFO:SkyLight Pass 4: 7 chunks | ||
INFO:SkyLight Pass 5: 2 chunks | ||
INFO:SkyLight Pass 6: 0 chunks | ||
INFO:SkyLight Pass 7: 0 chunks | ||
INFO:SkyLight Pass 8: 0 chunks | ||
INFO:SkyLight Pass 9: 0 chunks | ||
INFO:SkyLight Pass 10: 0 chunks | ||
INFO:SkyLight Pass 11: 0 chunks | ||
INFO:SkyLight Pass 12: 0 chunks | ||
INFO:SkyLight Pass 13: 0 chunks | ||
INFO:Completed in 0:00:02.024000, 0:00:00.337333 per chunk | ||
INFO:Saved 20 chunks | ||
World4> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from mclevel import * | ||
import items |
Oops, something went wrong.