Merge remote branch 'eminence/master'
This commit is contained in:
@@ -22,6 +22,7 @@ import functools
|
|||||||
import re
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import collections
|
import collections
|
||||||
|
import json
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
@@ -119,6 +120,11 @@ class QuadtreeGen(object):
|
|||||||
with open(os.path.join(self.destdir, "index.html"), 'w') as output:
|
with open(os.path.join(self.destdir, "index.html"), 'w') as output:
|
||||||
output.write(html)
|
output.write(html)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
with open(os.path.join(self.destdir, "markers.js"), 'w') as output:
|
||||||
|
output.write("var markerData=%s" % json.dumps(self.world.POI))
|
||||||
|
|
||||||
def _get_cur_depth(self):
|
def _get_cur_depth(self):
|
||||||
"""How deep is the quadtree currently in the destdir? This glances in
|
"""How deep is the quadtree currently in the destdir? This glances in
|
||||||
index.html to see what maxZoom is set to.
|
index.html to see what maxZoom is set to.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; }
|
body { height: 100%; margin: 0px; padding: 0px ; background-color: #000; }
|
||||||
#mcmap { height: 100% }
|
#mcmap { height: 100% }
|
||||||
</style>
|
</style>
|
||||||
|
<script type="text/javascript" src="markers.js"></script>
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
src="http://maps.google.com/maps/api/js?sensor=false">
|
src="http://maps.google.com/maps/api/js?sensor=false">
|
||||||
</script>
|
</script>
|
||||||
@@ -74,7 +75,57 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
var map;
|
var map;
|
||||||
|
var prot;
|
||||||
|
|
||||||
|
var markersInit = false;
|
||||||
|
|
||||||
|
function convertCoords (x,y,z) {
|
||||||
|
|
||||||
|
var imgx = 0;
|
||||||
|
var imgy = 0;
|
||||||
|
|
||||||
|
imgx = imgx + (12*x);
|
||||||
|
imgy = imgy - (6*x);
|
||||||
|
|
||||||
|
imgx = imgx + (12 * y);
|
||||||
|
imgy = imgy + (6* y);
|
||||||
|
|
||||||
|
imgy = imgy - (12*z);
|
||||||
|
|
||||||
|
// this math is mysterious. i don't fully understand it
|
||||||
|
// but the idea is to assume that block 0,0,0 in chunk 0,0
|
||||||
|
// is drawn in the very middle of the gmap at (192,192)
|
||||||
|
return [192*Math.pow(2,config.maxZoom)+imgx, 192*Math.pow(2,config.maxZoom)+imgy+768+768];
|
||||||
|
}
|
||||||
|
|
||||||
|
function initMarkers() {
|
||||||
|
if (markersInit) { return; }
|
||||||
|
|
||||||
|
markersInit = true;
|
||||||
|
|
||||||
|
prot = map.getProjection();
|
||||||
|
|
||||||
|
for (i in markerData) {
|
||||||
|
var item = markerData[i];
|
||||||
|
|
||||||
|
var converted = convertCoords(item.x-16, item.z, item.y);
|
||||||
|
|
||||||
|
|
||||||
|
var x = converted[0] / Math.pow(2, config.maxZoom);
|
||||||
|
var y = converted[1] / Math.pow(2, config.maxZoom);
|
||||||
|
var p = new google.maps.Point(x,y);
|
||||||
|
var marker = new google.maps.Marker({
|
||||||
|
position: prot.fromPointToLatLng(p),
|
||||||
|
map: map,
|
||||||
|
title:item.msg
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
function initialize() {
|
function initialize() {
|
||||||
var mapOptions = {
|
var mapOptions = {
|
||||||
zoom: config.defaultZoom,
|
zoom: config.defaultZoom,
|
||||||
@@ -89,12 +140,33 @@
|
|||||||
if(config.debug) {
|
if(config.debug) {
|
||||||
map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(config.tileSize, config.tileSize)));
|
map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(config.tileSize, config.tileSize)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Now attach the coordinate map type to the map's registry
|
// Now attach the coordinate map type to the map's registry
|
||||||
map.mapTypes.set('mcmap', MCMapType);
|
map.mapTypes.set('mcmap', MCMapType);
|
||||||
|
|
||||||
// We can now set the map to use the 'coordinate' map type
|
// We can now set the map to use the 'coordinate' map type
|
||||||
map.setMapTypeId('mcmap');
|
map.setMapTypeId('mcmap');
|
||||||
|
|
||||||
|
prot = map.getProjection();
|
||||||
|
|
||||||
|
if (config.debug)
|
||||||
|
google.maps.event.addListener(map, 'click', function(event) {
|
||||||
|
console.log("latLng: " + event.latLng.lat() + ", " + event.latLng.lng());
|
||||||
|
var pnt = prot.fromLatLngToPoint(event.latLng);
|
||||||
|
|
||||||
|
console.log("point: " + pnt);//
|
||||||
|
var pxx = pnt.x * Math.pow(2,config.maxZoom);
|
||||||
|
var pxy = pnt.y * Math.pow(2,config.maxZoom);
|
||||||
|
console.log("pixel: " + pxx + ", " + pxy);
|
||||||
|
});
|
||||||
|
|
||||||
|
google.maps.event.addListener(map, 'projection_changed', function(event) {
|
||||||
|
initMarkers();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
50
textures.py
50
textures.py
@@ -151,7 +151,7 @@ def _transform_image_side(img):
|
|||||||
return newimg
|
return newimg
|
||||||
|
|
||||||
|
|
||||||
def _build_block(top, side):
|
def _build_block(top, side, texID=None):
|
||||||
"""From a top texture and a side texture, build a block image.
|
"""From a top texture and a side texture, build a block image.
|
||||||
top and side should be 16x16 image objects. Returns a 24x24 image
|
top and side should be 16x16 image objects. Returns a 24x24 image
|
||||||
|
|
||||||
@@ -178,6 +178,14 @@ def _build_block(top, side):
|
|||||||
otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
|
otherside = ImageEnhance.Brightness(otherside).enhance(0.8)
|
||||||
otherside.putalpha(othersidealpha)
|
otherside.putalpha(othersidealpha)
|
||||||
|
|
||||||
|
## special case for non-block things
|
||||||
|
if texID in (12,13,15,28,29,80,73): ## flowers, sapling, mushrooms, regular torch, reeds
|
||||||
|
# instead of pasting these blocks at the cube edges, place them in the middle:
|
||||||
|
# and omit the top
|
||||||
|
img.paste(side, (6,3), side)
|
||||||
|
img.paste(otherside, (6,3), otherside)
|
||||||
|
return img
|
||||||
|
|
||||||
img.paste(side, (0,6), side)
|
img.paste(side, (0,6), side)
|
||||||
img.paste(otherside, (12,6), otherside)
|
img.paste(otherside, (12,6), otherside)
|
||||||
img.paste(top, (0,0), top)
|
img.paste(top, (0,0), top)
|
||||||
@@ -203,21 +211,35 @@ def _build_blockimages():
|
|||||||
# Top textures of all block types. The number here is the index in the
|
# Top textures of all block types. The number here is the index in the
|
||||||
# texture array (terrain_images), which comes from terrain.png's cells, left to right top to
|
# texture array (terrain_images), which comes from terrain.png's cells, left to right top to
|
||||||
# bottom.
|
# bottom.
|
||||||
topids = [-1,1,0,2,16,4,15,17,205,205,237,237,18,19,32,33,
|
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||||
34,21,52,48,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, # Cloths are left out
|
topids = [ -1, 1, 0, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33,
|
||||||
-1,-1,-1,64,64,13,12,29,28,23,22,6,6,7,8,35, # Gold/iron blocks? Doublestep? TNT from above?
|
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
||||||
36,37,-1,-1,65,4,25,101,98,24,43,-1,86,1,1,-1, # Torch from above? leaving out fire. Redstone wire? Crops left out. sign post
|
34, 21, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, # Cloths are left out
|
||||||
-1,-1,-1,16,-1,-1,-1,-1,-1,51,51,-1,-1,1,66,67, # door,ladder left out. Minecart rail orientation
|
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
||||||
66,69,72,-1,74 # clay?
|
-1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35, # Gold/iron blocks? Doublestep? TNT from above?
|
||||||
|
# 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
||||||
|
36, 37, 80, -1, 65, 4, 25,101, 98, 24, 43, -1, 86, 1, 1, -1, # Torch from above? leaving out fire. Redstone wire? Crops left out. sign post
|
||||||
|
# 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
||||||
|
-1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67, # door,ladder left out. Minecart rail orientation
|
||||||
|
# 80 81 82 83 84
|
||||||
|
66, 69, 72, 73, 74 # clay?
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# NOTE: For non-block textures, the sideid is ignored, but can't be -1
|
||||||
|
|
||||||
# And side textures of all block types
|
# And side textures of all block types
|
||||||
sideids = [-1,1,3,2,16,4,15,17,205,205,237,237,18,19,32,33,
|
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||||
34,20,52,48,49,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
|
sideids = [ -1, 1, 3, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33,
|
||||||
-1,-1,-1,64,64,13,12,29,28,23,22,6,6,7,8,35,
|
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
||||||
36,37,-1,-1,65,4,25,101,98,24,43,-1,86,1,1,-1,
|
34, 20, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1,- 1, -1, -1, -1,
|
||||||
-1,-1,-1,16,-1,-1,-1,-1,-1,51,51,-1,-1,1,66,67,
|
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
||||||
66,69,72,-1,74
|
-1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35,
|
||||||
|
# 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
||||||
|
36, 37, 80, -1, 65, 4, 25,101, 98, 24, 43, -1, 86, 1, 1, -1,
|
||||||
|
# 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
||||||
|
-1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67,
|
||||||
|
# 80 81 82 83 84
|
||||||
|
66, 69, 72, 73, 74
|
||||||
]
|
]
|
||||||
|
|
||||||
# This maps block id to the texture that goes on the side of the block
|
# This maps block id to the texture that goes on the side of the block
|
||||||
@@ -230,7 +252,7 @@ def _build_blockimages():
|
|||||||
toptexture = terrain_images[toptextureid]
|
toptexture = terrain_images[toptextureid]
|
||||||
sidetexture = terrain_images[sidetextureid]
|
sidetexture = terrain_images[sidetextureid]
|
||||||
|
|
||||||
img = _build_block(toptexture, sidetexture)
|
img = _build_block(toptexture, sidetexture, toptextureid)
|
||||||
|
|
||||||
allimages.append((img.convert("RGB"), img.split()[3]))
|
allimages.append((img.convert("RGB"), img.split()[3]))
|
||||||
|
|
||||||
|
|||||||
67
world.py
67
world.py
@@ -17,6 +17,7 @@ import functools
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import numpy
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
@@ -57,6 +58,29 @@ def _convert_coords(chunks):
|
|||||||
|
|
||||||
return mincol, maxcol, minrow, maxrow, chunks_translated
|
return mincol, maxcol, minrow, maxrow, chunks_translated
|
||||||
|
|
||||||
|
|
||||||
|
def base36encode(number, alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
|
||||||
|
'''
|
||||||
|
Convert an integer to a base36 string.
|
||||||
|
'''
|
||||||
|
if not isinstance(number, (int, long)):
|
||||||
|
raise TypeError('number must be an integer')
|
||||||
|
|
||||||
|
newn = abs(number)
|
||||||
|
|
||||||
|
# Special case for zero
|
||||||
|
if number == 0:
|
||||||
|
return '0'
|
||||||
|
|
||||||
|
base36 = ''
|
||||||
|
while newn != 0:
|
||||||
|
newn, i = divmod(newn, len(alphabet))
|
||||||
|
base36 = alphabet[i] + base36
|
||||||
|
|
||||||
|
if number < 0:
|
||||||
|
return "-" + base36
|
||||||
|
return base36
|
||||||
|
|
||||||
class WorldRenderer(object):
|
class WorldRenderer(object):
|
||||||
"""Renders a world's worth of chunks.
|
"""Renders a world's worth of chunks.
|
||||||
worlddir is the path to the minecraft world
|
worlddir is the path to the minecraft world
|
||||||
@@ -67,6 +91,47 @@ class WorldRenderer(object):
|
|||||||
self.caves = False
|
self.caves = False
|
||||||
self.cachedir = cachedir
|
self.cachedir = cachedir
|
||||||
|
|
||||||
|
# stores Points Of Interest to be mapped with markers
|
||||||
|
# a list of dictionaries, see below for an example
|
||||||
|
self.POI = []
|
||||||
|
|
||||||
|
def findTrueSpawn(self):
|
||||||
|
"""Adds the true spawn location to self.POI. The spawn Y coordinate
|
||||||
|
is almost always the default of 64. Find the first air block above
|
||||||
|
that point for the true spawn location"""
|
||||||
|
|
||||||
|
## read spawn info from level.dat
|
||||||
|
data = nbt.load(os.path.join(self.worlddir, "level.dat"))[1]
|
||||||
|
spawnX = data['Data']['SpawnX']
|
||||||
|
spawnY = data['Data']['SpawnY']
|
||||||
|
spawnZ = data['Data']['SpawnZ']
|
||||||
|
|
||||||
|
## The chunk that holds the spawn location
|
||||||
|
chunkX = spawnX/16
|
||||||
|
chunkY = spawnZ/16
|
||||||
|
|
||||||
|
## The filename of this chunk
|
||||||
|
chunkFile = "%s/%s/c.%s.%s.dat" % (base36encode(chunkX % 64),
|
||||||
|
base36encode(chunkY % 64),
|
||||||
|
base36encode(chunkX),
|
||||||
|
base36encode(chunkY))
|
||||||
|
|
||||||
|
|
||||||
|
data=nbt.load(os.path.join(self.worlddir, chunkFile))[1]
|
||||||
|
level = data['Level']
|
||||||
|
blockArray = numpy.frombuffer(level['Blocks'], dtype=numpy.uint8).reshape((16,16,128))
|
||||||
|
|
||||||
|
## The block for spawn *within* the chunk
|
||||||
|
inChunkX = spawnX - (chunkX*16)
|
||||||
|
inChunkZ = spawnZ - (chunkY*16)
|
||||||
|
|
||||||
|
## find the first air block
|
||||||
|
while (blockArray[inChunkX, inChunkZ, spawnY] != 0):
|
||||||
|
spawnY += 1
|
||||||
|
|
||||||
|
|
||||||
|
self.POI.append( dict(x=spawnX, y=spawnY, z=spawnZ, msg="Spawn"))
|
||||||
|
|
||||||
def go(self, procs):
|
def go(self, procs):
|
||||||
"""Starts the render. This returns when it is finished"""
|
"""Starts the render. This returns when it is finished"""
|
||||||
|
|
||||||
@@ -84,6 +149,8 @@ class WorldRenderer(object):
|
|||||||
self.minrow = minrow
|
self.minrow = minrow
|
||||||
self.maxrow = maxrow
|
self.maxrow = maxrow
|
||||||
|
|
||||||
|
self.findTrueSpawn()
|
||||||
|
|
||||||
def _find_chunkfiles(self):
|
def _find_chunkfiles(self):
|
||||||
"""Returns a list of all the chunk file locations, and the file they
|
"""Returns a list of all the chunk file locations, and the file they
|
||||||
correspond to.
|
correspond to.
|
||||||
|
|||||||
Reference in New Issue
Block a user