0

Merge remote branch 'eminence/master'

This commit is contained in:
Andrew Brown
2010-09-26 23:05:34 -04:00
4 changed files with 182 additions and 15 deletions

View File

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

View File

@@ -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,6 +75,56 @@
}; };
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 = {
@@ -90,11 +141,32 @@
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>

View File

@@ -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.
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
topids = [ -1, 1, 0, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33, topids = [ -1, 1, 0, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33,
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
34, 21, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, # Cloths are left out 34, 21, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, # Cloths are left out
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
-1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35, # Gold/iron blocks? Doublestep? TNT from above? -1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35, # Gold/iron blocks? Doublestep? TNT from above?
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 # 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 -1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67, # door,ladder left out. Minecart rail orientation
66,69,72,-1,74 # clay? # 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
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
sideids = [ -1, 1, 3, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33, sideids = [ -1, 1, 3, 2, 16, 4, 15, 17,205,205,237,237, 18, 19, 32, 33,
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
34, 20, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1,- 1, -1, -1, -1, 34, 20, 52, 48, 49, -1, -1, -1, -1, -1, -1, -1,- 1, -1, -1, -1,
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
-1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35, -1, -1, -1, 64, 64, 13, 12, 29, 28, 23, 22, 6, 6, 7, 8, 35,
36,37,-1,-1,65,4,25,101,98,24,43,-1,86,1,1,-1, # 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, -1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67,
66,69,72,-1,74 # 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]))

View File

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