diff --git a/chunk.py b/chunk.py index fef3a84..aaee2e4 100644 --- a/chunk.py +++ b/chunk.py @@ -59,6 +59,11 @@ def get_skylight_array(level): """ return numpy.frombuffer(level['SkyLight'], dtype=numpy.uint8).reshape((16,16,64)) +def get_blockdata_array(level): + """Returns the ancillary data from the 'Data' byte array. Data is packed + in a similar manner to skylight data""" + return numpy.frombuffer(level['Data'], dtype=numpy.uint8).reshape((16,16,64)) + # This set holds blocks ids that can be seen through, for occlusion calculations transparent_blocks = set([0, 6, 8, 9, 18, 20, 37, 38, 39, 40, 44, 50, 51, 52, 53, 59, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 79, 81, 83, 85]) @@ -237,6 +242,13 @@ class ChunkRenderer(object): blocks = blocks.copy() blocks[skylight_expanded != 0] = 21 + blockData = get_blockdata_array(self.level) + blockData_expanded = numpy.empty((16,16,128), dtype=numpy.uint8) + # Even elements get the lower 4 bits + blockData_expanded[:,:,::2] = blockData & 0x0F + # Odd elements get the upper 4 bits + blockData_expanded[:,:,1::2] = blockData >> 4 + # Each block is 24x24 # The next block on the X axis adds 12px to x and subtracts 6px from y in the image @@ -255,7 +267,17 @@ class ChunkRenderer(object): for z in xrange(128): try: blockid = blocks[x,y,z] - t = textures.blockmap[blockid] + + # the following blocks don't have textures that can be pre-computed from the blockid + # alone. additional data is required. + # TODO torches, redstone torches, crops, ladders, stairs, + # levers, doors, buttons, and signs all need to be handled here (and in textures.py) + if blockid in (66,): ## minecart track + ancilData = blockData_expanded[x,y,z] + t = textures.generate_special_texture(blockid, ancilData) + + else: + t = textures.blockmap[blockid] if not t: continue diff --git a/textures.py b/textures.py index 8d34b03..a73517f 100644 --- a/textures.py +++ b/textures.py @@ -114,7 +114,7 @@ def _split_terrain(terrain): # This maps terainids to 16x16 images terrain_images = _split_terrain(_get_terrain_image()) -def _transform_image(img, blockID): +def _transform_image(img, blockID=None): """Takes a PIL image and rotates it left 45 degrees and shrinks the y axis by a factor of 2. Returns the resulting image, which will be 24x12 pixels @@ -201,6 +201,8 @@ def _build_block(top, side, blockID=None): otherside.putalpha(othersidealpha) ## special case for non-block things + # TODO once torches are handled by generate_special_texture, remove + # them from this list if blockID in (37,38,6,39,40,50,83): ## flowers, sapling, mushrooms, regular torch, reeds # instead of pasting these blocks at the cube edges, place them in the middle: # and omit the top @@ -321,3 +323,41 @@ def load_water(): blockmap[10] = lavablock.convert("RGB"), lavablock blockmap[11] = blockmap[10] load_water() + + +def generate_special_texture(blockID, data): + """Generates a special texture, such as a correctly facing minecraft track""" + #print "%s has ancillary data: %X" %(blockID, data) + # TODO torches, redstone torches, crops, ladders, stairs, + # levers, doors, buttons, and signs all need to be handled here (and in chunkpy) + if blockID == 66: # minetrack: + raw_straight = terrain_images[128] + raw_corner = terrain_images[112] + + ## use _transform_image to scale and shear + if data == 0: + track = _transform_image(raw_straight, blockID) + elif data == 6: + track = _transform_image(raw_corner, blockID) + elif data == 7: + track = _transform_image(raw_corner.rotate(270), blockID) + elif data == 8: + # flip + track = _transform_image(raw_corner.transpose(Image.FLIP_TOP_BOTTOM).rotate(90), + blockID) + elif data == 9: + track = _transform_image(raw_corner.transpose(Image.FLIP_TOP_BOTTOM), + blockID) + elif data == 1: + track = _transform_image(raw_straight.rotate(90), blockID) + else: + # TODO render carts that slop up or down + track = _transform_image(raw_straight, blockID) + + img = Image.new("RGBA", (24,24), (38,92,255,0)) + img.paste(track, (0,12), track) + + return (img.convert("RGB"), img.split()[3]) + + + return None