0

Merge pull request #440 from Fenixin/pistons

Pistons + better glass.
This commit is contained in:
Andrew Chin
2011-07-25 17:10:37 -07:00
3 changed files with 171 additions and 89 deletions

View File

@@ -114,10 +114,10 @@ def get_tileentity_data(level):
return data return data
# This set holds blocks ids that can be seen through, for occlusion calculations # This set holds blocks ids that can be seen through, for occlusion calculations
transparent_blocks = set([ 0, 6, 8, 9, 18, 20, 26, 27, 28, 30, 31, 32, 37, 38, transparent_blocks = set([ 0, 6, 8, 9, 18, 20, 26, 27, 28, 29, 30, 31, 32, 33,
39, 40, 44, 50, 51, 52, 53, 55, 59, 63, 64, 65, 66, 67, 34, 37, 38, 39, 40, 44, 50, 51, 52, 53, 55, 59, 63, 64,
68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 83, 85, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79,
90, 92, 93, 94, 96]) 81, 83, 85, 90, 92, 93, 94, 96])
# This set holds block ids that are solid blocks # This set holds block ids that are solid blocks
solid_blocks = set([1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, solid_blocks = set([1, 2, 3, 4, 5, 7, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
@@ -321,67 +321,6 @@ class ChunkRenderer(object):
return self._up_left_skylight return self._up_left_skylight
up_left_skylight = property(_load_up_left_skylight) up_left_skylight = property(_load_up_left_skylight)
def generate_pseudo_ancildata(self,x,y,z,blockid, north_position = 0 ):
""" Generates a pseudo ancillary data for blocks that depend of
what are surrounded and don't have ancillary data
This uses a binary number of 4 digits to encode the info.
The encode is:
Bit: 1 2 3 4
Side: x y -x -y
Values: bit = 0 -> The corresponding side block has different blockid
bit = 1 -> The corresponding side block has same blockid
Example: if the bit1 is 1 that means that there is a block with
blockid in the side of the +x direction.
You can rotate the pseudo data multiplying by 2 and
if it is > 15 subtracting 15 and adding 1. (moving bits
in the left direction is like rotate 90 degree in anticlockwise
direction). In this way can be used for maps with other
north orientation.
North position can have the values 0, 1, 2, 3, corresponding to
north in bottom-left, bottom-right, top-right and top-left of
the screen.
The rotation feature is not used anywhere yet.
"""
blocks = self.blocks
up_left_blocks = self.up_left_blocks
up_right_blocks = self.up_right_blocks
left_blocks = self.left_blocks
right_blocks = self.right_blocks
pseudo_data = 0
# first check if we are in the border of a chunk, next check for chunks adjacent to this
# and finally check for a block with same blockid. I we aren't in the border of a chunk,
# check for the block having the sme blockid.
if (up_right_blocks is not None and up_right_blocks[0,y,z] == blockid) if x == 15 else blocks[x+1,y,z] == blockid:
pseudo_data = pseudo_data | 0b1000
if (right_blocks is not None and right_blocks[x,0,z] == blockid) if y == 15 else blocks[x,y + 1,z] == blockid:
pseudo_data = pseudo_data | 0b0100
if (left_blocks is not None and left_blocks[15,y,z] == blockid) if x == 0 else blocks[x - 1,y,z] == blockid:
pseudo_data = pseudo_data | 0b0010
if (up_left_blocks is not None and up_left_blocks[x,15,z] == blockid) if y == 0 else blocks[x,y - 1,z] == blockid:
pseudo_data = pseudo_data | 0b0001
# rotate the bits for other north orientations
while north_position > 0:
pseudo_data *= 2
if pseudo_data > 15:
pseudo_data -= 16
pseudo_data +=1
north_position -= 1
return pseudo_data
def chunk_render(self, img=None, xoff=0, yoff=0, cave=False): def chunk_render(self, img=None, xoff=0, yoff=0, cave=False):
"""Renders a chunk with the given parameters, and returns the image. """Renders a chunk with the given parameters, and returns the image.
If img is given, the chunk is rendered to that image object. Otherwise, If img is given, the chunk is rendered to that image object. Otherwise,

View File

@@ -174,12 +174,18 @@ generate_pseudo_data(RenderState *state, unsigned char ancilData) {
data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f); data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f);
return data; return data;
} }
} else if (state->block == 20) { /* glass */
/* an aditional bit for top is added to the 4 bits of check_adjacent_blocks */
if ((z != 127) && (getArrayByte3D(state->blocks, x, y, z+1) == 20)) {
data = 0;
} else {
data = 16;
}
data = (check_adjacent_blocks(state, x, y, z, state->block) ^ 0x0f) | data;
return data;
} else if (state->block == 85) { /* fences */ } else if (state->block == 85) { /* fences */
return check_adjacent_blocks(state, x, y, z, state->block); return check_adjacent_blocks(state, x, y, z, state->block);
} else if (state->block == 55) { /* redstone */ } else if (state->block == 55) { /* redstone */
/* three addiotional bit are added, one for on/off state, and /* three addiotional bit are added, one for on/off state, and
* another two for going-up redstone wire in the same block * another two for going-up redstone wire in the same block
@@ -402,7 +408,10 @@ chunk_render(PyObject *self, PyObject *args) {
PyObject *tmp; PyObject *tmp;
unsigned char ancilData = getArrayByte3D(state.blockdata_expanded, state.x, state.y, state.z); unsigned char ancilData = getArrayByte3D(state.blockdata_expanded, state.x, state.y, state.z);
if ((state.block == 85) || (state.block == 9) || (state.block == 55) || (state.block == 54) || (state.block == 2) || (state.block == 90)) { if ((state.block == 2) || (state.block == 9) ||
(state.block == 20) || (state.block == 54) ||
(state.block == 55) || (state.block == 85) ||
(state.block == 90)) {
ancilData = generate_pseudo_data(&state, ancilData); ancilData = generate_pseudo_data(&state, ancilData);
} }

View File

@@ -339,7 +339,7 @@ def _build_full_block(top, side1, side2, side3, side4, bottom=None, blockID=None
increment = 0 increment = 0
if isinstance(top, tuple): if isinstance(top, tuple):
increment = int(math.floor((top[1] / 16.)*12.)) # range increment in the block height in pixels (half texture size) increment = int(round((top[1] / 16.)*12.)) # range increment in the block height in pixels (half texture size)
crop_height = increment crop_height = increment
top = top[0] top = top[0]
if side1 != None: if side1 != None:
@@ -382,7 +382,7 @@ def _build_full_block(top, side1, side2, side3, side4, bottom=None, blockID=None
if bottom != None : if bottom != None :
bottom = transform_image(bottom, blockID) bottom = transform_image(bottom, blockID)
composite.alpha_over(img, bottom, (0,12), top) composite.alpha_over(img, bottom, (0,12), bottom)
# front sides # front sides
if side3 != None : if side3 != None :
@@ -425,7 +425,7 @@ def _build_blockimages():
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
topids = [ -1, 1, 0, 2, 16, 4, -1, 17,205,205,237,237, 18, 19, 32, 33, topids = [ -1, 1, 0, 2, 16, 4, -1, 17,205,205,237,237, 18, 19, 32, 33,
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
34, -1, 52, 48, 49,160,144, -1,176, 74, -1, -1, -1, -1, 11, -1, 34, -1, 52, 48, -1,160,144, -1,176, 74, -1, -1, -1, -1, 11, -1,
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 # 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
55, -1, -1, -1, -1, 13, 12, 29, 28, 23, 22, -1, -1, 7, 9, 4, 55, -1, -1, -1, -1, 13, 12, 29, 28, 23, 22, -1, -1, 7, 9, 4,
# 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 # 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
@@ -442,7 +442,7 @@ def _build_blockimages():
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
sideids = [ -1, 1, 3, 2, 16, 4, -1, 17,205,205,237,237, 18, 19, 32, 33, sideids = [ -1, 1, 3, 2, 16, 4, -1, 17,205,205,237,237, 18, 19, 32, 33,
# 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 # 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
34, -1, 52, 48, 49,160,144, -1,192, 74, -1, -1,- 1, -1, 11, -1, 34, -1, 52, 48, -1,160,144, -1,192, 74, -1, -1,- 1, -1, 11, -1,
# 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 # 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
55, -1, -1, -1, -1, 13, 12, 29, 28, 23, 22, -1, -1, 7, 8, 35, 55, -1, -1, -1, -1, 13, 12, 29, 28, 23, 22, -1, -1, 7, 8, 35,
# 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 # 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
@@ -553,33 +553,35 @@ def generate_special_texture(blockID, data):
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
if blockID == 9: # spring water, flowing water and waterfall water if blockID == 9 or blockID == 20: # spring water, flowing water and waterfall water, AND glass
# water and glass share the way to be rendered
watertexture = _load_image("water.png") if blockID == 9:
texture = _load_image("water.png")
else:
texture = terrain_images[49]
if (data & 0b10000) == 16: if (data & 0b10000) == 16:
top = watertexture top = texture
else: top = None else: top = None
if (data & 0b0001) == 1: if (data & 0b0001) == 1:
side1 = watertexture # top left side1 = texture # top left
else: side1 = None else: side1 = None
if (data & 0b1000) == 8: if (data & 0b1000) == 8:
side2 = watertexture # top right side2 = texture # top right
else: side2 = None else: side2 = None
if (data & 0b0010) == 2: if (data & 0b0010) == 2:
side3 = watertexture # bottom left side3 = texture # bottom left
else: side3 = None else: side3 = None
if (data & 0b0100) == 4: if (data & 0b0100) == 4:
side4 = watertexture # bottom right side4 = texture # bottom right
else: side4 = None else: side4 = None
img = _build_full_block(top,None,None,side3,side4) img = _build_full_block(top,None,None,side3,side4)
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
@@ -649,6 +651,7 @@ def generate_special_texture(blockID, data):
return generate_texture_tuple(img, blockID) return generate_texture_tuple(img, blockID)
if blockID == 31: # tall grass if blockID == 31: # tall grass
if data == 0: # dead shrub if data == 0: # dead shrub
texture = terrain_images[55] texture = terrain_images[55]
@@ -661,8 +664,134 @@ def generate_special_texture(blockID, data):
img = _build_block(texture, texture, blockID) img = _build_block(texture, texture, blockID)
return generate_texture_tuple(img,31) return generate_texture_tuple(img,31)
if blockID in (29,33): # sticky and normal body piston.
if blockID == 29: # sticky
piston_t = terrain_images[106].copy()
else: # normal
piston_t = terrain_images[107].copy()
# other textures
side_t = terrain_images[108].copy()
back_t = terrain_images[109].copy()
interior_t = terrain_images[110].copy()
if data & 0x08 == 0x08: # pushed out, non full blocks, tricky stuff
# remove piston texture from piston body
ImageDraw.Draw(side_t).rectangle((0, 0,16,3),outline=(0,0,0,0),fill=(0,0,0,0))
if data & 0x07 == 0x0: # down
side_t = side_t.rotate(180)
img = _build_full_block(back_t ,None ,None ,side_t, side_t)
elif data & 0x07 == 0x1: # up
img = _build_full_block((interior_t, 4) ,None ,None ,side_t, side_t)
elif data & 0x07 == 0x2: # east
img = _build_full_block(side_t , None, None ,side_t.rotate(90), back_t)
elif data & 0x07 == 0x3: # west
img = _build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), None)
temp = transform_image_side(interior_t, blockID)
temp = temp.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, temp, (9,5), temp)
elif data & 0x07 == 0x4: # north
img = _build_full_block(side_t.rotate(90) ,None ,None , None, side_t.rotate(270))
temp = transform_image_side(interior_t, blockID)
composite.alpha_over(img, temp, (3,5), temp)
elif data & 0x07 == 0x5: # south
img = _build_full_block(side_t.rotate(270) ,None , None ,back_t, side_t.rotate(90))
else: # pushed in, normal full blocks, easy stuff
if data & 0x07 == 0x0: # down
side_t = side_t.rotate(180)
img = _build_full_block(back_t ,None ,None ,side_t, side_t)
elif data & 0x07 == 0x1: # up
img = _build_full_block(piston_t ,None ,None ,side_t, side_t)
elif data & 0x07 == 0x2: # east
img = _build_full_block(side_t ,None ,None ,side_t.rotate(90), back_t)
elif data & 0x07 == 0x3: # west
img = _build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), piston_t)
elif data & 0x07 == 0x4: # north
img = _build_full_block(side_t.rotate(90) ,None ,None ,piston_t, side_t.rotate(270))
elif data & 0x07 == 0x5: # south
img = _build_full_block(side_t.rotate(270) ,None ,None ,back_t, side_t.rotate(90))
return generate_texture_tuple(img, blockID)
if blockID == 34: # piston extension (sticky and normal)
if (data & 0x8) == 0x8: # sticky
piston_t = terrain_images[106].copy()
else: # normal
piston_t = terrain_images[107].copy()
# other textures
side_t = terrain_images[108].copy()
back_t = terrain_images[107].copy()
# crop piston body
ImageDraw.Draw(side_t).rectangle((0, 4,16,16),outline=(0,0,0,0),fill=(0,0,0,0))
# generate the horizontal piston extension stick
h_stick = Image.new("RGBA", (24,24), (38,92,255,0))
temp = transform_image_side(side_t, blockID)
composite.alpha_over(h_stick, temp, (1,7), temp)
temp = transform_image(side_t.rotate(90))
composite.alpha_over(h_stick, temp, (1,1), temp)
# Darken it
sidealpha = h_stick.split()[3]
h_stick = ImageEnhance.Brightness(h_stick).enhance(0.85)
h_stick.putalpha(sidealpha)
# generate the vertical piston extension stick
v_stick = Image.new("RGBA", (24,24), (38,92,255,0))
temp = transform_image_side(side_t.rotate(90), blockID)
composite.alpha_over(v_stick, temp, (12,6), temp)
temp = temp.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(v_stick, temp, (1,6), temp)
# Darken it
sidealpha = v_stick.split()[3]
v_stick = ImageEnhance.Brightness(v_stick).enhance(0.85)
v_stick.putalpha(sidealpha)
# Piston orientation is stored in the 3 first bits
if data & 0x07 == 0x0: # down
side_t = side_t.rotate(180)
img = _build_full_block((back_t, 12) ,None ,None ,side_t, side_t)
composite.alpha_over(img, v_stick, (0,-3), v_stick)
elif data & 0x07 == 0x1: # up
img = Image.new("RGBA", (24,24), (38,92,255,0))
img2 = _build_full_block(piston_t ,None ,None ,side_t, side_t)
composite.alpha_over(img, v_stick, (0,4), v_stick)
composite.alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x2: # east
img = _build_full_block(side_t ,None ,None ,side_t.rotate(90), None)
temp = transform_image_side(back_t, blockID).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, temp, (2,2), temp)
composite.alpha_over(img, h_stick, (6,3), h_stick)
elif data & 0x07 == 0x3: # west
img = Image.new("RGBA", (24,24), (38,92,255,0))
img2 = _build_full_block(side_t.rotate(180) ,None ,None ,side_t.rotate(270), piston_t)
composite.alpha_over(img, h_stick, (0,0), h_stick)
composite.alpha_over(img, img2, (0,0), img2)
elif data & 0x07 == 0x4: # north
img = _build_full_block(side_t.rotate(90) ,None ,None , piston_t, side_t.rotate(270))
composite.alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (0,0), h_stick.transpose(Image.FLIP_LEFT_RIGHT))
elif data & 0x07 == 0x5: # south
img = Image.new("RGBA", (24,24), (38,92,255,0))
img2 = _build_full_block(side_t.rotate(270) ,None ,None ,None, side_t.rotate(90))
temp = transform_image_side(back_t, blockID)
composite.alpha_over(img2, temp, (10,2), temp)
composite.alpha_over(img, img2, (0,0), img2)
composite.alpha_over(img, h_stick.transpose(Image.FLIP_LEFT_RIGHT), (-3,2), h_stick.transpose(Image.FLIP_LEFT_RIGHT))
return generate_texture_tuple(img, blockID)
if blockID == 35: # wool if blockID == 35: # wool
if data == 0: # white if data == 0: # white
top = side = terrain_images[64] top = side = terrain_images[64]
@@ -1081,7 +1210,7 @@ def generate_special_texture(blockID, data):
# mask out the high bits to figure out the orientation # mask out the high bits to figure out the orientation
img = Image.new("RGBA", (24,24), (38,92,255,0)) img = Image.new("RGBA", (24,24), (38,92,255,0))
if (data & 0x03) == 0: if (data & 0x03) == 0: # northeast corner
if not swung: if not swung:
tex = transform_image_side(raw_door) tex = transform_image_side(raw_door)
composite.alpha_over(img, tex, (0,6), tex) composite.alpha_over(img, tex, (0,6), tex)
@@ -1091,7 +1220,7 @@ def generate_special_texture(blockID, data):
tex = tex.transpose(Image.FLIP_LEFT_RIGHT) tex = tex.transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (0,0), tex) composite.alpha_over(img, tex, (0,0), tex)
if (data & 0x03) == 1: if (data & 0x03) == 1: # southeast corner
if not swung: if not swung:
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT) tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (0,0), tex) composite.alpha_over(img, tex, (0,0), tex)
@@ -1099,7 +1228,7 @@ def generate_special_texture(blockID, data):
tex = transform_image_side(raw_door) tex = transform_image_side(raw_door)
composite.alpha_over(img, tex, (12,0), tex) composite.alpha_over(img, tex, (12,0), tex)
if (data & 0x03) == 2: if (data & 0x03) == 2: # southwest corner
if not swung: if not swung:
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)) tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT))
composite.alpha_over(img, tex, (12,0), tex) composite.alpha_over(img, tex, (12,0), tex)
@@ -1107,7 +1236,7 @@ def generate_special_texture(blockID, data):
tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT) tex = transform_image_side(raw_door).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (12,6), tex) composite.alpha_over(img, tex, (12,6), tex)
if (data & 0x03) == 3: if (data & 0x03) == 3: # northwest corner
if not swung: if not swung:
tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT) tex = transform_image_side(raw_door.transpose(Image.FLIP_LEFT_RIGHT)).transpose(Image.FLIP_LEFT_RIGHT)
composite.alpha_over(img, tex, (12,6), tex) composite.alpha_over(img, tex, (12,6), tex)
@@ -1609,9 +1738,10 @@ def getBiomeData(worlddir, chunkX, chunkY):
# (when adding new blocks here and in generate_special_textures, # (when adding new blocks here and in generate_special_textures,
# please, if possible, keep the ascending order of blockid value) # please, if possible, keep the ascending order of blockid value)
special_blocks = set([ 2, 6, 9, 17, 18, 26, 23, 27, 28, 31, 35, 43, 44, special_blocks = set([ 2, 6, 9, 17, 18, 20, 26, 23, 27, 28, 29, 31, 33,
50, 51, 53, 54, 55, 58, 59, 61, 62, 63, 64, 65, 66, 34, 35, 43, 44, 50, 51, 53, 54, 55, 58, 59, 61, 62,
67, 68, 71, 75, 76, 85, 86, 90, 91, 92, 93, 94, 96]) 63, 64, 65, 66, 67, 68, 71, 75, 76, 85, 86, 90, 91,
92, 93, 94, 96])
# this is a map of special blockIDs to a list of all # this is a map of special blockIDs to a list of all
# possible values for ancillary data that it might have. # possible values for ancillary data that it might have.
@@ -1621,10 +1751,14 @@ special_map = {}
special_map[6] = range(16) # saplings: usual, spruce, birch and future ones (rendered as usual saplings) special_map[6] = range(16) # saplings: usual, spruce, birch and future ones (rendered as usual saplings)
special_map[9] = range(32) # water: spring,flowing, waterfall, and others (unknown) ancildata values, uses pseudo data special_map[9] = range(32) # water: spring,flowing, waterfall, and others (unknown) ancildata values, uses pseudo data
special_map[17] = range(3) # wood: normal, birch and pine special_map[17] = range(3) # wood: normal, birch and pine
special_map[20] = range(32) # glass, used to only render the exterior surface, uses pseudo data
special_map[26] = range(12) # bed, orientation special_map[26] = range(12) # bed, orientation
special_map[23] = range(6) # dispensers, orientation special_map[23] = range(6) # dispensers, orientation
special_map[27] = range(14) # powered rail, orientation/slope and powered/unpowered special_map[27] = range(14) # powered rail, orientation/slope and powered/unpowered
special_map[28] = range(6) # detector rail, orientation/slope special_map[28] = range(6) # detector rail, orientation/slope
special_map[29] = (0,1,2,3,4,5,8,9,10,11,12,13) # sticky piston body, orientation, pushed in/out
special_map[33] = (0,1,2,3,4,5,8,9,10,11,12,13) # normal piston body, orientation, pushed in/out
special_map[34] = (0,1,2,3,4,5,8,9,10,11,12,13) # normal and sticky piston extension, orientation, sticky/normal
special_map[35] = range(16) # wool, colored and white special_map[35] = range(16) # wool, colored and white
special_map[43] = range(4) # stone, sandstone, wooden and cobblestone double-slab special_map[43] = range(4) # stone, sandstone, wooden and cobblestone double-slab
special_map[44] = range(4) # stone, sandstone, wooden and cobblestone slab special_map[44] = range(4) # stone, sandstone, wooden and cobblestone slab