0

preliminary chunk-scan algorithm activated.

forcerender and stochastic are currently broken.
This commit is contained in:
Andrew Brown
2011-11-07 22:18:51 -05:00
parent 636913af57
commit 13f3ba90ab

View File

@@ -218,7 +218,11 @@ class QuadtreeGen(object):
def get_chunks_in_range(self, colstart, colend, rowstart, rowend): def get_chunks_in_range(self, colstart, colend, rowstart, rowend):
"""Get chunks that are relevant to the tile rendering function that's """Get chunks that are relevant to the tile rendering function that's
rendering that range""" rendering that range
Returns a list of chunks where each item is
(col, row, chunkx, chunky, regionfilename)
"""
chunklist = [] chunklist = []
unconvert_coords = self.world.unconvert_coords unconvert_coords = self.world.unconvert_coords
#get_region_path = self.world.get_region_path #get_region_path = self.world.get_region_path
@@ -250,17 +254,14 @@ class QuadtreeGen(object):
return chunklist return chunklist
def get_worldtiles(self): def get_worldtiles(self):
"""Returns an iterator over the tiles of the most detailed layer """Returns an iterator over the tiles of the most detailed layer that
""" need to be rendered
for path in iterate_base4(self.p):
# Get the range for this tile
tile = Tile.from_path(path)
# Put this in the batch to be submited to the pool. """
# The quadtree object gets replaced by the caller in rendernode.py, # This quadtree object gets replaced by the caller in rendernode.py,
# but we still have to let them know which quadtree this tile # but we still have to let them know which quadtree this tile belongs
# belongs to. # to. Hence returning both self and the tile.
yield [self, tile] return ((self, tile) for tile in self.scan_chunks())
def get_innertiles(self,zoom): def get_innertiles(self,zoom):
"""Same as get_worldtiles but for the inntertile routine. """Same as get_worldtiles but for the inntertile routine.
@@ -340,15 +341,21 @@ class QuadtreeGen(object):
def render_worldtile(self, tile): def render_worldtile(self, tile, check_tile=False):
"""Renders the given tile. All the other relevant information is """Renders the given tile. All the other relevant information is
already stored in this quadtree object or in self.world. already stored in this quadtree object or in self.world.
This function is typically called in the child process. The tile is
assumed to need rendering unless the check_tile flag is given.
If check_tile is true, the mtimes of the chunk are compared with the
mtime of this tile and the tile is conditionally rendered.
The image is rendered and saved to disk in the place this quadtree is The image is rendered and saved to disk in the place this quadtree is
configured to store images. configured to store images.
If there are no chunks, this tile is not saved (if it already exists, it is If there are no chunks, this tile is not saved. If this is the case but
deleted) the tile exists, it is deleted
There is no return value There is no return value
""" """
@@ -371,19 +378,26 @@ class QuadtreeGen(object):
chunks = self.get_chunks_in_range(colstart, colend, rowstart, rowend) chunks = self.get_chunks_in_range(colstart, colend, rowstart, rowend)
world = self.world world = self.world
tile_mtime = None
if check_tile:
#stat the file, we need to know if it exists or it's mtime #stat the file, we need to know if it exists or it's mtime
try: try:
tile_mtime = os.stat(imgpath)[stat.ST_MTIME] tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
except OSError, e: except OSError, e:
# ignore only if the error was "file not found"
if e.errno != errno.ENOENT: if e.errno != errno.ENOENT:
raise raise
tile_mtime = None
if not chunks: if not chunks:
# No chunks were found in this tile # No chunks were found in this tile
if tile_mtime is not None: try:
os.unlink(imgpath) os.unlink(imgpath)
return None except OSError, e:
# ignore only if the error was "file not found"
if e.errno != errno.ENOENT:
raise
return
# Create the directory if not exists # Create the directory if not exists
dirdest = os.path.dirname(imgpath) dirdest = os.path.dirname(imgpath)
@@ -391,13 +405,15 @@ class QuadtreeGen(object):
try: try:
os.makedirs(dirdest) os.makedirs(dirdest)
except OSError, e: except OSError, e:
# Ignore errno EEXIST: file exists. Since this is multithreaded, # Ignore errno EEXIST: file exists. Due to a race condition,
# two processes could conceivably try and create the same directory # two processes could conceivably try and create the same
# at the same time. # directory at the same time
if e.errno != errno.EEXIST: if e.errno != errno.EEXIST:
raise raise
# check chunk mtimes to see if they are newer if check_tile:
# Look at all the chunks that touch this tile and their mtimes to
# determine if this tile actually needs rendering
try: try:
needs_rerender = False needs_rerender = False
get_region_mtime = world.get_region_mtime get_region_mtime = world.get_region_mtime
@@ -414,13 +430,6 @@ class QuadtreeGen(object):
needs_rerender = True needs_rerender = True
break break
# check region file mtime first.
# on windows (and possibly elsewhere) minecraft won't update
# the region file mtime until after shutdown.
# for servers this is unacceptable, so skip this check.
#if regionMtime <= tile_mtime:
# continue
# checking chunk mtime # checking chunk mtime
if region.get_chunk_timestamp(chunkx, chunky) > tile_mtime: if region.get_chunk_timestamp(chunkx, chunky) > tile_mtime:
needs_rerender = True needs_rerender = True
@@ -432,17 +441,19 @@ class QuadtreeGen(object):
# if after all that, we don't need a rerender, return # if after all that, we don't need a rerender, return
if not needs_rerender: if not needs_rerender:
return None return
except OSError: except OSError:
# couldn't get tile mtime, skip check # couldn't get tile mtime, skip check and assume it does
pass pass
# We have all the necessary info and this tile has passed the checks
# and should be rendered. So do it!
#logging.debug("writing out worldtile {0}".format(imgpath)) #logging.debug("writing out worldtile {0}".format(imgpath))
# Compile this image # Compile this image
tileimg = Image.new("RGBA", (width, height), self.bgcolor) tileimg = Image.new("RGBA", (width, height), self.bgcolor)
world = self.world
rendermode = self.rendermode rendermode = self.rendermode
# col colstart will get drawn on the image starting at x coordinates -(384/2) # col colstart will get drawn on the image starting at x coordinates -(384/2)
# row rowstart will get drawn on the image starting at y coordinates -(192/2) # row rowstart will get drawn on the image starting at y coordinates -(192/2)