Initial Python 3 port
Many things work, some don't. Notably, genPOI doesn't work, and there's some signedness comparison stuff going on in the C extension. This also completely drops support for Python 2, as maintaining a C extension for both Python 2 and 3 is a pain and not worth it for the 9 months that Python 2 is still going to be supported upstream. The documentation needs to be adjusted as well. All of the few tests we have pass, and rendering a map works, both with a configuration file and without. We can also use optimizeimages. Concerns #1528.
This commit is contained in:
parent
99eebd5b69
commit
e348a548b6
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# This file is part of the Minecraft Overviewer.
|
||||
#
|
||||
|
@ -21,10 +21,8 @@ import platform
|
|||
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")
|
||||
if sys.version_info[0] >= 3:
|
||||
print("and will not run on Python 3.0 or later")
|
||||
if sys.version_info[0] == 2 or (sys.version_info[0] == 3 and sys.version_info[1] < 4):
|
||||
print("Sorry, the Overviewer requires at least Python 3.4 to run.")
|
||||
sys.exit(1)
|
||||
|
||||
import os
|
||||
|
@ -35,6 +33,7 @@ import multiprocessing
|
|||
import time
|
||||
import logging
|
||||
from argparse import ArgumentParser
|
||||
from collections import OrderedDict
|
||||
|
||||
from overviewer_core import util
|
||||
from overviewer_core import logger
|
||||
|
@ -136,7 +135,7 @@ def main():
|
|||
# Check for possible shell quoting issues
|
||||
if len(unknowns) > 0:
|
||||
possible_mistakes = []
|
||||
for i in xrange(len(unknowns) + 1):
|
||||
for i in range(len(unknowns) + 1):
|
||||
possible_mistakes.append(" ".join([args.world, args.output] + unknowns[:i]))
|
||||
possible_mistakes.append(" ".join([args.output] + unknowns[:i]))
|
||||
for mistake in possible_mistakes:
|
||||
|
@ -183,9 +182,9 @@ def main():
|
|||
print("Currently running Minecraft Overviewer %s" % util.findGitVersion() +
|
||||
" (%s)" % util.findGitHash()[:7])
|
||||
try:
|
||||
import urllib
|
||||
from urllib import request
|
||||
import json
|
||||
latest_ver = json.loads(urllib.urlopen("http://overviewer.org/download.json")
|
||||
latest_ver = json.loads(request.urlopen("http://overviewer.org/download.json")
|
||||
.read())['src']
|
||||
print("Latest version of Minecraft Overviewer %s (%s)" % (latest_ver['version'],
|
||||
latest_ver['commit'][:7]))
|
||||
|
@ -294,7 +293,7 @@ def main():
|
|||
rendermodes = args.rendermodes.replace("-", "_").split(",")
|
||||
|
||||
# Now for some good defaults
|
||||
renders = util.OrderedDict()
|
||||
renders = OrderedDict()
|
||||
for rm in rendermodes:
|
||||
renders["world-" + rm] = {
|
||||
"world": "world",
|
||||
|
@ -337,7 +336,7 @@ def main():
|
|||
|
||||
if args.check_terrain: # we are already in the "if configfile" branch
|
||||
logging.info("Looking for a few common texture files...")
|
||||
for render_name, render in config['renders'].iteritems():
|
||||
for render_name, render in config['renders'].items():
|
||||
logging.info("Looking at render %r.", render_name)
|
||||
|
||||
# find or create the textures object
|
||||
|
@ -356,7 +355,7 @@ def main():
|
|||
logging.debug("Current log level: {0}.".format(logging.getLogger().level))
|
||||
|
||||
def set_renderchecks(checkname, num):
|
||||
for name, render in config['renders'].iteritems():
|
||||
for name, render in config['renders'].items():
|
||||
if render.get('renderchecks', 0) == 3:
|
||||
logging.warning(checkname + " ignoring render " + repr(name) + " since it's "
|
||||
"marked as \"don't render\".")
|
||||
|
@ -381,7 +380,7 @@ def main():
|
|||
|
||||
#####################
|
||||
# Do a few last minute things to each render dictionary here
|
||||
for rname, render in config['renders'].iteritems():
|
||||
for rname, render in config['renders'].items():
|
||||
# Convert render['world'] to the world path, and store the original
|
||||
# in render['worldname_orig']
|
||||
try:
|
||||
|
@ -437,7 +436,7 @@ def main():
|
|||
|
||||
# The changelist support.
|
||||
changelists = {}
|
||||
for render in config['renders'].itervalues():
|
||||
for render in config['renders'].values():
|
||||
if 'changelist' in render:
|
||||
path = render['changelist']
|
||||
if path not in changelists:
|
||||
|
@ -461,7 +460,7 @@ def main():
|
|||
# TODO: optionally more caching layers here
|
||||
|
||||
renders = config['renders']
|
||||
for render_name, render in renders.iteritems():
|
||||
for render_name, render in renders.items():
|
||||
logging.debug("Found the following render thing: %r", render)
|
||||
|
||||
# find or create the world object
|
||||
|
@ -572,7 +571,7 @@ def main():
|
|||
|
||||
assetMrg.finalize(tilesets)
|
||||
|
||||
for out in changelists.itervalues():
|
||||
for out in changelists.values():
|
||||
logging.debug("Closing %s (%s).", out, out.fileno())
|
||||
out.close()
|
||||
|
||||
|
@ -603,8 +602,8 @@ def list_worlds():
|
|||
formatString = "%-" + str(worldNameLen) + "s | %-8s | %-16s | %s "
|
||||
print(formatString % ("World", "Playtime", "Modified", "Path"))
|
||||
print(formatString % ("-" * worldNameLen, "-" * 8, '-' * 16, '-' * 4))
|
||||
for name, info in sorted(worlds.iteritems()):
|
||||
if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
|
||||
for name, info in sorted(worlds.items()):
|
||||
if isinstance(name, str) and name.startswith("World") and len(name) == 6:
|
||||
try:
|
||||
world_n = int(name[-1])
|
||||
# we'll catch this one later, when it shows up as an
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
# Code to check to make sure c_overviewer is built and working
|
||||
#
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os.path
|
||||
import os
|
||||
import platform
|
||||
import traceback
|
||||
import sys
|
||||
|
||||
import util
|
||||
from . import util
|
||||
|
||||
def check_c_overviewer():
|
||||
"""Check to make sure c_overviewer works and is up-to-date. Prints
|
||||
|
@ -18,29 +20,28 @@ def check_c_overviewer():
|
|||
root_dir = util.get_program_path()
|
||||
# make sure the c_overviewer extension is available
|
||||
try:
|
||||
import c_overviewer
|
||||
from . import c_overviewer
|
||||
except ImportError:
|
||||
if os.environ.get("OVERVIEWER_DEBUG_IMPORT") == "1":
|
||||
traceback.print_exc()
|
||||
## if this is a frozen windows package, the following error messages about
|
||||
## building the c_overviewer extension are not appropriate
|
||||
if hasattr(sys, "frozen") and platform.system() == 'Windows':
|
||||
print "Something has gone wrong importing the c_overviewer extension. Please"
|
||||
print "make sure the 2008 and 2010 redistributable packages from Microsoft"
|
||||
print "are installed."
|
||||
print("Something has gone wrong importing the c_overviewer extension. Please make sure "
|
||||
"the 2008 and 2010 redistributable packages from Microsoft are installed.")
|
||||
return 1
|
||||
|
||||
## try to find the build extension
|
||||
ext = os.path.join(root_dir, "overviewer_core", "c_overviewer.%s" % ("pyd" if platform.system() == "Windows" else "so"))
|
||||
if os.path.exists(ext):
|
||||
traceback.print_exc()
|
||||
print ""
|
||||
print "Something has gone wrong importing the c_overviewer extension. Please"
|
||||
print "make sure it is up-to-date (clean and rebuild)"
|
||||
print()
|
||||
print("Something has gone wrong importing the c_overviewer extension. Please make sure "
|
||||
"it is up-to-date. (clean and rebuild)")
|
||||
return 1
|
||||
|
||||
print "You need to compile the c_overviewer module to run Minecraft Overviewer."
|
||||
print "Run `python setup.py build`, or see the README for details."
|
||||
print("You need to compile the c_overviewer module to run Minecraft Overviewer.")
|
||||
print("Run `python setup.py build`, or see the README for details.")
|
||||
return 1
|
||||
|
||||
#
|
||||
|
@ -54,14 +55,15 @@ def check_c_overviewer():
|
|||
if os.path.exists(os.path.join(root_dir, "overviewer_core", "src", "overviewer.h")):
|
||||
with open(os.path.join(root_dir, "overviewer_core", "src", "overviewer.h")) as f:
|
||||
lines = f.readlines()
|
||||
lines = filter(lambda x: x.startswith("#define OVERVIEWER_EXTENSION_VERSION"), lines)
|
||||
lines = list(filter(lambda x: x.startswith("#define OVERVIEWER_EXTENSION_VERSION"),
|
||||
lines))
|
||||
if lines:
|
||||
l = lines[0]
|
||||
if int(l.split()[2].strip()) != c_overviewer.extension_version():
|
||||
print "Please rebuild your c_overviewer module. It is out of date!"
|
||||
print("Please rebuild your c_overviewer module. It is out of date!")
|
||||
return 1
|
||||
else:
|
||||
print "Please rebuild your c_overviewer module. It is out of date!"
|
||||
print("Please rebuild your c_overviewer module. It is out of date!")
|
||||
return 1
|
||||
|
||||
# all good!
|
||||
|
|
|
@ -23,9 +23,9 @@ import traceback
|
|||
|
||||
from PIL import Image
|
||||
|
||||
import world
|
||||
import util
|
||||
from files import FileReplacer, mirror_dir, get_fs_caps
|
||||
from . import world
|
||||
from . import util
|
||||
from .files import FileReplacer, mirror_dir, get_fs_caps
|
||||
|
||||
|
||||
class AssetManager(object):
|
||||
|
@ -53,7 +53,7 @@ top-level directory.
|
|||
with open(config_loc) as c:
|
||||
ovconf_str = "{" + "\n".join(c.readlines()[1:-1]) + "}"
|
||||
self.overviewerConfig = json.loads(ovconf_str)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
if os.path.exists(config_loc):
|
||||
logging.warning("A previous overviewerConfig.js was found, "
|
||||
"but I couldn't read it for some reason."
|
||||
|
@ -61,16 +61,6 @@ top-level directory.
|
|||
logging.debug(traceback.format_exc())
|
||||
self.overviewerConfig = dict(tilesets=dict())
|
||||
|
||||
# Make sure python knows the preferred encoding. If it does not, set it
|
||||
# to utf-8"
|
||||
self.preferredencoding = locale.getpreferredencoding()
|
||||
try:
|
||||
# We don't care what is returned, just that we can get a codec.
|
||||
codecs.lookup(self.preferredencoding)
|
||||
except LookupError:
|
||||
self.preferredencoding = "utf_8"
|
||||
logging.debug("Preferred enoding set to: %s", self.preferredencoding)
|
||||
|
||||
def get_tileset_config(self, name):
|
||||
"Return the correct dictionary from the parsed overviewerConfig.js"
|
||||
for conf in self.overviewerConfig['tilesets']:
|
||||
|
@ -213,10 +203,7 @@ top-level directory.
|
|||
|
||||
index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
|
||||
index = index.replace("{title}", "Minecraft Overviewer")
|
||||
index = index.replace("{time}",
|
||||
time.strftime("%a, %d %b %Y %H:%M:%S %Z",
|
||||
time.localtime())
|
||||
.decode(self.preferredencoding))
|
||||
index = index.replace("{time}", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()))
|
||||
versionstr = "%s (%s)" % (util.findGitVersion(),
|
||||
util.findGitHash()[:7])
|
||||
index = index.replace("{version}", versionstr)
|
||||
|
|
|
@ -4,8 +4,8 @@ import os.path
|
|||
import logging
|
||||
import traceback
|
||||
|
||||
import settingsDefinition
|
||||
import settingsValidators
|
||||
from . import settingsDefinition
|
||||
from . import settingsValidators
|
||||
|
||||
class MissingConfigException(Exception):
|
||||
"To be thrown when the config file can't be found"
|
||||
|
@ -76,12 +76,14 @@ class MultiWorldParser(object):
|
|||
|
||||
# The global environment should be the rendermode module, so the config
|
||||
# file has access to those resources.
|
||||
import rendermodes
|
||||
from . import rendermodes
|
||||
|
||||
try:
|
||||
execfile(settings_file, rendermodes.__dict__, self._config_state)
|
||||
with open(settings_file, "rb") as settings_file_handle:
|
||||
exec(compile(settings_file_handle.read(), settings_file, 'exec'),
|
||||
rendermodes.__dict__, self._config_state)
|
||||
|
||||
except Exception, ex:
|
||||
except Exception as ex:
|
||||
if isinstance(ex, SyntaxError):
|
||||
logging.error("Syntax error parsing %s" % settings_file)
|
||||
logging.error("The traceback below will tell you which line triggered the syntax error\n")
|
||||
|
@ -109,7 +111,7 @@ class MultiWorldParser(object):
|
|||
# At this point, make a pass through the file to possibly set global
|
||||
# render defaults
|
||||
render_settings = self._settings['renders'].validator.valuevalidator.config
|
||||
for key in self._config_state.iterkeys():
|
||||
for key in self._config_state.keys():
|
||||
if key not in self._settings:
|
||||
if key in render_settings:
|
||||
setting = render_settings[key]
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
# You should have received a copy of the GNU General Public License along
|
||||
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import util
|
||||
from . import util
|
||||
import multiprocessing
|
||||
import multiprocessing.managers
|
||||
import Queue
|
||||
import queue
|
||||
import time
|
||||
from signals import Signal
|
||||
from .signals import Signal
|
||||
|
||||
class Dispatcher(object):
|
||||
"""This class coordinates the work of all the TileSet objects
|
||||
|
@ -51,7 +51,7 @@ class Dispatcher(object):
|
|||
|
||||
# iterate through all possible phases
|
||||
num_phases = [tileset.get_num_phases() for tileset in tilesetlist]
|
||||
for phase in xrange(max(num_phases)):
|
||||
for phase in range(max(num_phases)):
|
||||
# construct a list of iterators to use for this phase
|
||||
work_iterators = []
|
||||
for i, tileset in enumerate(tilesetlist):
|
||||
|
@ -235,7 +235,7 @@ class MultiprocessingDispatcherProcess(multiprocessing.Process):
|
|||
def handler(*args, **kwargs):
|
||||
self.signal_queue.put((name, args, kwargs), False)
|
||||
sig.set_interceptor(handler)
|
||||
for name, sig in Signal.signals.iteritems():
|
||||
for name, sig in Signal.signals.items():
|
||||
register_signal(name, sig)
|
||||
|
||||
# notify that we're starting up
|
||||
|
@ -259,7 +259,7 @@ class MultiprocessingDispatcherProcess(multiprocessing.Process):
|
|||
ret = self.tilesets[ti].do_work(workitem)
|
||||
result = (ti, workitem, ret,)
|
||||
self.result_queue.put(result, False)
|
||||
except Queue.Empty:
|
||||
except queue.Empty:
|
||||
pass
|
||||
|
||||
class MultiprocessingDispatcher(Dispatcher):
|
||||
|
@ -288,7 +288,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||
|
||||
# create and fill the pool
|
||||
self.pool = []
|
||||
for i in xrange(self.local_procs):
|
||||
for i in range(self.local_procs):
|
||||
proc = MultiprocessingDispatcherProcess(self.manager)
|
||||
proc.start()
|
||||
self.pool.append(proc)
|
||||
|
@ -300,7 +300,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||
self._handle_messages()
|
||||
|
||||
# send of the end-of-jobs sentinel
|
||||
for p in xrange(self.num_workers):
|
||||
for p in range(self.num_workers):
|
||||
self.job_queue.put(None, False)
|
||||
|
||||
# TODO better way to be sure worker processes get the message
|
||||
|
@ -350,7 +350,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||
else:
|
||||
# new worker
|
||||
self.num_workers += 1
|
||||
except Queue.Empty:
|
||||
except queue.Empty:
|
||||
result_empty = True
|
||||
if not signal_empty:
|
||||
try:
|
||||
|
@ -363,7 +363,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||
|
||||
sig = Signal.signals[name]
|
||||
sig.emit_intercepted(*args, **kwargs)
|
||||
except Queue.Empty:
|
||||
except queue.Empty:
|
||||
signal_empty = True
|
||||
|
||||
return finished_jobs
|
||||
|
|
|
@ -144,7 +144,7 @@ class FileReplacer(object):
|
|||
# error
|
||||
try:
|
||||
os.remove(self.tmpname)
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
logging.warning("An error was raised, so I was doing "
|
||||
"some cleanup first, but I couldn't remove "
|
||||
"'%s'!", self.tmpname)
|
||||
|
@ -153,7 +153,7 @@ class FileReplacer(object):
|
|||
if self.caps.get("chmod_works") and os.path.exists(self.destname):
|
||||
try:
|
||||
shutil.copymode(self.destname, self.tmpname)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||
# condition, two processes could conceivably try and update
|
||||
# the same temp file at the same time
|
||||
|
@ -162,7 +162,7 @@ class FileReplacer(object):
|
|||
# atomic rename into place
|
||||
try:
|
||||
os.rename(self.tmpname, self.destname)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||
# condition, two processes could conceivably try and update
|
||||
# the same temp file at the same time
|
||||
|
|
|
@ -18,7 +18,7 @@ import logging
|
|||
import os
|
||||
import platform
|
||||
import sys
|
||||
from cStringIO import StringIO
|
||||
from io import BytesIO
|
||||
|
||||
# Some cool code for colored logging:
|
||||
# For background, add 40. For foreground, add 30
|
||||
|
@ -88,7 +88,7 @@ class WindowsOutputStream(object):
|
|||
|
||||
def write(self, s):
|
||||
|
||||
msg_strm = StringIO(s)
|
||||
msg_strm = BytesIO(s)
|
||||
|
||||
while (True):
|
||||
c = msg_strm.read(1)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
import functools
|
||||
import gzip
|
||||
import StringIO
|
||||
from io import BytesIO
|
||||
import struct
|
||||
import zlib
|
||||
|
||||
|
@ -25,7 +25,7 @@ import zlib
|
|||
def _file_loader(func):
|
||||
@functools.wraps(func)
|
||||
def wrapper(fileobj, *args):
|
||||
if isinstance(fileobj, basestring):
|
||||
if type(fileobj) == str:
|
||||
# Is actually a filename
|
||||
fileobj = open(fileobj, 'rb', 4096)
|
||||
return func(fileobj, *args)
|
||||
|
@ -92,7 +92,7 @@ class NBTFileReader(object):
|
|||
# pure zlib stream -- maybe later replace this with
|
||||
# a custom zlib file object?
|
||||
data = zlib.decompress(fileobj.read())
|
||||
self._file = StringIO.StringIO(data)
|
||||
self._file = BytesIO(data)
|
||||
|
||||
# mapping of NBT type ids to functions to read them out
|
||||
self._read_tagmap = {
|
||||
|
@ -168,7 +168,7 @@ class NBTFileReader(object):
|
|||
|
||||
read_method = self._read_tagmap[tagid]
|
||||
l = []
|
||||
for _ in xrange(length):
|
||||
for _ in range(length):
|
||||
l.append(read_method())
|
||||
return l
|
||||
|
||||
|
@ -203,7 +203,7 @@ class NBTFileReader(object):
|
|||
name = self._read_tag_string()
|
||||
payload = self._read_tag_compound()
|
||||
return (name, payload)
|
||||
except (struct.error, ValueError, TypeError), e:
|
||||
except (struct.error, ValueError, TypeError) as e:
|
||||
raise CorruptNBTError("could not parse nbt: %s" % (str(e),))
|
||||
|
||||
|
||||
|
@ -252,9 +252,9 @@ class MCRFileReader(object):
|
|||
file, as (x, z) coordinate tuples. To load these chunks,
|
||||
provide these coordinates to load_chunk()."""
|
||||
|
||||
for x in xrange(32):
|
||||
for z in xrange(32):
|
||||
if self._locations[x + z * 32] >> 8 != 0:
|
||||
for x in range(32):
|
||||
for z in range(32):
|
||||
if self._locations[int(x + z * 32)] >> 8 != 0:
|
||||
yield (x, z)
|
||||
|
||||
def get_chunk_timestamp(self, x, z):
|
||||
|
@ -264,13 +264,13 @@ class MCRFileReader(object):
|
|||
"""
|
||||
x = x % 32
|
||||
z = z % 32
|
||||
return self._timestamps[x + z * 32]
|
||||
return self._timestamps[int(x + z * 32)]
|
||||
|
||||
def chunk_exists(self, x, z):
|
||||
"""Determines if a chunk exists."""
|
||||
x = x % 32
|
||||
z = z % 32
|
||||
return self._locations[x + z * 32] >> 8 != 0
|
||||
return self._locations[int(x + z * 32)] >> 8 != 0
|
||||
|
||||
def load_chunk(self, x, z):
|
||||
"""Return a (name, data) tuple for the given chunk, or
|
||||
|
@ -281,7 +281,7 @@ class MCRFileReader(object):
|
|||
have the chunks load out of regions properly."""
|
||||
x = x % 32
|
||||
z = z % 32
|
||||
location = self._locations[x + z * 32]
|
||||
location = self._locations[int(x + z * 32)]
|
||||
offset = (location >> 8) * 4096
|
||||
sectors = location & 0xff
|
||||
|
||||
|
@ -311,16 +311,16 @@ class MCRFileReader(object):
|
|||
raise CorruptRegionError("unsupported chunk compression type: %i "
|
||||
"(should be 1 or 2)" % (compression,))
|
||||
|
||||
# turn the rest of the data into a StringIO object
|
||||
# turn the rest of the data into a BytesIO object
|
||||
# (using data_length - 1, as we already read 1 byte for compression)
|
||||
data = self._file.read(data_length - 1)
|
||||
if len(data) != data_length - 1:
|
||||
raise CorruptRegionError("chunk length is invalid")
|
||||
data = StringIO.StringIO(data)
|
||||
data = BytesIO(data)
|
||||
|
||||
try:
|
||||
return NBTFileReader(data, is_gzip=is_gzip).read_all()
|
||||
except CorruptionError:
|
||||
raise
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
raise CorruptChunkError("Misc error parsing chunk: " + str(e))
|
||||
|
|
|
@ -19,8 +19,8 @@ import os
|
|||
import sys
|
||||
import time
|
||||
|
||||
import progressbar
|
||||
import rcon
|
||||
from . import progressbar
|
||||
from . import rcon
|
||||
|
||||
|
||||
class Observer(object):
|
||||
|
|
|
@ -34,8 +34,7 @@ class Optimizer:
|
|||
path = os.environ.get("PATH").split(os.pathsep)
|
||||
|
||||
def exists_in_path(prog):
|
||||
result = filter(lambda x: os.path.exists(os.path.join(x, prog)),
|
||||
path)
|
||||
result = [x for x in path if os.path.exists(os.path.join(x, prog))]
|
||||
return len(result) != 0
|
||||
|
||||
binaries = self.binarynames + [x + ".exe" for x in self.binarynames]
|
||||
|
|
|
@ -189,13 +189,13 @@ class Bar(ProgressBarWidgetHFill):
|
|||
self.left = left
|
||||
self.right = right
|
||||
def _format_marker(self, pbar):
|
||||
if isinstance(self.marker, (str, unicode)):
|
||||
if isinstance(self.marker, str):
|
||||
return self.marker
|
||||
else:
|
||||
return self.marker.update(pbar)
|
||||
def update(self, pbar, width):
|
||||
percent = pbar.percentage()
|
||||
cwidth = width - len(self.left) - len(self.right)
|
||||
cwidth = int(width - len(self.left) - len(self.right))
|
||||
marked_width = int(percent * cwidth / 100)
|
||||
m = self._format_marker(pbar)
|
||||
bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
|
||||
|
@ -283,7 +283,7 @@ class ProgressBar(object):
|
|||
r.append(w)
|
||||
hfill_inds.append(i)
|
||||
num_hfill += 1
|
||||
elif isinstance(w, (str, unicode)):
|
||||
elif isinstance(w, str):
|
||||
r.append(w)
|
||||
currwidth += len(w)
|
||||
else:
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from PIL import Image
|
||||
import textures
|
||||
from . import textures
|
||||
|
||||
"""The contents of this file are imported into the namespace of config files.
|
||||
It also defines the render primitive objects, which are used by the C code.
|
||||
|
@ -31,13 +31,13 @@ class RenderPrimitive(object):
|
|||
raise RuntimeError("RenderPrimitive cannot be used directly")
|
||||
|
||||
self.option_values = {}
|
||||
for key, val in kwargs.iteritems():
|
||||
for key, val in kwargs.items():
|
||||
if not key in self.options:
|
||||
raise ValueError("primitive `{0}' has no option `{1}'".format(self.name, key))
|
||||
self.option_values[key] = val
|
||||
|
||||
# set up defaults
|
||||
for name, (description, default) in self.options.iteritems():
|
||||
for name, (description, default) in self.options.items():
|
||||
if not name in self.option_values:
|
||||
self.option_values[name] = default
|
||||
|
||||
|
|
|
@ -43,10 +43,11 @@
|
|||
# available during the execution of the config file. This way, container types
|
||||
# can be initialized and then appended/added to when the config file is parsed.
|
||||
|
||||
from settingsValidators import *
|
||||
import util
|
||||
from observer import ProgressBarObserver, LoggingObserver, JSObserver
|
||||
from optimizeimages import pngnq, optipng, pngcrush
|
||||
from collections import OrderedDict
|
||||
|
||||
from .settingsValidators import *
|
||||
from .observer import ProgressBarObserver, LoggingObserver, JSObserver
|
||||
from .optimizeimages import pngnq, optipng, pngcrush
|
||||
import platform
|
||||
import sys
|
||||
|
||||
|
@ -60,7 +61,7 @@ import sys
|
|||
# objects with their respective validators.
|
||||
|
||||
# config file.
|
||||
renders = Setting(required=True, default=util.OrderedDict(),
|
||||
renders = Setting(required=True, default=OrderedDict(),
|
||||
validator=make_dictValidator(validateStr, make_configDictValidator(
|
||||
{
|
||||
"world": Setting(required=True, validator=validateStr, default=None),
|
||||
|
@ -99,7 +100,7 @@ renders = Setting(required=True, default=util.OrderedDict(),
|
|||
)))
|
||||
|
||||
# The worlds dict, mapping world names to world paths
|
||||
worlds = Setting(required=True, validator=make_dictValidator(validateStr, validateWorldPath), default=util.OrderedDict())
|
||||
worlds = Setting(required=True, validator=make_dictValidator(validateStr, validateWorldPath), default=OrderedDict())
|
||||
|
||||
outputdir = Setting(required=True, validator=validateOutputDir, default=None)
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
import logging
|
||||
import os
|
||||
import os.path
|
||||
from collections import OrderedDict
|
||||
|
||||
import rendermodes
|
||||
import util
|
||||
from optimizeimages import Optimizer
|
||||
from world import LOWER_LEFT, LOWER_RIGHT, UPPER_LEFT, UPPER_RIGHT
|
||||
from . import rendermodes
|
||||
from . import util
|
||||
from .optimizeimages import Optimizer
|
||||
from .world import LOWER_LEFT, LOWER_RIGHT, UPPER_LEFT, UPPER_RIGHT
|
||||
|
||||
|
||||
class ValidationException(Exception):
|
||||
|
@ -179,8 +180,8 @@ def validateBGColor(color):
|
|||
|
||||
|
||||
def validateOptImg(optimizers):
|
||||
if isinstance(optimizers, (int, long)):
|
||||
from optimizeimages import pngcrush
|
||||
if isinstance(optimizers, int):
|
||||
from .optimizeimages import pngcrush
|
||||
logging.warning("You're using a deprecated definition of optimizeimg. "
|
||||
"We'll do what you say for now, but please fix this as soon as possible.")
|
||||
optimizers = [pngcrush()]
|
||||
|
@ -189,7 +190,7 @@ def validateOptImg(optimizers):
|
|||
"Make sure you specify them like [foo()], with square brackets.")
|
||||
|
||||
if optimizers:
|
||||
for opt, next_opt in zip(optimizers, optimizers[1:]) + [(optimizers[-1], None)]:
|
||||
for opt, next_opt in list(zip(optimizers, optimizers[1:])) + [(optimizers[-1], None)]:
|
||||
if not isinstance(opt, Optimizer):
|
||||
raise ValidationException("Invalid Optimizer!")
|
||||
|
||||
|
@ -272,7 +273,7 @@ def validateCrop(value):
|
|||
|
||||
|
||||
def validateObserver(observer):
|
||||
if all(map(lambda m: hasattr(observer, m), ['start', 'add', 'update', 'finish'])):
|
||||
if all([hasattr(observer, m) for m in ['start', 'add', 'update', 'finish']]):
|
||||
return observer
|
||||
else:
|
||||
raise ValidationException("%r does not look like an observer." % repr(observer))
|
||||
|
@ -316,8 +317,8 @@ def make_dictValidator(keyvalidator, valuevalidator):
|
|||
|
||||
"""
|
||||
def v(d):
|
||||
newd = util.OrderedDict()
|
||||
for key, value in d.iteritems():
|
||||
newd = OrderedDict()
|
||||
for key, value in d.items():
|
||||
newd[keyvalidator(key)] = valuevalidator(value)
|
||||
return newd
|
||||
# Put these objects as attributes of the function so they can be accessed
|
||||
|
@ -345,7 +346,7 @@ def make_configDictValidator(config, ignore_undefined=False):
|
|||
|
||||
"""
|
||||
def configDictValidator(d):
|
||||
newdict = util.OrderedDict()
|
||||
newdict = OrderedDict()
|
||||
|
||||
# values are config keys that the user specified that don't match any
|
||||
# valid key
|
||||
|
@ -353,10 +354,10 @@ def make_configDictValidator(config, ignore_undefined=False):
|
|||
undefined_key_matches = {}
|
||||
|
||||
# Go through the keys the user gave us and make sure they're all valid.
|
||||
for key in d.iterkeys():
|
||||
for key in d.keys():
|
||||
if key not in config:
|
||||
# Try to find a probable match
|
||||
match = _get_closest_match(key, config.iterkeys())
|
||||
match = _get_closest_match(key, iter(config.keys()))
|
||||
if match and ignore_undefined:
|
||||
# Save this for later. It only matters if this is a typo of
|
||||
# some required key that wasn't specified. (If all required
|
||||
|
@ -377,7 +378,7 @@ def make_configDictValidator(config, ignore_undefined=False):
|
|||
# Iterate through the defined keys in the configuration (`config`),
|
||||
# checking each one to see if the user specified it (in `d`). Then
|
||||
# validate it and copy the result to `newdict`
|
||||
for configkey, configsetting in config.iteritems():
|
||||
for configkey, configsetting in config.items():
|
||||
if configkey in d:
|
||||
# This key /was/ specified in the user's dict. Make sure it validates.
|
||||
newdict[configkey] = configsetting.validator(d[configkey])
|
||||
|
@ -414,9 +415,9 @@ def _levenshtein(s1, s2):
|
|||
l1 = len(s1)
|
||||
l2 = len(s2)
|
||||
|
||||
matrix = [range(l1 + 1)] * (l2 + 1)
|
||||
matrix = [list(range(l1 + 1))] * (l2 + 1)
|
||||
for zz in range(l2 + 1):
|
||||
matrix[zz] = range(zz, zz + l1 + 1)
|
||||
matrix[zz] = list(range(zz, zz + l1 + 1))
|
||||
for zz in range(0, l2):
|
||||
for sz in range(0, l1):
|
||||
if s1[sz] == s2[zz]:
|
||||
|
|
|
@ -40,7 +40,6 @@ PyObject *init_chunk_render(void) {
|
|||
if (textures) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
textures = PyImport_ImportModule("overviewer_core.textures");
|
||||
/* ensure none of these pointers are NULL */
|
||||
if ((!textures)) {
|
||||
|
@ -50,13 +49,13 @@ PyObject *init_chunk_render(void) {
|
|||
tmp = PyObject_GetAttrString(textures, "max_blockid");
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
max_blockid = PyInt_AsLong(tmp);
|
||||
max_blockid = PyLong_AsLong(tmp);
|
||||
Py_DECREF(tmp);
|
||||
|
||||
tmp = PyObject_GetAttrString(textures, "max_data");
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
max_data = PyInt_AsLong(tmp);
|
||||
max_data = PyLong_AsLong(tmp);
|
||||
Py_DECREF(tmp);
|
||||
|
||||
/* assemble the property table */
|
||||
|
@ -81,7 +80,7 @@ PyObject *init_chunk_render(void) {
|
|||
|
||||
block_properties = calloc(max_blockid, sizeof(unsigned char));
|
||||
for (i = 0; i < max_blockid; i++) {
|
||||
PyObject *block = PyInt_FromLong(i);
|
||||
PyObject *block = PyLong_FromLong(i);
|
||||
|
||||
if (PySequence_Contains(known_blocks, block))
|
||||
block_properties[i] |= 1 << KNOWN;
|
||||
|
@ -177,7 +176,7 @@ int load_chunk(RenderState* state, int x, int z, unsigned char required) {
|
|||
if (!ycoord)
|
||||
continue;
|
||||
|
||||
sectiony = PyInt_AsLong(ycoord);
|
||||
sectiony = PyLong_AsLong(ycoord);
|
||||
if (sectiony >= 0 && sectiony < SECTIONS_PER_CHUNK)
|
||||
load_chunk_section(dest, sectiony, section);
|
||||
}
|
||||
|
@ -487,7 +486,7 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) {
|
|||
PyObject *texrot;
|
||||
int northdir;
|
||||
texrot = PyObject_GetAttrString(state->textures, "rotation");
|
||||
northdir = PyInt_AsLong(texrot);
|
||||
northdir = PyLong_AsLong(texrot);
|
||||
|
||||
/* fix the rotation value for different northdirections */
|
||||
#define FIX_ROT(x) (((x) & ~0x3) | repair_rot[((x) & 0x3) | (northdir << 2)])
|
||||
|
@ -617,8 +616,8 @@ chunk_render(PyObject *self, PyObject *args) {
|
|||
imgsize1_py = PySequence_GetItem(imgsize, 1);
|
||||
Py_DECREF(imgsize);
|
||||
|
||||
imgsize0 = PyInt_AsLong(imgsize0_py);
|
||||
imgsize1 = PyInt_AsLong(imgsize1_py);
|
||||
imgsize0 = PyLong_AsLong(imgsize0_py);
|
||||
imgsize1 = PyLong_AsLong(imgsize1_py);
|
||||
Py_DECREF(imgsize0_py);
|
||||
Py_DECREF(imgsize1_py);
|
||||
|
||||
|
|
|
@ -38,12 +38,20 @@ static PyMethodDef COverviewerMethods[] = {
|
|||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyModuleDef COverviewerModule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"c_overviewer",
|
||||
"", // TODO: Add documentation here.
|
||||
-1,
|
||||
COverviewerMethods
|
||||
};
|
||||
|
||||
|
||||
PyMODINIT_FUNC
|
||||
initc_overviewer(void)
|
||||
PyInit_c_overviewer(void)
|
||||
{
|
||||
PyObject *mod, *numpy;
|
||||
mod = Py_InitModule("c_overviewer", COverviewerMethods);
|
||||
mod = PyModule_Create(&COverviewerModule);
|
||||
|
||||
/* for numpy
|
||||
normally you should use import_array(), but that will break across
|
||||
|
@ -57,8 +65,9 @@ initc_overviewer(void)
|
|||
if (!init_chunk_render()) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
init_endian();
|
||||
return mod;
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
// increment this value if you've made a change to the c extesion
|
||||
// and want to force users to rebuild
|
||||
#define OVERVIEWER_EXTENSION_VERSION 56
|
||||
#define OVERVIEWER_EXTENSION_VERSION 57
|
||||
|
||||
/* Python PIL, and numpy headers */
|
||||
#include <Python.h>
|
||||
|
|
|
@ -234,9 +234,9 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec
|
|||
|
||||
/* look up color! */
|
||||
color = PySequence_GetItem(color_table, tabley * 256 + tablex);
|
||||
r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
Py_DECREF(color);
|
||||
|
||||
/* do the after-coloration */
|
||||
|
|
|
@ -56,9 +56,9 @@ depth_tinting_draw(void *data, RenderState *state, PyObject *src, PyObject *mask
|
|||
y = (y * 128) / (16 * SECTIONS_PER_CHUNK);
|
||||
|
||||
/* get the colors and tint and tint */
|
||||
r = PyInt_AsLong(PyList_GetItem(self->depth_colors, 0 + y*3));
|
||||
g = PyInt_AsLong(PyList_GetItem(self->depth_colors, 1 + y*3));
|
||||
b = PyInt_AsLong(PyList_GetItem(self->depth_colors, 2 + y*3));
|
||||
r = PyLong_AsLong(PyList_GetItem(self->depth_colors, 0 + y*3));
|
||||
g = PyLong_AsLong(PyList_GetItem(self->depth_colors, 1 + y*3));
|
||||
b = PyLong_AsLong(PyList_GetItem(self->depth_colors, 2 + y*3));
|
||||
|
||||
tint_with_mask(state->img, r, g, b, 255, mask, state->imgx, state->imgy, 0, 0);
|
||||
}
|
||||
|
|
|
@ -52,9 +52,9 @@ hide_start(void *data, RenderState *state, PyObject *support) {
|
|||
for (i = 0; i < blocks_size; i++) {
|
||||
PyObject *block = PyList_GET_ITEM(opt, i);
|
||||
|
||||
if (PyInt_Check(block)) {
|
||||
if (PyLong_Check(block)) {
|
||||
/* format 1: just a block id */
|
||||
self->rules[i].blockid = PyInt_AsLong(block);
|
||||
self->rules[i].blockid = PyLong_AsLong(block);
|
||||
self->rules[i].has_data = 0;
|
||||
} else if (PyArg_ParseTuple(block, "Hb", &(self->rules[i].blockid), &(self->rules[i].data))) {
|
||||
/* format 2: (blockid, data) */
|
||||
|
|
|
@ -45,9 +45,9 @@ calculate_light_color_fancy(void *data,
|
|||
index = skylight + blocklight * 16;
|
||||
color = PySequence_GetItem(mode->lightcolor, index);
|
||||
|
||||
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
*r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
*g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
*b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
|
||||
Py_DECREF(color);
|
||||
}
|
||||
|
@ -78,9 +78,9 @@ calculate_light_color_fancy_night(void *data,
|
|||
index = skylight + blocklight * 16;
|
||||
color = PySequence_GetItem(mode->lightcolor, index);
|
||||
|
||||
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
*r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||
*g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||
*b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||
|
||||
Py_DECREF(color);
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ RenderPrimitive *render_primitive_create(PyObject *prim, RenderState *state) {
|
|||
pyname = PyObject_GetAttrString(prim, "name");
|
||||
if (!pyname)
|
||||
return NULL;
|
||||
name = PyString_AsString(pyname);
|
||||
name = PyUnicode_AsUTF8(pyname);
|
||||
|
||||
for (i = 0; render_primitives[i] != NULL; i++) {
|
||||
if (strcmp(render_primitives[i]->name, name) == 0) {
|
||||
|
@ -204,11 +204,10 @@ int render_mode_parse_option(PyObject *support, const char *name, const char *fo
|
|||
Py_DECREF(dict);
|
||||
|
||||
if (!ret) {
|
||||
PyObject *errtype, *errvalue, *errtraceback;
|
||||
const char *errstring;
|
||||
PyObject *errtype, *errvalue, *errtraceback, *errstring;
|
||||
|
||||
PyErr_Fetch(&errtype, &errvalue, &errtraceback);
|
||||
errstring = PyString_AsString(errvalue);
|
||||
errstring = PyUnicode_AsUTF8String(errvalue);
|
||||
|
||||
PyErr_Format(PyExc_TypeError, "rendermode option \"%s\" has incorrect type (%s)", name, errstring);
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ import imp
|
|||
import os
|
||||
import os.path
|
||||
import zipfile
|
||||
from cStringIO import StringIO
|
||||
from io import BytesIO
|
||||
import math
|
||||
from random import randint
|
||||
import numpy
|
||||
|
@ -26,8 +26,32 @@ from PIL import Image, ImageEnhance, ImageOps, ImageDraw
|
|||
import logging
|
||||
import functools
|
||||
|
||||
import util
|
||||
from c_overviewer import alpha_over
|
||||
from . import util
|
||||
|
||||
|
||||
# global variables to collate information in @material decorators
|
||||
blockmap_generators = {}
|
||||
|
||||
known_blocks = set()
|
||||
used_datas = set()
|
||||
max_blockid = 0
|
||||
max_data = 0
|
||||
|
||||
transparent_blocks = set()
|
||||
solid_blocks = set()
|
||||
fluid_blocks = set()
|
||||
nospawn_blocks = set()
|
||||
nodata_blocks = set()
|
||||
|
||||
|
||||
# This is here for circular import reasons.
|
||||
# Please don't ask, I choose to repress these memories.
|
||||
# ... okay fine I'll tell you.
|
||||
# Initialising the C extension requires access to the globals above.
|
||||
# Due to the circular import, this wouldn't work, unless we reload the
|
||||
# module in the C extension or just move the import below its dependencies.
|
||||
from .c_overviewer import alpha_over
|
||||
|
||||
|
||||
class TextureException(Exception):
|
||||
"To be thrown when a texture is not found."
|
||||
|
@ -37,6 +61,7 @@ class TextureException(Exception):
|
|||
color_map = ["white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray",
|
||||
"light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"]
|
||||
|
||||
|
||||
##
|
||||
## Textures object
|
||||
##
|
||||
|
@ -76,10 +101,11 @@ class Textures(object):
|
|||
del attributes[attr]
|
||||
except KeyError:
|
||||
pass
|
||||
attributes['jar'] = None
|
||||
return attributes
|
||||
def __setstate__(self, attrs):
|
||||
# regenerate textures, if needed
|
||||
for attr, val in attrs.iteritems():
|
||||
for attr, val in list(attrs.items()):
|
||||
setattr(self, attr, val)
|
||||
self.texture_cache = {}
|
||||
if self.generated:
|
||||
|
@ -99,7 +125,7 @@ class Textures(object):
|
|||
global known_blocks, used_datas
|
||||
self.blockmap = [None] * max_blockid * max_data
|
||||
|
||||
for (blockid, data), texgen in blockmap_generators.iteritems():
|
||||
for (blockid, data), texgen in list(blockmap_generators.items()):
|
||||
tex = texgen(self, blockid, data)
|
||||
self.blockmap[blockid * max_data + data] = self.generate_texture_tuple(tex)
|
||||
|
||||
|
@ -224,7 +250,7 @@ class Textures(object):
|
|||
self.jar.getinfo(jarfilename)
|
||||
if verbose: logging.info("Found (cached) %s in '%s'", jarfilename, self.jarpath)
|
||||
return self.jar.open(jarfilename)
|
||||
except (KeyError, IOError), e:
|
||||
except (KeyError, IOError) as e:
|
||||
pass
|
||||
|
||||
# Find an installed minecraft client jar and look in it for the texture
|
||||
|
@ -285,7 +311,7 @@ class Textures(object):
|
|||
if verbose: logging.info("Found %s in '%s'", jarfilename, jarpath)
|
||||
self.jar, self.jarpath = jar, jarpath
|
||||
return jar.open(jarfilename)
|
||||
except (KeyError, IOError), e:
|
||||
except (KeyError, IOError) as e:
|
||||
pass
|
||||
|
||||
if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath))
|
||||
|
@ -334,7 +360,7 @@ class Textures(object):
|
|||
return self.texture_cache[filename]
|
||||
|
||||
fileobj = self.find_file(filename)
|
||||
buffer = StringIO(fileobj.read())
|
||||
buffer = BytesIO(fileobj.read())
|
||||
img = Image.open(buffer).convert("RGBA")
|
||||
self.texture_cache[filename] = img
|
||||
return img
|
||||
|
@ -444,8 +470,8 @@ class Textures(object):
|
|||
textures = []
|
||||
(terrain_width, terrain_height) = terrain.size
|
||||
texture_resolution = terrain_width / 16
|
||||
for y in xrange(16):
|
||||
for x in xrange(16):
|
||||
for y in range(16):
|
||||
for x in range(16):
|
||||
left = x*texture_resolution
|
||||
upper = y*texture_resolution
|
||||
right = left+texture_resolution
|
||||
|
@ -815,19 +841,6 @@ class Textures(object):
|
|||
## The other big one: @material and associated framework
|
||||
##
|
||||
|
||||
# global variables to collate information in @material decorators
|
||||
blockmap_generators = {}
|
||||
|
||||
known_blocks = set()
|
||||
used_datas = set()
|
||||
max_blockid = 0
|
||||
max_data = 0
|
||||
|
||||
transparent_blocks = set()
|
||||
solid_blocks = set()
|
||||
fluid_blocks = set()
|
||||
nospawn_blocks = set()
|
||||
nodata_blocks = set()
|
||||
|
||||
# the material registration decorator
|
||||
def material(blockid=[], data=[0], **kwargs):
|
||||
|
@ -837,11 +850,11 @@ def material(blockid=[], data=[0], **kwargs):
|
|||
# make sure blockid and data are iterable
|
||||
try:
|
||||
iter(blockid)
|
||||
except:
|
||||
except Exception:
|
||||
blockid = [blockid,]
|
||||
try:
|
||||
iter(data)
|
||||
except:
|
||||
except Exception:
|
||||
data = [data,]
|
||||
|
||||
def inner_material(func):
|
||||
|
@ -924,7 +937,7 @@ def billboard(blockid=[], imagename=None, **kwargs):
|
|||
##
|
||||
|
||||
# stone
|
||||
@material(blockid=1, data=range(7), solid=True)
|
||||
@material(blockid=1, data=list(range(7)), solid=True)
|
||||
def stone(self, blockid, data):
|
||||
if data == 0: # regular old-school stone
|
||||
img = self.load_image_texture("assets/minecraft/textures/block/stone.png")
|
||||
|
@ -942,7 +955,7 @@ def stone(self, blockid, data):
|
|||
img = self.load_image_texture("assets/minecraft/textures/block/polished_andesite.png")
|
||||
return self.build_block(img, img)
|
||||
|
||||
@material(blockid=2, data=range(11)+[0x10,], solid=True)
|
||||
@material(blockid=2, data=list(range(11))+[0x10,], solid=True)
|
||||
def grass(self, blockid, data):
|
||||
# 0x10 bit means SNOW
|
||||
side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png")
|
||||
|
@ -954,7 +967,7 @@ def grass(self, blockid, data):
|
|||
return img
|
||||
|
||||
# dirt
|
||||
@material(blockid=3, data=range(3), solid=True)
|
||||
@material(blockid=3, data=list(range(3)), solid=True)
|
||||
def dirt_blocks(self, blockid, data):
|
||||
side_img = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
||||
if data == 0: # normal
|
||||
|
@ -970,7 +983,7 @@ def dirt_blocks(self, blockid, data):
|
|||
block(blockid=4, top_image="assets/minecraft/textures/block/cobblestone.png")
|
||||
|
||||
# wooden planks
|
||||
@material(blockid=5, data=range(6), solid=True)
|
||||
@material(blockid=5, data=list(range(6)), solid=True)
|
||||
def wooden_planks(self, blockid, data):
|
||||
if data == 0: # normal
|
||||
return self.build_block(self.load_image_texture("assets/minecraft/textures/block/oak_planks.png"), self.load_image_texture("assets/minecraft/textures/block/oak_planks.png"))
|
||||
|
@ -985,7 +998,7 @@ def wooden_planks(self, blockid, data):
|
|||
if data == 5: # dark oak
|
||||
return self.build_block(self.load_image_texture("assets/minecraft/textures/block/dark_oak_planks.png"),self.load_image_texture("assets/minecraft/textures/block/dark_oak_planks.png"))
|
||||
|
||||
@material(blockid=6, data=range(16), transparent=True)
|
||||
@material(blockid=6, data=list(range(16)), transparent=True)
|
||||
def saplings(self, blockid, data):
|
||||
# usual saplings
|
||||
tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png")
|
||||
|
@ -1007,7 +1020,7 @@ block(blockid=7, top_image="assets/minecraft/textures/block/bedrock.png")
|
|||
|
||||
# water, glass, and ice (no inner surfaces)
|
||||
# uses pseudo-ancildata found in iterate.c
|
||||
@material(blockid=[8, 9, 20, 79, 95], data=range(512), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95))
|
||||
@material(blockid=[8, 9, 20, 79, 95], data=list(range(512)), fluid=(8, 9), transparent=True, nospawn=True, solid=(79, 20, 95))
|
||||
def no_inner_surfaces(self, blockid, data):
|
||||
if blockid == 8 or blockid == 9:
|
||||
texture = self.load_water()
|
||||
|
@ -1054,13 +1067,13 @@ def no_inner_surfaces(self, blockid, data):
|
|||
img = self.build_full_block(top,None,None,side3,side4)
|
||||
return img
|
||||
|
||||
@material(blockid=[10, 11], data=range(16), fluid=True, transparent=False, nospawn=True)
|
||||
@material(blockid=[10, 11], data=list(range(16)), fluid=True, transparent=False, nospawn=True)
|
||||
def lava(self, blockid, data):
|
||||
lavatex = self.load_lava()
|
||||
return self.build_block(lavatex, lavatex)
|
||||
|
||||
# sand
|
||||
@material(blockid=12, data=range(2), solid=True)
|
||||
@material(blockid=12, data=list(range(2)), solid=True)
|
||||
def sand_blocks(self, blockid, data):
|
||||
if data == 0: # normal
|
||||
img = self.build_block(self.load_image_texture("assets/minecraft/textures/block/sand.png"), self.load_image_texture("assets/minecraft/textures/block/sand.png"))
|
||||
|
@ -1077,7 +1090,7 @@ block(blockid=15, top_image="assets/minecraft/textures/block/iron_ore.png")
|
|||
# coal ore
|
||||
block(blockid=16, top_image="assets/minecraft/textures/block/coal_ore.png")
|
||||
|
||||
@material(blockid=[17,162,11306,11307,11308,11309,11310,11311], data=range(12), solid=True)
|
||||
@material(blockid=[17,162,11306,11307,11308,11309,11310,11311], data=list(range(12)), solid=True)
|
||||
def wood(self, blockid, data):
|
||||
# extract orientation and wood type frorm data bits
|
||||
wood_type = data & 3
|
||||
|
@ -1191,7 +1204,7 @@ def wood(self, blockid, data):
|
|||
elif wood_orientation == 8: # north-south orientation
|
||||
return self.build_full_block(side, None, None, side.rotate(270), top)
|
||||
|
||||
@material(blockid=[18, 161], data=range(16), transparent=True, solid=True)
|
||||
@material(blockid=[18, 161], data=list(range(16)), transparent=True, solid=True)
|
||||
def leaves(self, blockid, data):
|
||||
# mask out the bits 4 and 8
|
||||
# they are used for player placed and check-for-decay blocks
|
||||
|
@ -1217,7 +1230,7 @@ block(blockid=21, top_image="assets/minecraft/textures/block/lapis_ore.png")
|
|||
block(blockid=22, top_image="assets/minecraft/textures/block/lapis_block.png")
|
||||
|
||||
# dispensers, dropper, furnaces, and burning furnaces
|
||||
@material(blockid=[23, 61, 62, 158], data=range(6), solid=True)
|
||||
@material(blockid=[23, 61, 62, 158], data=list(range(6)), solid=True)
|
||||
def furnaces(self, blockid, data):
|
||||
# first, do the rotation if needed
|
||||
if self.rotation == 1:
|
||||
|
@ -1266,7 +1279,7 @@ def furnaces(self, blockid, data):
|
|||
return self.build_full_block(top, None, None, side, side)
|
||||
|
||||
# sandstone
|
||||
@material(blockid=24, data=range(3), solid=True)
|
||||
@material(blockid=24, data=list(range(3)), solid=True)
|
||||
def sandstone(self, blockid, data):
|
||||
top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png")
|
||||
if data == 0: # normal
|
||||
|
@ -1277,7 +1290,7 @@ def sandstone(self, blockid, data):
|
|||
return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/cut_sandstone.png"))
|
||||
|
||||
# red sandstone
|
||||
@material(blockid=179, data=range(3), solid=True)
|
||||
@material(blockid=179, data=list(range(3)), solid=True)
|
||||
def sandstone(self, blockid, data):
|
||||
top = self.load_image_texture("assets/minecraft/textures/block/red_sandstone_top.png")
|
||||
if data == 0: # normal
|
||||
|
@ -1291,7 +1304,7 @@ def sandstone(self, blockid, data):
|
|||
# note block
|
||||
block(blockid=25, top_image="assets/minecraft/textures/block/note_block.png")
|
||||
|
||||
@material(blockid=26, data=range(12), transparent=True, nospawn=True)
|
||||
@material(blockid=26, data=list(range(12)), transparent=True, nospawn=True)
|
||||
def bed(self, blockid, data):
|
||||
# first get rotation done
|
||||
# Masked to not clobber block head/foot info
|
||||
|
@ -1381,7 +1394,7 @@ def bed(self, blockid, data):
|
|||
return self.build_full_block(top_face, None, None, left_face, right_face)
|
||||
|
||||
# powered, detector, activator and normal rails
|
||||
@material(blockid=[27, 28, 66, 157], data=range(14), transparent=True)
|
||||
@material(blockid=[27, 28, 66, 157], data=list(range(14)), transparent=True)
|
||||
def rails(self, blockid, data):
|
||||
# first, do rotation
|
||||
# Masked to not clobber powered rail on/off info
|
||||
|
@ -1664,7 +1677,7 @@ def piston_extension(self, blockid, data):
|
|||
# cobweb
|
||||
sprite(blockid=30, imagename="assets/minecraft/textures/block/cobweb.png", nospawn=True)
|
||||
|
||||
@material(blockid=31, data=range(3), transparent=True)
|
||||
@material(blockid=31, data=list(range(3)), transparent=True)
|
||||
def tall_grass(self, blockid, data):
|
||||
if data == 0: # dead shrub
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/dead_bush.png")
|
||||
|
@ -1678,7 +1691,7 @@ def tall_grass(self, blockid, data):
|
|||
# dead bush
|
||||
billboard(blockid=32, imagename="assets/minecraft/textures/block/dead_bush.png")
|
||||
|
||||
@material(blockid=35, data=range(16), solid=True)
|
||||
@material(blockid=35, data=list(range(16)), solid=True)
|
||||
def wool(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data])
|
||||
|
||||
|
@ -1688,7 +1701,7 @@ def wool(self, blockid, data):
|
|||
sprite(blockid=37, imagename="assets/minecraft/textures/block/dandelion.png")
|
||||
|
||||
# flowers
|
||||
@material(blockid=38, data=range(10), transparent=True)
|
||||
@material(blockid=38, data=list(range(10)), transparent=True)
|
||||
def flower(self, blockid, data):
|
||||
flower_map = ["poppy", "blue_orchid", "allium", "azure_bluet", "red_tulip", "orange_tulip",
|
||||
"white_tulip", "pink_tulip", "oxeye_daisy", "dandelion"]
|
||||
|
@ -1708,7 +1721,7 @@ block(blockid=42, top_image="assets/minecraft/textures/block/iron_block.png")
|
|||
# double slabs and slabs
|
||||
# these wooden slabs are unobtainable without cheating, they are still
|
||||
# here because lots of pre-1.3 worlds use this blocks
|
||||
@material(blockid=[43, 44, 181, 182, 204, 205], data=range(16), transparent=(44,182,205), solid=True)
|
||||
@material(blockid=[43, 44, 181, 182, 204, 205], data=list(range(16)), transparent=(44,182,205), solid=True)
|
||||
def slabs(self, blockid, data):
|
||||
if blockid == 44 or blockid == 182:
|
||||
texture = data & 7
|
||||
|
@ -1847,7 +1860,7 @@ def torches(self, blockid, data):
|
|||
return img
|
||||
|
||||
# fire
|
||||
@material(blockid=51, data=range(16), transparent=True)
|
||||
@material(blockid=51, data=list(range(16)), transparent=True)
|
||||
def fire(self, blockid, data):
|
||||
firetextures = self.load_fire()
|
||||
side1 = self.transform_image_side(firetextures[0])
|
||||
|
@ -1867,7 +1880,7 @@ def fire(self, blockid, data):
|
|||
block(blockid=52, top_image="assets/minecraft/textures/block/spawner.png", transparent=True)
|
||||
|
||||
# wooden, cobblestone, red brick, stone brick, netherbrick, sandstone, spruce, birch, jungle, quartz, and red sandstone stairs.
|
||||
@material(blockid=[53,67,108,109,114,128,134,135,136,156,163,164,180,203], data=range(128), transparent=True, solid=True, nospawn=True)
|
||||
@material(blockid=[53,67,108,109,114,128,134,135,136,156,163,164,180,203], data=list(range(128)), transparent=True, solid=True, nospawn=True)
|
||||
def stairs(self, blockid, data):
|
||||
# preserve the upside-down bit
|
||||
upside_down = data & 0x4
|
||||
|
@ -1991,7 +2004,7 @@ def stairs(self, blockid, data):
|
|||
|
||||
# normal, locked (used in april's fool day), ender and trapped chest
|
||||
# NOTE: locked chest used to be id95 (which is now stained glass)
|
||||
@material(blockid=[54,130,146], data=range(30), transparent = True)
|
||||
@material(blockid=[54,130,146], data=list(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.
|
||||
|
@ -2188,7 +2201,7 @@ def chests(self, blockid, data):
|
|||
|
||||
# redstone wire
|
||||
# uses pseudo-ancildata found in iterate.c
|
||||
@material(blockid=55, data=range(128), transparent=True)
|
||||
@material(blockid=55, data=list(range(128)), transparent=True)
|
||||
def wire(self, blockid, data):
|
||||
|
||||
if data & 0b1000000 == 64: # powered redstone wire
|
||||
|
@ -2281,7 +2294,7 @@ def crafting_table(self, blockid, data):
|
|||
return img
|
||||
|
||||
# crops with 8 data values (like wheat)
|
||||
@material(blockid=59, data=range(8), transparent=True, nospawn=True)
|
||||
@material(blockid=59, data=list(range(8)), transparent=True, nospawn=True)
|
||||
def crops8(self, blockid, data):
|
||||
raw_crop = self.load_image_texture("assets/minecraft/textures/block/wheat_stage%d.png" % data)
|
||||
crop1 = self.transform_image_top(raw_crop)
|
||||
|
@ -2295,7 +2308,7 @@ def crops8(self, blockid, data):
|
|||
return img
|
||||
|
||||
# farmland and grass path (15/16 blocks)
|
||||
@material(blockid=[60,208], data=range(9), solid=True)
|
||||
@material(blockid=[60,208], data=list(range(9)), solid=True)
|
||||
def farmland(self, blockid, data):
|
||||
if blockid == 60:
|
||||
side = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
||||
|
@ -2315,7 +2328,7 @@ def farmland(self, blockid, data):
|
|||
|
||||
|
||||
# signposts
|
||||
@material(blockid=63, data=range(16), transparent=True)
|
||||
@material(blockid=63, data=list(range(16)), transparent=True)
|
||||
def signpost(self, blockid, data):
|
||||
|
||||
# first rotations
|
||||
|
@ -2369,7 +2382,7 @@ def signpost(self, blockid, data):
|
|||
|
||||
# wooden and iron door
|
||||
# uses pseudo-ancildata found in iterate.c
|
||||
@material(blockid=[64,71,193,194,195,196,197], data=range(32), transparent=True)
|
||||
@material(blockid=[64,71,193,194,195,196,197], data=list(range(32)), transparent=True)
|
||||
def door(self, blockid, data):
|
||||
#Masked to not clobber block top/bottom & swung info
|
||||
if self.rotation == 1:
|
||||
|
@ -2618,7 +2631,7 @@ def wall_sign(self, blockid, data): # wall sign
|
|||
return img
|
||||
|
||||
# levers
|
||||
@material(blockid=69, data=range(16), transparent=True)
|
||||
@material(blockid=69, data=list(range(16)), transparent=True)
|
||||
def levers(self, blockid, data):
|
||||
if data & 8 == 8: powered = True
|
||||
else: powered = False
|
||||
|
@ -2802,7 +2815,7 @@ def pressure_plate(self, blockid, data):
|
|||
block(blockid=[73, 74], top_image="assets/minecraft/textures/block/redstone_ore.png")
|
||||
|
||||
# stone a wood buttons
|
||||
@material(blockid=(77,143,11326,11327,11328,11329,11330), data=range(16), transparent=True)
|
||||
@material(blockid=(77,143,11326,11327,11328,11329,11330), data=list(range(16)), transparent=True)
|
||||
def buttons(self, blockid, data):
|
||||
|
||||
# 0x8 is set if the button is pressed mask this info and render
|
||||
|
@ -2899,7 +2912,7 @@ def buttons(self, blockid, data):
|
|||
return img
|
||||
|
||||
# snow
|
||||
@material(blockid=78, data=range(16), transparent=True, solid=True)
|
||||
@material(blockid=78, data=list(range(16)), transparent=True, solid=True)
|
||||
def snow(self, blockid, data):
|
||||
# still not rendered correctly: data other than 0
|
||||
|
||||
|
@ -2926,7 +2939,7 @@ def snow(self, blockid, data):
|
|||
block(blockid=80, top_image="assets/minecraft/textures/block/snow.png")
|
||||
|
||||
# cactus
|
||||
@material(blockid=81, data=range(15), transparent=True, solid=True, nospawn=True)
|
||||
@material(blockid=81, data=list(range(15)), transparent=True, solid=True, nospawn=True)
|
||||
def cactus(self, blockid, data):
|
||||
top = self.load_image_texture("assets/minecraft/textures/block/cactus_top.png")
|
||||
side = self.load_image_texture("assets/minecraft/textures/block/cactus_side.png")
|
||||
|
@ -2954,19 +2967,19 @@ def cactus(self, blockid, data):
|
|||
block(blockid=82, top_image="assets/minecraft/textures/block/clay.png")
|
||||
|
||||
# sugar cane
|
||||
@material(blockid=83, data=range(16), transparent=True)
|
||||
@material(blockid=83, data=list(range(16)), transparent=True)
|
||||
def sugar_cane(self, blockid, data):
|
||||
tex = self.load_image_texture("assets/minecraft/textures/block/sugar_cane.png")
|
||||
return self.build_sprite(tex)
|
||||
|
||||
# jukebox
|
||||
@material(blockid=84, data=range(16), solid=True)
|
||||
@material(blockid=84, data=list(range(16)), solid=True)
|
||||
def jukebox(self, blockid, data):
|
||||
return self.build_block(self.load_image_texture("assets/minecraft/textures/block/jukebox_top.png"), self.load_image_texture("assets/minecraft/textures/block/note_block.png"))
|
||||
|
||||
# nether and normal fences
|
||||
# uses pseudo-ancildata found in iterate.c
|
||||
@material(blockid=[85, 188, 189, 190, 191, 192, 113], data=range(16), transparent=True, nospawn=True)
|
||||
@material(blockid=[85, 188, 189, 190, 191, 192, 113], data=list(range(16)), transparent=True, nospawn=True)
|
||||
def fence(self, blockid, data):
|
||||
# no need for rotations, it uses pseudo data.
|
||||
# create needed images for Big stick fence
|
||||
|
@ -3082,7 +3095,7 @@ def fence(self, blockid, data):
|
|||
return img
|
||||
|
||||
# pumpkin
|
||||
@material(blockid=[86, 91,11300], data=range(4), solid=True)
|
||||
@material(blockid=[86, 91,11300], data=list(range(4)), solid=True)
|
||||
def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern
|
||||
# rotation
|
||||
if self.rotation == 1:
|
||||
|
@ -3149,7 +3162,7 @@ def portal(self, blockid, data):
|
|||
return img
|
||||
|
||||
# cake!
|
||||
@material(blockid=92, data=range(6), transparent=True, nospawn=True)
|
||||
@material(blockid=92, data=list(range(6)), transparent=True, nospawn=True)
|
||||
def cake(self, blockid, data):
|
||||
|
||||
# cake textures
|
||||
|
@ -3273,7 +3286,7 @@ def cake(self, blockid, data):
|
|||
return img
|
||||
|
||||
# redstone repeaters ON and OFF
|
||||
@material(blockid=[93,94], data=range(16), transparent=True, nospawn=True)
|
||||
@material(blockid=[93,94], data=list(range(16)), transparent=True, nospawn=True)
|
||||
def repeater(self, blockid, data):
|
||||
# rotation
|
||||
# Masked to not clobber delay info
|
||||
|
@ -3418,7 +3431,7 @@ def repeater(self, blockid, data):
|
|||
return img
|
||||
|
||||
# redstone comparator (149 is inactive, 150 is active)
|
||||
@material(blockid=[149,150], data=range(16), transparent=True, nospawn=True)
|
||||
@material(blockid=[149,150], data=list(range(16)), transparent=True, nospawn=True)
|
||||
def comparator(self, blockid, data):
|
||||
|
||||
# rotation
|
||||
|
@ -3483,7 +3496,7 @@ def comparator(self, blockid, data):
|
|||
|
||||
# trapdoor
|
||||
# the trapdoor is looks like a sprite when opened, that's not good
|
||||
@material(blockid=[96,167,11332,11333,11334,11335,11336], data=range(16), transparent=True, nospawn=True)
|
||||
@material(blockid=[96,167,11332,11333,11334,11335,11336], data=list(range(16)), transparent=True, nospawn=True)
|
||||
def trapdoor(self, blockid, data):
|
||||
|
||||
# rotation
|
||||
|
@ -3539,7 +3552,7 @@ def trapdoor(self, blockid, data):
|
|||
return img
|
||||
|
||||
# block with hidden silverfish (stone, cobblestone and stone brick)
|
||||
@material(blockid=97, data=range(3), solid=True)
|
||||
@material(blockid=97, data=list(range(3)), solid=True)
|
||||
def hidden_silverfish(self, blockid, data):
|
||||
if data == 0: # stone
|
||||
t = self.load_image_texture("assets/minecraft/textures/block/stone.png")
|
||||
|
@ -3553,7 +3566,7 @@ def hidden_silverfish(self, blockid, data):
|
|||
return img
|
||||
|
||||
# stone brick
|
||||
@material(blockid=98, data=range(4), solid=True)
|
||||
@material(blockid=98, data=list(range(4)), solid=True)
|
||||
def stone_brick(self, blockid, data):
|
||||
if data == 0: # normal
|
||||
t = self.load_image_texture("assets/minecraft/textures/block/stone_bricks.png")
|
||||
|
@ -3569,7 +3582,7 @@ def stone_brick(self, blockid, data):
|
|||
return img
|
||||
|
||||
# huge brown and red mushroom
|
||||
@material(blockid=[99,100], data= range(11) + [14,15], solid=True)
|
||||
@material(blockid=[99,100], data= list(range(11)) + [14,15], solid=True)
|
||||
def huge_mushroom(self, blockid, data):
|
||||
# rotation
|
||||
if self.rotation == 1:
|
||||
|
@ -3653,7 +3666,7 @@ def huge_mushroom(self, blockid, data):
|
|||
# iron bars and glass pane
|
||||
# TODO glass pane is not a sprite, it has a texture for the side,
|
||||
# at the moment is not used
|
||||
@material(blockid=[101,102, 160], data=range(256), transparent=True, nospawn=True)
|
||||
@material(blockid=[101,102, 160], data=list(range(256)), transparent=True, nospawn=True)
|
||||
def panes(self, blockid, data):
|
||||
# no rotation, uses pseudo data
|
||||
if blockid == 101:
|
||||
|
@ -3705,7 +3718,7 @@ block(blockid=103, top_image="assets/minecraft/textures/block/melon_top.png", si
|
|||
# TODO To render it as in game needs from pseudo data and ancil data:
|
||||
# once fully grown the stem bends to the melon/pumpkin block,
|
||||
# at the moment only render the growing stem
|
||||
@material(blockid=[104,105], data=range(8), transparent=True)
|
||||
@material(blockid=[104,105], data=list(range(8)), transparent=True)
|
||||
def stem(self, blockid, data):
|
||||
# the ancildata value indicates how much of the texture
|
||||
# is shown.
|
||||
|
@ -3725,7 +3738,7 @@ def stem(self, blockid, data):
|
|||
|
||||
|
||||
# vines
|
||||
@material(blockid=106, data=range(16), transparent=True)
|
||||
@material(blockid=106, data=list(range(16)), transparent=True)
|
||||
def vines(self, blockid, data):
|
||||
# rotation
|
||||
# vines data is bit coded. decode it first.
|
||||
|
@ -3766,7 +3779,7 @@ def vines(self, blockid, data):
|
|||
return img
|
||||
|
||||
# fence gates
|
||||
@material(blockid=[107, 183, 184, 185, 186, 187], data=range(8), transparent=True, nospawn=True)
|
||||
@material(blockid=[107, 183, 184, 185, 186, 187], data=list(range(8)), transparent=True, nospawn=True)
|
||||
def fence_gate(self, blockid, data):
|
||||
|
||||
# rotation
|
||||
|
@ -3870,7 +3883,7 @@ block(blockid=110, top_image="assets/minecraft/textures/block/mycelium_top.png",
|
|||
# At the moment of writing this lilypads has no ancil data and their
|
||||
# orientation depends on their position on the map. So it uses pseudo
|
||||
# ancildata.
|
||||
@material(blockid=111, data=range(4), transparent=True)
|
||||
@material(blockid=111, data=list(range(4)), transparent=True)
|
||||
def lilypad(self, blockid, data):
|
||||
t = self.load_image_texture("assets/minecraft/textures/block/lily_pad.png").copy()
|
||||
if data == 0:
|
||||
|
@ -3888,7 +3901,7 @@ def lilypad(self, blockid, data):
|
|||
block(blockid=112, top_image="assets/minecraft/textures/block/nether_bricks.png")
|
||||
|
||||
# nether wart
|
||||
@material(blockid=115, data=range(4), transparent=True)
|
||||
@material(blockid=115, data=list(range(4)), transparent=True)
|
||||
def nether_wart(self, blockid, data):
|
||||
if data == 0: # just come up
|
||||
t = self.load_image_texture("assets/minecraft/textures/block/nether_wart_stage0.png")
|
||||
|
@ -3915,7 +3928,7 @@ def enchantment_table(self, blockid, data):
|
|||
|
||||
# brewing stand
|
||||
# TODO this is a place holder, is a 2d image pasted
|
||||
@material(blockid=117, data=range(5), transparent=True)
|
||||
@material(blockid=117, data=list(range(5)), transparent=True)
|
||||
def brewing_stand(self, blockid, data):
|
||||
base = self.load_image_texture("assets/minecraft/textures/block/brewing_stand_base.png")
|
||||
img = self.build_full_block(None, None, None, None, None, base)
|
||||
|
@ -3925,7 +3938,7 @@ def brewing_stand(self, blockid, data):
|
|||
return img
|
||||
|
||||
# cauldron
|
||||
@material(blockid=118, data=range(4), transparent=True)
|
||||
@material(blockid=118, data=list(range(4)), transparent=True)
|
||||
def cauldron(self, blockid, data):
|
||||
side = self.load_image_texture("assets/minecraft/textures/block/cauldron_side.png")
|
||||
top = self.load_image_texture("assets/minecraft/textures/block/cauldron_top.png")
|
||||
|
@ -3971,7 +3984,7 @@ def end_portal(self, blockid, data):
|
|||
return img
|
||||
|
||||
# end portal frame (data range 8 to get all orientations of filled)
|
||||
@material(blockid=120, data=range(8), transparent=True)
|
||||
@material(blockid=120, data=list(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
|
||||
|
@ -4046,7 +4059,7 @@ def daylight_sensor(self, blockid, data):
|
|||
# wooden double and normal slabs
|
||||
# these are the new wooden slabs, blockids 43 44 still have wooden
|
||||
# slabs, but those are unobtainable without cheating
|
||||
@material(blockid=[125, 126], data=range(16), transparent=(44,), solid=True)
|
||||
@material(blockid=[125, 126], data=list(range(16)), transparent=(44,), solid=True)
|
||||
def wooden_slabs(self, blockid, data):
|
||||
texture = data & 7
|
||||
if texture== 0: # oak
|
||||
|
@ -4076,7 +4089,7 @@ block(blockid=129, top_image="assets/minecraft/textures/block/emerald_ore.png")
|
|||
block(blockid=133, top_image="assets/minecraft/textures/block/emerald_block.png")
|
||||
|
||||
# cocoa plant
|
||||
@material(blockid=127, data=range(12), transparent=True)
|
||||
@material(blockid=127, data=list(range(12)), transparent=True)
|
||||
def cocoa_plant(self, blockid, data):
|
||||
orientation = data & 3
|
||||
# rotation
|
||||
|
@ -4198,7 +4211,7 @@ def beacon(self, blockid, data):
|
|||
|
||||
# cobblestone and mossy cobblestone walls, chorus plants
|
||||
# one additional bit of data value added for mossy and cobblestone
|
||||
@material(blockid=[139, 199], data=range(32), transparent=True, nospawn=True)
|
||||
@material(blockid=[139, 199], data=list(range(32)), transparent=True, nospawn=True)
|
||||
def cobblestone_wall(self, blockid, data):
|
||||
# chorus plants
|
||||
if blockid == 199:
|
||||
|
@ -4329,7 +4342,7 @@ def cobblestone_wall(self, blockid, data):
|
|||
return img
|
||||
|
||||
# carrots, potatoes
|
||||
@material(blockid=[141,142], data=range(8), transparent=True, nospawn=True)
|
||||
@material(blockid=[141,142], data=list(range(8)), transparent=True, nospawn=True)
|
||||
def crops4(self, blockid, data):
|
||||
# carrots and potatoes have 8 data, but only 4 visual stages
|
||||
stage = {0:0,
|
||||
|
@ -4355,7 +4368,7 @@ def crops4(self, blockid, data):
|
|||
return img
|
||||
|
||||
# anvils
|
||||
@material(blockid=145, data=range(12), transparent=True)
|
||||
@material(blockid=145, data=list(range(12)), transparent=True)
|
||||
def anvil(self, blockid, data):
|
||||
|
||||
# anvils only have two orientations, invert it for rotations 1 and 3
|
||||
|
@ -4447,7 +4460,7 @@ block(blockid=152, top_image="assets/minecraft/textures/block/redstone_block.png
|
|||
block(blockid=153, top_image="assets/minecraft/textures/block/nether_quartz_ore.png")
|
||||
|
||||
# block of quartz
|
||||
@material(blockid=155, data=range(5), solid=True)
|
||||
@material(blockid=155, data=list(range(5)), solid=True)
|
||||
def quartz_block(self, blockid, data):
|
||||
|
||||
if data in (0,1): # normal and chiseled quartz block
|
||||
|
@ -4475,7 +4488,7 @@ def quartz_block(self, blockid, data):
|
|||
return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90))
|
||||
|
||||
# hopper
|
||||
@material(blockid=154, data=range(4), transparent=True)
|
||||
@material(blockid=154, data=list(range(4)), transparent=True)
|
||||
def hopper(self, blockid, data):
|
||||
#build the top
|
||||
side = self.load_image_texture("assets/minecraft/textures/block/hopper_outside.png")
|
||||
|
@ -4502,7 +4515,7 @@ def hopper(self, blockid, data):
|
|||
block(blockid=165, top_image="assets/minecraft/textures/block/slime_block.png")
|
||||
|
||||
# prismarine block
|
||||
@material(blockid=168, data=range(3), solid=True)
|
||||
@material(blockid=168, data=list(range(3)), solid=True)
|
||||
def prismarine_block(self, blockid, data):
|
||||
|
||||
if data == 0: # prismarine
|
||||
|
@ -4520,7 +4533,7 @@ def prismarine_block(self, blockid, data):
|
|||
block(blockid=169, top_image="assets/minecraft/textures/block/sea_lantern.png")
|
||||
|
||||
# hay block
|
||||
@material(blockid=170, data=range(9), solid=True)
|
||||
@material(blockid=170, data=list(range(9)), solid=True)
|
||||
def hayblock(self, blockid, data):
|
||||
top = self.load_image_texture("assets/minecraft/textures/block/hay_block_top.png")
|
||||
side = self.load_image_texture("assets/minecraft/textures/block/hay_block_side.png")
|
||||
|
@ -4542,7 +4555,7 @@ def hayblock(self, blockid, data):
|
|||
|
||||
|
||||
# carpet - wool block that's small?
|
||||
@material(blockid=171, data=range(16), transparent=True)
|
||||
@material(blockid=171, data=list(range(16)), transparent=True)
|
||||
def carpet(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[data])
|
||||
|
||||
|
@ -4552,7 +4565,7 @@ def carpet(self, blockid, data):
|
|||
block(blockid=172, top_image="assets/minecraft/textures/block/terracotta.png")
|
||||
|
||||
#stained hardened clay
|
||||
@material(blockid=159, data=range(16), solid=True)
|
||||
@material(blockid=159, data=list(range(16)), solid=True)
|
||||
def stained_clay(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_terracotta.png" % color_map[data])
|
||||
|
||||
|
@ -4586,7 +4599,7 @@ block(blockid=11323, top_image="assets/minecraft/textures/block/dead_fire_coral_
|
|||
block(blockid=11324, top_image="assets/minecraft/textures/block/dead_horn_coral_block.png")
|
||||
block(blockid=11325, top_image="assets/minecraft/textures/block/dead_tube_coral_block.png")
|
||||
|
||||
@material(blockid=175, data=range(16), transparent=True)
|
||||
@material(blockid=175, data=list(range(16)), transparent=True)
|
||||
def flower(self, blockid, data):
|
||||
double_plant_map = ["sunflower", "lilac", "tall_grass", "large_fern", "rose_bush", "peony", "peony", "peony"]
|
||||
plant = double_plant_map[data & 0x7]
|
||||
|
@ -4608,7 +4621,7 @@ def flower(self, blockid, data):
|
|||
return img
|
||||
|
||||
# chorus flower
|
||||
@material(blockid=200, data=range(6), solid=True)
|
||||
@material(blockid=200, data=list(range(6)), solid=True)
|
||||
def chorus_flower(self, blockid, data):
|
||||
# aged 5, dead
|
||||
if data == 5:
|
||||
|
@ -4622,7 +4635,7 @@ def chorus_flower(self, blockid, data):
|
|||
block(blockid=201, top_image="assets/minecraft/textures/block/purpur_block.png")
|
||||
|
||||
# purpur pilar
|
||||
@material(blockid=202, data=range(12) , solid=True)
|
||||
@material(blockid=202, data=list(range(12)) , solid=True)
|
||||
def purpur_pillar(self, blockid, data):
|
||||
pillar_orientation = data & 12
|
||||
top=self.load_image_texture("assets/minecraft/textures/block/purpur_pillar_top.png")
|
||||
|
@ -4639,7 +4652,7 @@ def purpur_pillar(self, blockid, data):
|
|||
block(blockid=206, top_image="assets/minecraft/textures/block/end_stone_bricks.png")
|
||||
|
||||
# frosted ice
|
||||
@material(blockid=212, data=range(4), solid=True)
|
||||
@material(blockid=212, data=list(range(4)), solid=True)
|
||||
def frosted_ice(self, blockid, data):
|
||||
img = self.load_image_texture("assets/minecraft/textures/block/frosted_ice_%d.png" % data)
|
||||
return self.build_block(img, img)
|
||||
|
@ -4653,7 +4666,7 @@ block(blockid=214, top_image="assets/minecraft/textures/block/nether_wart_block.
|
|||
# red nether brick
|
||||
block(blockid=215, top_image="assets/minecraft/textures/block/red_nether_bricks.png")
|
||||
|
||||
@material(blockid=216, data=range(12), solid=True)
|
||||
@material(blockid=216, data=list(range(12)), solid=True)
|
||||
def boneblock(self, blockid, data):
|
||||
# extract orientation
|
||||
boneblock_orientation = data & 12
|
||||
|
@ -4676,7 +4689,7 @@ def boneblock(self, blockid, data):
|
|||
return self.build_full_block(side, None, None, side.rotate(270), top)
|
||||
|
||||
# observer
|
||||
@material(blockid=218, data=range(6), solid=True, nospawn=True)
|
||||
@material(blockid=218, data=list(range(6)), solid=True, nospawn=True)
|
||||
def observer(self, blockid, data):
|
||||
# first, do the rotation if needed
|
||||
if self.rotation == 1:
|
||||
|
@ -4718,7 +4731,7 @@ def observer(self, blockid, data):
|
|||
return img
|
||||
|
||||
# shulker box
|
||||
@material(blockid=range(219,235), data=range(6), solid=True, nospawn=True)
|
||||
@material(blockid=list(range(219,235)), data=list(range(6)), solid=True, nospawn=True)
|
||||
def shulker_box(self, blockid, data):
|
||||
# first, do the rotation if needed
|
||||
data = data & 7
|
||||
|
@ -4741,15 +4754,15 @@ def shulker_box(self, blockid, data):
|
|||
color = color_map[blockid - 219]
|
||||
shulker_t = self.load_image_texture("assets/minecraft/textures/entity/shulker/shulker_%s.png" % color).copy()
|
||||
w,h = shulker_t.size
|
||||
res = w / 4
|
||||
res = w // 4
|
||||
# Cut out the parts of the shulker texture we need for the box
|
||||
top = shulker_t.crop((res,0,res*2,res))
|
||||
bottom = shulker_t.crop((res*2,int(res*1.75),res*3,int(res*2.75)))
|
||||
side_top = shulker_t.crop((0,res,res,int(res*1.75)))
|
||||
side_bottom = shulker_t.crop((0,int(res*2.75),res,int(res*3.25)))
|
||||
side = Image.new('RGBA', (res,res))
|
||||
side.paste(side_top, (0,0), side_top)
|
||||
side.paste(side_bottom, (0,res/2), side_bottom)
|
||||
top = shulker_t.crop((res, 0, res * 2, res))
|
||||
bottom = shulker_t.crop((res * 2, int(res * 1.75), res * 3, int(res * 2.75)))
|
||||
side_top = shulker_t.crop((0, res, res, int(res * 1.75)))
|
||||
side_bottom = shulker_t.crop((0, int(res * 2.75), res, int(res * 3.25)))
|
||||
side = Image.new('RGBA', (res, res))
|
||||
side.paste(side_top, (0, 0), side_top)
|
||||
side.paste(side_bottom, (0, res // 2), side_bottom)
|
||||
|
||||
if data == 0: # down
|
||||
side = side.rotate(180)
|
||||
|
@ -4768,7 +4781,7 @@ def shulker_box(self, blockid, data):
|
|||
return img
|
||||
|
||||
# structure block
|
||||
@material(blockid=255, data=range(4), solid=True)
|
||||
@material(blockid=255, data=list(range(4)), solid=True)
|
||||
def structure_block(self, blockid, data):
|
||||
if data == 0:
|
||||
img = self.load_image_texture("assets/minecraft/textures/block/structure_block_save.png")
|
||||
|
@ -4781,7 +4794,7 @@ def structure_block(self, blockid, data):
|
|||
return self.build_block(img, img)
|
||||
|
||||
# beetroots
|
||||
@material(blockid=207, data=range(4), transparent=True, nospawn=True)
|
||||
@material(blockid=207, data=list(range(4)), transparent=True, nospawn=True)
|
||||
def crops(self, blockid, data):
|
||||
raw_crop = self.load_image_texture("assets/minecraft/textures/block/beetroots_stage%d.png" % data)
|
||||
crop1 = self.transform_image_top(raw_crop)
|
||||
|
@ -4795,19 +4808,19 @@ def crops(self, blockid, data):
|
|||
return img
|
||||
|
||||
# Concrete
|
||||
@material(blockid=251, data=range(16), solid=True)
|
||||
@material(blockid=251, data=list(range(16)), solid=True)
|
||||
def concrete(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete.png" % color_map[data])
|
||||
return self.build_block(texture, texture)
|
||||
|
||||
# Concrete Powder
|
||||
@material(blockid=252, data=range(16), solid=True)
|
||||
@material(blockid=252, data=list(range(16)), solid=True)
|
||||
def concrete(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete_powder.png" % color_map[data])
|
||||
return self.build_block(texture, texture)
|
||||
|
||||
# Glazed Terracotta
|
||||
@material(blockid=range(235,251), data=range(8), solid=True)
|
||||
@material(blockid=list(range(235,251)), data=list(range(8)), solid=True)
|
||||
def glazed_terracotta(self, blockid, data):
|
||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_glazed_terracotta.png" % color_map[blockid - 235])
|
||||
glazed_terracotta_orientation = data & 3
|
||||
|
|
|
@ -26,13 +26,13 @@ import stat
|
|||
import sys
|
||||
import time
|
||||
from collections import namedtuple
|
||||
from itertools import chain, izip, product
|
||||
from itertools import chain, product
|
||||
|
||||
from PIL import Image
|
||||
|
||||
import c_overviewer
|
||||
import rendermodes
|
||||
from c_overviewer import resize_half
|
||||
from . import c_overviewer
|
||||
from . import rendermodes
|
||||
from .c_overviewer import resize_half
|
||||
|
||||
from . import nbt, world
|
||||
from .files import FileReplacer, get_fs_caps
|
||||
|
@ -95,7 +95,7 @@ do_work(workobj)
|
|||
# small but useful
|
||||
def iterate_base4(d):
|
||||
"""Iterates over a base 4 number with d digits"""
|
||||
return product(xrange(4), repeat=d)
|
||||
return product(range(4), repeat=d)
|
||||
|
||||
|
||||
# A named tuple class storing the row and column bounds for the to-be-rendered
|
||||
|
@ -646,7 +646,7 @@ class TileSet(object):
|
|||
bounds = self._find_chunk_range()
|
||||
|
||||
# Calculate the depth of the tree
|
||||
for p in xrange(2, 33): # max 32
|
||||
for p in range(2, 33): # max 32
|
||||
# Will 2^p tiles wide and high suffice?
|
||||
|
||||
# X has twice as many chunks as tiles, then halved since this is a
|
||||
|
@ -686,13 +686,13 @@ class TileSet(object):
|
|||
if self.treedepth > curdepth:
|
||||
logging.warning("Your map seems to have expanded beyond its previous bounds.")
|
||||
logging.warning("Doing some tile re-arrangements... just a sec...")
|
||||
for _ in xrange(self.treedepth - curdepth):
|
||||
for _ in range(self.treedepth - curdepth):
|
||||
self._increase_depth()
|
||||
elif self.treedepth < curdepth:
|
||||
logging.warning(
|
||||
"Your map seems to have shrunk. Did you delete some "
|
||||
"chunks? No problem. Re-arranging tiles, just a sec...")
|
||||
for _ in xrange(curdepth - self.treedepth):
|
||||
for _ in range(curdepth - self.treedepth):
|
||||
self._decrease_depth()
|
||||
logging.info(
|
||||
"There, done. I'm switching to --check-tiles mode for "
|
||||
|
@ -798,12 +798,12 @@ class TileSet(object):
|
|||
os.rename(getpath("new3"), getpath("3"))
|
||||
|
||||
# Delete the files in the top directory to make sure they get re-created.
|
||||
files = [str(num) + "." + self.imgextension for num in xrange(4)] + \
|
||||
files = [str(num) + "." + self.imgextension for num in range(4)] + \
|
||||
["base." + self.imgextension]
|
||||
for f in files:
|
||||
try:
|
||||
os.unlink(getpath(f))
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore file doesn't exist errors
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
@ -964,7 +964,7 @@ class TileSet(object):
|
|||
if not quadPath_filtered:
|
||||
try:
|
||||
os.unlink(imgpath)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore errors if it's "file doesn't exist"
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
@ -988,14 +988,14 @@ class TileSet(object):
|
|||
quad = Image.new("RGBA", (192, 192), self.options['bgcolor'])
|
||||
resize_half(quad, src)
|
||||
img.paste(quad, path[0])
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
logging.warning("Couldn't open %s. It may be corrupt. Error was '%s'.", path[1], e)
|
||||
logging.warning(
|
||||
"I'm going to try and delete it. You will need to run "
|
||||
"the render again and with --check-tiles.")
|
||||
try:
|
||||
os.unlink(path[1])
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
logging.error(
|
||||
"While attempting to delete corrupt image %s, an error was encountered. "
|
||||
"You will need to delete it yourself. Error was '%s'", path[1], e)
|
||||
|
@ -1016,7 +1016,7 @@ class TileSet(object):
|
|||
|
||||
try:
|
||||
os.utime(tmppath, (max_mtime, max_mtime))
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||
# condition, two processes could conceivably try and update
|
||||
# the same temp file at the same time
|
||||
|
@ -1049,7 +1049,7 @@ class TileSet(object):
|
|||
"This may be a bug.", tile)
|
||||
try:
|
||||
os.unlink(imgpath)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# ignore only if the error was "file not found"
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
|
@ -1062,7 +1062,7 @@ class TileSet(object):
|
|||
if not os.path.exists(dirdest):
|
||||
try:
|
||||
os.makedirs(dirdest)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
# Ignore errno EEXIST: file exists. Due to a race condition,
|
||||
# two processes could conceivably try and create the same
|
||||
# directory at the same time
|
||||
|
@ -1098,7 +1098,7 @@ class TileSet(object):
|
|||
# Some chunks are present on disk but not fully initialized.
|
||||
# This is okay.
|
||||
pass
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
logging.error("Could not render chunk %s,%s for some reason. "
|
||||
"This is likely a render primitive option error.", chunkx, chunkz)
|
||||
logging.error("Full error was:", exc_info=1)
|
||||
|
@ -1154,7 +1154,7 @@ class TileSet(object):
|
|||
imgpath = tileobj.get_filepath(self.outputdir, self.imgextension)
|
||||
try:
|
||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
tile_mtime = 0
|
||||
|
@ -1198,7 +1198,7 @@ class TileSet(object):
|
|||
max_child_mtime = 0
|
||||
|
||||
# First, recurse to each of our children
|
||||
for childnum in xrange(4):
|
||||
for childnum in range(4):
|
||||
childpath = path + (childnum,)
|
||||
|
||||
# Check if this sub-tree should actually exist, so that we only
|
||||
|
@ -1238,7 +1238,7 @@ class TileSet(object):
|
|||
logging.debug("Testing mtime for composite-tile %s", imgpath)
|
||||
try:
|
||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
if e.errno != errno.ENOENT:
|
||||
raise
|
||||
tile_mtime = 0
|
||||
|
@ -1296,7 +1296,7 @@ def unconvert_coords(col, row):
|
|||
|
||||
# col + row = chunkz + chunkz => (col + row)/2 = chunkz
|
||||
# col - row = chunkx + chunkx => (col - row)/2 = chunkx
|
||||
return ((col - row) / 2, (col + row) / 2)
|
||||
return ((col - row) // 2, (col + row) // 2)
|
||||
|
||||
|
||||
######################
|
||||
|
@ -1325,9 +1325,9 @@ def get_tiles_by_chunk(chunkcol, chunkrow):
|
|||
# tile above it as well. Also touches the next 4 tiles down (16
|
||||
# rows)
|
||||
if chunkrow % 4 == 0:
|
||||
rowrange = xrange(tilerow - 4, tilerow + 32 + 1, 4)
|
||||
rowrange = range(tilerow - 4, tilerow + 32 + 1, 4)
|
||||
else:
|
||||
rowrange = xrange(tilerow, tilerow + 32 + 1, 4)
|
||||
rowrange = range(tilerow, tilerow + 32 + 1, 4)
|
||||
|
||||
return product(colrange, rowrange)
|
||||
|
||||
|
@ -1358,13 +1358,13 @@ def get_chunks_by_tile(tile, regionset):
|
|||
# First do the odd. For each chunk in the tile's odd column the tile
|
||||
# "passes through" three chunk sections.
|
||||
oddcol_sections = []
|
||||
for i, y in enumerate(reversed(xrange(16))):
|
||||
for row in xrange(tile.row + 3 - i * 2, tile.row - 2 - i * 2, -2):
|
||||
for i, y in enumerate(reversed(range(16))):
|
||||
for row in range(tile.row + 3 - i * 2, tile.row - 2 - i * 2, -2):
|
||||
oddcol_sections.append((tile.col + 1, row, y))
|
||||
|
||||
evencol_sections = []
|
||||
for i, y in enumerate(reversed(xrange(16))):
|
||||
for row in xrange(tile.row + 4 - i * 2, tile.row - 3 - i * 2, -2):
|
||||
for i, y in enumerate(reversed(range(16))):
|
||||
for row in range(tile.row + 4 - i * 2, tile.row - 3 - i * 2, -2):
|
||||
evencol_sections.append((tile.col + 2, row, y))
|
||||
evencol_sections.append((tile.col, row, y))
|
||||
|
||||
|
@ -1589,7 +1589,7 @@ class RendertileSet(object):
|
|||
# or more of the children down the tree are True.
|
||||
return True
|
||||
|
||||
def __nonzero__(self):
|
||||
def __bool__(self):
|
||||
"""Returns the boolean context of this particular node. If any
|
||||
descendent of this node is True return True. Otherwise, False.
|
||||
|
||||
|
@ -1604,8 +1604,8 @@ class RendertileSet(object):
|
|||
# XXX There seems to be something wrong with the num_tiles calculation.
|
||||
# Calculate the number of tiles by iteration and emit a warning if it
|
||||
# does not match.
|
||||
from itertools import imap
|
||||
num = sum(imap(lambda _: 1, self.iterate()))
|
||||
|
||||
num = sum(map(lambda _: 1, self.iterate()))
|
||||
if num != self.num_tiles:
|
||||
logging.error("Please report this to the developers: RendertileSet num_tiles=%r, "
|
||||
"count=%r, children=%r", self.num_tiles, num, self.children)
|
||||
|
@ -1619,22 +1619,23 @@ class RendertileSet(object):
|
|||
# XXX There seems to be something wrong with the num_tiles calculation.
|
||||
# Calculate the number of tiles by iteration and emit a warning if it
|
||||
# does not match.
|
||||
from itertools import imap
|
||||
num = sum(imap(lambda _: 1, self.posttraversal()))
|
||||
|
||||
num = sum(map(lambda _: 1, self.posttraversal()))
|
||||
if num != self.num_tiles_all:
|
||||
logging.error("Please report this to the developers: RendertileSet num_tiles_all=%r, "
|
||||
"count_all=%r, children=%r", self.num_tiles, num, self.children)
|
||||
return num
|
||||
|
||||
|
||||
def distance_sort(children, (off_x, off_y)):
|
||||
def distance_sort(children, xxx_todo_changeme):
|
||||
(off_x, off_y) = xxx_todo_changeme
|
||||
order = []
|
||||
for child, (dx, dy) in izip(children, [(-1, -1), (1, -1), (-1, 1), (1, 1)]):
|
||||
for child, (dx, dy) in zip(children, [(-1, -1), (1, -1), (-1, 1), (1, 1)]):
|
||||
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)
|
||||
return sorted(order, key=lambda __x_y: __x_y[1][0] * __x_y[1][0] + __x_y[1][1] * __x_y[1][1])
|
||||
|
||||
|
||||
class RenderTile(object):
|
||||
|
@ -1733,7 +1734,7 @@ class RenderTile(object):
|
|||
|
||||
path = []
|
||||
|
||||
for level in xrange(depth):
|
||||
for level in range(depth):
|
||||
# Strategy: Find the midpoint of this level, and determine which
|
||||
# quadrant this row/col is in. Then set the bounds to that level
|
||||
# and repeat
|
||||
|
|
|
@ -48,7 +48,7 @@ def findGitHash():
|
|||
return line
|
||||
except Exception:
|
||||
try:
|
||||
import overviewer_version
|
||||
from . import overviewer_version
|
||||
return overviewer_version.HASH
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -77,7 +77,7 @@ def findGitVersion():
|
|||
return line
|
||||
except Exception:
|
||||
try:
|
||||
import overviewer_version
|
||||
from . import overviewer_version
|
||||
return overviewer_version.VERSION
|
||||
except Exception:
|
||||
return "unknown"
|
||||
|
@ -108,7 +108,7 @@ def nice_exit(ret=0):
|
|||
if ret and is_bare_console():
|
||||
print("")
|
||||
print("Press [Enter] to close this window.")
|
||||
raw_input()
|
||||
input()
|
||||
sys.exit(ret)
|
||||
|
||||
|
||||
|
@ -117,7 +117,7 @@ def roundrobin(iterables):
|
|||
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
|
||||
# Recipe credited to George Sakkis
|
||||
pending = len(iterables)
|
||||
nexts = cycle(iter(it).next for it in iterables)
|
||||
nexts = cycle(iter(it).__next__ for it in iterables)
|
||||
while pending:
|
||||
try:
|
||||
for next in nexts:
|
||||
|
@ -136,281 +136,13 @@ def dict_subset(d, keys):
|
|||
return n
|
||||
|
||||
|
||||
# (from http://code.activestate.com/recipes/576693/ [r9])
|
||||
# Backport of OrderedDict() class that runs on Python 2.4, 2.5, 2.6, 2.7 and pypy.
|
||||
# Passes Python2.7's test suite and incorporates all the latest updates.
|
||||
try:
|
||||
from thread import get_ident as _get_ident
|
||||
except ImportError:
|
||||
from dummy_thread import get_ident as _get_ident
|
||||
|
||||
try:
|
||||
from _abcoll import KeysView, ValuesView, ItemsView
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
|
||||
class OrderedDict(dict):
|
||||
'Dictionary that remembers insertion order'
|
||||
# An inherited dict maps keys to values.
|
||||
# The inherited dict provides __getitem__, __len__, __contains__, and get.
|
||||
# The remaining methods are order-aware.
|
||||
# Big-O running times for all methods are the same as for regular dictionaries.
|
||||
|
||||
# The internal self.__map dictionary maps keys to links in a doubly linked list.
|
||||
# The circular doubly linked list starts and ends with a sentinel element.
|
||||
# The sentinel element never gets deleted (this simplifies the algorithm).
|
||||
# Each link is stored as a list of length three: [PREV, NEXT, KEY].
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
'''Initialize an ordered dictionary. Signature is the same as for
|
||||
regular dictionaries, but keyword arguments are not recommended
|
||||
because their insertion order is arbitrary.
|
||||
|
||||
'''
|
||||
if len(args) > 1:
|
||||
raise TypeError('expected at most 1 arguments, got %d' % len(args))
|
||||
try:
|
||||
self.__root
|
||||
except AttributeError:
|
||||
self.__root = root = [] # sentinel node
|
||||
root[:] = [root, root, None]
|
||||
self.__map = {}
|
||||
self.__update(*args, **kwds)
|
||||
|
||||
def __setitem__(self, key, value, dict_setitem=dict.__setitem__):
|
||||
'od.__setitem__(i, y) <==> od[i]=y'
|
||||
# Setting a new item creates a new link which goes at the end of the linked
|
||||
# list, and the inherited dictionary is updated with the new key/value pair.
|
||||
if key not in self:
|
||||
root = self.__root
|
||||
last = root[0]
|
||||
last[1] = root[0] = self.__map[key] = [last, root, key]
|
||||
dict_setitem(self, key, value)
|
||||
|
||||
def __delitem__(self, key, dict_delitem=dict.__delitem__):
|
||||
'od.__delitem__(y) <==> del od[y]'
|
||||
# Deleting an existing item uses self.__map to find the link which is
|
||||
# then removed by updating the links in the predecessor and successor nodes.
|
||||
dict_delitem(self, key)
|
||||
link_prev, link_next, key = self.__map.pop(key)
|
||||
link_prev[1] = link_next
|
||||
link_next[0] = link_prev
|
||||
|
||||
def __iter__(self):
|
||||
'od.__iter__() <==> iter(od)'
|
||||
root = self.__root
|
||||
curr = root[1]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[1]
|
||||
|
||||
def __reversed__(self):
|
||||
'od.__reversed__() <==> reversed(od)'
|
||||
root = self.__root
|
||||
curr = root[0]
|
||||
while curr is not root:
|
||||
yield curr[2]
|
||||
curr = curr[0]
|
||||
|
||||
def clear(self):
|
||||
'od.clear() -> None. Remove all items from od.'
|
||||
try:
|
||||
for node in self.__map.itervalues():
|
||||
del node[:]
|
||||
root = self.__root
|
||||
root[:] = [root, root, None]
|
||||
self.__map.clear()
|
||||
except AttributeError:
|
||||
pass
|
||||
dict.clear(self)
|
||||
|
||||
def popitem(self, last=True):
|
||||
'''od.popitem() -> (k, v), return and remove a (key, value) pair.
|
||||
Pairs are returned in LIFO order if last is true or FIFO order if false.
|
||||
|
||||
'''
|
||||
if not self:
|
||||
raise KeyError('dictionary is empty')
|
||||
root = self.__root
|
||||
if last:
|
||||
link = root[0]
|
||||
link_prev = link[0]
|
||||
link_prev[1] = root
|
||||
root[0] = link_prev
|
||||
else:
|
||||
link = root[1]
|
||||
link_next = link[1]
|
||||
root[1] = link_next
|
||||
link_next[0] = root
|
||||
key = link[2]
|
||||
del self.__map[key]
|
||||
value = dict.pop(self, key)
|
||||
return key, value
|
||||
|
||||
# -- the following methods do not depend on the internal structure --
|
||||
|
||||
def keys(self):
|
||||
'od.keys() -> list of keys in od'
|
||||
return list(self)
|
||||
|
||||
def values(self):
|
||||
'od.values() -> list of values in od'
|
||||
return [self[key] for key in self]
|
||||
|
||||
def items(self):
|
||||
'od.items() -> list of (key, value) pairs in od'
|
||||
return [(key, self[key]) for key in self]
|
||||
|
||||
def iterkeys(self):
|
||||
'od.iterkeys() -> an iterator over the keys in od'
|
||||
return iter(self)
|
||||
|
||||
def itervalues(self):
|
||||
'od.itervalues -> an iterator over the values in od'
|
||||
for k in self:
|
||||
yield self[k]
|
||||
|
||||
def iteritems(self):
|
||||
'od.iteritems -> an iterator over the (key, value) items in od'
|
||||
for k in self:
|
||||
yield (k, self[k])
|
||||
|
||||
def update(*args, **kwds):
|
||||
'''od.update(E, **F) -> None. Update od from dict/iterable E and F.
|
||||
|
||||
If E is a dict instance, does: for k in E: od[k] = E[k]
|
||||
If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]
|
||||
Or if E is an iterable of items, does: for k, v in E: od[k] = v
|
||||
In either case, this is followed by: for k, v in F.items(): od[k] = v
|
||||
|
||||
'''
|
||||
if len(args) > 2:
|
||||
raise TypeError('update() takes at most 2 positional '
|
||||
'arguments (%d given)' % (len(args),))
|
||||
elif not args:
|
||||
raise TypeError('update() takes at least 1 argument (0 given)')
|
||||
self = args[0]
|
||||
# Make progressively weaker assumptions about "other"
|
||||
other = ()
|
||||
if len(args) == 2:
|
||||
other = args[1]
|
||||
if isinstance(other, dict):
|
||||
for key in other:
|
||||
self[key] = other[key]
|
||||
elif hasattr(other, 'keys'):
|
||||
for key in other.keys():
|
||||
self[key] = other[key]
|
||||
else:
|
||||
for key, value in other:
|
||||
self[key] = value
|
||||
for key, value in kwds.items():
|
||||
self[key] = value
|
||||
|
||||
__update = update # let subclasses override update without breaking __init__
|
||||
|
||||
__marker = object()
|
||||
|
||||
def pop(self, key, default=__marker):
|
||||
'''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.
|
||||
If key is not found, d is returned if given, otherwise KeyError is raised.
|
||||
|
||||
'''
|
||||
if key in self:
|
||||
result = self[key]
|
||||
del self[key]
|
||||
return result
|
||||
if default is self.__marker:
|
||||
raise KeyError(key)
|
||||
return default
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'
|
||||
if key in self:
|
||||
return self[key]
|
||||
self[key] = default
|
||||
return default
|
||||
|
||||
def __repr__(self, _repr_running={}):
|
||||
'od.__repr__() <==> repr(od)'
|
||||
call_key = id(self), _get_ident()
|
||||
if call_key in _repr_running:
|
||||
return '...'
|
||||
_repr_running[call_key] = 1
|
||||
try:
|
||||
if not self:
|
||||
return '%s()' % (self.__class__.__name__,)
|
||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
||||
finally:
|
||||
del _repr_running[call_key]
|
||||
|
||||
def __reduce__(self):
|
||||
'Return state information for pickling'
|
||||
items = [[k, self[k]] for k in self]
|
||||
inst_dict = vars(self).copy()
|
||||
for k in vars(OrderedDict()):
|
||||
inst_dict.pop(k, None)
|
||||
if inst_dict:
|
||||
return (self.__class__, (items,), inst_dict)
|
||||
return self.__class__, (items,)
|
||||
|
||||
def copy(self):
|
||||
'od.copy() -> a shallow copy of od'
|
||||
return self.__class__(self)
|
||||
|
||||
@classmethod
|
||||
def fromkeys(cls, iterable, value=None):
|
||||
'''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
|
||||
and values equal to v (which defaults to None).
|
||||
|
||||
'''
|
||||
d = cls()
|
||||
for key in iterable:
|
||||
d[key] = value
|
||||
return d
|
||||
|
||||
def __eq__(self, other):
|
||||
'''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive
|
||||
while comparison to a regular mapping is order-insensitive.
|
||||
|
||||
'''
|
||||
if isinstance(other, OrderedDict):
|
||||
return len(self) == len(other) and self.items() == other.items()
|
||||
return dict.__eq__(self, other)
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
# -- the following methods are only used in Python 2.7 --
|
||||
|
||||
def viewkeys(self):
|
||||
"od.viewkeys() -> a set-like object providing a view on od's keys"
|
||||
return KeysView(self)
|
||||
|
||||
def viewvalues(self):
|
||||
"od.viewvalues() -> an object providing a view on od's values"
|
||||
return ValuesView(self)
|
||||
|
||||
def viewitems(self):
|
||||
"od.viewitems() -> a set-like object providing a view on od's items"
|
||||
return ItemsView(self)
|
||||
|
||||
|
||||
# now replace all that with the official version, if available
|
||||
try:
|
||||
import collections
|
||||
OrderedDict = collections.OrderedDict
|
||||
except (ImportError, AttributeError):
|
||||
pass
|
||||
|
||||
|
||||
def pid_exists(pid): # http://stackoverflow.com/a/6940314/1318435
|
||||
"""Check whether pid exists in the current process table."""
|
||||
if pid < 0:
|
||||
return False
|
||||
try:
|
||||
os.kill(pid, 0)
|
||||
except OSError, e:
|
||||
except OSError as e:
|
||||
return e.errno != errno.ESRCH
|
||||
else:
|
||||
return True
|
||||
|
|
|
@ -53,7 +53,7 @@ def log_other_exceptions(func):
|
|||
return func(*args)
|
||||
except ChunkDoesntExist:
|
||||
raise
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
logging.exception("%s raised this exception", func.func_name)
|
||||
raise
|
||||
return newfunc
|
||||
|
@ -1139,7 +1139,7 @@ class RegionSet(object):
|
|||
try:
|
||||
region = self._get_regionobj(regionfile)
|
||||
data = region.load_chunk(x, z)
|
||||
except nbt.CorruptionError, e:
|
||||
except nbt.CorruptionError as e:
|
||||
tries -= 1
|
||||
if tries > 0:
|
||||
# Flush the region cache to possibly read a new region file
|
||||
|
@ -1251,7 +1251,7 @@ class RegionSet(object):
|
|||
|
||||
"""
|
||||
|
||||
for (regionx, regiony), (regionfile, filemtime) in self.regionfiles.iteritems():
|
||||
for (regionx, regiony), (regionfile, filemtime) in self.regionfiles.items():
|
||||
try:
|
||||
mcr = self._get_regionobj(regionfile)
|
||||
except nbt.CorruptRegionError:
|
||||
|
@ -1267,7 +1267,7 @@ class RegionSet(object):
|
|||
|
||||
"""
|
||||
|
||||
for (regionx, regiony), (regionfile, filemtime) in self.regionfiles.iteritems():
|
||||
for (regionx, regiony), (regionfile, filemtime) in self.regionfiles.items():
|
||||
""" SKIP LOADING A REGION WHICH HAS NOT BEEN MODIFIED! """
|
||||
if (filemtime < mtime):
|
||||
continue
|
||||
|
@ -1561,7 +1561,6 @@ def get_worlds():
|
|||
"Returns {world # or name : level.dat information}"
|
||||
ret = {}
|
||||
save_dir = get_save_dir()
|
||||
loc = locale.getpreferredencoding()
|
||||
|
||||
# No dirs found - most likely not running from inside minecraft-dir
|
||||
if not save_dir is None:
|
||||
|
@ -1571,14 +1570,15 @@ def get_worlds():
|
|||
if not os.path.exists(world_dat): continue
|
||||
try:
|
||||
info = nbt.load(world_dat)[1]
|
||||
info['Data']['path'] = os.path.join(save_dir, dir).decode(loc)
|
||||
info['Data']['path'] = os.path.join(save_dir, dir)
|
||||
if 'LevelName' in info['Data'].keys():
|
||||
ret[info['Data']['LevelName']] = info['Data']
|
||||
except nbt.CorruptNBTError:
|
||||
ret[os.path.basename(world_path).decode(loc) + " (corrupt)"] = {'path': world_path.decode(loc),
|
||||
'LastPlayed': 0,
|
||||
'Time': 0,
|
||||
'IsCorrupt': True}
|
||||
ret[os.path.basename(world_path) + " (corrupt)"] = {
|
||||
'path': world_path,
|
||||
'LastPlayed': 0,
|
||||
'Time': 0,
|
||||
'IsCorrupt': True}
|
||||
|
||||
|
||||
for dir in os.listdir("."):
|
||||
|
|
16
setup.py
16
setup.py
|
@ -1,15 +1,15 @@
|
|||
#!/usr/bin/env python2
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
|
||||
# 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")
|
||||
if sys.version_info[0] >= 3:
|
||||
print("and will not run on Python 3.0 or later")
|
||||
if sys.version_info[0] == 2 or (sys.version_info[0] == 3 and sys.version_info[1] < 4):
|
||||
print("Sorry, the Overviewer requires at least Python 3.4 to run.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
from distutils.core import setup
|
||||
from distutils.extension import Extension
|
||||
from distutils.command.build import build
|
||||
|
@ -176,12 +176,12 @@ for name in glob.glob("overviewer_core/src/primitives/*.c"):
|
|||
primitives.append(name)
|
||||
|
||||
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
|
||||
c_overviewer_files += map(lambda mode: 'primitives/%s.c' % (mode,), primitives)
|
||||
c_overviewer_files += ['primitives/%s.c' % (mode) for mode in primitives]
|
||||
c_overviewer_files += ['Draw.c']
|
||||
c_overviewer_includes = ['overviewer.h', 'rendermodes.h']
|
||||
|
||||
c_overviewer_files = map(lambda s: 'overviewer_core/src/'+s, c_overviewer_files)
|
||||
c_overviewer_includes = map(lambda s: 'overviewer_core/src/'+s, c_overviewer_includes)
|
||||
c_overviewer_files = ['overviewer_core/src/' + s for s in c_overviewer_files]
|
||||
c_overviewer_includes = ['overviewer_core/src/' + s for s in c_overviewer_includes]
|
||||
|
||||
setup_kwargs['ext_modules'].append(Extension('overviewer_core.c_overviewer', c_overviewer_files, include_dirs=['.', numpy_include] + pil_include, depends=c_overviewer_includes, extra_link_args=[]))
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import unittest
|
||||
|
||||
# For convenience
|
||||
|
|
|
@ -9,15 +9,15 @@ class TestLRU(unittest.TestCase):
|
|||
|
||||
def test_single_insert(self):
|
||||
self.lru[1] = 2
|
||||
self.assertEquals(self.lru[1], 2)
|
||||
self.assertEqual(self.lru[1], 2)
|
||||
|
||||
def test_multiple_insert(self):
|
||||
self.lru[1] = 2
|
||||
self.lru[3] = 4
|
||||
self.lru[5] = 6
|
||||
self.assertEquals(self.lru[1], 2)
|
||||
self.assertEquals(self.lru[3], 4)
|
||||
self.assertEquals(self.lru[5], 6)
|
||||
self.assertEqual(self.lru[1], 2)
|
||||
self.assertEqual(self.lru[3], 4)
|
||||
self.assertEqual(self.lru[5], 6)
|
||||
|
||||
def test_full(self):
|
||||
self.lru[1] = 'asdf'
|
||||
|
@ -27,11 +27,11 @@ class TestLRU(unittest.TestCase):
|
|||
self.lru[5] = 'asdf'
|
||||
self.lru[6] = 'asdf'
|
||||
self.assertRaises(KeyError, self.lru.__getitem__, 1)
|
||||
self.assertEquals(self.lru[2], 'asdf')
|
||||
self.assertEquals(self.lru[3], 'asdf')
|
||||
self.assertEquals(self.lru[4], 'asdf')
|
||||
self.assertEquals(self.lru[5], 'asdf')
|
||||
self.assertEquals(self.lru[6], 'asdf')
|
||||
self.assertEqual(self.lru[2], 'asdf')
|
||||
self.assertEqual(self.lru[3], 'asdf')
|
||||
self.assertEqual(self.lru[4], 'asdf')
|
||||
self.assertEqual(self.lru[5], 'asdf')
|
||||
self.assertEqual(self.lru[6], 'asdf')
|
||||
|
||||
def test_lru(self):
|
||||
self.lru[1] = 'asdf'
|
||||
|
@ -40,17 +40,17 @@ class TestLRU(unittest.TestCase):
|
|||
self.lru[4] = 'asdf'
|
||||
self.lru[5] = 'asdf'
|
||||
|
||||
self.assertEquals(self.lru[1], 'asdf')
|
||||
self.assertEquals(self.lru[2], 'asdf')
|
||||
self.assertEquals(self.lru[4], 'asdf')
|
||||
self.assertEquals(self.lru[5], 'asdf')
|
||||
self.assertEqual(self.lru[1], 'asdf')
|
||||
self.assertEqual(self.lru[2], 'asdf')
|
||||
self.assertEqual(self.lru[4], 'asdf')
|
||||
self.assertEqual(self.lru[5], 'asdf')
|
||||
|
||||
# 3 should be evicted now
|
||||
self.lru[6] = 'asdf'
|
||||
|
||||
self.assertRaises(KeyError, self.lru.__getitem__, 3)
|
||||
self.assertEquals(self.lru[1], 'asdf')
|
||||
self.assertEquals(self.lru[2], 'asdf')
|
||||
self.assertEquals(self.lru[4], 'asdf')
|
||||
self.assertEquals(self.lru[5], 'asdf')
|
||||
self.assertEquals(self.lru[6], 'asdf')
|
||||
self.assertEqual(self.lru[1], 'asdf')
|
||||
self.assertEqual(self.lru[2], 'asdf')
|
||||
self.assertEqual(self.lru[4], 'asdf')
|
||||
self.assertEqual(self.lru[5], 'asdf')
|
||||
self.assertEqual(self.lru[6], 'asdf')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import unittest
|
||||
|
||||
from itertools import chain, izip
|
||||
from itertools import chain
|
||||
|
||||
from overviewer_core.tileset import iterate_base4, RendertileSet
|
||||
from overviewer_core.util import roundrobin
|
||||
|
@ -150,7 +150,7 @@ class RendertileSetTest(unittest.TestCase):
|
|||
self.assertRaises(AssertionError, self.test_iterate)
|
||||
|
||||
def test_count(self):
|
||||
self.assertEquals(self.tree.count(), len(self.tile_paths))
|
||||
self.assertEqual(self.tree.count(), len(self.tile_paths))
|
||||
|
||||
def test_bool(self):
|
||||
"Tests the boolean status of a node"
|
||||
|
@ -202,7 +202,7 @@ class RendertileSetTest(unittest.TestCase):
|
|||
"""Test a post-traversal of the tree's dirty tiles"""
|
||||
# Expect the results in this proper order.
|
||||
iterator = iter(self.tree.posttraversal())
|
||||
for expected, actual in izip(self.tile_paths_posttraversal, iterator):
|
||||
for expected, actual in zip(self.tile_paths_posttraversal, iterator):
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
self.assertRaises(StopIteration, next, iterator)
|
||||
|
@ -211,7 +211,7 @@ class RendertileSetTest(unittest.TestCase):
|
|||
"""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):
|
||||
for expected, actual in zip(self.tile_paths_posttraversal_robin, iterator):
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
self.assertRaises(StopIteration, next, iterator)
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import unittest
|
||||
from collections import OrderedDict
|
||||
|
||||
from overviewer_core import configParser
|
||||
from overviewer_core.settingsValidators import ValidationException
|
||||
|
@ -6,7 +7,6 @@ from overviewer_core.settingsValidators import ValidationException
|
|||
from overviewer_core import world
|
||||
from overviewer_core import rendermodes
|
||||
|
||||
from overviewer_core.util import OrderedDict
|
||||
|
||||
class SettingsTest(unittest.TestCase):
|
||||
|
||||
|
@ -23,12 +23,12 @@ class SettingsTest(unittest.TestCase):
|
|||
# no exceptions so far. that's a good thing
|
||||
|
||||
# Test the default
|
||||
self.assertEquals(things['renders']['myworld']['bgcolor'], (26,26,26,0))
|
||||
self.assertEqual(things['renders']['myworld']['bgcolor'], (26,26,26,0))
|
||||
|
||||
# Test a non-default
|
||||
self.assertEquals(things['renders']['otherworld']['bgcolor'], (255,255,255,0))
|
||||
self.assertEqual(things['renders']['otherworld']['bgcolor'], (255,255,255,0))
|
||||
|
||||
self.assertEquals(things['renders']['myworld']['northdirection'],
|
||||
self.assertEqual(things['renders']['myworld']['northdirection'],
|
||||
world.UPPER_LEFT)
|
||||
|
||||
def test_rendermode_validation(self):
|
||||
|
@ -63,7 +63,7 @@ class SettingsTest(unittest.TestCase):
|
|||
}),
|
||||
]))
|
||||
self.s.set_config_item("outputdir", "/tmp/fictional/outputdir")
|
||||
self.assertEquals(fromfile.get_validated_config(), self.s.get_validated_config())
|
||||
self.assertEqual(fromfile.get_validated_config(), self.s.get_validated_config())
|
||||
|
||||
def test_rendermode_string(self):
|
||||
self.s.set_config_item("worlds", {
|
||||
|
@ -79,7 +79,7 @@ class SettingsTest(unittest.TestCase):
|
|||
},
|
||||
})
|
||||
p = self.s.get_validated_config()
|
||||
self.assertEquals(p['renders']['myworld']['rendermode'], rendermodes.normal)
|
||||
self.assertEqual(p['renders']['myworld']['rendermode'], rendermodes.normal)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -50,11 +50,11 @@ class FakeRegionset(object):
|
|||
return NotImplementedError()
|
||||
|
||||
def iterate_chunks(self):
|
||||
for (x,z),mtime in self.chunks.iteritems():
|
||||
for (x,z),mtime in self.chunks.items():
|
||||
yield x,z,mtime
|
||||
|
||||
def iterate_newer_chunks(self, filemtime):
|
||||
for (x,z),mtime in self.chunks.iteritems():
|
||||
for (x,z),mtime in self.chunks.items():
|
||||
yield x,z,mtime
|
||||
|
||||
def get_chunk_mtime(self, x, z):
|
||||
|
@ -77,7 +77,7 @@ def get_tile_set(chunks):
|
|||
the compare_iterate_to_expected() method.
|
||||
"""
|
||||
tile_set = defaultdict(int)
|
||||
for (chunkx, chunkz), chunkmtime in chunks.iteritems():
|
||||
for (chunkx, chunkz), chunkmtime in chunks.items():
|
||||
|
||||
col, row = tileset.convert_coords(chunkx, chunkz)
|
||||
|
||||
|
@ -86,9 +86,9 @@ def get_tile_set(chunks):
|
|||
tile_set[tile.path] = max(tile_set[tile.path], chunkmtime)
|
||||
|
||||
# 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().items():
|
||||
# All render-tiles are length 5. Hard-code its upper tiles
|
||||
for i in reversed(xrange(5)):
|
||||
for i in reversed(range(5)):
|
||||
tile_set[tile[:i]] = max(tile_set[tile[:i]], tile_mtime)
|
||||
return dict(tile_set)
|
||||
|
||||
|
@ -98,7 +98,7 @@ def create_fakedir(outputdir, tiles):
|
|||
files) and sets mtimes appropriately
|
||||
|
||||
"""
|
||||
for tilepath, tilemtime in tiles.iteritems():
|
||||
for tilepath, tilemtime in tiles.items():
|
||||
dirpath = os.path.join(outputdir, *(str(x) for x in tilepath[:-1]))
|
||||
if len(tilepath) == 0:
|
||||
imgname = "base.png"
|
||||
|
@ -175,7 +175,7 @@ class TilesetTest(unittest.TestCase):
|
|||
self.assertTrue(tilepath in expected, "%s was not expected to be returned. Expected %s" % (tilepath, expected))
|
||||
|
||||
# Now check that all expected tiles were indeed returned
|
||||
for tilepath in expected.iterkeys():
|
||||
for tilepath in expected.keys():
|
||||
self.assertTrue(tilepath in paths, "%s was expected to be returned but wasn't: %s" % (tilepath, paths))
|
||||
|
||||
def test_get_phase_length(self):
|
||||
|
@ -215,7 +215,7 @@ class TilesetTest(unittest.TestCase):
|
|||
"""Same as above but with a different set of chunks
|
||||
"""
|
||||
# Pick 3 random chunks to update
|
||||
chunks = self.rs.chunks.keys()
|
||||
chunks = list(self.rs.chunks.keys())
|
||||
self.r.shuffle(chunks)
|
||||
updated_chunks = {}
|
||||
for key in chunks[:3]:
|
||||
|
|
|
@ -17,19 +17,19 @@ class ExampleWorldTest(unittest.TestCase):
|
|||
w = world.World("test/data/worlds/exmaple")
|
||||
|
||||
regionsets = w.get_regionsets()
|
||||
self.assertEquals(len(regionsets), 3)
|
||||
self.assertEqual(len(regionsets), 3)
|
||||
|
||||
regionset = regionsets[0]
|
||||
self.assertEquals(regionset.get_region_path(0,0), 'test/data/worlds/exmaple/DIM-1/region/r.0.0.mcr')
|
||||
self.assertEquals(regionset.get_region_path(-1,0), 'test/data/worlds/exmaple/DIM-1/region/r.-1.0.mcr')
|
||||
self.assertEquals(regionset.get_region_path(1,1), 'test/data/worlds/exmaple/DIM-1/region/r.0.0.mcr')
|
||||
self.assertEquals(regionset.get_region_path(35,35), None)
|
||||
self.assertEqual(regionset.get_region_path(0,0), 'test/data/worlds/exmaple/DIM-1/region/r.0.0.mcr')
|
||||
self.assertEqual(regionset.get_region_path(-1,0), 'test/data/worlds/exmaple/DIM-1/region/r.-1.0.mcr')
|
||||
self.assertEqual(regionset.get_region_path(1,1), 'test/data/worlds/exmaple/DIM-1/region/r.0.0.mcr')
|
||||
self.assertEqual(regionset.get_region_path(35,35), None)
|
||||
|
||||
# a few random chunks. reference timestamps fetched with libredstone
|
||||
self.assertEquals(regionset.get_chunk_mtime(0,0), 1316728885)
|
||||
self.assertEquals(regionset.get_chunk_mtime(-1,-1), 1316728886)
|
||||
self.assertEquals(regionset.get_chunk_mtime(5,0), 1316728905)
|
||||
self.assertEquals(regionset.get_chunk_mtime(-22,16), 1316786786)
|
||||
self.assertEqual(regionset.get_chunk_mtime(0,0), 1316728885)
|
||||
self.assertEqual(regionset.get_chunk_mtime(-1,-1), 1316728886)
|
||||
self.assertEqual(regionset.get_chunk_mtime(5,0), 1316728905)
|
||||
self.assertEqual(regionset.get_chunk_mtime(-22,16), 1316786786)
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue