0

Merge remote-tracking branch 'ion1/master'

This commit is contained in:
Aaron Griffith
2013-12-28 01:12:46 -05:00
6 changed files with 208 additions and 276 deletions

View File

@@ -4,7 +4,7 @@ python:
- "2.7" - "2.7"
# - "3.2" # - "3.2"
env: env:
- MC_VERSION=1.7.2 - MC_VERSION=1.7.4
before_install: before_install:
- wget http://hg.effbot.org/pil-117/raw/f356a1f64271/libImaging/Imaging.h - wget http://hg.effbot.org/pil-117/raw/f356a1f64271/libImaging/Imaging.h
- wget http://hg.effbot.org/pil-117/raw/f356a1f64271/libImaging/ImPlatform.h - wget http://hg.effbot.org/pil-117/raw/f356a1f64271/libImaging/ImPlatform.h
@@ -16,9 +16,16 @@ before_script:
- git clone git://github.com/overviewer/Minecraft-Overviewer-Addons.git ~/mcoa/ - git clone git://github.com/overviewer/Minecraft-Overviewer-Addons.git ~/mcoa/
- wget -N https://s3.amazonaws.com/Minecraft.Download/versions/${MC_VERSION}/${MC_VERSION}.jar -P ~/.minecraft/versions/${MC_VERSION}/ - wget -N https://s3.amazonaws.com/Minecraft.Download/versions/${MC_VERSION}/${MC_VERSION}.jar -P ~/.minecraft/versions/${MC_VERSION}/
script: script:
- PYTHONPATH=. python test/test_all.py
- python overviewer.py ~/mcoa/exmaple ~/test-output --rendermodes=smooth-lighting -p1 - python overviewer.py ~/mcoa/exmaple ~/test-output --rendermodes=smooth-lighting -p1
notifications: notifications:
email: false email: false
irc:
channels:
- "irc.freenode.org#overviewer"
skip_join: true
template:
- "\x0313Minecraft-Overviewer\x03/\x0306%{branch}\x03 \x0314%{commit}\x03 %{build_url} %{message}"
# matrix: # matrix:
# allow_failures: # allow_failures:
# - python: "3.2" # - python: "3.2"

View File

@@ -25,7 +25,7 @@ import time
import errno import errno
import stat import stat
from collections import namedtuple from collections import namedtuple
from itertools import product, izip from itertools import product, izip, chain
from PIL import Image from PIL import Image
@@ -377,7 +377,7 @@ class TileSet(object):
# This warning goes here so it's only shown once # This warning goes here so it's only shown once
if self.treedepth >= 15: if self.treedepth >= 15:
logging.warning("Just letting you know, your map requries %s zoom levels. This is REALLY big!", logging.warning("Just letting you know, your map requires %s zoom levels. This is REALLY big!",
self.treedepth) self.treedepth)
# Do any tile re-arranging if necessary. Skip if there was no config # Do any tile re-arranging if necessary. Skip if there was no config
@@ -446,7 +446,7 @@ class TileSet(object):
# render. Iterate over the tiles in using the posttraversal() method. # render. Iterate over the tiles in using the posttraversal() method.
# Yield each item. Easy. # Yield each item. Easy.
if self.options['renderchecks'] in (0,2): if self.options['renderchecks'] in (0,2):
for tilepath in self.dirtytree.posttraversal(): for tilepath in self.dirtytree.posttraversal(robin=True):
dependencies = [] dependencies = []
# These tiles may or may not exist, but the dispatcher won't # These tiles may or may not exist, but the dispatcher won't
# care according to the worker interface protocol It will only # care according to the worker interface protocol It will only
@@ -1268,21 +1268,19 @@ class RendertileSet(object):
It is typically used to hold tiles that need rendering. This implementation It is typically used to hold tiles that need rendering. This implementation
collapses subtrees that are completely in or out of the set to save memory. collapses subtrees that are completely in or out of the set to save memory.
Each instance of this class is a node in the tree, and therefore each An instance of this class holds a full tree.
instance is the root of a subtree.
Each node knows its "level", which corresponds to the zoom level where 0 is The instance knows its "level", which corresponds to the zoom level where 1
the inner-most (most zoomed in) tiles. is the inner-most (most zoomed in) tiles.
Instances hold the state of their children (in or out of the set). Leaf Instances hold the state of their children (in or out of the set). Leaf
nodes are images and do not physically exist in the tree as objects, but nodes are images and do not physically exist in the tree as objects, but
are represented as booleans held by the objects at the second-to-last are represented as booleans held by the objects at the second-to-last
level; level 1 nodes keep track of leaf image state. Level 2 nodes keep level; level 1 nodes keep track of leaf image state. Level 2 nodes keep
track of level 1 state, and so fourth. track of level 1 state, and so forth.
""" """
__slots__ = ("depth", "children") __slots__ = ("depth", "children", "num_tiles", "num_tiles_all")
def __init__(self, depth): def __init__(self, depth):
"""Initialize a new tree with the specified depth. This actually """Initialize a new tree with the specified depth. This actually
initializes a node, which is the root of a subtree, with `depth` levels initializes a node, which is the root of a subtree, with `depth` levels
@@ -1303,52 +1301,15 @@ class RendertileSet(object):
# All children down this subtree are not in the set # All children down this subtree are not in the set
# True # True
# All children down this subtree are in the set # All children down this subtree are in the set
# A RendertileSet instance # An array of the same format
# the instance defines which children down that subtree are in the # The array defines which children down that subtree are in the set
# set.
# A node with depth=1 cannot have a RendertileSet instance in its # A node with depth=1 cannot have a RendertileSet instance in its
# children since its children are leaves, representing images, not more # children since its children are leaves, representing images, not more
# tree # tree
self.children = [False] * 4 self.children = [False] * 4
def posttraversal(self): self.num_tiles = 0
"""Returns an iterator over tile paths for every tile in the self.num_tiles_all = 0
set, including the explictly marked render-tiles, as well as the
implicitly marked ancestors of those render-tiles. Returns in
post-traversal order, so that tiles with dependencies will always be
yielded after their dependencies.
"""
return (tuple(reversed(rpath)) for rpath in self._posttraversal_helper())
def _posttraversal_helper(self):
"""Each node returns an iterator over lists of reversed paths"""
if self.depth == 1:
# Base case
if self.children[0]: yield [0]
if self.children[1]: yield [1]
if self.children[2]: yield [2]
if self.children[3]: yield [3]
else:
for childnum, child in enumerate(self.children):
if child == True:
for path in post_traversal_complete_subtree_recursion_helper(self.depth-1):
path.append(childnum)
yield path
elif child == False:
pass # do nothing
else:
# Recurse
for path in child._posttraversal_helper():
path.append(childnum)
yield path
# Now do this node itself
if bool(self):
yield []
def add(self, path): def add(self, path):
"""Marks the requested leaf node as in this set """Marks the requested leaf node as in this set
@@ -1359,72 +1320,66 @@ class RendertileSet(object):
""" """
path = list(path) path = list(path)
assert len(path) == self.depth assert len(path) == self.depth
path.reverse()
self._set_add_helper(path)
def _set_add_helper(self, path): if self.num_tiles == 0:
# The first child is being added. A root composite tile will be
# rendered.
self.num_tiles_all += 1
self._add_helper(self.children, list(reversed(path)))
def _add_helper(self, children, path):
"""Recursive helper for add() """Recursive helper for add()
Expects path to be a list in reversed order
If *all* the nodes below this one are in the set, this function returns
true. Otherwise, returns None.
""" """
if self.depth == 1:
# Base case
self.children[path[0]] = True
# Check to see if all children are in the set
if all(self.children):
return True
else:
# Recursive case
childnum = path.pop() childnum = path.pop()
child = self.children[childnum]
if child == False: if path:
# Create a new node and recurse. # We are not at the leaf, recurse.
# (The use of __class__ is so possible subclasses of this class
# work as expected) if children[childnum] == True:
child = self.__class__(self.depth-1) # The child is already in the tree.
child._set_add_helper(path)
self.children[childnum] = child
elif child == True:
# Every child is already in the set and the subtree is already
# collapsed. Nothing to do.
return return
else: elif children[childnum] == False:
# subtree is mixed. Recurse to the already existing child node # Expand all-false.
ret = child._set_add_helper(path) children[childnum] = [False]*4
if ret:
# Child says every descendent is in the set, so we can
# purge the subtree and mark it as such. The subtree will
# be garbage collected when this method exits.
self.children[childnum] = True
# Since we've marked an entire sub-tree as in the set, we # This also means an additional composite tile.
# may be able to signal to our parent to do the same self.num_tiles_all += 1
if all(x is True for x in self.children):
return True self._add_helper(children[childnum], path)
if children[childnum] == [True]*4:
# Collapse all-true.
children[childnum] = True
else:
# We are at the leaf.
if not children[childnum]:
self.num_tiles += 1
self.num_tiles_all += 1
children[childnum] = True
def __iter__(self): def __iter__(self):
return self.iterate() return self.iterate()
def iterate(self, level=None):
def iterate(self, level=None, robin=False, offset=(0,0)):
"""Returns an iterator over every tile in this set. Each item yielded """Returns an iterator over every tile in this set. Each item yielded
is a sequence of integers representing the quadtree path to the tiles is a sequence of integers representing the quadtree path to the tiles
in the set. Yielded sequences are of length self.depth. in the set. Yielded sequences are of length self.depth.
If level is None, iterates over tiles of the highest level, i.e. If level is None, iterates over tiles of the highest level, i.e.
worldtiles. If level is a value between 0 and the depth of this tree, worldtiles. If level is a value between 1 and the depth of this tree,
this method iterates over tiles at that level. Zoom level 0 is zoomed this method iterates over tiles at that level. Zoom level 1 is zoomed
all the way out, zoom level `depth` is all the way in. all the way out, zoom level `depth` is all the way in.
In other words, specifying level causes the tree to be iterated as if In other words, specifying level causes the tree to be iterated as if
it was only that depth. it was only that depth.
If the `robin` parameter is True, recurses to the four top-level
subtrees simultaneously in a round-robin manner.
""" """
if level is None: if level is None:
todepth = 1 todepth = 1
@@ -1433,30 +1388,47 @@ class RendertileSet(object):
raise ValueError("Level parameter must be between 1 and %s" % self.depth) raise ValueError("Level parameter must be between 1 and %s" % self.depth)
todepth = self.depth - level + 1 todepth = self.depth - level + 1
return (tuple(reversed(rpath)) for rpath in self._iterate_helper(todepth)) return (tuple(path) for path in self._iterate_helper([], self.children, self.depth, onlydepth=todepth, robin=robin, offset=offset))
def _iterate_helper(self, todepth): def posttraversal(self, robin=False, offset=(0,0)):
if self.depth == todepth: """Returns an iterator over tile paths for every tile in the
set, including the explictly marked render-tiles, as well as the
implicitly marked ancestors of those render-tiles. Returns in
post-traversal order, so that tiles with dependencies will always be
yielded after their dependencies.
If the `robin` parameter is True, recurses to the four top-level
subtrees simultaneously in a round-robin manner.
"""
return (tuple(path) for path in self._iterate_helper([], self.children, self.depth, robin=robin, offset=offset))
def _iterate_helper(self, path, children, depth, onlydepth=None, robin=False, offset=(0,0)):
"""Returns an iterator over tile paths for every tile in the set."""
# A variant of children with a collapsed False/True expanded to a list.
children_list = [children] * 4 if isinstance(children, bool) else children
targetdepth = 1 if onlydepth is None else onlydepth
if depth == targetdepth:
# Base case # Base case
if self.children[0]: yield [0] for (childnum, child), _ in distance_sort(enumerate(children_list), offset):
if self.children[1]: yield [1] if child:
if self.children[2]: yield [2] yield path + [childnum]
if self.children[3]: yield [3]
else: else:
# Higher levels: gens = []
for c, child in enumerate(self.children): for (childnum_, child), childoffset_ in distance_sort(enumerate(children_list), offset):
if child == True: if child:
# All render-tiles are in the set down this subtree, def go(childnum, childoffset):
# iterate over every leaf using iterate_base4 for p in self._iterate_helper(path + [childnum], children_list[childnum], depth-1, onlydepth=onlydepth, offset=childoffset):
for x in iterate_base4(self.depth-todepth): yield p
x = list(x) gens.append(go(childnum_, childoffset_))
x.append(c)
yield x for p in roundrobin(gens) if robin else chain(*gens):
elif child != False: yield p
# Mixed in/out of the set down this subtree, recurse
for path in child._iterate_helper(todepth): if onlydepth is None and children:
path.append(c)
yield path yield path
def query_path(self, path): def query_path(self, path):
@@ -1471,74 +1443,46 @@ class RendertileSet(object):
# collapsed, then just return the stored boolean. Otherwise, if we find # collapsed, then just return the stored boolean. Otherwise, if we find
# the specific tree node requested, return its state using the # the specific tree node requested, return its state using the
# __nonzero__ call. # __nonzero__ call.
treenode = self treenode = self.children
for pathelement in path: for pathelement in path:
treenode = treenode.children[pathelement] treenode = treenode[pathelement]
if not isinstance(treenode, RendertileSet): if isinstance(treenode, bool):
return treenode return treenode
# If the method has not returned at this point, treenode is the # If the method has not returned at this point, treenode is the
# requested node, but it is an inner node with possibly mixed state # requested node, but it is an inner node. That will only happen if one
# subtrees. If any of the children are True return True. This call # or more of the children down the tree are True.
# relies on the __nonzero__ method return True
return bool(treenode)
def __nonzero__(self): def __nonzero__(self):
"""Returns the boolean context of this particular node. If any """Returns the boolean context of this particular node. If any
descendent of this node is True return True. Otherwise, False. descendent of this node is True return True. Otherwise, False.
""" """
# Any chilren that are True or are a RendertileSet that evaluate to # Any children that are True or are a list evaluate to True.
# True
# IDEA: look at all children for True before recursing
# Better idea: every node except the root /must/ have a descendent in
# the set or it wouldn't exist. This assumption is only valid as long
# as there is no method to remove a tile from the set. So this should
# check to see if any children are not False.
return any(self.children) return any(self.children)
def count(self): def count(self):
"""Returns the total number of render-tiles in this set. """Returns the total number of render-tiles in this set.
""" """
# TODO: Make this more efficient (although for even the largest trees, return self.num_tiles
# this takes only seconds)
c = 0
for _ in self.iterate():
c += 1
return c
def count_all(self): def count_all(self):
"""Returns the total number of render-tiles plus implicitly marked """Returns the total number of render-tiles plus implicitly marked
upper-tiles in this set upper-tiles in this set
""" """
# TODO: Optimize this too with its own recursive method that avoids return self.num_tiles_all
# some of the overheads of posttraversal()
c = 0
for _ in self.posttraversal():
c += 1
return c
def post_traversal_complete_subtree_recursion_helper(depth): def distance_sort(children, (off_x, off_y)):
"""Fakes the recursive calls for RendertileSet.posttraversal() for the case order = []
that a subtree is collapsed, so that items are still yielded in the correct for child, (dx, dy) in izip(children, [(-1,-1), (1,-1), (-1,1), (1,1)]):
order. x = off_x*2 + dx
y = off_y*2 + dy
order.append((child, (x,y)))
""" return sorted(order, key=lambda (_, (x,y)): x*x + y*y)
if depth == 1:
# Base case
yield [0]
yield [1]
yield [2]
yield [3]
else:
for childnum in xrange(4):
for item in post_traversal_complete_subtree_recursion_helper(depth-1):
item.append(childnum)
yield item
yield []
class RenderTile(object): class RenderTile(object):
"""A simple container class that represents a single render-tile. """A simple container class that represents a single render-tile.

View File

@@ -2,7 +2,7 @@
import unittest import unittest
# For convenience # For convenience
import sys,os import sys,os,logging
sys.path.insert(0, os.getcwd()) sys.path.insert(0, os.getcwd())
sys.path.insert(0, os.path.join(os.getcwd(), os.pardir)) sys.path.insert(0, os.path.join(os.getcwd(), os.pardir))
@@ -15,7 +15,6 @@ from test_cache import TestLRU
# DISABLE THIS BLOCK TO GET LOG OUTPUT FROM TILESET FOR DEBUGGING # DISABLE THIS BLOCK TO GET LOG OUTPUT FROM TILESET FOR DEBUGGING
if 0: if 0:
import logging
root = logging.getLogger() root = logging.getLogger()
class NullHandler(logging.Handler): class NullHandler(logging.Handler):
def handle(self, record): def handle(self, record):

View File

@@ -1,6 +1,9 @@
import unittest import unittest
from itertools import chain, izip
from overviewer_core.tileset import iterate_base4, RendertileSet from overviewer_core.tileset import iterate_base4, RendertileSet
from overviewer_core.util import roundrobin
class RendertileSetTest(unittest.TestCase): class RendertileSetTest(unittest.TestCase):
# If you change this definition, you must also change the hard-coded # If you change this definition, you must also change the hard-coded
@@ -34,6 +37,61 @@ class RendertileSetTest(unittest.TestCase):
(2,3,3), (2,3,3),
# Nothing under quadrant 3 # Nothing under quadrant 3
]) ])
# The paths as yielded by posttraversal, in an expanding-from-the-center
# order.
tile_paths_posttraversal_lists = [
[
(0,0,3),
(0,0,1),
(0,0,2),
(0,0,0),
(0,0),
(0,),
],
[
(1,2,0),
(1,2),
(1,0,3),
(1,0),
(1,1,3),
(1,1),
(1,),
],
[
(2,1,1),
(2,1,0),
(2,1,3),
(2,1,2),
(2,1),
(2,0,1),
(2,0,3),
(2,0,0),
(2,0,2),
(2,0),
(2,3,1),
(2,3,0),
(2,3,3),
(2,3,2),
(2,3),
(2,2,1),
(2,2,0),
(2,2,3),
(2,2,2),
(2,2),
(2,),
],
]
# Non-round robin post-traversal: finish the first top-level quadrant
# before moving to the second etc.
tile_paths_posttraversal = list(chain(*tile_paths_posttraversal_lists)) + [()]
# Round-robin post-traversal: start rendering to all directions from the
# center.
tile_paths_posttraversal_robin = list(roundrobin(tile_paths_posttraversal_lists)) + [()]
def setUp(self): def setUp(self):
self.tree = RendertileSet(3) self.tree = RendertileSet(3)
@@ -142,56 +200,18 @@ class RendertileSetTest(unittest.TestCase):
def test_posttraverse(self): def test_posttraverse(self):
"""Test a post-traversal of the tree's dirty tiles""" """Test a post-traversal of the tree's dirty tiles"""
# Expect these results in this proper order. # Expect the results in this proper order.
expected_list = [
(0,0,0),
(0,0,1),
(0,0,2),
(0,0,3),
(0,0),
(0,),
(1,0,3),
(1,0),
(1,1,3),
(1,1),
(1,2,0),
(1,2),
(1,),
(2,0,0),
(2,0,1),
(2,0,2),
(2,0,3),
(2,0),
(2,1,0),
(2,1,1),
(2,1,2),
(2,1,3),
(2,1),
(2,2,0),
(2,2,1),
(2,2,2),
(2,2,3),
(2,2),
(2,3,0),
(2,3,1),
(2,3,2),
(2,3,3),
(2,3),
(2,),
# We should expect the root tile to need rendering too.
(),
]
iterator = iter(self.tree.posttraversal()) iterator = iter(self.tree.posttraversal())
from itertools import izip for expected, actual in izip(self.tile_paths_posttraversal, iterator):
for expected, actual in izip(expected_list, iterator): self.assertEqual(actual, expected)
self.assertRaises(StopIteration, next, iterator)
def test_posttraverse_roundrobin(self):
"""Test a round-robin post-traversal of the tree's dirty tiles"""
# Expect the results in this proper order.
iterator = iter(self.tree.posttraversal(robin=True))
for expected, actual in izip(self.tile_paths_posttraversal_robin, iterator):
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
self.assertRaises(StopIteration, next, iterator) self.assertRaises(StopIteration, next, iterator)

View File

@@ -6,6 +6,8 @@ from overviewer_core.settingsValidators import ValidationException
from overviewer_core import world from overviewer_core import world
from overviewer_core import rendermodes from overviewer_core import rendermodes
from overviewer_core.util import OrderedDict
class SettingsTest(unittest.TestCase): class SettingsTest(unittest.TestCase):
def setUp(self): def setUp(self):
@@ -13,7 +15,7 @@ class SettingsTest(unittest.TestCase):
def test_missing(self): def test_missing(self):
"Validates that a non-existant settings.py causes an exception" "Validates that a non-existant settings.py causes an exception"
self.assertRaises(ValueError, self.s.parse, "doesnotexist.py") self.assertRaises(configParser.MissingConfigException, self.s.parse, "doesnotexist.py")
def test_existing_file(self): def test_existing_file(self):
self.s.parse("test/data/settings/settings_test_1.py") self.s.parse("test/data/settings/settings_test_1.py")
@@ -45,21 +47,21 @@ class SettingsTest(unittest.TestCase):
self.s.set_config_item("worlds", { self.s.set_config_item("worlds", {
'test': "test/data/settings/test_world", 'test': "test/data/settings/test_world",
}) })
self.s.set_config_item("renders", { self.s.set_config_item("renders", OrderedDict([
"myworld": { ("myworld", {
"title": "myworld title", "title": "myworld title",
"world": "test", "world": "test",
"rendermode": rendermodes.normal, "rendermode": rendermodes.normal,
"northdirection": "upper-left", "northdirection": "upper-left",
}, }),
"otherworld": { ("otherworld", {
"title": "otherworld title", "title": "otherworld title",
"world": "test", "world": "test",
"rendermode": rendermodes.normal, "rendermode": rendermodes.normal,
"bgcolor": "#ffffff" "bgcolor": "#ffffff"
}, }),
}) ]))
self.s.set_config_item("outputdir", "/tmp/fictional/outputdir") self.s.set_config_item("outputdir", "/tmp/fictional/outputdir")
self.assertEquals(fromfile.get_validated_config(), self.s.get_validated_config()) self.assertEquals(fromfile.get_validated_config(), self.s.get_validated_config())

View File

@@ -39,51 +39,6 @@ chunks = {
(4, 4): 5, # 8, 0 (4, 4): 5, # 8, 0
} }
# The resulting tile tree, in the correct post-traversal order.
correct_tiles = [
(0, 3, 3),
(0, 3),
(0,),
(1, 2, 1),
(1, 2, 2),
(1, 2, 3),
(1, 2),
(1, 3, 0),
(1, 3, 2),
(1, 3, 3),
(1, 3),
(1,),
(2, 1, 1),
(2, 1, 3),
(2, 1),
(2, 3, 1),
(2, 3, 3),
(2, 3),
(2,),
(3, 0, 0),
(3, 0, 1),
(3, 0, 2),
(3, 0, 3),
(3, 0),
(3, 1, 0),
(3, 1, 1),
(3, 1, 2),
(3, 1, 3),
(3, 1),
(3, 2, 0),
(3, 2, 1),
(3, 2, 2),
(3, 2, 3),
(3, 2),
(3, 3, 0),
(3, 3, 1),
(3, 3, 2),
(3, 3, 3),
(3, 3),
(3,),
(),
]
# Supporting resources # Supporting resources
###################### ######################
@@ -123,15 +78,14 @@ def get_tile_set(chunks):
col, row = tileset.convert_coords(chunkx, chunkz) col, row = tileset.convert_coords(chunkx, chunkz)
for tilec, tiler in tileset.get_tiles_by_chunk(col, row): for tilec, tiler in tileset.get_tiles_by_chunk(col, row):
tile = tileset.RenderTile.compute_path(tilec, tiler, 3) tile = tileset.RenderTile.compute_path(tilec, tiler, 5)
tile_set[tile.path] = max(tile_set[tile.path], chunkmtime) tile_set[tile.path] = max(tile_set[tile.path], chunkmtime)
# At this point, tile_set holds all the render-tiles # At this point, tile_set holds all the render-tiles
for tile, tile_mtime in tile_set.copy().iteritems(): for tile, tile_mtime in tile_set.copy().iteritems():
# All render-tiles are length 3. Hard-code its upper tiles # All render-tiles are length 5. Hard-code its upper tiles
tile_set[tile[:2]] = max(tile_set[tile[:2]], tile_mtime) for i in reversed(xrange(5)):
tile_set[tile[:1]] = max(tile_set[tile[:1]], tile_mtime) tile_set[tile[:i]] = max(tile_set[tile[:i]], tile_mtime)
tile_set[tile[:0]] = max(tile_set[tile[:0]], tile_mtime)
return dict(tile_set) return dict(tile_set)
def create_fakedir(outputdir, tiles): def create_fakedir(outputdir, tiles):
@@ -184,6 +138,7 @@ class TilesetTest(unittest.TestCase):
is called before do_preprocessing() is called before do_preprocessing()
""" """
defoptions = { defoptions = {
'name': 'world name',
'bgcolor': '#000000', 'bgcolor': '#000000',
'imgformat': 'png', 'imgformat': 'png',
'optimizeimg': 0, 'optimizeimg': 0,
@@ -191,7 +146,7 @@ class TilesetTest(unittest.TestCase):
'rerenderprob': 0 'rerenderprob': 0
} }
defoptions.update(options) defoptions.update(options)
ts = tileset.TileSet(self.rs, FakeAssetmanager(0), None, defoptions, outputdir) ts = tileset.TileSet(None, self.rs, FakeAssetmanager(0), None, defoptions, outputdir)
if preprocess: if preprocess:
preprocess(ts) preprocess(ts)
ts.do_preprocessing() ts.do_preprocessing()
@@ -222,7 +177,7 @@ class TilesetTest(unittest.TestCase):
def test_get_phase_length(self): def test_get_phase_length(self):
ts = self.get_tileset({'renderchecks': 2}, self.get_outputdir()) ts = self.get_tileset({'renderchecks': 2}, self.get_outputdir())
self.assertEqual(ts.get_num_phases(), 1) self.assertEqual(ts.get_num_phases(), 1)
self.assertEqual(ts.get_phase_length(0), 41) self.assertEqual(ts.get_phase_length(0), len(get_tile_set(chunks)))
def test_forcerender_iterate(self): def test_forcerender_iterate(self):
"""Tests that a rendercheck mode 2 iteration returns every render-tile """Tests that a rendercheck mode 2 iteration returns every render-tile
@@ -278,18 +233,23 @@ class TilesetTest(unittest.TestCase):
# object. # object.
# Chosen at random: # Chosen at random:
outdated_tiles = [ outdated_tiles = [
(0,3,3), (0,3,3,3,3),
(1,2,1), (1,2,2,2,1),
(2,1), (2,1,1),
(3,) (3,)
] ]
# These are the tiles that we also expect it to return, even though # These are the tiles that we also expect it to return, even though
# they were not outdated, since they depend on the outdated tiles # they were not outdated, since they depend on the outdated tiles
additional = [ additional = [
(0,3,3,3),
(0,3,3),
(0,3), (0,3),
(0,), (0,),
(1,2,2,2),
(1,2,2),
(1,2), (1,2),
(1,), (1,),
(2,1),
(2,), (2,),
(), (),
] ]