From 545f0db46a4dd5de650f13b01505d7e0df3c2f38 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sun, 6 Jan 2013 16:00:49 -0500 Subject: [PATCH 01/18] Add support for Quartz ore and redstone block See #863 --- overviewer_core/textures.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index f55c041..cc741af 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -3519,6 +3519,12 @@ block(blockid=129, top_index=171) # emerald block block(blockid=133, top_index=25) +# nether quartz ore +block(blockid=153, top_index=191) + +# block of redstone +block(blockid=152, top_index=26) + # cocoa plant @material(blockid=127, data=range(12), transparent=True) def cocoa_plant(self, blockid, data): From 7f9d6e6508a3e0fa9660945f9111e3874f68ba07 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sun, 6 Jan 2013 19:13:15 -0500 Subject: [PATCH 02/18] First pass an rendering comparators See #863 --- overviewer_core/textures.py | 64 +++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index cc741af..3f5c357 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -2982,6 +2982,70 @@ def repeater(self, blockid, data): alpha_over(img, torch, moving_torch, torch) return img + +# redstone comparator (149 is inactive, 150 is active) +@material(blockid=[149,150], data=range(16), transparent=True, nospawn=True) +def comparator(self, blockid, data): + + # rotation + # add self.rotation to the lower 2 bits, mod 4 + data = data & 0b1100 | (((data & 0b11) + self.rotation) % 4) + + + top = self.terrain_images[187] if blockid == 149 else self.terrain_images[188] + side = self.terrain_images[5] + increment = 13 + + if (data & 0x3) == 0: # pointing north + pass + static_torch = (-3,-1) + torch = ((0,2),(6,-1)) + + if (data & 0x3) == 1: # pointing east + top = top.rotate(270) + static_torch = (5,-1) + torch = ((-4,-1),(0,2)) + + if (data & 0x3) == 2: # pointing south + top = top.rotate(180) + static_torch = (5,3) + torch = ((0,-4),(-4,-1)) + + if (data & 0x3) == 3: # pointing west + top = top.rotate(90) + static_torch = (-3,3) + torch = ((1,-4),(6,-1)) + + + def build_torch(active): + # compose a "3d" redstone torch + t = self.terrain_images[115].copy() if not active else self.terrain_images[99].copy() + torch = Image.new("RGBA", (24,24), self.bgcolor) + + t_crop = t.crop((2,2,14,14)) + slice = t_crop.copy() + ImageDraw.Draw(slice).rectangle((6,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0)) + ImageDraw.Draw(slice).rectangle((0,0,4,12),outline=(0,0,0,0),fill=(0,0,0,0)) + + alpha_over(torch, slice, (6,4)) + alpha_over(torch, t_crop, (5,5)) + alpha_over(torch, t_crop, (6,5)) + alpha_over(torch, slice, (6,6)) + + return torch + + active_torch = build_torch(True) + inactive_torch = build_torch(False) + back_torch = active_torch if blockid == 150 else inactive_torch + static_torch_img = active_torch if (data & 0b100 == 0b100) else inactive_torch + + img = self.build_full_block( (top, increment), None, None, side, side) + + alpha_over(img, static_torch_img, static_torch, static_torch_img) + alpha_over(img, back_torch, torch[0], back_torch) + alpha_over(img, back_torch, torch[1], back_torch) + return img + # trapdoor # TODO the trapdoor is looks like a sprite when opened, that's not good From bec35bda1ee93b6d80288ed64867eeb4108552ab Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sat, 12 Jan 2013 00:49:36 -0500 Subject: [PATCH 03/18] Load textures from the new textures folder (intead of terrain.png) See #863 --- overviewer_core/textures.py | 561 +++++++++++++++++------------------- 1 file changed, 270 insertions(+), 291 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 3f5c357..6e8848a 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -53,6 +53,9 @@ class Textures(object): # this is set in in generate() self.generated = False + + # see load_image() + self.texture_cache = {} ## ## pickle support @@ -61,7 +64,7 @@ class Textures(object): def __getstate__(self): # we must get rid of the huge image lists, and other images attributes = self.__dict__.copy() - for attr in ['terrain_images', 'blockmap', 'biome_grass_texture', 'watertexture', 'lavatexture', 'firetexture', 'portaltexture', 'lightcolor', 'grasscolor', 'foliagecolor', 'watercolor']: + for attr in ['blockmap', 'biome_grass_texture', 'watertexture', 'lavatexture', 'firetexture', 'portaltexture', 'lightcolor', 'grasscolor', 'foliagecolor', 'watercolor', 'texture_cache']: try: del attributes[attr] except KeyError: @@ -71,6 +74,7 @@ class Textures(object): # regenerate textures, if needed for attr, val in attrs.iteritems(): setattr(self, attr, val) + self.texture_cache = {} if self.generated: self.generate() @@ -79,11 +83,9 @@ class Textures(object): ## def generate(self): - # maps terrainids to 16x16 images - self.terrain_images = self._split_terrain(self.load_image("terrain.png")) # generate biome grass mask - self.biome_grass_texture = self.build_block(self.terrain_images[0], self.terrain_images[38]) + self.biome_grass_texture = self.build_block(self.load_image("textures/blocks/grass_top.png"), self.load_image("textures/blocks/grass_side_overlay.png")) # generate the blocks global blockmap_generators @@ -222,9 +224,17 @@ class Textures(object): def load_image(self, filename): """Returns an image object""" + + if filename in self.texture_cache: + return self.texture_cache[filename] + fileobj = self.find_file(filename) buffer = StringIO(fileobj.read()) - return Image.open(buffer).convert("RGBA") + img = Image.open(buffer).convert("RGBA") + self.texture_cache[filename] = img + return img + + def load_water(self): """Special-case function for loading water, handles @@ -701,45 +711,45 @@ def material(blockid=[], data=[0], **kwargs): return inner_material # shortcut function for pure blocks, default to solid, nodata -def block(blockid=[], top_index=None, side_index=None, **kwargs): +def block(blockid=[], top_image=None, side_image=None, **kwargs): new_kwargs = {'solid' : True, 'nodata' : True} new_kwargs.update(kwargs) - if top_index is None: - raise ValueError("top_index was not provided") + if top_image is None: + raise ValueError("top_image was not provided") - if side_index is None: - side_index = top_index + if side_image is None: + side_image = top_image @material(blockid=blockid, **new_kwargs) def inner_block(self, unused_id, unused_data): - return self.build_block(self.terrain_images[top_index], self.terrain_images[side_index]) + return self.build_block(self.load_image(top_image), self.load_image(side_image)) return inner_block # shortcut function for sprite blocks, defaults to transparent, nodata -def sprite(blockid=[], index=None, **kwargs): +def sprite(blockid=[], imagename=None, **kwargs): new_kwargs = {'transparent' : True, 'nodata' : True} new_kwargs.update(kwargs) - if index is None: - raise ValueError("index was not provided") + if imagename is None: + raise ValueError("imagename was not provided") @material(blockid=blockid, **new_kwargs) def inner_sprite(self, unused_id, unused_data): - return self.build_sprite(self.terrain_images[index]) + return self.build_sprite(self.load_image(imagename)) return inner_sprite # shortcut function for billboard blocks, defaults to transparent, nodata -def billboard(blockid=[], index=None, **kwargs): +def billboard(blockid=[], imagename=None, **kwargs): new_kwargs = {'transparent' : True, 'nodata' : True} new_kwargs.update(kwargs) - if index is None: - raise ValueError("index was not provided") + if imagename is None: + raise ValueError("imagename was not provided") @material(blockid=blockid, **new_kwargs) def inner_billboard(self, unused_id, unused_data): - return self.build_billboard(self.terrain_images[index]) + return self.build_billboard(self.load_image(imagename)) return inner_billboard ## @@ -747,51 +757,51 @@ def billboard(blockid=[], index=None, **kwargs): ## # stone -block(blockid=1, top_index=1) +block(blockid=1, top_image="textures/blocks/stone.png") @material(blockid=2, data=range(11)+[0x10,], solid=True) def grass(self, blockid, data): # 0x10 bit means SNOW - side_img = self.terrain_images[3] + side_img = self.load_image("textures/blocks/grass_side.png") if data & 0x10: - side_img = self.terrain_images[68] - img = self.build_block(self.terrain_images[0], side_img) + side_img = self.load_image("textures/blocks/snow_side.png") + img = self.build_block(self.load_image("textures/blocks/grass_top.png"), side_img) if not data & 0x10: alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) return img # dirt -block(blockid=3, top_index=2) +block(blockid=3, top_image="textures/blocks/dirt.png") # cobblestone -block(blockid=4, top_index=16) +block(blockid=4, top_image="textures/blocks/stonebrick.png") # wooden planks @material(blockid=5, data=range(4), solid=True) def wooden_planks(self, blockid, data): if data == 0: # normal - return self.build_block(self.terrain_images[4],self.terrain_images[4]) + return self.build_block(self.load_image("textures/blocks/wood.png"), self.load_image("textures/blocks/wood.png")) if data == 1: # pine - return self.build_block(self.terrain_images[198],self.terrain_images[198]) + return self.build_block(self.load_image("textures/blocks/wood_spruce.png"),self.load_image("textures/blocks/wood_spruce.png")) if data == 2: # birch - return self.build_block(self.terrain_images[214],self.terrain_images[214]) + return self.build_block(self.load_image("textures/blocks/wood_birch.png"),self.load_image("textures/blocks/wood_birch.png")) if data == 3: # jungle wood - return self.build_block(self.terrain_images[199],self.terrain_images[199]) + return self.build_block(self.load_image("textures/blocks/wood_jungle.png"),self.load_image("textures/blocks/wood_jungle.png")) @material(blockid=6, data=range(16), transparent=True) def saplings(self, blockid, data): # usual saplings - tex = self.terrain_images[15] + tex = self.load_image("textures/blocks/sapling.png") if data & 0x3 == 1: # spruce sapling - tex = self.terrain_images[63] + tex = self.load_image("textures/blocks/sapling_spruce.png") elif data & 0x3 == 2: # birch sapling - tex = self.terrain_images[79] + tex = self.load_image("textures/blocks/sapling_birch.png") elif data & 0x3 == 3: # jungle sapling - tex = self.terrain_images[30] + tex = self.load_image("textures/blocks/sapling_jungle.png") return self.build_sprite(tex) # bedrock -block(blockid=7, top_index=17) +block(blockid=7, top_image="textures/blocks/bedrock.png") @material(blockid=8, data=range(16), fluid=True, transparent=True, nospawn=True) def water(self, blockid, data): @@ -805,9 +815,9 @@ def no_inner_surfaces(self, blockid, data): if blockid == 9: texture = self.load_water() elif blockid == 20: - texture = self.terrain_images[49] + texture = self.load_image("textures/blocks/glass.png") else: - texture = self.terrain_images[67] + texture = self.load_image("textures/blocks/ice.png") if (data & 0b10000) == 16: top = texture @@ -847,15 +857,15 @@ def lava(self, blockid, data): return self.build_block(lavatex, lavatex) # sand -block(blockid=12, top_index=18) +block(blockid=12, top_image="textures/blocks/sand.png") # gravel -block(blockid=13, top_index=19) +block(blockid=13, top_image="textures/blocks/gravel.png") # gold ore -block(blockid=14, top_index=32) +block(blockid=14, top_image="textures/blocks/oreGold.png") # iron ore -block(blockid=15, top_index=33) +block(blockid=15, top_image="textures/blocks/oreIron.png") # coal ore -block(blockid=16, top_index=34) +block(blockid=16, top_image="textures/blocks/oreCoal.png") @material(blockid=17, data=range(12), solid=True) def wood(self, blockid, data): @@ -870,15 +880,15 @@ def wood(self, blockid, data): elif wood_orientation == 8: wood_orientation = 4 # choose textures - top = self.terrain_images[21] + top = self.load_image("textures/blocks/tree_top.png") if wood_type == 0: # normal - side = self.terrain_images[20] - if wood_type == 1: # birch - side = self.terrain_images[116] - if wood_type == 2: # pine - side = self.terrain_images[117] + side = self.load_image("textures/blocks/tree_side.png") + if wood_type == 1: # spruce + side = self.load_image("textures/blocks/tree_spruce.png") + if wood_type == 2: # birch + side = self.load_image("textures/blocks/tree_birch.png") if wood_type == 3: # jungle wood - side = self.terrain_images[153] + side = self.load_image("textures/blocks/tree_jungle.png") # choose orientation and paste textures if wood_orientation == 0: @@ -893,21 +903,21 @@ def leaves(self, blockid, data): # mask out the bits 4 and 8 # they are used for player placed and check-for-decay blocks data = data & 0x3 - t = self.terrain_images[52] + t = self.load_image("textures/blocks/leaves.png") if data == 1: # pine! - t = self.terrain_images[132] + t = self.load_image("textures/blocks/leaves_spruce.png") elif data == 3: # jungle tree - t = self.terrain_images[196] + t = self.load_image("textures/blocks/leaves_jungle.png") return self.build_block(t, t) # sponge -block(blockid=19, top_index=48) +block(blockid=19, top_image="textures/blocks/sponge.png") # lapis lazuli ore -block(blockid=21, top_index=160) +block(blockid=21, top_image="textures/blocks/oreLapis.png") # lapis lazuli block -block(blockid=22, top_index=144) +block(blockid=22, top_image="textures/blocks/blockLapis.png") # dispensers, furnaces, and burning furnaces @material(blockid=[23, 61, 62], data=range(6), solid=True) @@ -929,15 +939,15 @@ def furnaces(self, blockid, data): elif data == 4: data = 3 elif data == 5: data = 2 - top = self.terrain_images[62] - side = self.terrain_images[45] + top = self.load_image("textures/blocks/furnace_top.png") + side = self.load_image("textures/blocks/furnace_side.png") if blockid == 61: - front = self.terrain_images[44] + front = self.load_image("textures/blocks/furnace_front.png") elif blockid == 62: - front = self.terrain_images[61] + front = self.load_image("textures/blocks/furnace_front_lit.png") elif blockid == 23: - front = self.terrain_images[46] + front = self.load_image("textures/blocks/dispenser_front.png") if data == 3: # pointing west return self.build_full_block(top, None, None, side, front) @@ -949,16 +959,16 @@ def furnaces(self, blockid, data): # sandstone @material(blockid=24, data=range(3), solid=True) def sandstone(self, blockid, data): - top = self.terrain_images[176] + top = self.load_image("textures/blocks/sandstone_top.png") if data == 0: # normal - return self.build_block(top, self.terrain_images[192]) + return self.build_block(top, self.load_image("textures/blocks/sandstone_side.png")) if data == 1: # hieroglyphic - return self.build_block(top, self.terrain_images[229]) + return self.build_block(top, self.load_image("textures/blocks/sandstone_carved.png")) if data == 2: # soft - return self.build_block(top, self.terrain_images[230]) + return self.build_block(top, self.load_image("textures/blocks/sandstone_smooth.png")) # note block -block(blockid=25, top_index=74) +block(blockid=25, top_image="textures/blocks/musicBlock.png") @material(blockid=26, data=range(12), transparent=True, nospawn=True) def bed(self, blockid, data): @@ -984,40 +994,40 @@ def bed(self, blockid, data): left_face = None right_face = None if data & 0x8 == 0x8: # head of the bed - top = self.terrain_images[135] + top = self.load_image("textures/blocks/bed_head_top.png") if data & 0x00 == 0x00: # head pointing to West top = top.copy().rotate(270) - left_face = self.terrain_images[151] - right_face = self.terrain_images[152] + left_face = self.load_image("textures/blocks/bed_head_side.png") + right_face = self.load_image("textures/blocks/bed_head_end.png") if data & 0x01 == 0x01: # ... North top = top.rotate(270) - left_face = self.terrain_images[152] - right_face = self.terrain_images[151] + left_face = self.load_image("textures/blocks/bed_head_end.png") + right_face = self.load_image("textures/blocks/bed_head_side.png") if data & 0x02 == 0x02: # East top = top.rotate(180) - left_face = self.terrain_images[151].transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) right_face = None if data & 0x03 == 0x03: # South right_face = None - right_face = self.terrain_images[151].transpose(Image.FLIP_LEFT_RIGHT) + right_face = self.load_image("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) else: # foot of the bed - top = self.terrain_images[134] + top = self.load_image("textures/blocks/bed_feet_top.png") if data & 0x00 == 0x00: # head pointing to West top = top.rotate(270) - left_face = self.terrain_images[150] + left_face = self.load_image("textures/blocks/bed_feet_side.png") right_face = None if data & 0x01 == 0x01: # ... North top = top.rotate(270) left_face = None - right_face = self.terrain_images[150] + right_face = self.load_image("textures/blocks/bed_feet_side.png") if data & 0x02 == 0x02: # East top = top.rotate(180) - left_face = self.terrain_images[150].transpose(Image.FLIP_LEFT_RIGHT) - right_face = self.terrain_images[149].transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) + right_face = self.load_image("textures/blocks/bed_feet_end.png").transpose(Image.FLIP_LEFT_RIGHT) if data & 0x03 == 0x03: # South - left_face = self.terrain_images[149] - right_face = self.terrain_images[150].transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image("textures/blocks/bed_feet_end.png") + right_face = self.load_image("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) top = (top, increment) return self.build_full_block(top, None, None, left_face, right_face) @@ -1068,22 +1078,22 @@ def rails(self, blockid, data): if blockid == 27: # powered rail if data & 0x8 == 0: # unpowered - raw_straight = self.terrain_images[163] - raw_corner = self.terrain_images[112] # they don't exist but make the code + raw_straight = self.load_image("textures/blocks/goldenRail.png") + raw_corner = self.load_image("textures/blocks/rail_turn.png") # they don't exist but make the code # much simplier elif data & 0x8 == 0x8: # powered - raw_straight = self.terrain_images[179] - raw_corner = self.terrain_images[112] # leave corners for code simplicity + raw_straight = self.load_image("textures/blocks/goldenRail_powered.png") + raw_corner = self.load_image("textures/blocks/rail_turn.png") # leave corners for code simplicity # filter the 'powered' bit data = data & 0x7 elif blockid == 28: # detector rail - raw_straight = self.terrain_images[195] - raw_corner = self.terrain_images[112] # leave corners for code simplicity + raw_straight = self.load_image("textures/blocks/detectorRail.png") + raw_corner = self.load_image("textures/blocks/rail_turn.png") # leave corners for code simplicity elif blockid == 66: # normal rail - raw_straight = self.terrain_images[128] - raw_corner = self.terrain_images[112] + raw_straight = self.load_image("textures/blocks/rail.png") + raw_corner = self.load_image("textures/blocks/rail_turn.png") ## use transform_image to scale and shear if data == 0: @@ -1151,14 +1161,14 @@ def piston(self, blockid, data): elif (data & 0b0111) == 5: data = data & 0b1000 | 2 if blockid == 29: # sticky - piston_t = self.terrain_images[106].copy() + piston_t = self.load_image("textures/blocks/piston_top_sticky.png").copy() else: # normal - piston_t = self.terrain_images[107].copy() + piston_t = self.load_image("textures/blocks/piston_top.png").copy() # other textures - side_t = self.terrain_images[108].copy() - back_t = self.terrain_images[109].copy() - interior_t = self.terrain_images[110].copy() + side_t = self.load_image("textures/blocks/piston_side.png").copy() + back_t = self.load_image("textures/blocks/piston_bottom.png").copy() + interior_t = self.load_image("textures/blocks/piston_inner_top.png").copy() if data & 0x08 == 0x08: # pushed out, non full blocks, tricky stuff # remove piston texture from piston body @@ -1227,13 +1237,13 @@ def piston_extension(self, blockid, data): elif (data & 0b0111) == 5: data = data & 0b1000 | 2 if (data & 0x8) == 0x8: # sticky - piston_t = self.terrain_images[106].copy() + piston_t = self.load_image("textures/blocks/piston_top_sticky.png").copy() else: # normal - piston_t = self.terrain_images[107].copy() + piston_t = self.load_image("textures/blocks/piston_top.png").copy() # other textures - side_t = self.terrain_images[108].copy() - back_t = self.terrain_images[107].copy() + side_t = self.load_image("textures/blocks/piston_side.png").copy() + back_t = self.load_image("textures/blocks/piston_top.png").copy() # crop piston body ImageDraw.Draw(side_t).rectangle((0, 4,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1293,71 +1303,40 @@ def piston_extension(self, blockid, data): return img # cobweb -sprite(blockid=30, index=11, nospawn=True) +sprite(blockid=30, imagename="textures/blocks/web.png", nospawn=True) @material(blockid=31, data=range(3), transparent=True) def tall_grass(self, blockid, data): if data == 0: # dead shrub - texture = self.terrain_images[55] + texture = self.load_image("textures/blocks/deadbush.png") elif data == 1: # tall grass - texture = self.terrain_images[39] + texture = self.load_image("textures/blocks/tallgrass.png") elif data == 2: # fern - texture = self.terrain_images[56] + texture = self.load_image("textures/blocks/fern.png") return self.build_billboard(texture) # dead bush -billboard(blockid=32, index=55) +billboard(blockid=32, imagename="textures/blocks/deadbush.png") @material(blockid=35, data=range(16), solid=True) def wool(self, blockid, data): - if data == 0: # white - texture = self.terrain_images[64] - elif data == 1: # orange - texture = self.terrain_images[210] - elif data == 2: # magenta - texture = self.terrain_images[194] - elif data == 3: # light blue - texture = self.terrain_images[178] - elif data == 4: # yellow - texture = self.terrain_images[162] - elif data == 5: # light green - texture = self.terrain_images[146] - elif data == 6: # pink - texture = self.terrain_images[130] - elif data == 7: # grey - texture = self.terrain_images[114] - elif data == 8: # light grey - texture = self.terrain_images[225] - elif data == 9: # cyan - texture = self.terrain_images[209] - elif data == 10: # purple - texture = self.terrain_images[193] - elif data == 11: # blue - texture = self.terrain_images[177] - elif data == 12: # brown - texture = self.terrain_images[161] - elif data == 13: # dark green - texture = self.terrain_images[145] - elif data == 14: # red - texture = self.terrain_images[129] - elif data == 15: # black - texture = self.terrain_images[113] + texture = self.load_image("textures/blocks/cloth_%d.png" % data) return self.build_block(texture, texture) # dandelion -sprite(blockid=37, index=13) +sprite(blockid=37, imagename="textures/blocks/flower.png") # rose -sprite(blockid=38, index=12) +sprite(blockid=38, imagename="textures/blocks/rose.png") # brown mushroom -sprite(blockid=39, index=29) +sprite(blockid=39, imagename="textures/blocks/mushroom_brown.png") # red mushroom -sprite(blockid=40, index=28) +sprite(blockid=40, imagename="textures/blocks/mushroom_red.png") # block of gold -block(blockid=41, top_index=23) +block(blockid=41, top_image="textures/blocks/blockGold.png") # block of iron -block(blockid=42, top_index=22) +block(blockid=42, top_image="textures/blocks/blockIron.png") # double slabs and slabs # these wooden slabs are unobtainable without cheating, they are still @@ -1366,21 +1345,21 @@ block(blockid=42, top_index=22) def slabs(self, blockid, data): texture = data & 7 if texture== 0: # stone slab - top = self.terrain_images[6] - side = self.terrain_images[5] - elif texture== 1: # stone slab - top = self.terrain_images[176] - side = self.terrain_images[192] + top = self.load_image("textures/blocks/stoneslab_top.png") + side = self.load_image("textures/blocks/stoneslab_side.png") + elif texture== 1: # smooth stone + top = self.load_image("textures/blocks/sandstone_top.png") + side = self.load_image("textures/blocks/sandstone_side.png") elif texture== 2: # wooden slab - top = side = self.terrain_images[4] + top = side = self.load_image("textures/blocks/wood.png") elif texture== 3: # cobblestone slab - top = side = self.terrain_images[16] + top = side = self.load_image("textures/blocks/stonebrick.png") elif texture== 4: # brick - top = side = self.terrain_images[7] + top = side = self.load_image("textures/blocks/brick.png") elif texture== 5: # stone brick - top = side = self.terrain_images[54] + top = side = self.load_image("textures/blocks/stonebricksmooth.png") elif texture== 6: # nether brick slab - top = side = self.terrain_images[224] + top = side = self.load_image("textures/blocks/netherBrick.png") else: return None @@ -1417,15 +1396,15 @@ def slabs(self, blockid, data): return img # brick block -block(blockid=45, top_index=7) +block(blockid=45, top_image="textures/blocks/brick.png") # TNT -block(blockid=46, top_index=9, side_index=8, nospawn=True) +block(blockid=46, top_image="textures/blocks/tnt_top.png", side_image="textures/blocks/tnt_side.png", nospawn=True) # bookshelf -block(blockid=47, top_index=4, side_index=35) +block(blockid=47, top_image="textures/blocks/wood.png", side_image="textures/blocks/bookshelf.png") # moss stone -block(blockid=48, top_index=36) +block(blockid=48, top_image="textures/blocks/stoneMoss.png") # obsidian -block(blockid=49, top_index=37) +block(blockid=49, top_image="textures/blocks/obsidian.png") # torch, redstone torch (off), redstone torch(on) @material(blockid=[50, 75, 76], data=[1, 2, 3, 4, 5], transparent=True) @@ -1449,11 +1428,11 @@ def torches(self, blockid, data): # choose the proper texture if blockid == 50: # torch - small = self.terrain_images[80] + small = self.load_image("textures/blocks/torch.png") elif blockid == 75: # off redstone torch - small = self.terrain_images[115] + small = self.load_image("textures/blocks/redtorch.png") else: # on redstone torch - small = self.terrain_images[99] + small = self.load_image("textures/blocks/redtorch_lit.png") # compose a torch bigger than the normal # (better for doing transformations) @@ -1515,7 +1494,7 @@ def fire(self, blockid, data): return img # monster spawner -block(blockid=52, top_index=65, transparent=True) +block(blockid=52, top_image="textures/blocks/mobSpawner.png", transparent=True) # wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch and jungle stairs. @material(blockid=[53,67,108,109,114,128,134,135,136], data=range(8), transparent=True, solid=True, nospawn=True) @@ -1543,23 +1522,23 @@ def stairs(self, blockid, data): data = data | upside_down if blockid == 53: # wooden - texture = self.terrain_images[4] + texture = self.load_image("textures/blocks/wood.png") elif blockid == 67: # cobblestone - texture = self.terrain_images[16] + texture = self.load_image("textures/blocks/stonebrick.png") elif blockid == 108: # red brick stairs - texture = self.terrain_images[7] + texture = self.load_image("textures/blocks/brick.png") elif blockid == 109: # stone brick stairs - texture = self.terrain_images[54] + texture = self.load_image("textures/blocks/stonebricksmooth.png") elif blockid == 114: # netherbrick stairs - texture = self.terrain_images[224] + texture = self.load_image("textures/blocks/netherBrick.png") elif blockid == 128: # sandstone stairs - texture = self.terrain_images[192] + texture = self.load_image("textures/blocks/sandstone_side.png") elif blockid == 134: # spruce wood stairs - texture = self.terrain_images[198] + texture = self.load_image("textures/blocks/wood_spruce.png") elif blockid == 135: # birch wood stairs - texture = self.terrain_images[214] + texture = self.load_image("textures/blocks/wood_birch.png") elif blockid == 136: # jungle good stairs - texture = self.terrain_images[199] + texture = self.load_image("textures/blocks/wood_jungle.png") side = texture.copy() @@ -1570,9 +1549,9 @@ def stairs(self, blockid, data): # sandstone stairs have spcial top texture if blockid == 128: - half_block_u = self.terrain_images[176].copy() - half_block_d = self.terrain_images[176].copy() - texture = self.terrain_images[176].copy() + half_block_u = self.load_image("textures/blocks/sandstone_top.png").copy() + half_block_d = self.load_image("textures/blocks/sandstone_top.png").copy() + texture = self.load_image("textures/blocks/sandstone_top.png").copy() # generate needed geometries ImageDraw.Draw(side).rectangle((0,0,7,6),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1849,18 +1828,18 @@ def chests(self, blockid, data): def wire(self, blockid, data): if data & 0b1000000 == 64: # powered redstone wire - redstone_wire_t = self.terrain_images[165] + redstone_wire_t = self.load_image("textures/blocks/redstoneDust_line.png") redstone_wire_t = self.tint_texture(redstone_wire_t,(255,0,0)) - redstone_cross_t = self.terrain_images[164] + redstone_cross_t = self.load_image("textures/blocks/redstoneDust_cross.png") redstone_cross_t = self.tint_texture(redstone_cross_t,(255,0,0)) else: # unpowered redstone wire - redstone_wire_t = self.terrain_images[165] + redstone_wire_t = self.load_image("textures/blocks/redstoneDust_line.png") redstone_wire_t = self.tint_texture(redstone_wire_t,(48,0,0)) - redstone_cross_t = self.terrain_images[164] + redstone_cross_t = self.load_image("textures/blocks/redstoneDust_cross.png") redstone_cross_t = self.tint_texture(redstone_cross_t,(48,0,0)) # generate an image per redstone direction @@ -1924,17 +1903,17 @@ def wire(self, blockid, data): return img # diamond ore -block(blockid=56, top_index=50) +block(blockid=56, top_image="textures/blocks/oreDiamond.png") # diamond block -block(blockid=57, top_index=24) +block(blockid=57, top_image="textures/blocks/blockDiamond.png") # crafting table # needs two different sides @material(blockid=58, solid=True, nodata=True) def crafting_table(self, blockid, data): - top = self.terrain_images[43] - side3 = self.terrain_images[43+16] - side4 = self.terrain_images[43+16+1] + top = self.load_image("textures/blocks/workbench_top.png") + side3 = self.load_image("textures/blocks/workbench_side.png") + side4 = self.load_image("textures/blocks/workbench_front.png") img = self.build_full_block(top, None, None, side3, side4, None) return img @@ -1942,7 +1921,7 @@ def crafting_table(self, blockid, data): # crops @material(blockid=59, data=range(8), transparent=True, nospawn=True) def crops(self, blockid, data): - raw_crop = self.terrain_images[88+data] + raw_crop = self.load_image("textures/blocks/crops_%d.png" % data) crop1 = self.transform_image_top(raw_crop) crop2 = self.transform_image_side(raw_crop) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) @@ -1956,10 +1935,10 @@ def crops(self, blockid, data): # farmland @material(blockid=60, data=range(9), solid=True) def farmland(self, blockid, data): - top = self.terrain_images[86] + top = self.load_image("textures/blocks/farmland_wet.png") if data == 0: - top = self.terrain_images[87] - return self.build_block(top, self.terrain_images[2]) + top = self.load_image("textures/blocks/farmland_dry.png") + return self.build_block(top, self.load_image("textures/blocks/dirt.png")) # signposts @material(blockid=63, data=range(16), transparent=True) @@ -1973,7 +1952,7 @@ def signpost(self, blockid, data): elif self.rotation == 3: data = (data + 12) % 16 - texture = self.terrain_images[4].copy() + texture = self.load_image("textures/blocks/wood.png").copy() # cut the planks to the size of a signpost ImageDraw.Draw(texture).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1986,7 +1965,7 @@ def signpost(self, blockid, data): texture.putpixel((x,y),(0,0,0,255)) # Minecraft uses wood texture for the signpost stick - texture_stick = self.terrain_images[20] + texture_stick = self.load_image("textures/blocks/tree_side.png") texture_stick = texture_stick.resize((12,12), Image.ANTIALIAS) ImageDraw.Draw(texture_stick).rectangle((2,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2036,9 +2015,9 @@ def door(self, blockid, data): elif (data & 0b00011) == 3: data = data & 0b11100 | 2 if data & 0x8 == 0x8: # top of the door - raw_door = self.terrain_images[81 if blockid == 64 else 82] + raw_door = self.load_image("textures/blocks/%s.png" % ("doorWood_upper" if blockid == 64 else "doorIron_upper")) else: # bottom of the door - raw_door = self.terrain_images[97 if blockid == 64 else 98] + raw_door = self.load_image("textures/blocks/%s.png" % ("doorWood_lower" if blockid == 64 else "doorIron_lower")) # if you want to render all doors as closed, then force # force closed to be True @@ -2158,7 +2137,7 @@ def ladder(self, blockid, data): elif data == 5: data = 2 img = Image.new("RGBA", (24,24), self.bgcolor) - raw_texture = self.terrain_images[83] + raw_texture = self.load_image("textures/blocks/ladder.png") if data == 5: # normally this ladder would be obsured by the block it's attached to @@ -2202,7 +2181,7 @@ def wall_sign(self, blockid, data): # wall sign elif data == 4: data = 3 elif data == 5: data = 2 - texture = self.terrain_images[4].copy() + texture = self.load_image("textures/blocks/wood.png").copy() # cut the planks to the size of a signpost ImageDraw.Draw(texture).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2272,7 +2251,7 @@ def levers(self, blockid, data): elif data == 6: data = 5 # generate the texture for the base of the lever - t_base = self.terrain_images[16].copy() + t_base = self.load_image("textures/blocks/stonebrick.png").copy() ImageDraw.Draw(t_base).rectangle((0,0,15,3),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(t_base).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2280,7 +2259,7 @@ def levers(self, blockid, data): ImageDraw.Draw(t_base).rectangle((11,0,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) # generate the texture for the stick - stick = self.terrain_images[96].copy() + stick = self.load_image("textures/blocks/lever.png").copy() c_stick = Image.new("RGBA", (16,16), self.bgcolor) tmp = ImageEnhance.Brightness(stick).enhance(0.8) @@ -2385,9 +2364,9 @@ def levers(self, blockid, data): @material(blockid=[70, 72], data=[0,1], transparent=True) def pressure_plate(self, blockid, data): if blockid == 70: # stone - t = self.terrain_images[1].copy() + t = self.load_image("textures/blocks/stone.png").copy() else: # wooden - t = self.terrain_images[4].copy() + t = self.load_image("textures/blocks/wood.png").copy() # cut out the outside border, pressure plates are smaller # than a normal block @@ -2413,7 +2392,7 @@ def pressure_plate(self, blockid, data): return img # normal and glowing redstone ore -block(blockid=[73, 74], top_index=51) +block(blockid=[73, 74], top_image="textures/blocks/oreRedstone.png") # stone a wood buttons @material(blockid=(77,143), data=range(16), transparent=True) @@ -2440,9 +2419,9 @@ def buttons(self, blockid, data): elif data == 4: data = 2 if blockid == 77: - t = self.terrain_images[1].copy() + t = self.load_image("textures/blocks/stone.png").copy() else: - t = self.terrain_images[4].copy() + t = self.load_image("textures/blocks/wood.png").copy() # generate the texture for the button ImageDraw.Draw(t).rectangle((0,0,15,5),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2492,7 +2471,7 @@ def buttons(self, blockid, data): def snow(self, blockid, data): # still not rendered correctly: data other than 0 - tex = self.terrain_images[66] + tex = self.load_image("textures/blocks/snow.png") # make the side image, top 3/4 transparent mask = tex.crop((0,12,16,16)) @@ -2512,13 +2491,13 @@ def snow(self, blockid, data): return img # snow block -block(blockid=80, top_index=66) +block(blockid=80, top_image="textures/blocks/snow.png") # cactus @material(blockid=81, data=range(15), transparent=True, solid=True, nospawn=True) def cactus(self, blockid, data): - top = self.terrain_images[69] - side = self.terrain_images[70] + top = self.load_image("textures/blocks/cactus_top.png") + side = self.load_image("textures/blocks/cactus_side.png") img = Image.new("RGBA", (24,24), self.bgcolor) @@ -2540,18 +2519,18 @@ def cactus(self, blockid, data): return img # clay block -block(blockid=82, top_index=72) +block(blockid=82, top_image="textures/blocks/clay.png") # sugar cane @material(blockid=83, data=range(16), transparent=True) def sugar_cane(self, blockid, data): - tex = self.terrain_images[73] + tex = self.load_image("textures/blocks/reeds.png") return self.build_sprite(tex) # jukebox @material(blockid=84, data=range(16), solid=True) def jukebox(self, blockid, data): - return self.build_block(self.terrain_images[75], self.terrain_images[74]) + return self.build_block(self.load_image("textures/blocks/jukebox_top.png"), self.load_image("textures/blocks/musicBlock.png")) # nether and normal fences # uses pseudo-ancildata found in iterate.c @@ -2560,13 +2539,13 @@ def fence(self, blockid, data): # no need for rotations, it uses pseudo data. # create needed images for Big stick fence if blockid == 85: # normal fence - fence_top = self.terrain_images[4].copy() - fence_side = self.terrain_images[4].copy() - fence_small_side = self.terrain_images[4].copy() + fence_top = self.load_image("textures/blocks/wood.png").copy() + fence_side = self.load_image("textures/blocks/wood.png").copy() + fence_small_side = self.load_image("textures/blocks/wood.png").copy() else: # netherbrick fence - fence_top = self.terrain_images[224].copy() - fence_side = self.terrain_images[224].copy() - fence_small_side = self.terrain_images[224].copy() + fence_top = self.load_image("textures/blocks/netherBrick.png").copy() + fence_side = self.load_image("textures/blocks/netherBrick.png").copy() + fence_small_side = self.load_image("textures/blocks/netherBrick.png").copy() # generate the textures of the fence ImageDraw.Draw(fence_top).rectangle((0,0,5,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2671,10 +2650,10 @@ def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern elif data == 3: data = 2 # texture generation - top = self.terrain_images[102] - frontID = 119 if blockid == 86 else 120 - front = self.terrain_images[frontID] - side = self.terrain_images[118] + top = self.load_image("textures/blocks/pumpkin_top.png") + frontName = "textures/blocks/pumpkin_face.png" if blockid == 86 else "textures/blocks/pumpkin_jack.png" + front = self.load_image(frontName) + side = self.load_image("textures/blocks/pumpkin_side.png") if data == 0: # pointing west img = self.build_full_block(top, None, None, side, front) @@ -2688,13 +2667,13 @@ def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern return img # netherrack -block(blockid=87, top_index=103) +block(blockid=87, top_image="textures/blocks/hellrock.png") # soul sand -block(blockid=88, top_index=104) +block(blockid=88, top_image="textures/blocks/hellsand.png") # glowstone -block(blockid=89, top_index=105) +block(blockid=89, top_image="textures/blocks/lightgem.png") # portal @material(blockid=90, data=[1, 2, 4, 8], transparent=True) @@ -2719,10 +2698,10 @@ def portal(self, blockid, data): def cake(self, blockid, data): # cake textures - top = self.terrain_images[121].copy() - side = self.terrain_images[122].copy() + top = self.load_image("textures/blocks/cake_top.png").copy() + side = self.load_image("textures/blocks/cake_side.png").copy() fullside = side.copy() - inside = self.terrain_images[123] + inside = self.load_image("textures/blocks/cake_inner.png") img = Image.new("RGBA", (24,24), self.bgcolor) if data == 0: # unbitten cake @@ -2860,8 +2839,8 @@ def repeater(self, blockid, data): elif (data & 0b0011) == 3: data = data & 0b1100 | 2 # generate the diode - top = self.terrain_images[131] if blockid == 93 else self.terrain_images[147] - side = self.terrain_images[5] + top = self.load_image("textures/blocks/repeater.png") if blockid == 93 else self.load_image("textures/blocks/repeater_lit.png") + side = self.load_image("textures/blocks/stoneslab_side.png") increment = 13 if (data & 0x3) == 0: # pointing east @@ -2879,7 +2858,7 @@ def repeater(self, blockid, data): img = self.build_full_block( (top, increment), None, None, side, side) # compose a "3d" redstone torch - t = self.terrain_images[115].copy() if blockid == 93 else self.terrain_images[99].copy() + t = self.load_image("textures/blocks/redtorch.png").copy() if blockid == 93 else self.load_image("textures/blocks/redtorch_lit.png").copy() torch = Image.new("RGBA", (24,24), self.bgcolor) t_crop = t.crop((2,2,14,14)) @@ -2992,8 +2971,8 @@ def comparator(self, blockid, data): data = data & 0b1100 | (((data & 0b11) + self.rotation) % 4) - top = self.terrain_images[187] if blockid == 149 else self.terrain_images[188] - side = self.terrain_images[5] + top = self.load_image("textures/blocks/comparator.png") if blockid == 149 else self.load_image("textures/blocks/comparator_lit.png") + side = self.load_image("textures/blocks/stoneslab_side.png") increment = 13 if (data & 0x3) == 0: # pointing north @@ -3019,7 +2998,7 @@ def comparator(self, blockid, data): def build_torch(active): # compose a "3d" redstone torch - t = self.terrain_images[115].copy() if not active else self.terrain_images[99].copy() + t = self.load_image("textures/blocks/redtorch.png").copy() if not active else self.load_image("textures/blocks/redtorch_lit.png").copy() torch = Image.new("RGBA", (24,24), self.bgcolor) t_crop = t.crop((2,2,14,14)) @@ -3071,7 +3050,7 @@ def trapdoor(self, blockid, data): elif (data & 0b0011) == 3: data = data & 0b1100 | 0 # texture generation - texture = self.terrain_images[84] + texture = self.load_image("textures/blocks/trapdoor.png") if data & 0x4 == 0x4: # opened trapdoor if data & 0x3 == 0: # west img = self.build_full_block(None, None, None, None, texture) @@ -3096,11 +3075,11 @@ def trapdoor(self, blockid, data): @material(blockid=97, data=range(3), solid=True) def hidden_silverfish(self, blockid, data): if data == 0: # stone - t = self.terrain_images[1] + t = self.load_image("textures/blocks/stone.png") elif data == 1: # cobblestone - t = self.terrain_images[16] + t = self.load_image("textures/blocks/stonebrick.png") elif data == 2: # stone brick - t = self.terrain_images[54] + t = self.load_image("textures/blocks/stonebricksmooth.png") img = self.build_block(t, t) @@ -3110,13 +3089,13 @@ def hidden_silverfish(self, blockid, data): @material(blockid=98, data=range(4), solid=True) def stone_brick(self, blockid, data): if data == 0: # normal - t = self.terrain_images[54] + t = self.load_image("textures/blocks/stonebricksmooth.png") elif data == 1: # mossy - t = self.terrain_images[100] + t = self.load_image("textures/blocks/stonebricksmooth_mossy.png") elif data == 2: # cracked - t = self.terrain_images[101] + t = self.load_image("textures/blocks/stonebricksmooth_cracked.png") elif data == 3: # "circle" stone brick - t = self.terrain_images[213] + t = self.load_image("textures/blocks/stonebricksmooth_carved.png") img = self.build_full_block(t, None, None, t, t) @@ -3156,12 +3135,12 @@ def huge_mushroom(self, blockid, data): # texture generation if blockid == 99: # brown - cap = self.terrain_images[126] + cap = self.load_image("textures/blocks/mushroom_skin_brown.png") else: # red - cap = self.terrain_images[125] + cap = self.load_image("textures/blocks/mushroom_skin_red.png") - stem = self.terrain_images[141] - porous = self.terrain_images[142] + stem = self.load_image("textures/blocks/mushroom_skin_stem.png") + porous = self.load_image("textures/blocks/mushroom_inside.png") if data == 0: # fleshy piece img = self.build_full_block(porous, None, None, porous, porous) @@ -3206,10 +3185,10 @@ def panes(self, blockid, data): # no rotation, uses pseudo data if blockid == 101: # iron bars - t = self.terrain_images[85] + t = self.load_image("textures/blocks/fenceIron.png") else: # glass panes - t = self.terrain_images[49] + t = self.load_image("textures/blocks/glass.png") left = t.copy() right = t.copy() @@ -3242,7 +3221,7 @@ def panes(self, blockid, data): return img # melon -block(blockid=103, top_index=137, side_index=136, solid=True) +block(blockid=103, top_image="textures/blocks/melon_top.png", side_image="textures/blocks/melon_side.png", solid=True) # pumpkin and melon stem # TODO To render it as in game needs from pseudo data and ancil data: @@ -3255,7 +3234,7 @@ def stem(self, blockid, data): # not fully grown stem or no pumpkin/melon touching it, # straight up stem - t = self.terrain_images[111].copy() + t = self.load_image("textures/blocks/stem_straight.png").copy() img = Image.new("RGBA", (16,16), self.bgcolor) alpha_over(img, t, (0, int(16 - 16*((data + 1)/8.))), t) img = self.build_sprite(t) @@ -3291,7 +3270,7 @@ def vines(self, blockid, data): data = (data - 16) | 1 # decode data and prepare textures - raw_texture = self.terrain_images[143] + raw_texture = self.load_image("textures/blocks/vine.png") s = w = n = e = None if data & 1: # south @@ -3336,7 +3315,7 @@ def fence_gate(self, blockid, data): data = data | 0x4 # create the closed gate side - gate_side = self.terrain_images[4].copy() + gate_side = self.load_image("textures/blocks/wood.png").copy() gate_side_draw = ImageDraw.Draw(gate_side) gate_side_draw.rectangle((7,0,15,0),outline=(0,0,0,0),fill=(0,0,0,0)) gate_side_draw.rectangle((7,4,9,6),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -3393,7 +3372,7 @@ def fence_gate(self, blockid, data): return img # mycelium -block(blockid=110, top_index=78, side_index=77) +block(blockid=110, top_image="textures/blocks/mycel_top.png", side_image="textures/blocks/mycel_side.png") # lilypad # At the moment of writing this lilypads has no ancil data and their @@ -3402,21 +3381,21 @@ block(blockid=110, top_index=78, side_index=77) # with ancil data. @material(blockid=111, data=range(4), transparent=True) def lilypad(self, blockid, data): - t = self.terrain_images[76] + t = self.load_image("textures/blocks/waterlily.png") return self.build_full_block(None, None, None, None, None, t) # nether brick -block(blockid=112, top_index=224, side_index=224) +block(blockid=112, top_image="textures/blocks/netherBrick.png") # nether wart @material(blockid=115, data=range(4), transparent=True) def nether_wart(self, blockid, data): if data == 0: # just come up - t = self.terrain_images[226] + t = self.load_image("textures/blocks/netherStalk_0.png") elif data in (1, 2): - t = self.terrain_images[227] + t = self.load_image("textures/blocks/netherStalk_1.png") else: # fully grown - t = self.terrain_images[228] + t = self.load_image("textures/blocks/netherStalk_2.png") # use the same technic as tall grass img = self.build_billboard(t) @@ -3428,8 +3407,8 @@ def nether_wart(self, blockid, data): @material(blockid=116, transparent=True, nodata=True) def enchantment_table(self, blockid, data): # no book at the moment - top = self.terrain_images[166] - side = self.terrain_images[182] + top = self.load_image("textures/blocks/enchantment_top.png") + side = self.load_image("textures/blocks/enchantment_side.png") img = self.build_full_block((top, 4), None, None, side, side) return img @@ -3438,9 +3417,9 @@ def enchantment_table(self, blockid, data): # TODO this is a place holder, is a 2d image pasted @material(blockid=117, data=range(5), transparent=True) def brewing_stand(self, blockid, data): - base = self.terrain_images[156] + base = self.load_image("textures/blocks/brewingStand_base.png") img = self.build_full_block(None, None, None, None, None, base) - t = self.terrain_images[157] + t = self.load_image("textures/blocks/brewingStand.png") stand = self.build_billboard(t) alpha_over(img,stand,(0,-2)) return img @@ -3448,9 +3427,9 @@ def brewing_stand(self, blockid, data): # cauldron @material(blockid=118, data=range(4), transparent=True) def cauldron(self, blockid, data): - side = self.terrain_images[154] - top = self.terrain_images[138] - bottom = self.terrain_images[139] + side = self.load_image("textures/blocks/cauldron_side.png") + top = self.load_image("textures/blocks/cauldron_top.png") + bottom = self.load_image("textures/blocks/cauldron_inner.png") water = self.transform_image_top(self.load_water()) if data == 0: # empty img = self.build_full_block(top, side, side, side, side) @@ -3494,14 +3473,14 @@ def end_portal(self, blockid, data): def end_portal_frame(self, blockid, data): # The bottom 2 bits are oritation info but seems there is no # graphical difference between orientations - top = self.terrain_images[158] - eye_t = self.terrain_images[174] - side = self.terrain_images[159] + top = self.load_image("textures/blocks/endframe_top.png") + eye_t = self.load_image("textures/blocks/endframe_eye.png") + side = self.load_image("textures/blocks/endframe_side.png") img = self.build_full_block((top, 4), None, None, side, side) if data & 0x4 == 0x4: # ender eye on it # generate the eye - eye_t = self.terrain_images[174].copy() - eye_t_s = self.terrain_images[174].copy() + eye_t = self.load_image("textures/blocks/endframe_eye.png").copy() + eye_t_s = self.load_image("textures/blocks/endframe_eye.png").copy() # cut out from the texture the side and the top of the eye ImageDraw.Draw(eye_t).rectangle((0,0,15,4),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(eye_t_s).rectangle((0,4,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -3516,17 +3495,17 @@ def end_portal_frame(self, blockid, data): return img # end stone -block(blockid=121, top_index=175) +block(blockid=121, top_image="textures/blocks/whiteStone.png") # dragon egg # NOTE: this isn't a block, but I think it's better than nothing -block(blockid=122, top_index=37) +block(blockid=122, top_image="textures/blocks/dragonEgg.png") # inactive redstone lamp -block(blockid=123, top_index=211) +block(blockid=123, top_image="textures/blocks/redstoneLight.png") # active redstone lamp -block(blockid=124, top_index=212) +block(blockid=124, top_image="textures/blocks/redstoneLight_lit.png") # wooden double and normal slabs # these are the new wooden slabs, blockids 43 44 still have wooden @@ -3535,13 +3514,13 @@ block(blockid=124, top_index=212) def wooden_slabs(self, blockid, data): texture = data & 7 if texture== 0: # oak - top = side = self.terrain_images[4] + top = side = self.load_image("textures/blocks/wood.png") elif texture== 1: # spruce - top = side = self.terrain_images[198] + top = side = self.load_image("textures/blocks/wood_spruce.png") elif texture== 2: # birch - top = side = self.terrain_images[214] + top = side = self.load_image("textures/blocks/wood_birch.png") elif texture== 3: # jungle - top = side = self.terrain_images[199] + top = side = self.load_image("textures/blocks/wood_jungle.png") else: return None @@ -3578,16 +3557,16 @@ def wooden_slabs(self, blockid, data): return img # emerald ore -block(blockid=129, top_index=171) +block(blockid=129, top_image="textures/blocks/oreEmerald.png") # emerald block -block(blockid=133, top_index=25) +block(blockid=133, top_image="textures/blocks/blockEmerald.png") # nether quartz ore -block(blockid=153, top_index=191) +block(blockid=153, top_image="textures/blocks/netherquartz.png") # block of redstone -block(blockid=152, top_index=26) +block(blockid=152, top_image="textures/blocks/blockRedstone.png") # cocoa plant @material(blockid=127, data=range(12), transparent=True) @@ -3612,17 +3591,17 @@ def cocoa_plant(self, blockid, data): size = data & 12 if size == 8: # big - t = self.terrain_images[168] + t = self.load_image("textures/blocks/cocoa_2.png") c_left = (0,3) c_right = (8,3) c_top = (5,2) elif size == 4: # normal - t = self.terrain_images[169] + t = self.load_image("textures/blocks/cocoa_1.png") c_left = (-2,2) c_right = (8,2) c_top = (5,2) elif size == 0: # small - t = self.terrain_images[170] + t = self.load_image("textures/blocks/cocoa_0.png") c_left = (-3,2) c_right = (6,2) c_top = (5,2) @@ -3671,7 +3650,7 @@ def cocoa_plant(self, blockid, data): return img # command block -block(blockid=137, top_index=184) +block(blockid=137, top_image="textures/blocks/commandBlock.png") # beacon block # at the moment of writing this, it seems the beacon block doens't use @@ -3679,12 +3658,12 @@ block(blockid=137, top_index=184) @material(blockid=138, transparent=True, nodata = True) def beacon(self, blockid, data): # generate the three pieces of the block - t = self.terrain_images[49] + t = self.load_image("textures/blocks/glass.png") glass = self.build_block(t,t) - t = self.terrain_images[37] + t = self.load_image("textures/blocks/obsidian.png") obsidian = self.build_full_block((t,12),None, None, t, t) obsidian = obsidian.resize((20,20), Image.ANTIALIAS) - t = self.terrain_images[41] + t = self.load_image("textures/blocks/beacon.png") crystal = self.build_block(t,t) crystal = crystal.resize((16,16),Image.ANTIALIAS) @@ -3703,10 +3682,10 @@ def cobblestone_wall(self, blockid, data): # no rotation, uses pseudo data if data & 0b10000 == 0: # cobblestone - t = self.terrain_images[16].copy() + t = self.load_image("textures/blocks/stonebrick.png").copy() else: # mossy cobblestone - t = self.terrain_images[36].copy() + t = self.load_image("textures/blocks/stoneMoss.png").copy() wall_pole_top = t.copy() wall_pole_side = t.copy() @@ -3831,11 +3810,11 @@ def crops(self, blockid, data): if data != 7: # when growing they look the same # data = 7 -> fully grown, everything else is growing # this seems to work, but still not sure - raw_crop = self.terrain_images[200 + (data % 3)] + raw_crop = self.load_image("textures/blocks/potatoes_%d.png" % (data % 3)) elif blockid == 141: # carrots - raw_crop = self.terrain_images[203] + raw_crop = self.load_image("textures/blocks/carrots_3.png") else: # potatoes - raw_crop = self.terrain_images[204] + raw_crop = self.load_image("textures/blocks/potatoes_3.png") crop1 = self.transform_image_top(raw_crop) crop2 = self.transform_image_side(raw_crop) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) @@ -3861,16 +3840,16 @@ def anvil(self, blockid, data): # get the correct textures # the bits 0x4 and 0x8 determine how damaged is the anvil if (data & 0xc) == 0: # non damaged anvil - top = self.terrain_images[231] + top = self.load_image("textures/blocks/anvil_top.png") elif (data & 0xc) == 0x4: # slightly damaged - top = self.terrain_images[232] + top = self.load_image("textures/blocks/anvil_top_damaged_1.png") elif (data & 0xc) == 0x8: # very damaged - top = self.terrain_images[216] + top = self.load_image("textures/blocks/anvil_top_damaged_2.png") # everything else use this texture - big_side = self.terrain_images[215].copy() - small_side = self.terrain_images[215].copy() - base = self.terrain_images[215].copy() - small_base = self.terrain_images[215].copy() + big_side = self.load_image("textures/blocks/anvil_base.png").copy() + small_side = self.load_image("textures/blocks/anvil_base.png").copy() + base = self.load_image("textures/blocks/anvil_base.png").copy() + small_base = self.load_image("textures/blocks/anvil_base.png").copy() # cut needed patterns ImageDraw.Draw(big_side).rectangle((0,8,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) From 6ece185b1f96b10309e341f63e1219c113ecea5d Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sat, 12 Jan 2013 13:44:04 -0500 Subject: [PATCH 04/18] Handle HD textures and animated textures --- overviewer_core/textures.py | 410 +++++++++++++++++++----------------- 1 file changed, 212 insertions(+), 198 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 6e8848a..9e8e964 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -54,7 +54,7 @@ class Textures(object): # this is set in in generate() self.generated = False - # see load_image() + # see load_image_texture() self.texture_cache = {} ## @@ -85,7 +85,7 @@ class Textures(object): def generate(self): # generate biome grass mask - self.biome_grass_texture = self.build_block(self.load_image("textures/blocks/grass_top.png"), self.load_image("textures/blocks/grass_side_overlay.png")) + self.biome_grass_texture = self.build_block(self.load_image_texture("textures/blocks/grass_top.png"), self.load_image_texture("textures/blocks/grass_side_overlay.png")) # generate the blocks global blockmap_generators @@ -222,16 +222,30 @@ class Textures(object): raise TextureException("Could not find the file `{0}'. Try specifying the 'texturepath' option in your config file. Set it to the directory where I can find {0}. Also see ".format(filename)) + def load_image_texture(self, filename): + # Textures may be animated or in a different resolution than 16x16. + # This method will always return a 16x16 image + if filename in self.texture_cache: + return self.texture_cache[filename] + + img = self.load_image(filename) + + w,h = img.size + if w != h: + img = img.crop((0,0,w,w)) + if w != 16: + img = img.resize((16, 16), Image.ANTIALIAS) + + self.texture_cache[filename] = img + return img + def load_image(self, filename): """Returns an image object""" - if filename in self.texture_cache: - return self.texture_cache[filename] fileobj = self.find_file(filename) buffer = StringIO(fileobj.read()) img = Image.open(buffer).convert("RGBA") - self.texture_cache[filename] = img return img @@ -723,7 +737,7 @@ def block(blockid=[], top_image=None, side_image=None, **kwargs): @material(blockid=blockid, **new_kwargs) def inner_block(self, unused_id, unused_data): - return self.build_block(self.load_image(top_image), self.load_image(side_image)) + return self.build_block(self.load_image_texture(top_image), self.load_image_texture(side_image)) return inner_block # shortcut function for sprite blocks, defaults to transparent, nodata @@ -736,7 +750,7 @@ def sprite(blockid=[], imagename=None, **kwargs): @material(blockid=blockid, **new_kwargs) def inner_sprite(self, unused_id, unused_data): - return self.build_sprite(self.load_image(imagename)) + return self.build_sprite(self.load_image_texture(imagename)) return inner_sprite # shortcut function for billboard blocks, defaults to transparent, nodata @@ -749,7 +763,7 @@ def billboard(blockid=[], imagename=None, **kwargs): @material(blockid=blockid, **new_kwargs) def inner_billboard(self, unused_id, unused_data): - return self.build_billboard(self.load_image(imagename)) + return self.build_billboard(self.load_image_texture(imagename)) return inner_billboard ## @@ -762,10 +776,10 @@ block(blockid=1, top_image="textures/blocks/stone.png") @material(blockid=2, data=range(11)+[0x10,], solid=True) def grass(self, blockid, data): # 0x10 bit means SNOW - side_img = self.load_image("textures/blocks/grass_side.png") + side_img = self.load_image_texture("textures/blocks/grass_side.png") if data & 0x10: - side_img = self.load_image("textures/blocks/snow_side.png") - img = self.build_block(self.load_image("textures/blocks/grass_top.png"), side_img) + side_img = self.load_image_texture("textures/blocks/snow_side.png") + img = self.build_block(self.load_image_texture("textures/blocks/grass_top.png"), side_img) if not data & 0x10: alpha_over(img, self.biome_grass_texture, (0, 0), self.biome_grass_texture) return img @@ -779,25 +793,25 @@ block(blockid=4, top_image="textures/blocks/stonebrick.png") @material(blockid=5, data=range(4), solid=True) def wooden_planks(self, blockid, data): if data == 0: # normal - return self.build_block(self.load_image("textures/blocks/wood.png"), self.load_image("textures/blocks/wood.png")) + return self.build_block(self.load_image_texture("textures/blocks/wood.png"), self.load_image_texture("textures/blocks/wood.png")) if data == 1: # pine - return self.build_block(self.load_image("textures/blocks/wood_spruce.png"),self.load_image("textures/blocks/wood_spruce.png")) + return self.build_block(self.load_image_texture("textures/blocks/wood_spruce.png"),self.load_image_texture("textures/blocks/wood_spruce.png")) if data == 2: # birch - return self.build_block(self.load_image("textures/blocks/wood_birch.png"),self.load_image("textures/blocks/wood_birch.png")) + return self.build_block(self.load_image_texture("textures/blocks/wood_birch.png"),self.load_image_texture("textures/blocks/wood_birch.png")) if data == 3: # jungle wood - return self.build_block(self.load_image("textures/blocks/wood_jungle.png"),self.load_image("textures/blocks/wood_jungle.png")) + return self.build_block(self.load_image_texture("textures/blocks/wood_jungle.png"),self.load_image_texture("textures/blocks/wood_jungle.png")) @material(blockid=6, data=range(16), transparent=True) def saplings(self, blockid, data): # usual saplings - tex = self.load_image("textures/blocks/sapling.png") + tex = self.load_image_texture("textures/blocks/sapling.png") if data & 0x3 == 1: # spruce sapling - tex = self.load_image("textures/blocks/sapling_spruce.png") + tex = self.load_image_texture("textures/blocks/sapling_spruce.png") elif data & 0x3 == 2: # birch sapling - tex = self.load_image("textures/blocks/sapling_birch.png") + tex = self.load_image_texture("textures/blocks/sapling_birch.png") elif data & 0x3 == 3: # jungle sapling - tex = self.load_image("textures/blocks/sapling_jungle.png") + tex = self.load_image_texture("textures/blocks/sapling_jungle.png") return self.build_sprite(tex) # bedrock @@ -815,9 +829,9 @@ def no_inner_surfaces(self, blockid, data): if blockid == 9: texture = self.load_water() elif blockid == 20: - texture = self.load_image("textures/blocks/glass.png") + texture = self.load_image_texture("textures/blocks/glass.png") else: - texture = self.load_image("textures/blocks/ice.png") + texture = self.load_image_texture("textures/blocks/ice.png") if (data & 0b10000) == 16: top = texture @@ -880,15 +894,15 @@ def wood(self, blockid, data): elif wood_orientation == 8: wood_orientation = 4 # choose textures - top = self.load_image("textures/blocks/tree_top.png") + top = self.load_image_texture("textures/blocks/tree_top.png") if wood_type == 0: # normal - side = self.load_image("textures/blocks/tree_side.png") + side = self.load_image_texture("textures/blocks/tree_side.png") if wood_type == 1: # spruce - side = self.load_image("textures/blocks/tree_spruce.png") + side = self.load_image_texture("textures/blocks/tree_spruce.png") if wood_type == 2: # birch - side = self.load_image("textures/blocks/tree_birch.png") + side = self.load_image_texture("textures/blocks/tree_birch.png") if wood_type == 3: # jungle wood - side = self.load_image("textures/blocks/tree_jungle.png") + side = self.load_image_texture("textures/blocks/tree_jungle.png") # choose orientation and paste textures if wood_orientation == 0: @@ -903,13 +917,13 @@ def leaves(self, blockid, data): # mask out the bits 4 and 8 # they are used for player placed and check-for-decay blocks data = data & 0x3 - t = self.load_image("textures/blocks/leaves.png") + t = self.load_image_texture("textures/blocks/leaves.png") if data == 1: # pine! - t = self.load_image("textures/blocks/leaves_spruce.png") + t = self.load_image_texture("textures/blocks/leaves_spruce.png") elif data == 3: # jungle tree - t = self.load_image("textures/blocks/leaves_jungle.png") + t = self.load_image_texture("textures/blocks/leaves_jungle.png") return self.build_block(t, t) # sponge @@ -939,15 +953,15 @@ def furnaces(self, blockid, data): elif data == 4: data = 3 elif data == 5: data = 2 - top = self.load_image("textures/blocks/furnace_top.png") - side = self.load_image("textures/blocks/furnace_side.png") + top = self.load_image_texture("textures/blocks/furnace_top.png") + side = self.load_image_texture("textures/blocks/furnace_side.png") if blockid == 61: - front = self.load_image("textures/blocks/furnace_front.png") + front = self.load_image_texture("textures/blocks/furnace_front.png") elif blockid == 62: - front = self.load_image("textures/blocks/furnace_front_lit.png") + front = self.load_image_texture("textures/blocks/furnace_front_lit.png") elif blockid == 23: - front = self.load_image("textures/blocks/dispenser_front.png") + front = self.load_image_texture("textures/blocks/dispenser_front.png") if data == 3: # pointing west return self.build_full_block(top, None, None, side, front) @@ -959,13 +973,13 @@ def furnaces(self, blockid, data): # sandstone @material(blockid=24, data=range(3), solid=True) def sandstone(self, blockid, data): - top = self.load_image("textures/blocks/sandstone_top.png") + top = self.load_image_texture("textures/blocks/sandstone_top.png") if data == 0: # normal - return self.build_block(top, self.load_image("textures/blocks/sandstone_side.png")) + return self.build_block(top, self.load_image_texture("textures/blocks/sandstone_side.png")) if data == 1: # hieroglyphic - return self.build_block(top, self.load_image("textures/blocks/sandstone_carved.png")) + return self.build_block(top, self.load_image_texture("textures/blocks/sandstone_carved.png")) if data == 2: # soft - return self.build_block(top, self.load_image("textures/blocks/sandstone_smooth.png")) + return self.build_block(top, self.load_image_texture("textures/blocks/sandstone_smooth.png")) # note block block(blockid=25, top_image="textures/blocks/musicBlock.png") @@ -994,40 +1008,40 @@ def bed(self, blockid, data): left_face = None right_face = None if data & 0x8 == 0x8: # head of the bed - top = self.load_image("textures/blocks/bed_head_top.png") + top = self.load_image_texture("textures/blocks/bed_head_top.png") if data & 0x00 == 0x00: # head pointing to West top = top.copy().rotate(270) - left_face = self.load_image("textures/blocks/bed_head_side.png") - right_face = self.load_image("textures/blocks/bed_head_end.png") + left_face = self.load_image_texture("textures/blocks/bed_head_side.png") + right_face = self.load_image_texture("textures/blocks/bed_head_end.png") if data & 0x01 == 0x01: # ... North top = top.rotate(270) - left_face = self.load_image("textures/blocks/bed_head_end.png") - right_face = self.load_image("textures/blocks/bed_head_side.png") + left_face = self.load_image_texture("textures/blocks/bed_head_end.png") + right_face = self.load_image_texture("textures/blocks/bed_head_side.png") if data & 0x02 == 0x02: # East top = top.rotate(180) - left_face = self.load_image("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image_texture("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) right_face = None if data & 0x03 == 0x03: # South right_face = None - right_face = self.load_image("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) + right_face = self.load_image_texture("textures/blocks/bed_head_side.png").transpose(Image.FLIP_LEFT_RIGHT) else: # foot of the bed - top = self.load_image("textures/blocks/bed_feet_top.png") + top = self.load_image_texture("textures/blocks/bed_feet_top.png") if data & 0x00 == 0x00: # head pointing to West top = top.rotate(270) - left_face = self.load_image("textures/blocks/bed_feet_side.png") + left_face = self.load_image_texture("textures/blocks/bed_feet_side.png") right_face = None if data & 0x01 == 0x01: # ... North top = top.rotate(270) left_face = None - right_face = self.load_image("textures/blocks/bed_feet_side.png") + right_face = self.load_image_texture("textures/blocks/bed_feet_side.png") if data & 0x02 == 0x02: # East top = top.rotate(180) - left_face = self.load_image("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) - right_face = self.load_image("textures/blocks/bed_feet_end.png").transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image_texture("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) + right_face = self.load_image_texture("textures/blocks/bed_feet_end.png").transpose(Image.FLIP_LEFT_RIGHT) if data & 0x03 == 0x03: # South - left_face = self.load_image("textures/blocks/bed_feet_end.png") - right_face = self.load_image("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) + left_face = self.load_image_texture("textures/blocks/bed_feet_end.png") + right_face = self.load_image_texture("textures/blocks/bed_feet_side.png").transpose(Image.FLIP_LEFT_RIGHT) top = (top, increment) return self.build_full_block(top, None, None, left_face, right_face) @@ -1078,22 +1092,22 @@ def rails(self, blockid, data): if blockid == 27: # powered rail if data & 0x8 == 0: # unpowered - raw_straight = self.load_image("textures/blocks/goldenRail.png") - raw_corner = self.load_image("textures/blocks/rail_turn.png") # they don't exist but make the code + raw_straight = self.load_image_texture("textures/blocks/goldenRail.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") # they don't exist but make the code # much simplier elif data & 0x8 == 0x8: # powered - raw_straight = self.load_image("textures/blocks/goldenRail_powered.png") - raw_corner = self.load_image("textures/blocks/rail_turn.png") # leave corners for code simplicity + raw_straight = self.load_image_texture("textures/blocks/goldenRail_powered.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") # leave corners for code simplicity # filter the 'powered' bit data = data & 0x7 elif blockid == 28: # detector rail - raw_straight = self.load_image("textures/blocks/detectorRail.png") - raw_corner = self.load_image("textures/blocks/rail_turn.png") # leave corners for code simplicity + raw_straight = self.load_image_texture("textures/blocks/detectorRail.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") # leave corners for code simplicity elif blockid == 66: # normal rail - raw_straight = self.load_image("textures/blocks/rail.png") - raw_corner = self.load_image("textures/blocks/rail_turn.png") + raw_straight = self.load_image_texture("textures/blocks/rail.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") ## use transform_image to scale and shear if data == 0: @@ -1161,14 +1175,14 @@ def piston(self, blockid, data): elif (data & 0b0111) == 5: data = data & 0b1000 | 2 if blockid == 29: # sticky - piston_t = self.load_image("textures/blocks/piston_top_sticky.png").copy() + piston_t = self.load_image_texture("textures/blocks/piston_top_sticky.png").copy() else: # normal - piston_t = self.load_image("textures/blocks/piston_top.png").copy() + piston_t = self.load_image_texture("textures/blocks/piston_top.png").copy() # other textures - side_t = self.load_image("textures/blocks/piston_side.png").copy() - back_t = self.load_image("textures/blocks/piston_bottom.png").copy() - interior_t = self.load_image("textures/blocks/piston_inner_top.png").copy() + side_t = self.load_image_texture("textures/blocks/piston_side.png").copy() + back_t = self.load_image_texture("textures/blocks/piston_bottom.png").copy() + interior_t = self.load_image_texture("textures/blocks/piston_inner_top.png").copy() if data & 0x08 == 0x08: # pushed out, non full blocks, tricky stuff # remove piston texture from piston body @@ -1237,13 +1251,13 @@ def piston_extension(self, blockid, data): elif (data & 0b0111) == 5: data = data & 0b1000 | 2 if (data & 0x8) == 0x8: # sticky - piston_t = self.load_image("textures/blocks/piston_top_sticky.png").copy() + piston_t = self.load_image_texture("textures/blocks/piston_top_sticky.png").copy() else: # normal - piston_t = self.load_image("textures/blocks/piston_top.png").copy() + piston_t = self.load_image_texture("textures/blocks/piston_top.png").copy() # other textures - side_t = self.load_image("textures/blocks/piston_side.png").copy() - back_t = self.load_image("textures/blocks/piston_top.png").copy() + side_t = self.load_image_texture("textures/blocks/piston_side.png").copy() + back_t = self.load_image_texture("textures/blocks/piston_top.png").copy() # crop piston body ImageDraw.Draw(side_t).rectangle((0, 4,16,16),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1308,11 +1322,11 @@ sprite(blockid=30, imagename="textures/blocks/web.png", nospawn=True) @material(blockid=31, data=range(3), transparent=True) def tall_grass(self, blockid, data): if data == 0: # dead shrub - texture = self.load_image("textures/blocks/deadbush.png") + texture = self.load_image_texture("textures/blocks/deadbush.png") elif data == 1: # tall grass - texture = self.load_image("textures/blocks/tallgrass.png") + texture = self.load_image_texture("textures/blocks/tallgrass.png") elif data == 2: # fern - texture = self.load_image("textures/blocks/fern.png") + texture = self.load_image_texture("textures/blocks/fern.png") return self.build_billboard(texture) @@ -1321,7 +1335,7 @@ billboard(blockid=32, imagename="textures/blocks/deadbush.png") @material(blockid=35, data=range(16), solid=True) def wool(self, blockid, data): - texture = self.load_image("textures/blocks/cloth_%d.png" % data) + texture = self.load_image_texture("textures/blocks/cloth_%d.png" % data) return self.build_block(texture, texture) @@ -1345,21 +1359,21 @@ block(blockid=42, top_image="textures/blocks/blockIron.png") def slabs(self, blockid, data): texture = data & 7 if texture== 0: # stone slab - top = self.load_image("textures/blocks/stoneslab_top.png") - side = self.load_image("textures/blocks/stoneslab_side.png") + top = self.load_image_texture("textures/blocks/stoneslab_top.png") + side = self.load_image_texture("textures/blocks/stoneslab_side.png") elif texture== 1: # smooth stone - top = self.load_image("textures/blocks/sandstone_top.png") - side = self.load_image("textures/blocks/sandstone_side.png") + top = self.load_image_texture("textures/blocks/sandstone_top.png") + side = self.load_image_texture("textures/blocks/sandstone_side.png") elif texture== 2: # wooden slab - top = side = self.load_image("textures/blocks/wood.png") + top = side = self.load_image_texture("textures/blocks/wood.png") elif texture== 3: # cobblestone slab - top = side = self.load_image("textures/blocks/stonebrick.png") + top = side = self.load_image_texture("textures/blocks/stonebrick.png") elif texture== 4: # brick - top = side = self.load_image("textures/blocks/brick.png") + top = side = self.load_image_texture("textures/blocks/brick.png") elif texture== 5: # stone brick - top = side = self.load_image("textures/blocks/stonebricksmooth.png") + top = side = self.load_image_texture("textures/blocks/stonebricksmooth.png") elif texture== 6: # nether brick slab - top = side = self.load_image("textures/blocks/netherBrick.png") + top = side = self.load_image_texture("textures/blocks/netherBrick.png") else: return None @@ -1428,11 +1442,11 @@ def torches(self, blockid, data): # choose the proper texture if blockid == 50: # torch - small = self.load_image("textures/blocks/torch.png") + small = self.load_image_texture("textures/blocks/torch.png") elif blockid == 75: # off redstone torch - small = self.load_image("textures/blocks/redtorch.png") + small = self.load_image_texture("textures/blocks/redtorch.png") else: # on redstone torch - small = self.load_image("textures/blocks/redtorch_lit.png") + small = self.load_image_texture("textures/blocks/redtorch_lit.png") # compose a torch bigger than the normal # (better for doing transformations) @@ -1522,23 +1536,23 @@ def stairs(self, blockid, data): data = data | upside_down if blockid == 53: # wooden - texture = self.load_image("textures/blocks/wood.png") + texture = self.load_image_texture("textures/blocks/wood.png") elif blockid == 67: # cobblestone - texture = self.load_image("textures/blocks/stonebrick.png") + texture = self.load_image_texture("textures/blocks/stonebrick.png") elif blockid == 108: # red brick stairs - texture = self.load_image("textures/blocks/brick.png") + texture = self.load_image_texture("textures/blocks/brick.png") elif blockid == 109: # stone brick stairs - texture = self.load_image("textures/blocks/stonebricksmooth.png") + texture = self.load_image_texture("textures/blocks/stonebricksmooth.png") elif blockid == 114: # netherbrick stairs - texture = self.load_image("textures/blocks/netherBrick.png") + texture = self.load_image_texture("textures/blocks/netherBrick.png") elif blockid == 128: # sandstone stairs - texture = self.load_image("textures/blocks/sandstone_side.png") + texture = self.load_image_texture("textures/blocks/sandstone_side.png") elif blockid == 134: # spruce wood stairs - texture = self.load_image("textures/blocks/wood_spruce.png") + texture = self.load_image_texture("textures/blocks/wood_spruce.png") elif blockid == 135: # birch wood stairs - texture = self.load_image("textures/blocks/wood_birch.png") + texture = self.load_image_texture("textures/blocks/wood_birch.png") elif blockid == 136: # jungle good stairs - texture = self.load_image("textures/blocks/wood_jungle.png") + texture = self.load_image_texture("textures/blocks/wood_jungle.png") side = texture.copy() @@ -1549,9 +1563,9 @@ def stairs(self, blockid, data): # sandstone stairs have spcial top texture if blockid == 128: - half_block_u = self.load_image("textures/blocks/sandstone_top.png").copy() - half_block_d = self.load_image("textures/blocks/sandstone_top.png").copy() - texture = self.load_image("textures/blocks/sandstone_top.png").copy() + half_block_u = self.load_image_texture("textures/blocks/sandstone_top.png").copy() + half_block_d = self.load_image_texture("textures/blocks/sandstone_top.png").copy() + texture = self.load_image_texture("textures/blocks/sandstone_top.png").copy() # generate needed geometries ImageDraw.Draw(side).rectangle((0,0,7,6),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1828,18 +1842,18 @@ def chests(self, blockid, data): def wire(self, blockid, data): if data & 0b1000000 == 64: # powered redstone wire - redstone_wire_t = self.load_image("textures/blocks/redstoneDust_line.png") + redstone_wire_t = self.load_image_texture("textures/blocks/redstoneDust_line.png") redstone_wire_t = self.tint_texture(redstone_wire_t,(255,0,0)) - redstone_cross_t = self.load_image("textures/blocks/redstoneDust_cross.png") + redstone_cross_t = self.load_image_texture("textures/blocks/redstoneDust_cross.png") redstone_cross_t = self.tint_texture(redstone_cross_t,(255,0,0)) else: # unpowered redstone wire - redstone_wire_t = self.load_image("textures/blocks/redstoneDust_line.png") + redstone_wire_t = self.load_image_texture("textures/blocks/redstoneDust_line.png") redstone_wire_t = self.tint_texture(redstone_wire_t,(48,0,0)) - redstone_cross_t = self.load_image("textures/blocks/redstoneDust_cross.png") + redstone_cross_t = self.load_image_texture("textures/blocks/redstoneDust_cross.png") redstone_cross_t = self.tint_texture(redstone_cross_t,(48,0,0)) # generate an image per redstone direction @@ -1911,9 +1925,9 @@ block(blockid=57, top_image="textures/blocks/blockDiamond.png") # needs two different sides @material(blockid=58, solid=True, nodata=True) def crafting_table(self, blockid, data): - top = self.load_image("textures/blocks/workbench_top.png") - side3 = self.load_image("textures/blocks/workbench_side.png") - side4 = self.load_image("textures/blocks/workbench_front.png") + top = self.load_image_texture("textures/blocks/workbench_top.png") + side3 = self.load_image_texture("textures/blocks/workbench_side.png") + side4 = self.load_image_texture("textures/blocks/workbench_front.png") img = self.build_full_block(top, None, None, side3, side4, None) return img @@ -1921,7 +1935,7 @@ def crafting_table(self, blockid, data): # crops @material(blockid=59, data=range(8), transparent=True, nospawn=True) def crops(self, blockid, data): - raw_crop = self.load_image("textures/blocks/crops_%d.png" % data) + raw_crop = self.load_image_texture("textures/blocks/crops_%d.png" % data) crop1 = self.transform_image_top(raw_crop) crop2 = self.transform_image_side(raw_crop) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) @@ -1935,10 +1949,10 @@ def crops(self, blockid, data): # farmland @material(blockid=60, data=range(9), solid=True) def farmland(self, blockid, data): - top = self.load_image("textures/blocks/farmland_wet.png") + top = self.load_image_texture("textures/blocks/farmland_wet.png") if data == 0: - top = self.load_image("textures/blocks/farmland_dry.png") - return self.build_block(top, self.load_image("textures/blocks/dirt.png")) + top = self.load_image_texture("textures/blocks/farmland_dry.png") + return self.build_block(top, self.load_image_texture("textures/blocks/dirt.png")) # signposts @material(blockid=63, data=range(16), transparent=True) @@ -1952,7 +1966,7 @@ def signpost(self, blockid, data): elif self.rotation == 3: data = (data + 12) % 16 - texture = self.load_image("textures/blocks/wood.png").copy() + texture = self.load_image_texture("textures/blocks/wood.png").copy() # cut the planks to the size of a signpost ImageDraw.Draw(texture).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1965,7 +1979,7 @@ def signpost(self, blockid, data): texture.putpixel((x,y),(0,0,0,255)) # Minecraft uses wood texture for the signpost stick - texture_stick = self.load_image("textures/blocks/tree_side.png") + texture_stick = self.load_image_texture("textures/blocks/tree_side.png") texture_stick = texture_stick.resize((12,12), Image.ANTIALIAS) ImageDraw.Draw(texture_stick).rectangle((2,0,12,12),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2015,9 +2029,9 @@ def door(self, blockid, data): elif (data & 0b00011) == 3: data = data & 0b11100 | 2 if data & 0x8 == 0x8: # top of the door - raw_door = self.load_image("textures/blocks/%s.png" % ("doorWood_upper" if blockid == 64 else "doorIron_upper")) + raw_door = self.load_image_texture("textures/blocks/%s.png" % ("doorWood_upper" if blockid == 64 else "doorIron_upper")) else: # bottom of the door - raw_door = self.load_image("textures/blocks/%s.png" % ("doorWood_lower" if blockid == 64 else "doorIron_lower")) + raw_door = self.load_image_texture("textures/blocks/%s.png" % ("doorWood_lower" if blockid == 64 else "doorIron_lower")) # if you want to render all doors as closed, then force # force closed to be True @@ -2137,7 +2151,7 @@ def ladder(self, blockid, data): elif data == 5: data = 2 img = Image.new("RGBA", (24,24), self.bgcolor) - raw_texture = self.load_image("textures/blocks/ladder.png") + raw_texture = self.load_image_texture("textures/blocks/ladder.png") if data == 5: # normally this ladder would be obsured by the block it's attached to @@ -2181,7 +2195,7 @@ def wall_sign(self, blockid, data): # wall sign elif data == 4: data = 3 elif data == 5: data = 2 - texture = self.load_image("textures/blocks/wood.png").copy() + texture = self.load_image_texture("textures/blocks/wood.png").copy() # cut the planks to the size of a signpost ImageDraw.Draw(texture).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2251,7 +2265,7 @@ def levers(self, blockid, data): elif data == 6: data = 5 # generate the texture for the base of the lever - t_base = self.load_image("textures/blocks/stonebrick.png").copy() + t_base = self.load_image_texture("textures/blocks/stonebrick.png").copy() ImageDraw.Draw(t_base).rectangle((0,0,15,3),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(t_base).rectangle((0,12,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2259,7 +2273,7 @@ def levers(self, blockid, data): ImageDraw.Draw(t_base).rectangle((11,0,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) # generate the texture for the stick - stick = self.load_image("textures/blocks/lever.png").copy() + stick = self.load_image_texture("textures/blocks/lever.png").copy() c_stick = Image.new("RGBA", (16,16), self.bgcolor) tmp = ImageEnhance.Brightness(stick).enhance(0.8) @@ -2364,9 +2378,9 @@ def levers(self, blockid, data): @material(blockid=[70, 72], data=[0,1], transparent=True) def pressure_plate(self, blockid, data): if blockid == 70: # stone - t = self.load_image("textures/blocks/stone.png").copy() + t = self.load_image_texture("textures/blocks/stone.png").copy() else: # wooden - t = self.load_image("textures/blocks/wood.png").copy() + t = self.load_image_texture("textures/blocks/wood.png").copy() # cut out the outside border, pressure plates are smaller # than a normal block @@ -2419,9 +2433,9 @@ def buttons(self, blockid, data): elif data == 4: data = 2 if blockid == 77: - t = self.load_image("textures/blocks/stone.png").copy() + t = self.load_image_texture("textures/blocks/stone.png").copy() else: - t = self.load_image("textures/blocks/wood.png").copy() + t = self.load_image_texture("textures/blocks/wood.png").copy() # generate the texture for the button ImageDraw.Draw(t).rectangle((0,0,15,5),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2471,7 +2485,7 @@ def buttons(self, blockid, data): def snow(self, blockid, data): # still not rendered correctly: data other than 0 - tex = self.load_image("textures/blocks/snow.png") + tex = self.load_image_texture("textures/blocks/snow.png") # make the side image, top 3/4 transparent mask = tex.crop((0,12,16,16)) @@ -2496,8 +2510,8 @@ block(blockid=80, top_image="textures/blocks/snow.png") # cactus @material(blockid=81, data=range(15), transparent=True, solid=True, nospawn=True) def cactus(self, blockid, data): - top = self.load_image("textures/blocks/cactus_top.png") - side = self.load_image("textures/blocks/cactus_side.png") + top = self.load_image_texture("textures/blocks/cactus_top.png") + side = self.load_image_texture("textures/blocks/cactus_side.png") img = Image.new("RGBA", (24,24), self.bgcolor) @@ -2524,13 +2538,13 @@ block(blockid=82, top_image="textures/blocks/clay.png") # sugar cane @material(blockid=83, data=range(16), transparent=True) def sugar_cane(self, blockid, data): - tex = self.load_image("textures/blocks/reeds.png") + tex = self.load_image_texture("textures/blocks/reeds.png") return self.build_sprite(tex) # jukebox @material(blockid=84, data=range(16), solid=True) def jukebox(self, blockid, data): - return self.build_block(self.load_image("textures/blocks/jukebox_top.png"), self.load_image("textures/blocks/musicBlock.png")) + return self.build_block(self.load_image_texture("textures/blocks/jukebox_top.png"), self.load_image_texture("textures/blocks/musicBlock.png")) # nether and normal fences # uses pseudo-ancildata found in iterate.c @@ -2539,13 +2553,13 @@ def fence(self, blockid, data): # no need for rotations, it uses pseudo data. # create needed images for Big stick fence if blockid == 85: # normal fence - fence_top = self.load_image("textures/blocks/wood.png").copy() - fence_side = self.load_image("textures/blocks/wood.png").copy() - fence_small_side = self.load_image("textures/blocks/wood.png").copy() + fence_top = self.load_image_texture("textures/blocks/wood.png").copy() + fence_side = self.load_image_texture("textures/blocks/wood.png").copy() + fence_small_side = self.load_image_texture("textures/blocks/wood.png").copy() else: # netherbrick fence - fence_top = self.load_image("textures/blocks/netherBrick.png").copy() - fence_side = self.load_image("textures/blocks/netherBrick.png").copy() - fence_small_side = self.load_image("textures/blocks/netherBrick.png").copy() + fence_top = self.load_image_texture("textures/blocks/netherBrick.png").copy() + fence_side = self.load_image_texture("textures/blocks/netherBrick.png").copy() + fence_small_side = self.load_image_texture("textures/blocks/netherBrick.png").copy() # generate the textures of the fence ImageDraw.Draw(fence_top).rectangle((0,0,5,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -2650,10 +2664,10 @@ def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern elif data == 3: data = 2 # texture generation - top = self.load_image("textures/blocks/pumpkin_top.png") + top = self.load_image_texture("textures/blocks/pumpkin_top.png") frontName = "textures/blocks/pumpkin_face.png" if blockid == 86 else "textures/blocks/pumpkin_jack.png" - front = self.load_image(frontName) - side = self.load_image("textures/blocks/pumpkin_side.png") + front = self.load_image_texture(frontName) + side = self.load_image_texture("textures/blocks/pumpkin_side.png") if data == 0: # pointing west img = self.build_full_block(top, None, None, side, front) @@ -2698,10 +2712,10 @@ def portal(self, blockid, data): def cake(self, blockid, data): # cake textures - top = self.load_image("textures/blocks/cake_top.png").copy() - side = self.load_image("textures/blocks/cake_side.png").copy() + top = self.load_image_texture("textures/blocks/cake_top.png").copy() + side = self.load_image_texture("textures/blocks/cake_side.png").copy() fullside = side.copy() - inside = self.load_image("textures/blocks/cake_inner.png") + inside = self.load_image_texture("textures/blocks/cake_inner.png") img = Image.new("RGBA", (24,24), self.bgcolor) if data == 0: # unbitten cake @@ -2839,8 +2853,8 @@ def repeater(self, blockid, data): elif (data & 0b0011) == 3: data = data & 0b1100 | 2 # generate the diode - top = self.load_image("textures/blocks/repeater.png") if blockid == 93 else self.load_image("textures/blocks/repeater_lit.png") - side = self.load_image("textures/blocks/stoneslab_side.png") + top = self.load_image_texture("textures/blocks/repeater.png") if blockid == 93 else self.load_image_texture("textures/blocks/repeater_lit.png") + side = self.load_image_texture("textures/blocks/stoneslab_side.png") increment = 13 if (data & 0x3) == 0: # pointing east @@ -2858,7 +2872,7 @@ def repeater(self, blockid, data): img = self.build_full_block( (top, increment), None, None, side, side) # compose a "3d" redstone torch - t = self.load_image("textures/blocks/redtorch.png").copy() if blockid == 93 else self.load_image("textures/blocks/redtorch_lit.png").copy() + t = self.load_image_texture("textures/blocks/redtorch.png").copy() if blockid == 93 else self.load_image_texture("textures/blocks/redtorch_lit.png").copy() torch = Image.new("RGBA", (24,24), self.bgcolor) t_crop = t.crop((2,2,14,14)) @@ -2971,8 +2985,8 @@ def comparator(self, blockid, data): data = data & 0b1100 | (((data & 0b11) + self.rotation) % 4) - top = self.load_image("textures/blocks/comparator.png") if blockid == 149 else self.load_image("textures/blocks/comparator_lit.png") - side = self.load_image("textures/blocks/stoneslab_side.png") + top = self.load_image_texture("textures/blocks/comparator.png") if blockid == 149 else self.load_image_texture("textures/blocks/comparator_lit.png") + side = self.load_image_texture("textures/blocks/stoneslab_side.png") increment = 13 if (data & 0x3) == 0: # pointing north @@ -2998,7 +3012,7 @@ def comparator(self, blockid, data): def build_torch(active): # compose a "3d" redstone torch - t = self.load_image("textures/blocks/redtorch.png").copy() if not active else self.load_image("textures/blocks/redtorch_lit.png").copy() + t = self.load_image_texture("textures/blocks/redtorch.png").copy() if not active else self.load_image_texture("textures/blocks/redtorch_lit.png").copy() torch = Image.new("RGBA", (24,24), self.bgcolor) t_crop = t.crop((2,2,14,14)) @@ -3050,7 +3064,7 @@ def trapdoor(self, blockid, data): elif (data & 0b0011) == 3: data = data & 0b1100 | 0 # texture generation - texture = self.load_image("textures/blocks/trapdoor.png") + texture = self.load_image_texture("textures/blocks/trapdoor.png") if data & 0x4 == 0x4: # opened trapdoor if data & 0x3 == 0: # west img = self.build_full_block(None, None, None, None, texture) @@ -3075,11 +3089,11 @@ def trapdoor(self, blockid, data): @material(blockid=97, data=range(3), solid=True) def hidden_silverfish(self, blockid, data): if data == 0: # stone - t = self.load_image("textures/blocks/stone.png") + t = self.load_image_texture("textures/blocks/stone.png") elif data == 1: # cobblestone - t = self.load_image("textures/blocks/stonebrick.png") + t = self.load_image_texture("textures/blocks/stonebrick.png") elif data == 2: # stone brick - t = self.load_image("textures/blocks/stonebricksmooth.png") + t = self.load_image_texture("textures/blocks/stonebricksmooth.png") img = self.build_block(t, t) @@ -3089,13 +3103,13 @@ def hidden_silverfish(self, blockid, data): @material(blockid=98, data=range(4), solid=True) def stone_brick(self, blockid, data): if data == 0: # normal - t = self.load_image("textures/blocks/stonebricksmooth.png") + t = self.load_image_texture("textures/blocks/stonebricksmooth.png") elif data == 1: # mossy - t = self.load_image("textures/blocks/stonebricksmooth_mossy.png") + t = self.load_image_texture("textures/blocks/stonebricksmooth_mossy.png") elif data == 2: # cracked - t = self.load_image("textures/blocks/stonebricksmooth_cracked.png") + t = self.load_image_texture("textures/blocks/stonebricksmooth_cracked.png") elif data == 3: # "circle" stone brick - t = self.load_image("textures/blocks/stonebricksmooth_carved.png") + t = self.load_image_texture("textures/blocks/stonebricksmooth_carved.png") img = self.build_full_block(t, None, None, t, t) @@ -3135,12 +3149,12 @@ def huge_mushroom(self, blockid, data): # texture generation if blockid == 99: # brown - cap = self.load_image("textures/blocks/mushroom_skin_brown.png") + cap = self.load_image_texture("textures/blocks/mushroom_skin_brown.png") else: # red - cap = self.load_image("textures/blocks/mushroom_skin_red.png") + cap = self.load_image_texture("textures/blocks/mushroom_skin_red.png") - stem = self.load_image("textures/blocks/mushroom_skin_stem.png") - porous = self.load_image("textures/blocks/mushroom_inside.png") + stem = self.load_image_texture("textures/blocks/mushroom_skin_stem.png") + porous = self.load_image_texture("textures/blocks/mushroom_inside.png") if data == 0: # fleshy piece img = self.build_full_block(porous, None, None, porous, porous) @@ -3185,10 +3199,10 @@ def panes(self, blockid, data): # no rotation, uses pseudo data if blockid == 101: # iron bars - t = self.load_image("textures/blocks/fenceIron.png") + t = self.load_image_texture("textures/blocks/fenceIron.png") else: # glass panes - t = self.load_image("textures/blocks/glass.png") + t = self.load_image_texture("textures/blocks/glass.png") left = t.copy() right = t.copy() @@ -3234,7 +3248,7 @@ def stem(self, blockid, data): # not fully grown stem or no pumpkin/melon touching it, # straight up stem - t = self.load_image("textures/blocks/stem_straight.png").copy() + t = self.load_image_texture("textures/blocks/stem_straight.png").copy() img = Image.new("RGBA", (16,16), self.bgcolor) alpha_over(img, t, (0, int(16 - 16*((data + 1)/8.))), t) img = self.build_sprite(t) @@ -3270,7 +3284,7 @@ def vines(self, blockid, data): data = (data - 16) | 1 # decode data and prepare textures - raw_texture = self.load_image("textures/blocks/vine.png") + raw_texture = self.load_image_texture("textures/blocks/vine.png") s = w = n = e = None if data & 1: # south @@ -3315,7 +3329,7 @@ def fence_gate(self, blockid, data): data = data | 0x4 # create the closed gate side - gate_side = self.load_image("textures/blocks/wood.png").copy() + gate_side = self.load_image_texture("textures/blocks/wood.png").copy() gate_side_draw = ImageDraw.Draw(gate_side) gate_side_draw.rectangle((7,0,15,0),outline=(0,0,0,0),fill=(0,0,0,0)) gate_side_draw.rectangle((7,4,9,6),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -3381,7 +3395,7 @@ block(blockid=110, top_image="textures/blocks/mycel_top.png", side_image="textur # with ancil data. @material(blockid=111, data=range(4), transparent=True) def lilypad(self, blockid, data): - t = self.load_image("textures/blocks/waterlily.png") + t = self.load_image_texture("textures/blocks/waterlily.png") return self.build_full_block(None, None, None, None, None, t) # nether brick @@ -3391,11 +3405,11 @@ block(blockid=112, top_image="textures/blocks/netherBrick.png") @material(blockid=115, data=range(4), transparent=True) def nether_wart(self, blockid, data): if data == 0: # just come up - t = self.load_image("textures/blocks/netherStalk_0.png") + t = self.load_image_texture("textures/blocks/netherStalk_0.png") elif data in (1, 2): - t = self.load_image("textures/blocks/netherStalk_1.png") + t = self.load_image_texture("textures/blocks/netherStalk_1.png") else: # fully grown - t = self.load_image("textures/blocks/netherStalk_2.png") + t = self.load_image_texture("textures/blocks/netherStalk_2.png") # use the same technic as tall grass img = self.build_billboard(t) @@ -3407,8 +3421,8 @@ def nether_wart(self, blockid, data): @material(blockid=116, transparent=True, nodata=True) def enchantment_table(self, blockid, data): # no book at the moment - top = self.load_image("textures/blocks/enchantment_top.png") - side = self.load_image("textures/blocks/enchantment_side.png") + top = self.load_image_texture("textures/blocks/enchantment_top.png") + side = self.load_image_texture("textures/blocks/enchantment_side.png") img = self.build_full_block((top, 4), None, None, side, side) return img @@ -3417,9 +3431,9 @@ def enchantment_table(self, blockid, data): # TODO this is a place holder, is a 2d image pasted @material(blockid=117, data=range(5), transparent=True) def brewing_stand(self, blockid, data): - base = self.load_image("textures/blocks/brewingStand_base.png") + base = self.load_image_texture("textures/blocks/brewingStand_base.png") img = self.build_full_block(None, None, None, None, None, base) - t = self.load_image("textures/blocks/brewingStand.png") + t = self.load_image_texture("textures/blocks/brewingStand.png") stand = self.build_billboard(t) alpha_over(img,stand,(0,-2)) return img @@ -3427,9 +3441,9 @@ def brewing_stand(self, blockid, data): # cauldron @material(blockid=118, data=range(4), transparent=True) def cauldron(self, blockid, data): - side = self.load_image("textures/blocks/cauldron_side.png") - top = self.load_image("textures/blocks/cauldron_top.png") - bottom = self.load_image("textures/blocks/cauldron_inner.png") + side = self.load_image_texture("textures/blocks/cauldron_side.png") + top = self.load_image_texture("textures/blocks/cauldron_top.png") + bottom = self.load_image_texture("textures/blocks/cauldron_inner.png") water = self.transform_image_top(self.load_water()) if data == 0: # empty img = self.build_full_block(top, side, side, side, side) @@ -3473,14 +3487,14 @@ def end_portal(self, blockid, data): def end_portal_frame(self, blockid, data): # The bottom 2 bits are oritation info but seems there is no # graphical difference between orientations - top = self.load_image("textures/blocks/endframe_top.png") - eye_t = self.load_image("textures/blocks/endframe_eye.png") - side = self.load_image("textures/blocks/endframe_side.png") + top = self.load_image_texture("textures/blocks/endframe_top.png") + eye_t = self.load_image_texture("textures/blocks/endframe_eye.png") + side = self.load_image_texture("textures/blocks/endframe_side.png") img = self.build_full_block((top, 4), None, None, side, side) if data & 0x4 == 0x4: # ender eye on it # generate the eye - eye_t = self.load_image("textures/blocks/endframe_eye.png").copy() - eye_t_s = self.load_image("textures/blocks/endframe_eye.png").copy() + eye_t = self.load_image_texture("textures/blocks/endframe_eye.png").copy() + eye_t_s = self.load_image_texture("textures/blocks/endframe_eye.png").copy() # cut out from the texture the side and the top of the eye ImageDraw.Draw(eye_t).rectangle((0,0,15,4),outline=(0,0,0,0),fill=(0,0,0,0)) ImageDraw.Draw(eye_t_s).rectangle((0,4,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -3514,13 +3528,13 @@ block(blockid=124, top_image="textures/blocks/redstoneLight_lit.png") def wooden_slabs(self, blockid, data): texture = data & 7 if texture== 0: # oak - top = side = self.load_image("textures/blocks/wood.png") + top = side = self.load_image_texture("textures/blocks/wood.png") elif texture== 1: # spruce - top = side = self.load_image("textures/blocks/wood_spruce.png") + top = side = self.load_image_texture("textures/blocks/wood_spruce.png") elif texture== 2: # birch - top = side = self.load_image("textures/blocks/wood_birch.png") + top = side = self.load_image_texture("textures/blocks/wood_birch.png") elif texture== 3: # jungle - top = side = self.load_image("textures/blocks/wood_jungle.png") + top = side = self.load_image_texture("textures/blocks/wood_jungle.png") else: return None @@ -3591,17 +3605,17 @@ def cocoa_plant(self, blockid, data): size = data & 12 if size == 8: # big - t = self.load_image("textures/blocks/cocoa_2.png") + t = self.load_image_texture("textures/blocks/cocoa_2.png") c_left = (0,3) c_right = (8,3) c_top = (5,2) elif size == 4: # normal - t = self.load_image("textures/blocks/cocoa_1.png") + t = self.load_image_texture("textures/blocks/cocoa_1.png") c_left = (-2,2) c_right = (8,2) c_top = (5,2) elif size == 0: # small - t = self.load_image("textures/blocks/cocoa_0.png") + t = self.load_image_texture("textures/blocks/cocoa_0.png") c_left = (-3,2) c_right = (6,2) c_top = (5,2) @@ -3658,12 +3672,12 @@ block(blockid=137, top_image="textures/blocks/commandBlock.png") @material(blockid=138, transparent=True, nodata = True) def beacon(self, blockid, data): # generate the three pieces of the block - t = self.load_image("textures/blocks/glass.png") + t = self.load_image_texture("textures/blocks/glass.png") glass = self.build_block(t,t) - t = self.load_image("textures/blocks/obsidian.png") + t = self.load_image_texture("textures/blocks/obsidian.png") obsidian = self.build_full_block((t,12),None, None, t, t) obsidian = obsidian.resize((20,20), Image.ANTIALIAS) - t = self.load_image("textures/blocks/beacon.png") + t = self.load_image_texture("textures/blocks/beacon.png") crystal = self.build_block(t,t) crystal = crystal.resize((16,16),Image.ANTIALIAS) @@ -3682,10 +3696,10 @@ def cobblestone_wall(self, blockid, data): # no rotation, uses pseudo data if data & 0b10000 == 0: # cobblestone - t = self.load_image("textures/blocks/stonebrick.png").copy() + t = self.load_image_texture("textures/blocks/stonebrick.png").copy() else: # mossy cobblestone - t = self.load_image("textures/blocks/stoneMoss.png").copy() + t = self.load_image_texture("textures/blocks/stoneMoss.png").copy() wall_pole_top = t.copy() wall_pole_side = t.copy() @@ -3810,11 +3824,11 @@ def crops(self, blockid, data): if data != 7: # when growing they look the same # data = 7 -> fully grown, everything else is growing # this seems to work, but still not sure - raw_crop = self.load_image("textures/blocks/potatoes_%d.png" % (data % 3)) + raw_crop = self.load_image_texture("textures/blocks/potatoes_%d.png" % (data % 3)) elif blockid == 141: # carrots - raw_crop = self.load_image("textures/blocks/carrots_3.png") + raw_crop = self.load_image_texture("textures/blocks/carrots_3.png") else: # potatoes - raw_crop = self.load_image("textures/blocks/potatoes_3.png") + raw_crop = self.load_image_texture("textures/blocks/potatoes_3.png") crop1 = self.transform_image_top(raw_crop) crop2 = self.transform_image_side(raw_crop) crop3 = crop2.transpose(Image.FLIP_LEFT_RIGHT) @@ -3840,16 +3854,16 @@ def anvil(self, blockid, data): # get the correct textures # the bits 0x4 and 0x8 determine how damaged is the anvil if (data & 0xc) == 0: # non damaged anvil - top = self.load_image("textures/blocks/anvil_top.png") + top = self.load_image_texture("textures/blocks/anvil_top.png") elif (data & 0xc) == 0x4: # slightly damaged - top = self.load_image("textures/blocks/anvil_top_damaged_1.png") + top = self.load_image_texture("textures/blocks/anvil_top_damaged_1.png") elif (data & 0xc) == 0x8: # very damaged - top = self.load_image("textures/blocks/anvil_top_damaged_2.png") + top = self.load_image_texture("textures/blocks/anvil_top_damaged_2.png") # everything else use this texture - big_side = self.load_image("textures/blocks/anvil_base.png").copy() - small_side = self.load_image("textures/blocks/anvil_base.png").copy() - base = self.load_image("textures/blocks/anvil_base.png").copy() - small_base = self.load_image("textures/blocks/anvil_base.png").copy() + big_side = self.load_image_texture("textures/blocks/anvil_base.png").copy() + small_side = self.load_image_texture("textures/blocks/anvil_base.png").copy() + base = self.load_image_texture("textures/blocks/anvil_base.png").copy() + small_base = self.load_image_texture("textures/blocks/anvil_base.png").copy() # cut needed patterns ImageDraw.Draw(big_side).rectangle((0,8,15,15),outline=(0,0,0,0),fill=(0,0,0,0)) From ef5e3e8fb990624920292eef682dc530386aa8f0 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sat, 12 Jan 2013 14:10:17 -0500 Subject: [PATCH 05/18] Weighted pressure plates See #863 --- overviewer_core/textures.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 9e8e964..e2f8a21 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -2374,13 +2374,17 @@ def levers(self, blockid, data): return img -# wooden and stone pressure plates -@material(blockid=[70, 72], data=[0,1], transparent=True) +# wooden and stone pressure plates, and weighted pressure plates +@material(blockid=[70, 72,147,148], data=[0,1], transparent=True) def pressure_plate(self, blockid, data): if blockid == 70: # stone t = self.load_image_texture("textures/blocks/stone.png").copy() - else: # wooden + elif blockid == 72: # wooden t = self.load_image_texture("textures/blocks/wood.png").copy() + elif blockid == 147: # light golden + t = self.load_image_texture("textures/blocks/blockGold.png").copy() + else: # blockid == 148: # heavy iron + t = self.load_image_texture("textures/blocks/blockIron.png").copy() # cut out the outside border, pressure plates are smaller # than a normal block From 45897c64183b08442a99a7bd52819410c8207dd8 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Sun, 13 Jan 2013 15:50:34 -0500 Subject: [PATCH 06/18] Support for the Daylight sensor See #863 --- overviewer_core/textures.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index e2f8a21..1a381c5 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -3525,6 +3525,37 @@ block(blockid=123, top_image="textures/blocks/redstoneLight.png") # active redstone lamp block(blockid=124, top_image="textures/blocks/redstoneLight_lit.png") +# daylight sensor. +@material(blockid=151, transparent=True) +def daylight_sensor(self, blockid, data): + top = self.load_image_texture("textures/blocks/daylightDetector_top.png") + side = self.load_image_texture("textures/blocks/daylightDetector_side.png") + + # cut the side texture in half + mask = side.crop((0,8,16,16)) + side = Image.new(side.mode, side.size, self.bgcolor) + alpha_over(side, mask,(0,0,16,8), mask) + + # plain slab + top = self.transform_image_top(top) + side = self.transform_image_side(side) + otherside = side.transpose(Image.FLIP_LEFT_RIGHT) + + sidealpha = side.split()[3] + side = ImageEnhance.Brightness(side).enhance(0.9) + side.putalpha(sidealpha) + othersidealpha = otherside.split()[3] + otherside = ImageEnhance.Brightness(otherside).enhance(0.8) + otherside.putalpha(othersidealpha) + + img = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(img, side, (0,12), side) + alpha_over(img, otherside, (12,12), otherside) + alpha_over(img, top, (0,6), top) + + return img + + # wooden double and normal slabs # these are the new wooden slabs, blockids 43 44 still have wooden # slabs, but those are unobtainable without cheating From 7cd207244114d58dc070eae1da35cc8e43db7f52 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Fri, 8 Feb 2013 10:58:51 +0100 Subject: [PATCH 07/18] Added: -droppers (still TODO vertical orientations) -activator rails -quartz stairs -trapped chests -quart blocks (all types) Also moved restone block and quartz ore block code to the end of the file. --- overviewer_core/textures.py | 76 ++++++++++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 14 deletions(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 1a381c5..0a2995b 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -933,8 +933,8 @@ block(blockid=21, top_image="textures/blocks/oreLapis.png") # lapis lazuli block block(blockid=22, top_image="textures/blocks/blockLapis.png") -# dispensers, furnaces, and burning furnaces -@material(blockid=[23, 61, 62], data=range(6), solid=True) +# dispensers, dropper, furnaces, and burning furnaces +@material(blockid=[23, 61, 62, 158], data=range(6), solid=True) def furnaces(self, blockid, data): # first, do the rotation if needed if self.rotation == 1: @@ -962,6 +962,8 @@ def furnaces(self, blockid, data): front = self.load_image_texture("textures/blocks/furnace_front_lit.png") elif blockid == 23: front = self.load_image_texture("textures/blocks/dispenser_front.png") + elif blockid == 158: + front = self.load_image_texture("textures/blocks/dropper_front.png") if data == 3: # pointing west return self.build_full_block(top, None, None, side, front) @@ -1046,8 +1048,8 @@ def bed(self, blockid, data): top = (top, increment) return self.build_full_block(top, None, None, left_face, right_face) -# powered, detector, and normal rails -@material(blockid=[27, 28, 66], data=range(14), transparent=True) +# powered, detector, activator and normal rails +@material(blockid=[27, 28, 66, 157], data=range(14), transparent=True) def rails(self, blockid, data): # first, do rotation # Masked to not clobber powered rail on/off info @@ -1108,6 +1110,17 @@ def rails(self, blockid, data): elif blockid == 66: # normal rail raw_straight = self.load_image_texture("textures/blocks/rail.png") raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") + + elif blockid == 157: # activator rail + if data & 0x8 == 0: # unpowered + raw_straight = self.load_image_texture("textures/blocks/activatorRail.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") # they don't exist but make the code + # much simplier + elif data & 0x8 == 0x8: # powered + raw_straight = self.load_image_texture("textures/blocks/activatorRail_powered.png") + raw_corner = self.load_image_texture("textures/blocks/rail_turn.png") # leave corners for code simplicity + # filter the 'powered' bit + data = data & 0x7 ## use transform_image to scale and shear if data == 0: @@ -1510,8 +1523,8 @@ def fire(self, blockid, data): # monster spawner block(blockid=52, top_image="textures/blocks/mobSpawner.png", transparent=True) -# wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch and jungle stairs. -@material(blockid=[53,67,108,109,114,128,134,135,136], data=range(8), transparent=True, solid=True, nospawn=True) +# wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, jungle and quartz stairs. +@material(blockid=[53,67,108,109,114,128,134,135,136,156], data=range(8), transparent=True, solid=True, nospawn=True) def stairs(self, blockid, data): # first, rotations @@ -1553,6 +1566,8 @@ def stairs(self, blockid, data): texture = self.load_image_texture("textures/blocks/wood_birch.png") elif blockid == 136: # jungle good stairs texture = self.load_image_texture("textures/blocks/wood_jungle.png") + elif blockid == 156: # quartz block stairs + texture = self.load_image_texture("textures/blocks/quartzblock_side.png") side = texture.copy() @@ -1566,6 +1581,10 @@ def stairs(self, blockid, data): half_block_u = self.load_image_texture("textures/blocks/sandstone_top.png").copy() half_block_d = self.load_image_texture("textures/blocks/sandstone_top.png").copy() texture = self.load_image_texture("textures/blocks/sandstone_top.png").copy() + elif blockid == 156: # also quartz stairs + half_block_u = self.load_image_texture("textures/blocks/quartzblock_top.png").copy() + half_block_d = self.load_image_texture("textures/blocks/quartzblock_top.png").copy() + texture = self.load_image_texture("textures/blocks/quartzblock_top.png").copy() # generate needed geometries ImageDraw.Draw(side).rectangle((0,0,7,6),outline=(0,0,0,0),fill=(0,0,0,0)) @@ -1644,8 +1663,8 @@ def stairs(self, blockid, data): return img -# normal, locked (used in april's fool day) and ender chests chests -@material(blockid=[54,95,130], data=range(30), transparent = True) +# normal, locked (used in april's fool day), ender and trapped chest +@material(blockid=[54,95,130,146], data=range(30), transparent = True) def chests(self, blockid, data): # the first 3 bits are the orientation as stored in minecraft, # bits 0x8 and 0x10 indicate which half of the double chest is it. @@ -3611,12 +3630,6 @@ block(blockid=129, top_image="textures/blocks/oreEmerald.png") # emerald block block(blockid=133, top_image="textures/blocks/blockEmerald.png") -# nether quartz ore -block(blockid=153, top_image="textures/blocks/netherquartz.png") - -# block of redstone -block(blockid=152, top_image="textures/blocks/blockRedstone.png") - # cocoa plant @material(blockid=127, data=range(12), transparent=True) def cocoa_plant(self, blockid, data): @@ -3958,3 +3971,38 @@ def anvil(self, blockid, data): alpha_over(img, right_side, right_pos, right_side) return img + + +# block of redstone +block(blockid=152, top_image="textures/blocks/blockRedstone.png") + +# nether quartz ore +block(blockid=153, top_image="textures/blocks/netherquartz.png") + +# block of quartz +@material(blockid=155, data=range(5), solid=True) +def quartz_block(self, blockid, data): + + if data in (0,1): # normal and chiseled quartz block + if data == 0: + top = self.load_image_texture("textures/blocks/quartzblock_top.png") + side = self.load_image_texture("textures/blocks/quartzblock_side.png") + else: + top = self.load_image_texture("textures/blocks/quartzblock_chiseled_top.png") + side = self.load_image_texture("textures/blocks/quartzblock_chiseled.png") + return self.build_block(top, side) + + # pillar quartz block with orientation + top = self.load_image_texture("textures/blocks/quartzblock_lines_top.png") + side = self.load_image_texture("textures/blocks/quartzblock_lines.png").copy() + if data == 2: # vertical + return self.build_block(top, side) + elif data == 3: # north-south oriented + if self.rotation in (0,2): + return self.build_full_block(side, None, None, top, side.rotate(90)) + return self.build_full_block(side.rotate(90), None, None, side.rotate(90), top) + + elif data == 4: # east-west oriented + if self.rotation in (0,2): + return self.build_full_block(side.rotate(90), None, None, side.rotate(90), top) + return self.build_full_block(side, None, None, top, side.rotate(90)) From 42debd6c9dec6c9188f9b2f47354736d7f5ee708 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Fri, 8 Feb 2013 11:06:14 +0100 Subject: [PATCH 08/18] Redstone now connects to trapped chests. --- overviewer_core/src/iterate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/overviewer_core/src/iterate.c b/overviewer_core/src/iterate.c index 4b1f313..2bc0a23 100644 --- a/overviewer_core/src/iterate.c +++ b/overviewer_core/src/iterate.c @@ -298,8 +298,8 @@ generate_pseudo_data(RenderState *state, unsigned char ancilData) { above_level_data = check_adjacent_blocks(state, x, y+1, z, state->block); } /* else above_level_data = 0 */ - /* check connection with same level */ - same_level_data = check_adjacent_blocks(state, x, y, z, 55); + /* check connection with same level (other redstone and trapped chests */ + same_level_data = check_adjacent_blocks(state, x, y, z, 55) | check_adjacent_blocks(state, x, y, z, 146); /* check the posibility of connection with y-1 level, check for air */ possibly_connected = check_adjacent_blocks(state, x, y, z, 0); From eb8d445822023a04f9beadc13121ea5da7dc45dd Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Tue, 26 Feb 2013 08:45:57 +0100 Subject: [PATCH 09/18] Updated png-it.py, now it has --autocrop option. --- contrib/png-it.py | 90 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 64 insertions(+), 26 deletions(-) diff --git a/contrib/png-it.py b/contrib/png-it.py index fa3c393..3e62312 100644 --- a/contrib/png-it.py +++ b/contrib/png-it.py @@ -27,6 +27,9 @@ def main(): parser.add_option('--center', '-e', help = 'Mark what will be the center of the image, two percentage values comma separated',\ metavar = '
', type = str, dest = 'center', default = None) + parser.add_option('--autocrop', '-a', help = 'Calculates the center and crop vales automatically to show all the tiles in the minimun image size.Unless you want a very specific image this options is very recommendedable.',\ + action = 'store_true', dest = 'autocrop', default = False) + parser.add_option('--output', '-o', help = 'Path for the resulting PNG. It will save it as PNG, no matter what extension do you use.',\ metavar = '', type = str, dest = 'output', default = "output.png") @@ -43,6 +46,9 @@ def main(): if not options.zoom_level: parser.error("Error! The option zoom-level is mandatory.") + if options.autocrop and (options.center or options.crop): + parser.error("Error! You can't mix --autocrop with --center or --crop.") + # check for the output folder, filename = split(options.output) if folder != '' and not exists(folder): @@ -54,32 +60,6 @@ def main(): tile_size = (384,384) px_size = 4 # bytes - # the vector that joins the center tile with the new center tile in - # tile coords (tile coords is how many tile are on the left, x, and - # how many above, y. The top-left tile has coords (0,0) - if options.center: - center_x, center_y = options.center.split(",") - center_x = int(center_x) - center_y = int(center_y) - center_tile_x = int(2**n*(center_x/100.)) - center_tile_y = int(2**n*(center_y/100.)) - center_vector = (int(center_tile_x - length_in_tiles/2.), int(center_tile_y - length_in_tiles/2.)) - else: - center_vector = (0,0) - - tiles_to_crop = int(2**n*(options.crop/100.)) - crop = (tiles_to_crop, tiles_to_crop) - - final_img_size = (tile_size[0]*length_in_tiles,tile_size[1]*length_in_tiles) - final_cropped_img_size = (final_img_size[0] - 2*crop[0]*tile_size[0],final_img_size[1] - 2*crop[1]*tile_size[1]) - - mem = final_cropped_img_size[0]*final_cropped_img_size[1]*px_size # bytes! - print "The image size will be {0}x{1}".format(final_cropped_img_size[0],final_cropped_img_size[1]) - print "A total of {0} MB of memory will be used.".format(mem/1024**2) - if mem/1024.**2. > options.memory_limit: - print "Warning! The expected RAM usage exceeds the spicifyed limit. Exiting." - sys.exit(1) - # create a list with all the images in the zoom level path = tileset for i in range(options.zoom_level): @@ -91,6 +71,64 @@ def main(): "Error! No images found in this zoom leve. Is this really an overviewer tile set directory?" sys.exit(1) + # autocrop will calculate the center and crop values automagically + if options.autocrop: + min_x = min_y = length_in_tiles + max_x = max_y = 0 + counter = 0 + total = len(all_images) + print "Checking tiles for autocrop calculations:" + # get the maximun and minimun tiles coordinates of the map + for path in all_images: + t = get_tuple_coords(options, path) + c = get_tile_coords_from_tuple(options, t) + min_x = min(min_x, c[0]) + min_y = min(min_y, c[1]) + max_x = max(max_x, c[0]) + max_y = max(max_y, c[1]) + counter += 1 + if (counter % 100 == 0 or counter == total or counter == 1): print "Checked {0} of {1}".format(counter, total) + + # the center of the map will be in the middle of the occupied zone + center = (int((min_x + max_x)/2.), int((min_y + max_y)/2.)) + # see the next next comment to know what's center_vector + center_vector = (int(center[0] - (length_in_tiles/2. - 1)), int(center[1] - (length_in_tiles/2. - 1))) + # I'm not completely sure why, but the - 1 factor in ^ makes everything nicer. + + # min_x - center_vector[0] will be the unused amount of tiles in + # the left and the right of the map (and this is true because we + # are in the actual center of the map) + crop = (min_x - center_vector[0], min_y - center_vector[1]) + + else: + # center_vector is the vector that joins the center tile with + # the new center tile in tile coords + #(tile coords are how many tile are on the left, x, and + # how many above, y. The top-left tile has coords (0,0) + if options.center: + center_x, center_y = options.center.split(",") + center_x = int(center_x) + center_y = int(center_y) + center_tile_x = int(2**n*(center_x/100.)) + center_tile_y = int(2**n*(center_y/100.)) + center_vector = (int(center_tile_x - length_in_tiles/2.), int(center_tile_y - length_in_tiles/2.)) + else: + center_vector = (0,0) + + # crop if needed + tiles_to_crop = int(2**n*(options.crop/100.)) + crop = (tiles_to_crop, tiles_to_crop) + + final_img_size = (tile_size[0]*length_in_tiles,tile_size[1]*length_in_tiles) + final_cropped_img_size = (final_img_size[0] - 2*crop[0]*tile_size[0],final_img_size[1] - 2*crop[1]*tile_size[1]) + + mem = final_cropped_img_size[0]*final_cropped_img_size[1]*px_size # bytes! + print "The image size will be {0}x{1}".format(final_cropped_img_size[0],final_cropped_img_size[1]) + print "A total of {0} MB of memory will be used.".format(mem/1024**2) + if mem/1024.**2. > options.memory_limit: + print "Warning! The expected RAM usage exceeds the spicifyed limit. Exiting." + sys.exit(1) + # Create a new huge image final_img = Image.new("RGBA", final_cropped_img_size, (26, 26, 26, 0)) From f40049a79c19779c235566c5e00154b3687edd1c Mon Sep 17 00:00:00 2001 From: skeight Date: Fri, 8 Mar 2013 07:48:25 -0800 Subject: [PATCH 10/18] 1.5 Pre-Release updates/fixes Fix for Ender Portal Frame, w/eye of ender, in all orientations Minor fix for Comparator back torches Update to lighting on Quartz stairs Added Quartz Half Slabs --- overviewer_core/src/primitives/lighting.c | 4 ++-- overviewer_core/textures.py | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/overviewer_core/src/primitives/lighting.c b/overviewer_core/src/primitives/lighting.c index d264ae7..4682351 100644 --- a/overviewer_core/src/primitives/lighting.c +++ b/overviewer_core/src/primitives/lighting.c @@ -159,7 +159,7 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, /* special half-step handling, stairs handling */ if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114 || - block == 128 || block == 134 || block == 135 || block == 136) { + block == 128 || block == 134 || block == 135 || block == 136 || block == 156) { unsigned int upper_block; /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ @@ -170,7 +170,7 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, upper_block = get_data(state, BLOCKS, x, y + upper_counter, z); } while (upper_block == 44 || upper_block == 53 || upper_block == 67 || upper_block == 108 || upper_block == 109 || upper_block == 114 || upper_block == 128 || upper_block == 134 || - upper_block == 135 || upper_block == 136); + upper_block == 135 || upper_block == 136 || upper_block == 156 ); if (is_transparent(upper_block)) { skylevel = get_data(state, SKYLIGHT, x, y + upper_counter, z); } else { diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 0a2995b..92c48cf 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -1387,6 +1387,8 @@ def slabs(self, blockid, data): top = side = self.load_image_texture("textures/blocks/stonebricksmooth.png") elif texture== 6: # nether brick slab top = side = self.load_image_texture("textures/blocks/netherBrick.png") + elif texture== 7: #quartz + top = side = self.load_image_texture("textures/blocks/quartzblock_side.png") else: return None @@ -3052,7 +3054,7 @@ def comparator(self, blockid, data): active_torch = build_torch(True) inactive_torch = build_torch(False) - back_torch = active_torch if blockid == 150 else inactive_torch + back_torch = active_torch if (blockid == 150 or data & 0b1000 == 0b1000) else inactive_torch static_torch_img = active_torch if (data & 0b100 == 0b100) else inactive_torch img = self.build_full_block( (top, increment), None, None, side, side) @@ -3505,8 +3507,8 @@ def end_portal(self, blockid, data): return img -# end portal frame -@material(blockid=120, data=range(5), transparent=True) +# end portal frame (data range 8 to get all orientations of filled) +@material(blockid=120, data=range(8), transparent=True) def end_portal_frame(self, blockid, data): # The bottom 2 bits are oritation info but seems there is no # graphical difference between orientations @@ -4005,4 +4007,4 @@ def quartz_block(self, blockid, data): elif data == 4: # east-west oriented if self.rotation in (0,2): return self.build_full_block(side.rotate(90), None, None, side.rotate(90), top) - return self.build_full_block(side, None, None, top, side.rotate(90)) + return self.build_full_block(side, None, None, top, side.rotate(90)) \ No newline at end of file From a1ebd9a03a9e86788a29d8185ac3624efca94a5a Mon Sep 17 00:00:00 2001 From: skeight Date: Fri, 8 Mar 2013 09:30:42 -0800 Subject: [PATCH 11/18] Added Hoppers Screenshot: http://i.imgur.com/nB2Nzp6.jpg --- overviewer_core/textures.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 92c48cf..223b495 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -4007,4 +4007,28 @@ def quartz_block(self, blockid, data): elif data == 4: # east-west oriented if self.rotation in (0,2): return self.build_full_block(side.rotate(90), None, None, side.rotate(90), top) - return self.build_full_block(side, None, None, top, side.rotate(90)) \ No newline at end of file + return self.build_full_block(side, None, None, top, side.rotate(90)) + +# hopper +@material(blockid=154, data=range(4), transparent=True) +def hopper(self, blockid, data): + #build the top + side = self.load_image_texture("textures/blocks/hopper.png") + top = self.load_image_texture("textures/blocks/hopper_top.png") + bottom = self.load_image_texture("textures/blocks/hopper_inside.png") + hop_top = self.build_full_block((top,10), side, side, side, side, side) + + #build a solid block for mid/top + hop_mid = self.build_full_block((top,5), side, side, side, side, side) + hop_bot = self.build_block(side,side) + + hop_mid = hop_mid.resize((17,17),Image.ANTIALIAS) + hop_bot = hop_bot.resize((10,10),Image.ANTIALIAS) + + #compose the final block + img = Image.new("RGBA", (24,24), self.bgcolor) + alpha_over(img, hop_bot, (7,14), hop_bot) + alpha_over(img, hop_mid, (3,3), hop_mid) + alpha_over(img, hop_top, (0,-6), hop_top) + + return img From d32b247db7f9139c6d9c6a6f069c217004cca05d Mon Sep 17 00:00:00 2001 From: Christoph Burschka Date: Sun, 10 Mar 2013 20:24:21 +0100 Subject: [PATCH 12/18] Follow symbolic links while finding region sets. --- overviewer_core/world.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 8480a98..84c07dd 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -116,7 +116,7 @@ class World(object): # seem to be any set standard on what dimensions are in each world, # just scan the directory heirarchy to find a directory with .mca # files. - for root, dirs, files in os.walk(self.worlddir): + for root, dirs, files in os.walk(self.worlddir, followlinks=True): # any .mcr files in this directory? mcas = [x for x in files if x.endswith(".mca")] if mcas: From 5bba5dab756bf8cac4fedb64cd3d63ac3ff26cc4 Mon Sep 17 00:00:00 2001 From: Alejandro Aguilera Date: Mon, 11 Mar 2013 14:02:36 +0100 Subject: [PATCH 13/18] - Fixed lighting for anvils. - Added vertical orientations for dispensers and droppers - Added special cases of stone and sandstone double slabs --- overviewer_core/src/primitives/lighting.c | 3 ++- overviewer_core/textures.py | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/overviewer_core/src/primitives/lighting.c b/overviewer_core/src/primitives/lighting.c index 4682351..beffff9 100644 --- a/overviewer_core/src/primitives/lighting.c +++ b/overviewer_core/src/primitives/lighting.c @@ -158,8 +158,9 @@ get_lighting_color(RenderPrimitiveLighting *self, RenderState *state, blocklevel = get_data(state, BLOCKLIGHT, x, y, z); /* special half-step handling, stairs handling */ + /* Anvil also needs to be here, blockid 145 */ if (block == 44 || block == 53 || block == 67 || block == 108 || block == 109 || block == 114 || - block == 128 || block == 134 || block == 135 || block == 136 || block == 156) { + block == 128 || block == 134 || block == 135 || block == 136 || block == 145 || block == 156) { unsigned int upper_block; /* stairs and half-blocks take the skylevel from the upper block if it's transparent */ diff --git a/overviewer_core/textures.py b/overviewer_core/textures.py index 223b495..b352425 100644 --- a/overviewer_core/textures.py +++ b/overviewer_core/textures.py @@ -962,8 +962,18 @@ def furnaces(self, blockid, data): front = self.load_image_texture("textures/blocks/furnace_front_lit.png") elif blockid == 23: front = self.load_image_texture("textures/blocks/dispenser_front.png") + if data == 0: # dispenser pointing down + return self.build_block(top, top) + elif data == 1: # dispenser pointing up + dispenser_top = self.load_image_texture("textures/blocks/dispenser_front_vertical.png") + return self.build_block(dispenser_top, top) elif blockid == 158: front = self.load_image_texture("textures/blocks/dropper_front.png") + if data == 0: # dropper pointing down + return self.build_block(top, top) + elif data == 1: # dispenser pointing up + dropper_top = self.load_image_texture("textures/blocks/dropper_front_vertical.png") + return self.build_block(dropper_top, top) if data == 3: # pointing west return self.build_full_block(top, None, None, side, front) @@ -1370,7 +1380,10 @@ block(blockid=42, top_image="textures/blocks/blockIron.png") # here because lots of pre-1.3 worlds use this blocks @material(blockid=[43, 44], data=range(16), transparent=(44,), solid=True) def slabs(self, blockid, data): - texture = data & 7 + if blockid == 44: + texture = data & 7 + else: # data > 8 are special double slabs + texture = data if texture== 0: # stone slab top = self.load_image_texture("textures/blocks/stoneslab_top.png") side = self.load_image_texture("textures/blocks/stoneslab_side.png") @@ -1379,7 +1392,7 @@ def slabs(self, blockid, data): side = self.load_image_texture("textures/blocks/sandstone_side.png") elif texture== 2: # wooden slab top = side = self.load_image_texture("textures/blocks/wood.png") - elif texture== 3: # cobblestone slab + elif texture== 3: # c43obblestone slab top = side = self.load_image_texture("textures/blocks/stonebrick.png") elif texture== 4: # brick top = side = self.load_image_texture("textures/blocks/brick.png") @@ -1389,6 +1402,10 @@ def slabs(self, blockid, data): top = side = self.load_image_texture("textures/blocks/netherBrick.png") elif texture== 7: #quartz top = side = self.load_image_texture("textures/blocks/quartzblock_side.png") + elif texture== 8: # special stone double slab with top texture only + top = side = self.load_image_texture("textures/blocks/stoneslab_top.png") + elif texture== 9: # special sandstone double slab with top texture only + top = side = self.load_image_texture("textures/blocks/sandstone_top.png") else: return None From 31daa558f90366bf0206db9713824f4e205cf417 Mon Sep 17 00:00:00 2001 From: "Nicolas F." Date: Mon, 11 Mar 2013 15:29:47 +0100 Subject: [PATCH 14/18] Fix error in documentation No parenthesis on the import statement. --- docs/config.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/config.rst b/docs/config.rst index 2284bc9..e603ca7 100644 --- a/docs/config.rst +++ b/docs/config.rst @@ -255,7 +255,7 @@ the form ``key = value``. Two items take a different form:, ``worlds`` and If you want to specify an observer manually, try something like: :: - from observer import ProgressBarObserver() + from observer import ProgressBarObserver observer = ProgressBarObserver() There are currently three observers available: ``LoggingObserver``, From 633dcd18c11466797294005e9b9505d79941d242 Mon Sep 17 00:00:00 2001 From: Nicolas Frattaroli Date: Mon, 11 Mar 2013 18:06:54 +0100 Subject: [PATCH 15/18] Fixed Python3 error message Up to this point, when launching overviewer with python3, overviewer would (ironic as it is) crash on the line where the error message would be displayed with a syntax error. I have now fixed this. --- overviewer.py | 56 +++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/overviewer.py b/overviewer.py index d44a127..dcf52b6 100755 --- a/overviewer.py +++ b/overviewer.py @@ -20,9 +20,9 @@ import sys # quick version check if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6): - print "Sorry, the Overviewer requires at least Python 2.6 to run" + print("Sorry, the Overviewer requires at least Python 2.6 to run") if sys.version_info[0] >= 3: - print "and will not run on Python 3.0 or later" + print("and will not run on Python 3.0 or later") sys.exit(1) import os @@ -125,15 +125,15 @@ def main(): # This section of main() runs in response to any one-time options we have, # such as -V for version reporting if options.version: - print "Minecraft Overviewer %s" % util.findGitVersion(), - print "(%s)" % util.findGitHash()[:7] + print("Minecraft Overviewer %s" % util.findGitVersion()), + print("(%s)" % util.findGitHash()[:7]) try: import overviewer_core.overviewer_version as overviewer_version - print "built on %s" % overviewer_version.BUILD_DATE + print("built on %s" % overviewer_version.BUILD_DATE) if options.verbose > 0: - print "Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM, overviewer_version.BUILD_OS) + print("Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM, overviewer_version.BUILD_OS)) except ImportError: - print "(build info not found)" + print("(build info not found)") return 0 if options.check_terrain: @@ -158,13 +158,13 @@ def main(): # first provide an appropriate error for bare-console users # that don't provide any options if util.is_bare_console(): - print "\n" - print "The Overviewer is a console program. Please open a Windows command prompt" - print "first and run Overviewer from there. Further documentation is available at" - print "http://docs.overviewer.org/\n" - print "\n" - print "For a quick-start guide on Windows, visit the following URL:\n" - print "http://docs.overviewer.org/en/latest/win_tut/windowsguide/\n" + print("\n") + print("The Overviewer is a console program. Please open a Windows command prompt") + print("first and run Overviewer from there. Further documentation is available at") + print("http://docs.overviewer.org/\n") + print("\n") + print("For a quick-start guide on Windows, visit the following URL:\n") + print("http://docs.overviewer.org/en/latest/win_tut/windowsguide/\n") else: # more helpful message for users who know what they're doing @@ -178,13 +178,13 @@ def main(): # in. It checks to see if --config was given that no worldname/destdir were # given, and vice versa if options.config and args: - print - print "If you specify --config, you need to specify the world to render as well as" - print "the destination in the config file, not on the command line." - print "Put something like this in your config file:" - print "worlds['myworld'] = %r" % args[0] - print "outputdir = %r" % (args[1] if len(args) > 1 else "/path/to/output") - print + print() + print("If you specify --config, you need to specify the world to render as well as") + print("the destination in the config file, not on the command line.") + print("Put something like this in your config file:") + print("worlds['myworld'] = %r" % args[0]) + print("outputdir = %r" % (args[1] if len(args) > 1 else "/path/to/output")) + print() logging.error("Cannot specify both --config AND a world + output directory on the command line.") parser.print_help() return 1 @@ -471,16 +471,16 @@ def list_worlds(): print worlds = world.get_worlds() if not worlds: - print 'No world saves found in the usual place' + print('No world saves found in the usual place') return - print "Detected saves:" + print("Detected saves:") # get max length of world name worldNameLen = max([len(str(x)) for x in worlds] + [len("World")]) formatString = "%-" + str(worldNameLen) + "s | %-8s | %-8s | %-16s | %s " - print formatString % ("World", "Size", "Playtime", "Modified", "Path") - print formatString % ("-"*worldNameLen, "-"*8, "-"*8, '-'*16, '-'*4) + print(formatString % ("World", "Size", "Playtime", "Modified", "Path")) + print(formatString % ("-"*worldNameLen, "-"*8, "-"*8, '-'*16, '-'*4)) for name, info in sorted(worlds.iteritems()): if isinstance(name, basestring) and name.startswith("World") and len(name) == 6: try: @@ -496,18 +496,18 @@ def list_worlds(): playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60) size = "%.2fMB" % (info['SizeOnDisk'] / 1024. / 1024.) path = info['path'] - print formatString % (name, size, playstamp, timestamp, path) + print(formatString % (name, size, playstamp, timestamp, path)) if __name__ == "__main__": multiprocessing.freeze_support() try: ret = main() util.nice_exit(ret) - except textures.TextureException, e: + except textures.TextureException as e: # this isn't a "bug", so don't print scary traceback logging.error(str(e)) util.nice_exit(1) - except Exception, e: + except Exception as e: logging.exception("""An error has occurred. This may be a bug. Please let us know! See http://docs.overviewer.org/en/latest/index.html#help From 284369840f4a6a7713795ece2070efd1811b3629 Mon Sep 17 00:00:00 2001 From: Michael Writhe Date: Mon, 11 Mar 2013 15:58:58 -0600 Subject: [PATCH 16/18] travis update, /dev/shm no longer avail, so 1 proc only --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 76cf3fe..76dfe6f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ before_script: - git clone git://github.com/overviewer/Minecraft-Overviewer-Addons.git ~/mcoa/ - wget -N http://s3.amazonaws.com/MinecraftDownload/minecraft.jar -P ~/.minecraft/bin/ script: - - python overviewer.py ~/mcoa/exmaple ~/test-output --rendermodes=smooth-lighting + - python overviewer.py ~/mcoa/exmaple ~/test-output --rendermodes=smooth-lighting -p1 notifications: email: false # matrix: # allow_failures: - # - python: "3.2" \ No newline at end of file + # - python: "3.2" From 44f624f64fa4a3cef8e1010318a0b80c9d52b865 Mon Sep 17 00:00:00 2001 From: Nicolas Frattaroli Date: Sat, 9 Mar 2013 15:35:42 +0100 Subject: [PATCH 17/18] Fixed paths with square brackets in them. --- overviewer_core/world.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index 8480a98..450c700 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -21,6 +21,7 @@ import logging import hashlib import time import random +import re import numpy @@ -492,14 +493,14 @@ class RegionSet(object): logging.debug("regiondir is %s", self.regiondir) - for path in glob(self.regiondir + "/r.*.*.mca"): - dirpath, f = os.path.split(path) - p = f.split(".") - x = int(p[1]) - y = int(p[2]) - if abs(x) > 500000 or abs(y) > 500000: - logging.warning("Holy shit what is up with region file %s !?" % f) - yield (x, y, path) + for f in os.listdir(self.regiondir): + if re.match(r"^r\.-?\d+\.-?\d+\.mca$", f): + p = f.split(".") + x = int(p[1]) + y = int(p[2]) + if abs(x) > 500000 or abs(y) > 500000: + logging.warning("Holy shit what is up with region file %s !?" % f) + yield (x, y, os.path.join(self.regiondir, f)) class RegionSetWrapper(object): """This is the base class for all "wrappers" of RegionSet objects. A From dd6538b55eaf27adf819ed77a94eea49eb185ce8 Mon Sep 17 00:00:00 2001 From: Andrew Chin Date: Wed, 13 Mar 2013 21:23:52 -0400 Subject: [PATCH 18/18] Print out regionset type when run with -v --- overviewer_core/world.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/overviewer_core/world.py b/overviewer_core/world.py index a4d414c..e16b33e 100644 --- a/overviewer_core/world.py +++ b/overviewer_core/world.py @@ -491,7 +491,7 @@ class RegionSet(object): Returns (regionx, regiony, filename)""" - logging.debug("regiondir is %s", self.regiondir) + logging.debug("regiondir is %s, has type %r", self.regiondir, self.type) for f in os.listdir(self.regiondir): if re.match(r"^r\.-?\d+\.-?\d+\.mca$", f):