0

Merge branch 'master' into dtt-merge

Conflicts:
	chunk.py
This commit is contained in:
Aaron Griffith
2011-03-06 18:05:28 -05:00
5 changed files with 231 additions and 227 deletions

View File

@@ -92,10 +92,10 @@ biome-accurate tinting, the Overviewer can use biome data produced by the
Minecraft Biome Extractor tool. This tool can be downloaded from: Minecraft Biome Extractor tool. This tool can be downloaded from:
http://www.minecraftforum.net/viewtopic.php?f=25&t=80902 http://www.minecraftforum.net/viewtopic.php?f=25&t=80902
If the EXTRACTEDBIOMES folder is present in the world directory, then the If the "biomes" folder is present in the world directory, then the Overviewer
Overviewer will use the biome data to tint grass and leaves automatically -- will use the biome data to tint grass and leaves automatically -- there is no
there is no command line option to turn this feature on. If this folder does command line option to turn this feature on. If this folder does not exist,
not exist, then the Overviewer will use a static tinting for grass and leaves. then the Overviewer will use a static tinting for grass and leaves.
Compiling the C Extension (optional) Compiling the C Extension (optional)
------------------------------------ ------------------------------------

420
chunk.py
View File

@@ -48,8 +48,13 @@ image
def get_lvldata(filename, x, y): def get_lvldata(filename, x, y):
"""Takes a filename and chunkcoords and returns the Level struct, which contains all the """Takes a filename and chunkcoords and returns the Level struct, which contains all the
level info""" level info"""
d = nbt.load_from_region(filename, x, y) try:
d = nbt.load_from_region(filename, x, y)
except Exception, e:
logging.warning("Error opening chunk (%i, %i) in %s. It may be corrupt. %s", x, y, filename, e)
raise ChunkCorrupt(str(e))
if not d: raise NoSuchChunk(x,y) if not d: raise NoSuchChunk(x,y)
return d[1]['Level'] return d[1]['Level']
@@ -96,21 +101,6 @@ def get_tileentity_data(level):
data = level['TileEntities'] data = level['TileEntities']
return data return data
def iterate_chunkblocks(xoff,yoff):
"""Iterates over the 16x16x128 blocks of a chunk in rendering order.
Yields (x,y,z,imgx,imgy)
x,y,z is the block coordinate in the chunk
imgx,imgy is the image offset in the chunk image where that block should go
"""
for x in xrange(15,-1,-1):
for y in xrange(16):
imgx = xoff + x*12 + y*12
imgy = yoff - x*6 + y*6 + 128*12 + 16*12//2
for z in xrange(128):
yield x,y,z,imgx,imgy
imgy -= 12
# 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, 37, 38, 39, 40, 44, 50, 51, 52, 53, 55, transparent_blocks = set([0, 6, 8, 9, 18, 20, 37, 38, 39, 40, 44, 50, 51, 52, 53, 55,
59, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 83, 85]) 59, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 74, 75, 76, 77, 78, 79, 81, 83, 85])
@@ -207,11 +197,8 @@ class ChunkRenderer(object):
try: try:
self._level = get_lvldata(self.regionfile, self.chunkX, self.chunkY) self._level = get_lvldata(self.regionfile, self.chunkX, self.chunkY)
except NoSuchChunk, e: except NoSuchChunk, e:
#logging.debug("Skipping non-existant chunk") logging.debug("Skipping non-existant chunk")
raise raise
except Exception, e:
logging.warning("Error opening chunk file %s. It may be corrupt. %s", self.regionfile, e)
raise ChunkCorrupt(str(e))
return self._level return self._level
level = property(_load_level) level = property(_load_level)
@@ -543,9 +530,9 @@ class ChunkRenderer(object):
if self.world.useBiomeData: if self.world.useBiomeData:
biomeColorData = textures.getBiomeData(self.world.worlddir, biomeColorData = textures.getBiomeData(self.world.worlddir,
self.chunkX, self.chunkY) self.chunkX, self.chunkY)
# in the 8x8 block of biome data, what chunk is this?l # in the 32x32 block of biome data, what chunk is this?l
startX = (self.chunkX - int(math.floor(self.chunkX/8)*8)) startX = self.chunkX % 32
startY = (self.chunkY - int(math.floor(self.chunkY/8)*8)) startY = self.chunkY % 32
# Each block is 24x24 # Each block is 24x24
# The next block on the X axis adds 12px to x and subtracts 6px from y in the image # The next block on the X axis adds 12px to x and subtracts 6px from y in the image
@@ -557,201 +544,214 @@ class ChunkRenderer(object):
if not img: if not img:
img = Image.new("RGBA", (384, 1728), (38,92,255,0)) img = Image.new("RGBA", (384, 1728), (38,92,255,0))
for x,y,z,imgx,imgy in iterate_chunkblocks(xoff,yoff): for x in xrange(15,-1,-1):
# make sure we're drawing within the image boundaries for y in xrange(16):
# 24 == approximate width, height of one block imgx = xoff + x*12 + y*12
if imgx >= img.size[0] + 24 or imgx <= -24: imgy = yoff - x*6 + y*6 + 128*12 + 16*12//2
continue imgy += 12
if imgy >= img.size[1] + 24 or imgy <= -24:
continue
blockid = blocks[x,y,z]
# the following blocks don't have textures that can be pre-computed from the blockid
# alone. additional data is required.
# TODO torches, redstone torches, crops, ladders, stairs,
# levers, doors, buttons, and signs all need to be handled here (and in textures.py)
## minecart track, crops, ladder, doors, etc.
if blockid in textures.special_blocks:
# also handle furnaces here, since one side has a different texture than the other
ancilData = blockData_expanded[x,y,z]
try:
if blockid in pseudo_ancildata_blocks:
pseudo_ancilData = self.generate_pseudo_ancildata(x,y,z,blockid)
ancilData = pseudo_ancilData
t = textures.specialblockmap[(blockid, ancilData)]
except KeyError:
t = None
else:
t = textures.blockmap[blockid]
if not t:
continue
if self.world.useBiomeData:
if blockid == 2: #grass
index = biomeColorData[ ((startY*16)+y) * 128 + (startX*16) + x]
c = textures.grasscolor[index]
# only tint the top texture
t = textures.prepareGrassTexture(c)
elif blockid == 18: # leaves
index = biomeColorData[ ((startY*16)+y) * 128 + (startX*16) + x]
c = textures.foliagecolor[index]
t = textures.prepareLeafTexture(c)
# Check if this block is occluded
if cave and (
x == 0 and y != 15 and z != 127
):
# If it's on the x face, only render if there's a
# transparent block in the y+1 direction OR the z-1
# direction
if (
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif cave and (
y == 15 and x != 0 and z != 127
):
# If it's on the facing y face, only render if there's
# a transparent block in the x-1 direction OR the z-1
# direction
if (
blocks[x-1,y,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif cave and (
y == 15 and x == 0 and z != 127
):
# If it's on the facing edge, only render if what's
# above it is transparent
if (
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks == None and right_blocks == None):
# Normal block or not cave mode, check sides for
# transparentcy or render if it's a border chunk.
if (
x != 0 and y != 15 and z != 127 and
blocks[x-1,y,z] not in transparent_blocks and
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks != None and right_blocks == None):
if (
# If it has the left face covered check for
# transparent blocks in left face
y != 15 and z != 127 and
(left_blocks[15,y,z] if x == 0 else blocks[x - 1,y,z]) not in transparent_blocks and
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks == None and right_blocks != None):
if (
# If it has the right face covered check for
# transparent blocks in right face
x != 0 and z != 127 and
blocks[x-1,y,z] not in transparent_blocks and
(right_blocks[x,0,z] if y == 15 else blocks[x,y + 1,z]) not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif ( # make sure we're drawing within the image boundaries
# If it's a interior chunk check for transparent blocks # 24 == approximate width, height of one block
# in the adjacent chunks. if imgx >= img.size[0] + 24 or imgx <= -24:
z != 127 and
(left_blocks[15,y,z] if x == 0 else blocks[x - 1,y,z]) not in transparent_blocks and
(right_blocks[x,0,z] if y == 15 else blocks[x,y + 1,z]) not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
# Don't render if all sides aren't transparent
):
continue continue
# Draw the actual block on the image. For cave images, for z in xrange(128):
# tint the block with a color proportional to its depth imgy -= 12
if cave:
# no lighting for cave -- depth is probably more useful
composite.alpha_over(img, Image.blend(t[0],depth_colors[z],0.3), (imgx, imgy), t[1])
else:
if not self.quadtree.lighting:
# no lighting at all
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
elif blockid in transparent_blocks:
# transparent means draw the whole
# block shaded with the current
# block's light
black_coeff, _ = self.get_lighting_coefficient(x, y, z)
if self.quadtree.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
blockid in nospawn_blocks or (
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
)
):
composite.alpha_over(img, Image.blend(t[0], red_color, black_coeff), (imgx, imgy), t[1])
else:
composite.alpha_over(img, Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
else:
# draw each face lit appropriately,
# but first just draw the block
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
# top face # similar check for y, as above
black_coeff, face_occlude = self.get_lighting_coefficient(x, y, z + 1) if imgy >= img.size[1] + 24 or imgy <= -24:
# Use red instead of black for spawnable blocks continue
if self.quadtree.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
blockid in nospawn_blocks or ( blockid = blocks[x,y,z]
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
) # the following blocks don't have textures that can be pre-computed from the blockid
): # alone. additional data is required.
over_color = red_color # TODO torches, redstone torches, crops, ladders, stairs,
# levers, doors, buttons, and signs all need to be handled here (and in textures.py)
## minecart track, crops, ladder, doors, etc.
if blockid in textures.special_blocks:
# also handle furnaces here, since one side has a different texture than the other
ancilData = blockData_expanded[x,y,z]
try:
if blockid in pseudo_ancildata_blocks:
pseudo_ancilData = self.generate_pseudo_ancildata(x,y,z,blockid)
ancilData = pseudo_ancilData
t = textures.specialblockmap[(blockid, ancilData)]
except KeyError:
t = None
else: else:
over_color = black_color t = textures.blockmap[blockid]
if not face_occlude: if not t:
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff)) continue
# left face
black_coeff, face_occlude = self.get_lighting_coefficient(x - 1, y, z)
if not face_occlude:
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
# right face if self.world.useBiomeData:
black_coeff, face_occlude = self.get_lighting_coefficient(x, y + 1, z) # 16 : number of blocks in a chunk (in one direction)
if not face_occlude: # 32 : number of chunks in a region (and biome file) in one direction
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff)) # so 16 * 32 == 512 : number of blocks in biome file, in one direction
if blockid == 2: #grass
index = biomeColorData[ ((startY*16)+y) * 512 + (startX*16) + x]
c = textures.grasscolor[index]
# Draw edge lines # only tint the top texture
if blockid in (44,): # step block t = textures.prepareGrassTexture(c)
increment = 6 elif blockid == 18: # leaves
elif blockid in (78,): # snow index = biomeColorData[ ((startY*16)+y) * 512 + (startX*16) + x]
increment = 9 c = textures.foliagecolor[index]
else:
increment = 0
if blockid not in transparent_blocks or blockid in (78,): #special case snow so the outline is still drawn t = textures.prepareLeafTexture(c)
draw = ImageDraw.Draw(img)
if x != 15 and blocks[x+1,y,z] == 0:
draw.line(((imgx+12,imgy+increment), (imgx+22,imgy+5+increment)), fill=(0,0,0), width=1)
if y != 0 and blocks[x,y-1,z] == 0:
draw.line(((imgx,imgy+6+increment), (imgx+12,imgy+increment)), fill=(0,0,0), width=1) # Check if this block is occluded
if cave and (
x == 0 and y != 15 and z != 127
):
# If it's on the x face, only render if there's a
# transparent block in the y+1 direction OR the z-1
# direction
if (
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif cave and (
y == 15 and x != 0 and z != 127
):
# If it's on the facing y face, only render if there's
# a transparent block in the x-1 direction OR the z-1
# direction
if (
blocks[x-1,y,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif cave and (
y == 15 and x == 0 and z != 127
):
# If it's on the facing edge, only render if what's
# above it is transparent
if (
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks == None and right_blocks == None):
# Normal block or not cave mode, check sides for
# transparentcy or render if it's a border chunk.
if (
x != 0 and y != 15 and z != 127 and
blocks[x-1,y,z] not in transparent_blocks and
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks != None and right_blocks == None):
if (
# If it has the left face covered check for
# transparent blocks in left face
y != 15 and z != 127 and
(left_blocks[15,y,z] if x == 0 else blocks[x - 1,y,z]) not in transparent_blocks and
blocks[x,y+1,z] not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (left_blocks == None and right_blocks != None):
if (
# If it has the right face covered check for
# transparent blocks in right face
x != 0 and z != 127 and
blocks[x-1,y,z] not in transparent_blocks and
(right_blocks[x,0,z] if y == 15 else blocks[x,y + 1,z]) not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
):
continue
elif (
# If it's a interior chunk check for transparent blocks
# in the adjacent chunks.
z != 127 and
(left_blocks[15,y,z] if x == 0 else blocks[x - 1,y,z]) not in transparent_blocks and
(right_blocks[x,0,z] if y == 15 else blocks[x,y + 1,z]) not in transparent_blocks and
blocks[x,y,z+1] not in transparent_blocks
# Don't render if all sides aren't transparent
):
continue
# Draw the actual block on the image. For cave images,
# tint the block with a color proportional to its depth
if cave:
# no lighting for cave -- depth is probably more useful
composite.alpha_over(img, Image.blend(t[0],depth_colors[z],0.3), (imgx, imgy), t[1])
else:
if not self.quadtree.lighting:
# no lighting at all
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
elif blockid in transparent_blocks:
# transparent means draw the whole
# block shaded with the current
# block's light
black_coeff, _ = self.get_lighting_coefficient(x, y, z)
if self.quadtree.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
blockid in nospawn_blocks or (
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
)
):
composite.alpha_over(img, Image.blend(t[0], red_color, black_coeff), (imgx, imgy), t[1])
else:
composite.alpha_over(img, Image.blend(t[0], black_color, black_coeff), (imgx, imgy), t[1])
else:
# draw each face lit appropriately,
# but first just draw the block
composite.alpha_over(img, t[0], (imgx, imgy), t[1])
# top face
black_coeff, face_occlude = self.get_lighting_coefficient(x, y, z + 1)
# Use red instead of black for spawnable blocks
if self.quadtree.spawn and black_coeff > 0.8 and blockid in solid_blocks and not (
blockid in nospawn_blocks or (
z != 127 and (blocks[x,y,z+1] in solid_blocks or blocks[x,y,z+1] in fluid_blocks)
)
):
over_color = red_color
else:
over_color = black_color
if not face_occlude:
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[0]).enhance(black_coeff))
# left face
black_coeff, face_occlude = self.get_lighting_coefficient(x - 1, y, z)
if not face_occlude:
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[1]).enhance(black_coeff))
# right face
black_coeff, face_occlude = self.get_lighting_coefficient(x, y + 1, z)
if not face_occlude:
composite.alpha_over(img, over_color, (imgx, imgy), ImageEnhance.Brightness(facemasks[2]).enhance(black_coeff))
# Draw edge lines
if blockid in (44,): # step block
increment = 6
elif blockid in (78,): # snow
increment = 9
else:
increment = 0
if blockid not in transparent_blocks or blockid in (78,): #special case snow so the outline is still drawn
draw = ImageDraw.Draw(img)
if x != 15 and blocks[x+1,y,z] == 0:
draw.line(((imgx+12,imgy+increment), (imgx+22,imgy+5+increment)), fill=(0,0,0), width=1)
if y != 0 and blocks[x,y-1,z] == 0:
draw.line(((imgx,imgy+6+increment), (imgx+12,imgy+increment)), fill=(0,0,0), width=1)
for entity in tileEntities: for entity in tileEntities:

13
gmap.py
View File

@@ -70,6 +70,13 @@ def main():
if not os.path.exists(worlddir): if not os.path.exists(worlddir):
# world given is either world number, or name # world given is either world number, or name
worlds = world.get_worlds() worlds = world.get_worlds()
# if there are no worlds found at all, exit now
if not worlds:
parser.print_help()
print "\nInvalid world path"
sys.exit(1)
try: try:
worldnum = int(worlddir) worldnum = int(worlddir)
worlddir = worlds[worldnum]['path'] worlddir = worlds[worldnum]['path']
@@ -79,13 +86,13 @@ def main():
worlddir = worlds[worlddir]['path'] worlddir = worlds[worlddir]['path']
except KeyError: except KeyError:
# it's not a number, name, or path # it's not a number, name, or path
print "Invalid world name or path"
parser.print_help() parser.print_help()
print "Invalid world name or path"
sys.exit(1) sys.exit(1)
except KeyError: except KeyError:
# it was an invalid number # it was an invalid number
print "Invalid world number"
parser.print_help() parser.print_help()
print "Invalid world number"
sys.exit(1) sys.exit(1)
if len(args) != 2: if len(args) != 2:
@@ -128,7 +135,7 @@ def main():
if not composite.extension_alpha_over: if not composite.extension_alpha_over:
logging.info("Notice: alpha_over extension not found; using default PIL paste()") logging.info("Notice: alpha_over extension not found; using default PIL paste()")
useBiomeData = os.path.exists(os.path.join(worlddir, 'EXTRACTEDBIOMES')) useBiomeData = os.path.exists(os.path.join(worlddir, 'biomes'))
if not useBiomeData: if not useBiomeData:
logging.info("Notice: Not using biome data for tinting") logging.info("Notice: Not using biome data for tinting")

View File

@@ -120,7 +120,7 @@ class QuadtreeGen(object):
yradius >= worldobj.maxrow and -yradius <= worldobj.minrow: yradius >= worldobj.maxrow and -yradius <= worldobj.minrow:
break break
else: else:
raise ValueError("Your map is waaaay too big!") raise ValueError("Your map is waaaay too big! Use the '-z' or '--zoom' options.")
self.p = p self.p = p
else: else:

View File

@@ -283,7 +283,7 @@ def _build_blockimages():
# 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
36, 37, 80, -1, 65, 4, 25, -1, 98, 24, 43, -1, 86, -1, -1, -1, # Torch from above? leaving out fire. Redstone wire? Crops/furnaces handled elsewhere. sign post 36, 37, 80, -1, 65, 4, 25, -1, 98, 24, 43, -1, 86, -1, -1, -1, # Torch from above? leaving out fire. Redstone wire? Crops/furnaces handled elsewhere. sign post
# 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 # 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
-1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67, # door,ladder left out. Minecart rail orientation -1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, -1, 66, 67, # door,ladder left out. Minecart rail orientation
# 80 81 82 83 84 85 86 87 88 89 90 91 # 80 81 82 83 84 85 86 87 88 89 90 91
66, 69, 72, 73, 74, -1,102,103,104,105,-1, 102 # clay? 66, 69, 72, 73, 74, -1,102,103,104,105,-1, 102 # clay?
] ]
@@ -300,7 +300,7 @@ def _build_blockimages():
# 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
36, 37, 80, -1, 65, 4, 25,101, 98, 24, 43, -1, 86, -1, -1, -1, 36, 37, 80, -1, 65, 4, 25,101, 98, 24, 43, -1, 86, -1, -1, -1,
# 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 # 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
-1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, 1, 66, 67, -1, -1, -1, 16, -1, -1, -1, -1, -1, 51, 51, -1, -1, -1, 66, 67,
# 80 81 82 83 84 85 86 87 88 89 90 91 # 80 81 82 83 84 85 86 87 88 89 90 91
66, 69, 72, 73, 74,-1 ,118,103,104,105, -1, 118 66, 69, 72, 73, 74,-1 ,118,103,104,105, -1, 118
] ]
@@ -824,9 +824,9 @@ def prepareBiomeData(worlddir):
if grasscolor and foliagecolor: if grasscolor and foliagecolor:
return return
biomeDir = os.path.join(worlddir, "EXTRACTEDBIOMES") biomeDir = os.path.join(worlddir, "biomes")
if not os.path.exists(biomeDir): if not os.path.exists(biomeDir):
raise Exception("EXTRACTEDBIOMES not found") raise Exception("biomes not found")
# try to find the biome color images. If _find_file can't locate them # try to find the biome color images. If _find_file can't locate them
# then try looking in the EXTRACTEDBIOMES folder # then try looking in the EXTRACTEDBIOMES folder
@@ -850,16 +850,13 @@ def getBiomeData(worlddir, chunkX, chunkY):
global currentBiomeFile, currentBiomeData global currentBiomeFile, currentBiomeData
biomeFile = "%d.%d.biome" % ( biomeFile = "b.%d.%d.biome" % (chunkX // 32, chunkY // 32)
int(math.floor(chunkX/8)*8),
int(math.floor(chunkY/8)*8)
)
if biomeFile == currentBiomeFile: if biomeFile == currentBiomeFile:
return currentBiomeData return currentBiomeData
currentBiomeFile = biomeFile currentBiomeFile = biomeFile
f = open(os.path.join(worlddir, "EXTRACTEDBIOMES", biomeFile), "rb") f = open(os.path.join(worlddir, "biomes", biomeFile), "rb")
rawdata = f.read() rawdata = f.read()
f.close() f.close()