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:
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
# This file is part of the Minecraft Overviewer.
|
# This file is part of the Minecraft Overviewer.
|
||||||
#
|
#
|
||||||
@@ -21,10 +21,8 @@ import platform
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
# quick version check
|
# quick version check
|
||||||
if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6):
|
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 2.6 to run")
|
print("Sorry, the Overviewer requires at least Python 3.4 to run.")
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
print("and will not run on Python 3.0 or later")
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -35,6 +33,7 @@ import multiprocessing
|
|||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from overviewer_core import util
|
from overviewer_core import util
|
||||||
from overviewer_core import logger
|
from overviewer_core import logger
|
||||||
@@ -136,7 +135,7 @@ def main():
|
|||||||
# Check for possible shell quoting issues
|
# Check for possible shell quoting issues
|
||||||
if len(unknowns) > 0:
|
if len(unknowns) > 0:
|
||||||
possible_mistakes = []
|
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.world, args.output] + unknowns[:i]))
|
||||||
possible_mistakes.append(" ".join([args.output] + unknowns[:i]))
|
possible_mistakes.append(" ".join([args.output] + unknowns[:i]))
|
||||||
for mistake in possible_mistakes:
|
for mistake in possible_mistakes:
|
||||||
@@ -183,9 +182,9 @@ def main():
|
|||||||
print("Currently running Minecraft Overviewer %s" % util.findGitVersion() +
|
print("Currently running Minecraft Overviewer %s" % util.findGitVersion() +
|
||||||
" (%s)" % util.findGitHash()[:7])
|
" (%s)" % util.findGitHash()[:7])
|
||||||
try:
|
try:
|
||||||
import urllib
|
from urllib import request
|
||||||
import json
|
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']
|
.read())['src']
|
||||||
print("Latest version of Minecraft Overviewer %s (%s)" % (latest_ver['version'],
|
print("Latest version of Minecraft Overviewer %s (%s)" % (latest_ver['version'],
|
||||||
latest_ver['commit'][:7]))
|
latest_ver['commit'][:7]))
|
||||||
@@ -294,7 +293,7 @@ def main():
|
|||||||
rendermodes = args.rendermodes.replace("-", "_").split(",")
|
rendermodes = args.rendermodes.replace("-", "_").split(",")
|
||||||
|
|
||||||
# Now for some good defaults
|
# Now for some good defaults
|
||||||
renders = util.OrderedDict()
|
renders = OrderedDict()
|
||||||
for rm in rendermodes:
|
for rm in rendermodes:
|
||||||
renders["world-" + rm] = {
|
renders["world-" + rm] = {
|
||||||
"world": "world",
|
"world": "world",
|
||||||
@@ -337,7 +336,7 @@ def main():
|
|||||||
|
|
||||||
if args.check_terrain: # we are already in the "if configfile" branch
|
if args.check_terrain: # we are already in the "if configfile" branch
|
||||||
logging.info("Looking for a few common texture files...")
|
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)
|
logging.info("Looking at render %r.", render_name)
|
||||||
|
|
||||||
# find or create the textures object
|
# find or create the textures object
|
||||||
@@ -356,7 +355,7 @@ def main():
|
|||||||
logging.debug("Current log level: {0}.".format(logging.getLogger().level))
|
logging.debug("Current log level: {0}.".format(logging.getLogger().level))
|
||||||
|
|
||||||
def set_renderchecks(checkname, num):
|
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:
|
if render.get('renderchecks', 0) == 3:
|
||||||
logging.warning(checkname + " ignoring render " + repr(name) + " since it's "
|
logging.warning(checkname + " ignoring render " + repr(name) + " since it's "
|
||||||
"marked as \"don't render\".")
|
"marked as \"don't render\".")
|
||||||
@@ -381,7 +380,7 @@ def main():
|
|||||||
|
|
||||||
#####################
|
#####################
|
||||||
# Do a few last minute things to each render dictionary here
|
# 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
|
# Convert render['world'] to the world path, and store the original
|
||||||
# in render['worldname_orig']
|
# in render['worldname_orig']
|
||||||
try:
|
try:
|
||||||
@@ -437,7 +436,7 @@ def main():
|
|||||||
|
|
||||||
# The changelist support.
|
# The changelist support.
|
||||||
changelists = {}
|
changelists = {}
|
||||||
for render in config['renders'].itervalues():
|
for render in config['renders'].values():
|
||||||
if 'changelist' in render:
|
if 'changelist' in render:
|
||||||
path = render['changelist']
|
path = render['changelist']
|
||||||
if path not in changelists:
|
if path not in changelists:
|
||||||
@@ -461,7 +460,7 @@ def main():
|
|||||||
# TODO: optionally more caching layers here
|
# TODO: optionally more caching layers here
|
||||||
|
|
||||||
renders = config['renders']
|
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)
|
logging.debug("Found the following render thing: %r", render)
|
||||||
|
|
||||||
# find or create the world object
|
# find or create the world object
|
||||||
@@ -572,7 +571,7 @@ def main():
|
|||||||
|
|
||||||
assetMrg.finalize(tilesets)
|
assetMrg.finalize(tilesets)
|
||||||
|
|
||||||
for out in changelists.itervalues():
|
for out in changelists.values():
|
||||||
logging.debug("Closing %s (%s).", out, out.fileno())
|
logging.debug("Closing %s (%s).", out, out.fileno())
|
||||||
out.close()
|
out.close()
|
||||||
|
|
||||||
@@ -603,8 +602,8 @@ def list_worlds():
|
|||||||
formatString = "%-" + str(worldNameLen) + "s | %-8s | %-16s | %s "
|
formatString = "%-" + str(worldNameLen) + "s | %-8s | %-16s | %s "
|
||||||
print(formatString % ("World", "Playtime", "Modified", "Path"))
|
print(formatString % ("World", "Playtime", "Modified", "Path"))
|
||||||
print(formatString % ("-" * worldNameLen, "-" * 8, '-' * 16, '-' * 4))
|
print(formatString % ("-" * worldNameLen, "-" * 8, '-' * 16, '-' * 4))
|
||||||
for name, info in sorted(worlds.iteritems()):
|
for name, info in sorted(worlds.items()):
|
||||||
if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
|
if isinstance(name, str) and name.startswith("World") and len(name) == 6:
|
||||||
try:
|
try:
|
||||||
world_n = int(name[-1])
|
world_n = int(name[-1])
|
||||||
# we'll catch this one later, when it shows up as an
|
# 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
|
# Code to check to make sure c_overviewer is built and working
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from __future__ import print_function
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import traceback
|
import traceback
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import util
|
from . import util
|
||||||
|
|
||||||
def check_c_overviewer():
|
def check_c_overviewer():
|
||||||
"""Check to make sure c_overviewer works and is up-to-date. Prints
|
"""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()
|
root_dir = util.get_program_path()
|
||||||
# make sure the c_overviewer extension is available
|
# make sure the c_overviewer extension is available
|
||||||
try:
|
try:
|
||||||
import c_overviewer
|
from . import c_overviewer
|
||||||
except ImportError:
|
except ImportError:
|
||||||
if os.environ.get("OVERVIEWER_DEBUG_IMPORT") == "1":
|
if os.environ.get("OVERVIEWER_DEBUG_IMPORT") == "1":
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
## if this is a frozen windows package, the following error messages about
|
## if this is a frozen windows package, the following error messages about
|
||||||
## building the c_overviewer extension are not appropriate
|
## building the c_overviewer extension are not appropriate
|
||||||
if hasattr(sys, "frozen") and platform.system() == 'Windows':
|
if hasattr(sys, "frozen") and platform.system() == 'Windows':
|
||||||
print "Something has gone wrong importing the c_overviewer extension. Please"
|
print("Something has gone wrong importing the c_overviewer extension. Please make sure "
|
||||||
print "make sure the 2008 and 2010 redistributable packages from Microsoft"
|
"the 2008 and 2010 redistributable packages from Microsoft are installed.")
|
||||||
print "are installed."
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
## try to find the build extension
|
## try to find the build extension
|
||||||
ext = os.path.join(root_dir, "overviewer_core", "c_overviewer.%s" % ("pyd" if platform.system() == "Windows" else "so"))
|
ext = os.path.join(root_dir, "overviewer_core", "c_overviewer.%s" % ("pyd" if platform.system() == "Windows" else "so"))
|
||||||
if os.path.exists(ext):
|
if os.path.exists(ext):
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
print ""
|
print()
|
||||||
print "Something has gone wrong importing the c_overviewer extension. Please"
|
print("Something has gone wrong importing the c_overviewer extension. Please make sure "
|
||||||
print "make sure it is up-to-date (clean and rebuild)"
|
"it is up-to-date. (clean and rebuild)")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
print "You need to compile the c_overviewer module to run Minecraft Overviewer."
|
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("Run `python setup.py build`, or see the README for details.")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -54,14 +55,15 @@ def check_c_overviewer():
|
|||||||
if os.path.exists(os.path.join(root_dir, "overviewer_core", "src", "overviewer.h")):
|
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:
|
with open(os.path.join(root_dir, "overviewer_core", "src", "overviewer.h")) as f:
|
||||||
lines = f.readlines()
|
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:
|
if lines:
|
||||||
l = lines[0]
|
l = lines[0]
|
||||||
if int(l.split()[2].strip()) != c_overviewer.extension_version():
|
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
|
return 1
|
||||||
else:
|
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
|
return 1
|
||||||
|
|
||||||
# all good!
|
# all good!
|
||||||
|
|||||||
@@ -23,9 +23,9 @@ import traceback
|
|||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
import world
|
from . import world
|
||||||
import util
|
from . import util
|
||||||
from files import FileReplacer, mirror_dir, get_fs_caps
|
from .files import FileReplacer, mirror_dir, get_fs_caps
|
||||||
|
|
||||||
|
|
||||||
class AssetManager(object):
|
class AssetManager(object):
|
||||||
@@ -53,7 +53,7 @@ top-level directory.
|
|||||||
with open(config_loc) as c:
|
with open(config_loc) as c:
|
||||||
ovconf_str = "{" + "\n".join(c.readlines()[1:-1]) + "}"
|
ovconf_str = "{" + "\n".join(c.readlines()[1:-1]) + "}"
|
||||||
self.overviewerConfig = json.loads(ovconf_str)
|
self.overviewerConfig = json.loads(ovconf_str)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
if os.path.exists(config_loc):
|
if os.path.exists(config_loc):
|
||||||
logging.warning("A previous overviewerConfig.js was found, "
|
logging.warning("A previous overviewerConfig.js was found, "
|
||||||
"but I couldn't read it for some reason."
|
"but I couldn't read it for some reason."
|
||||||
@@ -61,16 +61,6 @@ top-level directory.
|
|||||||
logging.debug(traceback.format_exc())
|
logging.debug(traceback.format_exc())
|
||||||
self.overviewerConfig = dict(tilesets=dict())
|
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):
|
def get_tileset_config(self, name):
|
||||||
"Return the correct dictionary from the parsed overviewerConfig.js"
|
"Return the correct dictionary from the parsed overviewerConfig.js"
|
||||||
for conf in self.overviewerConfig['tilesets']:
|
for conf in self.overviewerConfig['tilesets']:
|
||||||
@@ -213,10 +203,7 @@ top-level directory.
|
|||||||
|
|
||||||
index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
|
index = codecs.open(indexpath, 'r', encoding='UTF-8').read()
|
||||||
index = index.replace("{title}", "Minecraft Overviewer")
|
index = index.replace("{title}", "Minecraft Overviewer")
|
||||||
index = index.replace("{time}",
|
index = index.replace("{time}", time.strftime("%a, %d %b %Y %H:%M:%S %Z", time.localtime()))
|
||||||
time.strftime("%a, %d %b %Y %H:%M:%S %Z",
|
|
||||||
time.localtime())
|
|
||||||
.decode(self.preferredencoding))
|
|
||||||
versionstr = "%s (%s)" % (util.findGitVersion(),
|
versionstr = "%s (%s)" % (util.findGitVersion(),
|
||||||
util.findGitHash()[:7])
|
util.findGitHash()[:7])
|
||||||
index = index.replace("{version}", versionstr)
|
index = index.replace("{version}", versionstr)
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import os.path
|
|||||||
import logging
|
import logging
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
import settingsDefinition
|
from . import settingsDefinition
|
||||||
import settingsValidators
|
from . import settingsValidators
|
||||||
|
|
||||||
class MissingConfigException(Exception):
|
class MissingConfigException(Exception):
|
||||||
"To be thrown when the config file can't be found"
|
"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
|
# The global environment should be the rendermode module, so the config
|
||||||
# file has access to those resources.
|
# file has access to those resources.
|
||||||
import rendermodes
|
from . import rendermodes
|
||||||
|
|
||||||
try:
|
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):
|
if isinstance(ex, SyntaxError):
|
||||||
logging.error("Syntax error parsing %s" % settings_file)
|
logging.error("Syntax error parsing %s" % settings_file)
|
||||||
logging.error("The traceback below will tell you which line triggered the syntax error\n")
|
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
|
# At this point, make a pass through the file to possibly set global
|
||||||
# render defaults
|
# render defaults
|
||||||
render_settings = self._settings['renders'].validator.valuevalidator.config
|
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 not in self._settings:
|
||||||
if key in render_settings:
|
if key in render_settings:
|
||||||
setting = render_settings[key]
|
setting = render_settings[key]
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License along
|
# You should have received a copy of the GNU General Public License along
|
||||||
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import util
|
from . import util
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
import multiprocessing.managers
|
import multiprocessing.managers
|
||||||
import Queue
|
import queue
|
||||||
import time
|
import time
|
||||||
from signals import Signal
|
from .signals import Signal
|
||||||
|
|
||||||
class Dispatcher(object):
|
class Dispatcher(object):
|
||||||
"""This class coordinates the work of all the TileSet objects
|
"""This class coordinates the work of all the TileSet objects
|
||||||
@@ -51,7 +51,7 @@ class Dispatcher(object):
|
|||||||
|
|
||||||
# iterate through all possible phases
|
# iterate through all possible phases
|
||||||
num_phases = [tileset.get_num_phases() for tileset in tilesetlist]
|
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
|
# construct a list of iterators to use for this phase
|
||||||
work_iterators = []
|
work_iterators = []
|
||||||
for i, tileset in enumerate(tilesetlist):
|
for i, tileset in enumerate(tilesetlist):
|
||||||
@@ -235,7 +235,7 @@ class MultiprocessingDispatcherProcess(multiprocessing.Process):
|
|||||||
def handler(*args, **kwargs):
|
def handler(*args, **kwargs):
|
||||||
self.signal_queue.put((name, args, kwargs), False)
|
self.signal_queue.put((name, args, kwargs), False)
|
||||||
sig.set_interceptor(handler)
|
sig.set_interceptor(handler)
|
||||||
for name, sig in Signal.signals.iteritems():
|
for name, sig in Signal.signals.items():
|
||||||
register_signal(name, sig)
|
register_signal(name, sig)
|
||||||
|
|
||||||
# notify that we're starting up
|
# notify that we're starting up
|
||||||
@@ -259,7 +259,7 @@ class MultiprocessingDispatcherProcess(multiprocessing.Process):
|
|||||||
ret = self.tilesets[ti].do_work(workitem)
|
ret = self.tilesets[ti].do_work(workitem)
|
||||||
result = (ti, workitem, ret,)
|
result = (ti, workitem, ret,)
|
||||||
self.result_queue.put(result, False)
|
self.result_queue.put(result, False)
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class MultiprocessingDispatcher(Dispatcher):
|
class MultiprocessingDispatcher(Dispatcher):
|
||||||
@@ -288,7 +288,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||||||
|
|
||||||
# create and fill the pool
|
# create and fill the pool
|
||||||
self.pool = []
|
self.pool = []
|
||||||
for i in xrange(self.local_procs):
|
for i in range(self.local_procs):
|
||||||
proc = MultiprocessingDispatcherProcess(self.manager)
|
proc = MultiprocessingDispatcherProcess(self.manager)
|
||||||
proc.start()
|
proc.start()
|
||||||
self.pool.append(proc)
|
self.pool.append(proc)
|
||||||
@@ -300,7 +300,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||||||
self._handle_messages()
|
self._handle_messages()
|
||||||
|
|
||||||
# send of the end-of-jobs sentinel
|
# 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)
|
self.job_queue.put(None, False)
|
||||||
|
|
||||||
# TODO better way to be sure worker processes get the message
|
# TODO better way to be sure worker processes get the message
|
||||||
@@ -350,7 +350,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||||||
else:
|
else:
|
||||||
# new worker
|
# new worker
|
||||||
self.num_workers += 1
|
self.num_workers += 1
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
result_empty = True
|
result_empty = True
|
||||||
if not signal_empty:
|
if not signal_empty:
|
||||||
try:
|
try:
|
||||||
@@ -363,7 +363,7 @@ class MultiprocessingDispatcher(Dispatcher):
|
|||||||
|
|
||||||
sig = Signal.signals[name]
|
sig = Signal.signals[name]
|
||||||
sig.emit_intercepted(*args, **kwargs)
|
sig.emit_intercepted(*args, **kwargs)
|
||||||
except Queue.Empty:
|
except queue.Empty:
|
||||||
signal_empty = True
|
signal_empty = True
|
||||||
|
|
||||||
return finished_jobs
|
return finished_jobs
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ class FileReplacer(object):
|
|||||||
# error
|
# error
|
||||||
try:
|
try:
|
||||||
os.remove(self.tmpname)
|
os.remove(self.tmpname)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logging.warning("An error was raised, so I was doing "
|
logging.warning("An error was raised, so I was doing "
|
||||||
"some cleanup first, but I couldn't remove "
|
"some cleanup first, but I couldn't remove "
|
||||||
"'%s'!", self.tmpname)
|
"'%s'!", self.tmpname)
|
||||||
@@ -153,7 +153,7 @@ class FileReplacer(object):
|
|||||||
if self.caps.get("chmod_works") and os.path.exists(self.destname):
|
if self.caps.get("chmod_works") and os.path.exists(self.destname):
|
||||||
try:
|
try:
|
||||||
shutil.copymode(self.destname, self.tmpname)
|
shutil.copymode(self.destname, self.tmpname)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# Ignore errno ENOENT: file does not exist. Due to a race
|
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||||
# condition, two processes could conceivably try and update
|
# condition, two processes could conceivably try and update
|
||||||
# the same temp file at the same time
|
# the same temp file at the same time
|
||||||
@@ -162,7 +162,7 @@ class FileReplacer(object):
|
|||||||
# atomic rename into place
|
# atomic rename into place
|
||||||
try:
|
try:
|
||||||
os.rename(self.tmpname, self.destname)
|
os.rename(self.tmpname, self.destname)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# Ignore errno ENOENT: file does not exist. Due to a race
|
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||||
# condition, two processes could conceivably try and update
|
# condition, two processes could conceivably try and update
|
||||||
# the same temp file at the same time
|
# the same temp file at the same time
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
from cStringIO import StringIO
|
from io import BytesIO
|
||||||
|
|
||||||
# Some cool code for colored logging:
|
# Some cool code for colored logging:
|
||||||
# For background, add 40. For foreground, add 30
|
# For background, add 40. For foreground, add 30
|
||||||
@@ -88,7 +88,7 @@ class WindowsOutputStream(object):
|
|||||||
|
|
||||||
def write(self, s):
|
def write(self, s):
|
||||||
|
|
||||||
msg_strm = StringIO(s)
|
msg_strm = BytesIO(s)
|
||||||
|
|
||||||
while (True):
|
while (True):
|
||||||
c = msg_strm.read(1)
|
c = msg_strm.read(1)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import functools
|
import functools
|
||||||
import gzip
|
import gzip
|
||||||
import StringIO
|
from io import BytesIO
|
||||||
import struct
|
import struct
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ import zlib
|
|||||||
def _file_loader(func):
|
def _file_loader(func):
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
def wrapper(fileobj, *args):
|
def wrapper(fileobj, *args):
|
||||||
if isinstance(fileobj, basestring):
|
if type(fileobj) == str:
|
||||||
# Is actually a filename
|
# Is actually a filename
|
||||||
fileobj = open(fileobj, 'rb', 4096)
|
fileobj = open(fileobj, 'rb', 4096)
|
||||||
return func(fileobj, *args)
|
return func(fileobj, *args)
|
||||||
@@ -92,7 +92,7 @@ class NBTFileReader(object):
|
|||||||
# pure zlib stream -- maybe later replace this with
|
# pure zlib stream -- maybe later replace this with
|
||||||
# a custom zlib file object?
|
# a custom zlib file object?
|
||||||
data = zlib.decompress(fileobj.read())
|
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
|
# mapping of NBT type ids to functions to read them out
|
||||||
self._read_tagmap = {
|
self._read_tagmap = {
|
||||||
@@ -168,7 +168,7 @@ class NBTFileReader(object):
|
|||||||
|
|
||||||
read_method = self._read_tagmap[tagid]
|
read_method = self._read_tagmap[tagid]
|
||||||
l = []
|
l = []
|
||||||
for _ in xrange(length):
|
for _ in range(length):
|
||||||
l.append(read_method())
|
l.append(read_method())
|
||||||
return l
|
return l
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ class NBTFileReader(object):
|
|||||||
name = self._read_tag_string()
|
name = self._read_tag_string()
|
||||||
payload = self._read_tag_compound()
|
payload = self._read_tag_compound()
|
||||||
return (name, payload)
|
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),))
|
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,
|
file, as (x, z) coordinate tuples. To load these chunks,
|
||||||
provide these coordinates to load_chunk()."""
|
provide these coordinates to load_chunk()."""
|
||||||
|
|
||||||
for x in xrange(32):
|
for x in range(32):
|
||||||
for z in xrange(32):
|
for z in range(32):
|
||||||
if self._locations[x + z * 32] >> 8 != 0:
|
if self._locations[int(x + z * 32)] >> 8 != 0:
|
||||||
yield (x, z)
|
yield (x, z)
|
||||||
|
|
||||||
def get_chunk_timestamp(self, x, z):
|
def get_chunk_timestamp(self, x, z):
|
||||||
@@ -264,13 +264,13 @@ class MCRFileReader(object):
|
|||||||
"""
|
"""
|
||||||
x = x % 32
|
x = x % 32
|
||||||
z = z % 32
|
z = z % 32
|
||||||
return self._timestamps[x + z * 32]
|
return self._timestamps[int(x + z * 32)]
|
||||||
|
|
||||||
def chunk_exists(self, x, z):
|
def chunk_exists(self, x, z):
|
||||||
"""Determines if a chunk exists."""
|
"""Determines if a chunk exists."""
|
||||||
x = x % 32
|
x = x % 32
|
||||||
z = z % 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):
|
def load_chunk(self, x, z):
|
||||||
"""Return a (name, data) tuple for the given chunk, or
|
"""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."""
|
have the chunks load out of regions properly."""
|
||||||
x = x % 32
|
x = x % 32
|
||||||
z = z % 32
|
z = z % 32
|
||||||
location = self._locations[x + z * 32]
|
location = self._locations[int(x + z * 32)]
|
||||||
offset = (location >> 8) * 4096
|
offset = (location >> 8) * 4096
|
||||||
sectors = location & 0xff
|
sectors = location & 0xff
|
||||||
|
|
||||||
@@ -311,16 +311,16 @@ class MCRFileReader(object):
|
|||||||
raise CorruptRegionError("unsupported chunk compression type: %i "
|
raise CorruptRegionError("unsupported chunk compression type: %i "
|
||||||
"(should be 1 or 2)" % (compression,))
|
"(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)
|
# (using data_length - 1, as we already read 1 byte for compression)
|
||||||
data = self._file.read(data_length - 1)
|
data = self._file.read(data_length - 1)
|
||||||
if len(data) != data_length - 1:
|
if len(data) != data_length - 1:
|
||||||
raise CorruptRegionError("chunk length is invalid")
|
raise CorruptRegionError("chunk length is invalid")
|
||||||
data = StringIO.StringIO(data)
|
data = BytesIO(data)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return NBTFileReader(data, is_gzip=is_gzip).read_all()
|
return NBTFileReader(data, is_gzip=is_gzip).read_all()
|
||||||
except CorruptionError:
|
except CorruptionError:
|
||||||
raise
|
raise
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
raise CorruptChunkError("Misc error parsing chunk: " + str(e))
|
raise CorruptChunkError("Misc error parsing chunk: " + str(e))
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import progressbar
|
from . import progressbar
|
||||||
import rcon
|
from . import rcon
|
||||||
|
|
||||||
|
|
||||||
class Observer(object):
|
class Observer(object):
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ class Optimizer:
|
|||||||
path = os.environ.get("PATH").split(os.pathsep)
|
path = os.environ.get("PATH").split(os.pathsep)
|
||||||
|
|
||||||
def exists_in_path(prog):
|
def exists_in_path(prog):
|
||||||
result = filter(lambda x: os.path.exists(os.path.join(x, prog)),
|
result = [x for x in path if os.path.exists(os.path.join(x, prog))]
|
||||||
path)
|
|
||||||
return len(result) != 0
|
return len(result) != 0
|
||||||
|
|
||||||
binaries = self.binarynames + [x + ".exe" for x in self.binarynames]
|
binaries = self.binarynames + [x + ".exe" for x in self.binarynames]
|
||||||
|
|||||||
@@ -189,13 +189,13 @@ class Bar(ProgressBarWidgetHFill):
|
|||||||
self.left = left
|
self.left = left
|
||||||
self.right = right
|
self.right = right
|
||||||
def _format_marker(self, pbar):
|
def _format_marker(self, pbar):
|
||||||
if isinstance(self.marker, (str, unicode)):
|
if isinstance(self.marker, str):
|
||||||
return self.marker
|
return self.marker
|
||||||
else:
|
else:
|
||||||
return self.marker.update(pbar)
|
return self.marker.update(pbar)
|
||||||
def update(self, pbar, width):
|
def update(self, pbar, width):
|
||||||
percent = pbar.percentage()
|
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)
|
marked_width = int(percent * cwidth / 100)
|
||||||
m = self._format_marker(pbar)
|
m = self._format_marker(pbar)
|
||||||
bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
|
bar = (self.left + (m*marked_width).ljust(cwidth) + self.right)
|
||||||
@@ -283,7 +283,7 @@ class ProgressBar(object):
|
|||||||
r.append(w)
|
r.append(w)
|
||||||
hfill_inds.append(i)
|
hfill_inds.append(i)
|
||||||
num_hfill += 1
|
num_hfill += 1
|
||||||
elif isinstance(w, (str, unicode)):
|
elif isinstance(w, str):
|
||||||
r.append(w)
|
r.append(w)
|
||||||
currwidth += len(w)
|
currwidth += len(w)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
# with the Overviewer. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import textures
|
from . import textures
|
||||||
|
|
||||||
"""The contents of this file are imported into the namespace of config files.
|
"""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.
|
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")
|
raise RuntimeError("RenderPrimitive cannot be used directly")
|
||||||
|
|
||||||
self.option_values = {}
|
self.option_values = {}
|
||||||
for key, val in kwargs.iteritems():
|
for key, val in kwargs.items():
|
||||||
if not key in self.options:
|
if not key in self.options:
|
||||||
raise ValueError("primitive `{0}' has no option `{1}'".format(self.name, key))
|
raise ValueError("primitive `{0}' has no option `{1}'".format(self.name, key))
|
||||||
self.option_values[key] = val
|
self.option_values[key] = val
|
||||||
|
|
||||||
# set up defaults
|
# 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:
|
if not name in self.option_values:
|
||||||
self.option_values[name] = default
|
self.option_values[name] = default
|
||||||
|
|
||||||
|
|||||||
@@ -43,10 +43,11 @@
|
|||||||
# available during the execution of the config file. This way, container types
|
# 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.
|
# can be initialized and then appended/added to when the config file is parsed.
|
||||||
|
|
||||||
from settingsValidators import *
|
from collections import OrderedDict
|
||||||
import util
|
|
||||||
from observer import ProgressBarObserver, LoggingObserver, JSObserver
|
from .settingsValidators import *
|
||||||
from optimizeimages import pngnq, optipng, pngcrush
|
from .observer import ProgressBarObserver, LoggingObserver, JSObserver
|
||||||
|
from .optimizeimages import pngnq, optipng, pngcrush
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ import sys
|
|||||||
# objects with their respective validators.
|
# objects with their respective validators.
|
||||||
|
|
||||||
# config file.
|
# config file.
|
||||||
renders = Setting(required=True, default=util.OrderedDict(),
|
renders = Setting(required=True, default=OrderedDict(),
|
||||||
validator=make_dictValidator(validateStr, make_configDictValidator(
|
validator=make_dictValidator(validateStr, make_configDictValidator(
|
||||||
{
|
{
|
||||||
"world": Setting(required=True, validator=validateStr, default=None),
|
"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
|
# 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)
|
outputdir = Setting(required=True, validator=validateOutputDir, default=None)
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,12 @@
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
import rendermodes
|
from . import rendermodes
|
||||||
import util
|
from . import util
|
||||||
from optimizeimages import Optimizer
|
from .optimizeimages import Optimizer
|
||||||
from world import LOWER_LEFT, LOWER_RIGHT, UPPER_LEFT, UPPER_RIGHT
|
from .world import LOWER_LEFT, LOWER_RIGHT, UPPER_LEFT, UPPER_RIGHT
|
||||||
|
|
||||||
|
|
||||||
class ValidationException(Exception):
|
class ValidationException(Exception):
|
||||||
@@ -179,8 +180,8 @@ def validateBGColor(color):
|
|||||||
|
|
||||||
|
|
||||||
def validateOptImg(optimizers):
|
def validateOptImg(optimizers):
|
||||||
if isinstance(optimizers, (int, long)):
|
if isinstance(optimizers, int):
|
||||||
from optimizeimages import pngcrush
|
from .optimizeimages import pngcrush
|
||||||
logging.warning("You're using a deprecated definition of optimizeimg. "
|
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.")
|
"We'll do what you say for now, but please fix this as soon as possible.")
|
||||||
optimizers = [pngcrush()]
|
optimizers = [pngcrush()]
|
||||||
@@ -189,7 +190,7 @@ def validateOptImg(optimizers):
|
|||||||
"Make sure you specify them like [foo()], with square brackets.")
|
"Make sure you specify them like [foo()], with square brackets.")
|
||||||
|
|
||||||
if optimizers:
|
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):
|
if not isinstance(opt, Optimizer):
|
||||||
raise ValidationException("Invalid Optimizer!")
|
raise ValidationException("Invalid Optimizer!")
|
||||||
|
|
||||||
@@ -272,7 +273,7 @@ def validateCrop(value):
|
|||||||
|
|
||||||
|
|
||||||
def validateObserver(observer):
|
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
|
return observer
|
||||||
else:
|
else:
|
||||||
raise ValidationException("%r does not look like an observer." % repr(observer))
|
raise ValidationException("%r does not look like an observer." % repr(observer))
|
||||||
@@ -316,8 +317,8 @@ def make_dictValidator(keyvalidator, valuevalidator):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
def v(d):
|
def v(d):
|
||||||
newd = util.OrderedDict()
|
newd = OrderedDict()
|
||||||
for key, value in d.iteritems():
|
for key, value in d.items():
|
||||||
newd[keyvalidator(key)] = valuevalidator(value)
|
newd[keyvalidator(key)] = valuevalidator(value)
|
||||||
return newd
|
return newd
|
||||||
# Put these objects as attributes of the function so they can be accessed
|
# 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):
|
def configDictValidator(d):
|
||||||
newdict = util.OrderedDict()
|
newdict = OrderedDict()
|
||||||
|
|
||||||
# values are config keys that the user specified that don't match any
|
# values are config keys that the user specified that don't match any
|
||||||
# valid key
|
# valid key
|
||||||
@@ -353,10 +354,10 @@ def make_configDictValidator(config, ignore_undefined=False):
|
|||||||
undefined_key_matches = {}
|
undefined_key_matches = {}
|
||||||
|
|
||||||
# Go through the keys the user gave us and make sure they're all valid.
|
# 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:
|
if key not in config:
|
||||||
# Try to find a probable match
|
# 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:
|
if match and ignore_undefined:
|
||||||
# Save this for later. It only matters if this is a typo of
|
# Save this for later. It only matters if this is a typo of
|
||||||
# some required key that wasn't specified. (If all required
|
# 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`),
|
# Iterate through the defined keys in the configuration (`config`),
|
||||||
# checking each one to see if the user specified it (in `d`). Then
|
# checking each one to see if the user specified it (in `d`). Then
|
||||||
# validate it and copy the result to `newdict`
|
# validate it and copy the result to `newdict`
|
||||||
for configkey, configsetting in config.iteritems():
|
for configkey, configsetting in config.items():
|
||||||
if configkey in d:
|
if configkey in d:
|
||||||
# This key /was/ specified in the user's dict. Make sure it validates.
|
# This key /was/ specified in the user's dict. Make sure it validates.
|
||||||
newdict[configkey] = configsetting.validator(d[configkey])
|
newdict[configkey] = configsetting.validator(d[configkey])
|
||||||
@@ -414,9 +415,9 @@ def _levenshtein(s1, s2):
|
|||||||
l1 = len(s1)
|
l1 = len(s1)
|
||||||
l2 = len(s2)
|
l2 = len(s2)
|
||||||
|
|
||||||
matrix = [range(l1 + 1)] * (l2 + 1)
|
matrix = [list(range(l1 + 1))] * (l2 + 1)
|
||||||
for zz in range(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 zz in range(0, l2):
|
||||||
for sz in range(0, l1):
|
for sz in range(0, l1):
|
||||||
if s1[sz] == s2[zz]:
|
if s1[sz] == s2[zz]:
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ PyObject *init_chunk_render(void) {
|
|||||||
if (textures) {
|
if (textures) {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
textures = PyImport_ImportModule("overviewer_core.textures");
|
textures = PyImport_ImportModule("overviewer_core.textures");
|
||||||
/* ensure none of these pointers are NULL */
|
/* ensure none of these pointers are NULL */
|
||||||
if ((!textures)) {
|
if ((!textures)) {
|
||||||
@@ -50,13 +49,13 @@ PyObject *init_chunk_render(void) {
|
|||||||
tmp = PyObject_GetAttrString(textures, "max_blockid");
|
tmp = PyObject_GetAttrString(textures, "max_blockid");
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return NULL;
|
||||||
max_blockid = PyInt_AsLong(tmp);
|
max_blockid = PyLong_AsLong(tmp);
|
||||||
Py_DECREF(tmp);
|
Py_DECREF(tmp);
|
||||||
|
|
||||||
tmp = PyObject_GetAttrString(textures, "max_data");
|
tmp = PyObject_GetAttrString(textures, "max_data");
|
||||||
if (!tmp)
|
if (!tmp)
|
||||||
return NULL;
|
return NULL;
|
||||||
max_data = PyInt_AsLong(tmp);
|
max_data = PyLong_AsLong(tmp);
|
||||||
Py_DECREF(tmp);
|
Py_DECREF(tmp);
|
||||||
|
|
||||||
/* assemble the property table */
|
/* assemble the property table */
|
||||||
@@ -81,7 +80,7 @@ PyObject *init_chunk_render(void) {
|
|||||||
|
|
||||||
block_properties = calloc(max_blockid, sizeof(unsigned char));
|
block_properties = calloc(max_blockid, sizeof(unsigned char));
|
||||||
for (i = 0; i < max_blockid; i++) {
|
for (i = 0; i < max_blockid; i++) {
|
||||||
PyObject *block = PyInt_FromLong(i);
|
PyObject *block = PyLong_FromLong(i);
|
||||||
|
|
||||||
if (PySequence_Contains(known_blocks, block))
|
if (PySequence_Contains(known_blocks, block))
|
||||||
block_properties[i] |= 1 << KNOWN;
|
block_properties[i] |= 1 << KNOWN;
|
||||||
@@ -177,7 +176,7 @@ int load_chunk(RenderState* state, int x, int z, unsigned char required) {
|
|||||||
if (!ycoord)
|
if (!ycoord)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sectiony = PyInt_AsLong(ycoord);
|
sectiony = PyLong_AsLong(ycoord);
|
||||||
if (sectiony >= 0 && sectiony < SECTIONS_PER_CHUNK)
|
if (sectiony >= 0 && sectiony < SECTIONS_PER_CHUNK)
|
||||||
load_chunk_section(dest, sectiony, section);
|
load_chunk_section(dest, sectiony, section);
|
||||||
}
|
}
|
||||||
@@ -487,7 +486,7 @@ generate_pseudo_data(RenderState *state, unsigned short ancilData) {
|
|||||||
PyObject *texrot;
|
PyObject *texrot;
|
||||||
int northdir;
|
int northdir;
|
||||||
texrot = PyObject_GetAttrString(state->textures, "rotation");
|
texrot = PyObject_GetAttrString(state->textures, "rotation");
|
||||||
northdir = PyInt_AsLong(texrot);
|
northdir = PyLong_AsLong(texrot);
|
||||||
|
|
||||||
/* fix the rotation value for different northdirections */
|
/* fix the rotation value for different northdirections */
|
||||||
#define FIX_ROT(x) (((x) & ~0x3) | repair_rot[((x) & 0x3) | (northdir << 2)])
|
#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);
|
imgsize1_py = PySequence_GetItem(imgsize, 1);
|
||||||
Py_DECREF(imgsize);
|
Py_DECREF(imgsize);
|
||||||
|
|
||||||
imgsize0 = PyInt_AsLong(imgsize0_py);
|
imgsize0 = PyLong_AsLong(imgsize0_py);
|
||||||
imgsize1 = PyInt_AsLong(imgsize1_py);
|
imgsize1 = PyLong_AsLong(imgsize1_py);
|
||||||
Py_DECREF(imgsize0_py);
|
Py_DECREF(imgsize0_py);
|
||||||
Py_DECREF(imgsize1_py);
|
Py_DECREF(imgsize1_py);
|
||||||
|
|
||||||
|
|||||||
@@ -38,12 +38,20 @@ static PyMethodDef COverviewerMethods[] = {
|
|||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PyModuleDef COverviewerModule = {
|
||||||
|
PyModuleDef_HEAD_INIT,
|
||||||
|
"c_overviewer",
|
||||||
|
"", // TODO: Add documentation here.
|
||||||
|
-1,
|
||||||
|
COverviewerMethods
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
PyMODINIT_FUNC
|
PyMODINIT_FUNC
|
||||||
initc_overviewer(void)
|
PyInit_c_overviewer(void)
|
||||||
{
|
{
|
||||||
PyObject *mod, *numpy;
|
PyObject *mod, *numpy;
|
||||||
mod = Py_InitModule("c_overviewer", COverviewerMethods);
|
mod = PyModule_Create(&COverviewerModule);
|
||||||
|
|
||||||
/* for numpy
|
/* for numpy
|
||||||
normally you should use import_array(), but that will break across
|
normally you should use import_array(), but that will break across
|
||||||
@@ -57,8 +65,9 @@ initc_overviewer(void)
|
|||||||
if (!init_chunk_render()) {
|
if (!init_chunk_render()) {
|
||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
exit(1);
|
exit(1);
|
||||||
return;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_endian();
|
init_endian();
|
||||||
|
return mod;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
|
|
||||||
// increment this value if you've made a change to the c extesion
|
// increment this value if you've made a change to the c extesion
|
||||||
// and want to force users to rebuild
|
// and want to force users to rebuild
|
||||||
#define OVERVIEWER_EXTENSION_VERSION 56
|
#define OVERVIEWER_EXTENSION_VERSION 57
|
||||||
|
|
||||||
/* Python PIL, and numpy headers */
|
/* Python PIL, and numpy headers */
|
||||||
#include <Python.h>
|
#include <Python.h>
|
||||||
|
|||||||
@@ -234,9 +234,9 @@ base_draw(void *data, RenderState *state, PyObject *src, PyObject *mask, PyObjec
|
|||||||
|
|
||||||
/* look up color! */
|
/* look up color! */
|
||||||
color = PySequence_GetItem(color_table, tabley * 256 + tablex);
|
color = PySequence_GetItem(color_table, tabley * 256 + tablex);
|
||||||
r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
Py_DECREF(color);
|
Py_DECREF(color);
|
||||||
|
|
||||||
/* do the after-coloration */
|
/* 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);
|
y = (y * 128) / (16 * SECTIONS_PER_CHUNK);
|
||||||
|
|
||||||
/* get the colors and tint and tint */
|
/* get the colors and tint and tint */
|
||||||
r = PyInt_AsLong(PyList_GetItem(self->depth_colors, 0 + y*3));
|
r = PyLong_AsLong(PyList_GetItem(self->depth_colors, 0 + y*3));
|
||||||
g = PyInt_AsLong(PyList_GetItem(self->depth_colors, 1 + y*3));
|
g = PyLong_AsLong(PyList_GetItem(self->depth_colors, 1 + y*3));
|
||||||
b = PyInt_AsLong(PyList_GetItem(self->depth_colors, 2 + 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);
|
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++) {
|
for (i = 0; i < blocks_size; i++) {
|
||||||
PyObject *block = PyList_GET_ITEM(opt, i);
|
PyObject *block = PyList_GET_ITEM(opt, i);
|
||||||
|
|
||||||
if (PyInt_Check(block)) {
|
if (PyLong_Check(block)) {
|
||||||
/* format 1: just a block id */
|
/* 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;
|
self->rules[i].has_data = 0;
|
||||||
} else if (PyArg_ParseTuple(block, "Hb", &(self->rules[i].blockid), &(self->rules[i].data))) {
|
} else if (PyArg_ParseTuple(block, "Hb", &(self->rules[i].blockid), &(self->rules[i].data))) {
|
||||||
/* format 2: (blockid, data) */
|
/* format 2: (blockid, data) */
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ calculate_light_color_fancy(void *data,
|
|||||||
index = skylight + blocklight * 16;
|
index = skylight + blocklight * 16;
|
||||||
color = PySequence_GetItem(mode->lightcolor, index);
|
color = PySequence_GetItem(mode->lightcolor, index);
|
||||||
|
|
||||||
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
*r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
*g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
*b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
|
|
||||||
Py_DECREF(color);
|
Py_DECREF(color);
|
||||||
}
|
}
|
||||||
@@ -78,9 +78,9 @@ calculate_light_color_fancy_night(void *data,
|
|||||||
index = skylight + blocklight * 16;
|
index = skylight + blocklight * 16;
|
||||||
color = PySequence_GetItem(mode->lightcolor, index);
|
color = PySequence_GetItem(mode->lightcolor, index);
|
||||||
|
|
||||||
*r = PyInt_AsLong(PyTuple_GET_ITEM(color, 0));
|
*r = PyLong_AsLong(PyTuple_GET_ITEM(color, 0));
|
||||||
*g = PyInt_AsLong(PyTuple_GET_ITEM(color, 1));
|
*g = PyLong_AsLong(PyTuple_GET_ITEM(color, 1));
|
||||||
*b = PyInt_AsLong(PyTuple_GET_ITEM(color, 2));
|
*b = PyLong_AsLong(PyTuple_GET_ITEM(color, 2));
|
||||||
|
|
||||||
Py_DECREF(color);
|
Py_DECREF(color);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ RenderPrimitive *render_primitive_create(PyObject *prim, RenderState *state) {
|
|||||||
pyname = PyObject_GetAttrString(prim, "name");
|
pyname = PyObject_GetAttrString(prim, "name");
|
||||||
if (!pyname)
|
if (!pyname)
|
||||||
return NULL;
|
return NULL;
|
||||||
name = PyString_AsString(pyname);
|
name = PyUnicode_AsUTF8(pyname);
|
||||||
|
|
||||||
for (i = 0; render_primitives[i] != NULL; i++) {
|
for (i = 0; render_primitives[i] != NULL; i++) {
|
||||||
if (strcmp(render_primitives[i]->name, name) == 0) {
|
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);
|
Py_DECREF(dict);
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
PyObject *errtype, *errvalue, *errtraceback;
|
PyObject *errtype, *errvalue, *errtraceback, *errstring;
|
||||||
const char *errstring;
|
|
||||||
|
|
||||||
PyErr_Fetch(&errtype, &errvalue, &errtraceback);
|
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);
|
PyErr_Format(PyExc_TypeError, "rendermode option \"%s\" has incorrect type (%s)", name, errstring);
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import imp
|
|||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import zipfile
|
import zipfile
|
||||||
from cStringIO import StringIO
|
from io import BytesIO
|
||||||
import math
|
import math
|
||||||
from random import randint
|
from random import randint
|
||||||
import numpy
|
import numpy
|
||||||
@@ -26,8 +26,32 @@ from PIL import Image, ImageEnhance, ImageOps, ImageDraw
|
|||||||
import logging
|
import logging
|
||||||
import functools
|
import functools
|
||||||
|
|
||||||
import util
|
from . import util
|
||||||
from c_overviewer import alpha_over
|
|
||||||
|
|
||||||
|
# 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):
|
class TextureException(Exception):
|
||||||
"To be thrown when a texture is not found."
|
"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",
|
color_map = ["white", "orange", "magenta", "light_blue", "yellow", "lime", "pink", "gray",
|
||||||
"light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"]
|
"light_gray", "cyan", "purple", "blue", "brown", "green", "red", "black"]
|
||||||
|
|
||||||
|
|
||||||
##
|
##
|
||||||
## Textures object
|
## Textures object
|
||||||
##
|
##
|
||||||
@@ -76,10 +101,11 @@ class Textures(object):
|
|||||||
del attributes[attr]
|
del attributes[attr]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
attributes['jar'] = None
|
||||||
return attributes
|
return attributes
|
||||||
def __setstate__(self, attrs):
|
def __setstate__(self, attrs):
|
||||||
# regenerate textures, if needed
|
# regenerate textures, if needed
|
||||||
for attr, val in attrs.iteritems():
|
for attr, val in list(attrs.items()):
|
||||||
setattr(self, attr, val)
|
setattr(self, attr, val)
|
||||||
self.texture_cache = {}
|
self.texture_cache = {}
|
||||||
if self.generated:
|
if self.generated:
|
||||||
@@ -99,7 +125,7 @@ class Textures(object):
|
|||||||
global known_blocks, used_datas
|
global known_blocks, used_datas
|
||||||
self.blockmap = [None] * max_blockid * max_data
|
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)
|
tex = texgen(self, blockid, data)
|
||||||
self.blockmap[blockid * max_data + data] = self.generate_texture_tuple(tex)
|
self.blockmap[blockid * max_data + data] = self.generate_texture_tuple(tex)
|
||||||
|
|
||||||
@@ -224,7 +250,7 @@ class Textures(object):
|
|||||||
self.jar.getinfo(jarfilename)
|
self.jar.getinfo(jarfilename)
|
||||||
if verbose: logging.info("Found (cached) %s in '%s'", jarfilename, self.jarpath)
|
if verbose: logging.info("Found (cached) %s in '%s'", jarfilename, self.jarpath)
|
||||||
return self.jar.open(jarfilename)
|
return self.jar.open(jarfilename)
|
||||||
except (KeyError, IOError), e:
|
except (KeyError, IOError) as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Find an installed minecraft client jar and look in it for the texture
|
# 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)
|
if verbose: logging.info("Found %s in '%s'", jarfilename, jarpath)
|
||||||
self.jar, self.jarpath = jar, jarpath
|
self.jar, self.jarpath = jar, jarpath
|
||||||
return jar.open(jarfilename)
|
return jar.open(jarfilename)
|
||||||
except (KeyError, IOError), e:
|
except (KeyError, IOError) as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if verbose: logging.info("Did not find file {0} in jar {1}".format(filename, jarpath))
|
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]
|
return self.texture_cache[filename]
|
||||||
|
|
||||||
fileobj = self.find_file(filename)
|
fileobj = self.find_file(filename)
|
||||||
buffer = StringIO(fileobj.read())
|
buffer = BytesIO(fileobj.read())
|
||||||
img = Image.open(buffer).convert("RGBA")
|
img = Image.open(buffer).convert("RGBA")
|
||||||
self.texture_cache[filename] = img
|
self.texture_cache[filename] = img
|
||||||
return img
|
return img
|
||||||
@@ -444,8 +470,8 @@ class Textures(object):
|
|||||||
textures = []
|
textures = []
|
||||||
(terrain_width, terrain_height) = terrain.size
|
(terrain_width, terrain_height) = terrain.size
|
||||||
texture_resolution = terrain_width / 16
|
texture_resolution = terrain_width / 16
|
||||||
for y in xrange(16):
|
for y in range(16):
|
||||||
for x in xrange(16):
|
for x in range(16):
|
||||||
left = x*texture_resolution
|
left = x*texture_resolution
|
||||||
upper = y*texture_resolution
|
upper = y*texture_resolution
|
||||||
right = left+texture_resolution
|
right = left+texture_resolution
|
||||||
@@ -815,19 +841,6 @@ class Textures(object):
|
|||||||
## The other big one: @material and associated framework
|
## 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
|
# the material registration decorator
|
||||||
def material(blockid=[], data=[0], **kwargs):
|
def material(blockid=[], data=[0], **kwargs):
|
||||||
@@ -837,11 +850,11 @@ def material(blockid=[], data=[0], **kwargs):
|
|||||||
# make sure blockid and data are iterable
|
# make sure blockid and data are iterable
|
||||||
try:
|
try:
|
||||||
iter(blockid)
|
iter(blockid)
|
||||||
except:
|
except Exception:
|
||||||
blockid = [blockid,]
|
blockid = [blockid,]
|
||||||
try:
|
try:
|
||||||
iter(data)
|
iter(data)
|
||||||
except:
|
except Exception:
|
||||||
data = [data,]
|
data = [data,]
|
||||||
|
|
||||||
def inner_material(func):
|
def inner_material(func):
|
||||||
@@ -924,7 +937,7 @@ def billboard(blockid=[], imagename=None, **kwargs):
|
|||||||
##
|
##
|
||||||
|
|
||||||
# stone
|
# stone
|
||||||
@material(blockid=1, data=range(7), solid=True)
|
@material(blockid=1, data=list(range(7)), solid=True)
|
||||||
def stone(self, blockid, data):
|
def stone(self, blockid, data):
|
||||||
if data == 0: # regular old-school stone
|
if data == 0: # regular old-school stone
|
||||||
img = self.load_image_texture("assets/minecraft/textures/block/stone.png")
|
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")
|
img = self.load_image_texture("assets/minecraft/textures/block/polished_andesite.png")
|
||||||
return self.build_block(img, img)
|
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):
|
def grass(self, blockid, data):
|
||||||
# 0x10 bit means SNOW
|
# 0x10 bit means SNOW
|
||||||
side_img = self.load_image_texture("assets/minecraft/textures/block/grass_block_side.png")
|
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
|
return img
|
||||||
|
|
||||||
# dirt
|
# dirt
|
||||||
@material(blockid=3, data=range(3), solid=True)
|
@material(blockid=3, data=list(range(3)), solid=True)
|
||||||
def dirt_blocks(self, blockid, data):
|
def dirt_blocks(self, blockid, data):
|
||||||
side_img = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
side_img = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
||||||
if data == 0: # normal
|
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")
|
block(blockid=4, top_image="assets/minecraft/textures/block/cobblestone.png")
|
||||||
|
|
||||||
# wooden planks
|
# 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):
|
def wooden_planks(self, blockid, data):
|
||||||
if data == 0: # normal
|
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"))
|
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
|
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"))
|
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):
|
def saplings(self, blockid, data):
|
||||||
# usual saplings
|
# usual saplings
|
||||||
tex = self.load_image_texture("assets/minecraft/textures/block/oak_sapling.png")
|
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)
|
# water, glass, and ice (no inner surfaces)
|
||||||
# uses pseudo-ancildata found in iterate.c
|
# 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):
|
def no_inner_surfaces(self, blockid, data):
|
||||||
if blockid == 8 or blockid == 9:
|
if blockid == 8 or blockid == 9:
|
||||||
texture = self.load_water()
|
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)
|
img = self.build_full_block(top,None,None,side3,side4)
|
||||||
return img
|
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):
|
def lava(self, blockid, data):
|
||||||
lavatex = self.load_lava()
|
lavatex = self.load_lava()
|
||||||
return self.build_block(lavatex, lavatex)
|
return self.build_block(lavatex, lavatex)
|
||||||
|
|
||||||
# sand
|
# sand
|
||||||
@material(blockid=12, data=range(2), solid=True)
|
@material(blockid=12, data=list(range(2)), solid=True)
|
||||||
def sand_blocks(self, blockid, data):
|
def sand_blocks(self, blockid, data):
|
||||||
if data == 0: # normal
|
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"))
|
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
|
# coal ore
|
||||||
block(blockid=16, top_image="assets/minecraft/textures/block/coal_ore.png")
|
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):
|
def wood(self, blockid, data):
|
||||||
# extract orientation and wood type frorm data bits
|
# extract orientation and wood type frorm data bits
|
||||||
wood_type = data & 3
|
wood_type = data & 3
|
||||||
@@ -1191,7 +1204,7 @@ def wood(self, blockid, data):
|
|||||||
elif wood_orientation == 8: # north-south orientation
|
elif wood_orientation == 8: # north-south orientation
|
||||||
return self.build_full_block(side, None, None, side.rotate(270), top)
|
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):
|
def leaves(self, blockid, data):
|
||||||
# mask out the bits 4 and 8
|
# mask out the bits 4 and 8
|
||||||
# they are used for player placed and check-for-decay blocks
|
# 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")
|
block(blockid=22, top_image="assets/minecraft/textures/block/lapis_block.png")
|
||||||
|
|
||||||
# dispensers, dropper, furnaces, and burning furnaces
|
# 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):
|
def furnaces(self, blockid, data):
|
||||||
# first, do the rotation if needed
|
# first, do the rotation if needed
|
||||||
if self.rotation == 1:
|
if self.rotation == 1:
|
||||||
@@ -1266,7 +1279,7 @@ def furnaces(self, blockid, data):
|
|||||||
return self.build_full_block(top, None, None, side, side)
|
return self.build_full_block(top, None, None, side, side)
|
||||||
|
|
||||||
# sandstone
|
# sandstone
|
||||||
@material(blockid=24, data=range(3), solid=True)
|
@material(blockid=24, data=list(range(3)), solid=True)
|
||||||
def sandstone(self, blockid, data):
|
def sandstone(self, blockid, data):
|
||||||
top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png")
|
top = self.load_image_texture("assets/minecraft/textures/block/sandstone_top.png")
|
||||||
if data == 0: # normal
|
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"))
|
return self.build_block(top, self.load_image_texture("assets/minecraft/textures/block/cut_sandstone.png"))
|
||||||
|
|
||||||
# red sandstone
|
# red sandstone
|
||||||
@material(blockid=179, data=range(3), solid=True)
|
@material(blockid=179, data=list(range(3)), solid=True)
|
||||||
def sandstone(self, blockid, data):
|
def sandstone(self, blockid, data):
|
||||||
top = self.load_image_texture("assets/minecraft/textures/block/red_sandstone_top.png")
|
top = self.load_image_texture("assets/minecraft/textures/block/red_sandstone_top.png")
|
||||||
if data == 0: # normal
|
if data == 0: # normal
|
||||||
@@ -1291,7 +1304,7 @@ def sandstone(self, blockid, data):
|
|||||||
# note block
|
# note block
|
||||||
block(blockid=25, top_image="assets/minecraft/textures/block/note_block.png")
|
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):
|
def bed(self, blockid, data):
|
||||||
# first get rotation done
|
# first get rotation done
|
||||||
# Masked to not clobber block head/foot info
|
# 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)
|
return self.build_full_block(top_face, None, None, left_face, right_face)
|
||||||
|
|
||||||
# powered, detector, activator and normal rails
|
# 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):
|
def rails(self, blockid, data):
|
||||||
# first, do rotation
|
# first, do rotation
|
||||||
# Masked to not clobber powered rail on/off info
|
# Masked to not clobber powered rail on/off info
|
||||||
@@ -1664,7 +1677,7 @@ def piston_extension(self, blockid, data):
|
|||||||
# cobweb
|
# cobweb
|
||||||
sprite(blockid=30, imagename="assets/minecraft/textures/block/cobweb.png", nospawn=True)
|
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):
|
def tall_grass(self, blockid, data):
|
||||||
if data == 0: # dead shrub
|
if data == 0: # dead shrub
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/dead_bush.png")
|
texture = self.load_image_texture("assets/minecraft/textures/block/dead_bush.png")
|
||||||
@@ -1678,7 +1691,7 @@ def tall_grass(self, blockid, data):
|
|||||||
# dead bush
|
# dead bush
|
||||||
billboard(blockid=32, imagename="assets/minecraft/textures/block/dead_bush.png")
|
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):
|
def wool(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[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")
|
sprite(blockid=37, imagename="assets/minecraft/textures/block/dandelion.png")
|
||||||
|
|
||||||
# flowers
|
# flowers
|
||||||
@material(blockid=38, data=range(10), transparent=True)
|
@material(blockid=38, data=list(range(10)), transparent=True)
|
||||||
def flower(self, blockid, data):
|
def flower(self, blockid, data):
|
||||||
flower_map = ["poppy", "blue_orchid", "allium", "azure_bluet", "red_tulip", "orange_tulip",
|
flower_map = ["poppy", "blue_orchid", "allium", "azure_bluet", "red_tulip", "orange_tulip",
|
||||||
"white_tulip", "pink_tulip", "oxeye_daisy", "dandelion"]
|
"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
|
# double slabs and slabs
|
||||||
# these wooden slabs are unobtainable without cheating, they are still
|
# these wooden slabs are unobtainable without cheating, they are still
|
||||||
# here because lots of pre-1.3 worlds use this blocks
|
# 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):
|
def slabs(self, blockid, data):
|
||||||
if blockid == 44 or blockid == 182:
|
if blockid == 44 or blockid == 182:
|
||||||
texture = data & 7
|
texture = data & 7
|
||||||
@@ -1847,7 +1860,7 @@ def torches(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# fire
|
# fire
|
||||||
@material(blockid=51, data=range(16), transparent=True)
|
@material(blockid=51, data=list(range(16)), transparent=True)
|
||||||
def fire(self, blockid, data):
|
def fire(self, blockid, data):
|
||||||
firetextures = self.load_fire()
|
firetextures = self.load_fire()
|
||||||
side1 = self.transform_image_side(firetextures[0])
|
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)
|
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.
|
# 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):
|
def stairs(self, blockid, data):
|
||||||
# preserve the upside-down bit
|
# preserve the upside-down bit
|
||||||
upside_down = data & 0x4
|
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
|
# normal, locked (used in april's fool day), ender and trapped chest
|
||||||
# NOTE: locked chest used to be id95 (which is now stained glass)
|
# 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):
|
def chests(self, blockid, data):
|
||||||
# the first 3 bits are the orientation as stored in minecraft,
|
# the first 3 bits are the orientation as stored in minecraft,
|
||||||
# bits 0x8 and 0x10 indicate which half of the double chest is it.
|
# bits 0x8 and 0x10 indicate which half of the double chest is it.
|
||||||
@@ -2188,7 +2201,7 @@ def chests(self, blockid, data):
|
|||||||
|
|
||||||
# redstone wire
|
# redstone wire
|
||||||
# uses pseudo-ancildata found in iterate.c
|
# 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):
|
def wire(self, blockid, data):
|
||||||
|
|
||||||
if data & 0b1000000 == 64: # powered redstone wire
|
if data & 0b1000000 == 64: # powered redstone wire
|
||||||
@@ -2281,7 +2294,7 @@ def crafting_table(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# crops with 8 data values (like wheat)
|
# 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):
|
def crops8(self, blockid, data):
|
||||||
raw_crop = self.load_image_texture("assets/minecraft/textures/block/wheat_stage%d.png" % data)
|
raw_crop = self.load_image_texture("assets/minecraft/textures/block/wheat_stage%d.png" % data)
|
||||||
crop1 = self.transform_image_top(raw_crop)
|
crop1 = self.transform_image_top(raw_crop)
|
||||||
@@ -2295,7 +2308,7 @@ def crops8(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# farmland and grass path (15/16 blocks)
|
# 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):
|
def farmland(self, blockid, data):
|
||||||
if blockid == 60:
|
if blockid == 60:
|
||||||
side = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
side = self.load_image_texture("assets/minecraft/textures/block/dirt.png")
|
||||||
@@ -2315,7 +2328,7 @@ def farmland(self, blockid, data):
|
|||||||
|
|
||||||
|
|
||||||
# signposts
|
# signposts
|
||||||
@material(blockid=63, data=range(16), transparent=True)
|
@material(blockid=63, data=list(range(16)), transparent=True)
|
||||||
def signpost(self, blockid, data):
|
def signpost(self, blockid, data):
|
||||||
|
|
||||||
# first rotations
|
# first rotations
|
||||||
@@ -2369,7 +2382,7 @@ def signpost(self, blockid, data):
|
|||||||
|
|
||||||
# wooden and iron door
|
# wooden and iron door
|
||||||
# uses pseudo-ancildata found in iterate.c
|
# 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):
|
def door(self, blockid, data):
|
||||||
#Masked to not clobber block top/bottom & swung info
|
#Masked to not clobber block top/bottom & swung info
|
||||||
if self.rotation == 1:
|
if self.rotation == 1:
|
||||||
@@ -2618,7 +2631,7 @@ def wall_sign(self, blockid, data): # wall sign
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# levers
|
# levers
|
||||||
@material(blockid=69, data=range(16), transparent=True)
|
@material(blockid=69, data=list(range(16)), transparent=True)
|
||||||
def levers(self, blockid, data):
|
def levers(self, blockid, data):
|
||||||
if data & 8 == 8: powered = True
|
if data & 8 == 8: powered = True
|
||||||
else: powered = False
|
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")
|
block(blockid=[73, 74], top_image="assets/minecraft/textures/block/redstone_ore.png")
|
||||||
|
|
||||||
# stone a wood buttons
|
# 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):
|
def buttons(self, blockid, data):
|
||||||
|
|
||||||
# 0x8 is set if the button is pressed mask this info and render
|
# 0x8 is set if the button is pressed mask this info and render
|
||||||
@@ -2899,7 +2912,7 @@ def buttons(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# snow
|
# 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):
|
def snow(self, blockid, data):
|
||||||
# still not rendered correctly: data other than 0
|
# 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")
|
block(blockid=80, top_image="assets/minecraft/textures/block/snow.png")
|
||||||
|
|
||||||
# cactus
|
# 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):
|
def cactus(self, blockid, data):
|
||||||
top = self.load_image_texture("assets/minecraft/textures/block/cactus_top.png")
|
top = self.load_image_texture("assets/minecraft/textures/block/cactus_top.png")
|
||||||
side = self.load_image_texture("assets/minecraft/textures/block/cactus_side.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")
|
block(blockid=82, top_image="assets/minecraft/textures/block/clay.png")
|
||||||
|
|
||||||
# sugar cane
|
# 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):
|
def sugar_cane(self, blockid, data):
|
||||||
tex = self.load_image_texture("assets/minecraft/textures/block/sugar_cane.png")
|
tex = self.load_image_texture("assets/minecraft/textures/block/sugar_cane.png")
|
||||||
return self.build_sprite(tex)
|
return self.build_sprite(tex)
|
||||||
|
|
||||||
# jukebox
|
# jukebox
|
||||||
@material(blockid=84, data=range(16), solid=True)
|
@material(blockid=84, data=list(range(16)), solid=True)
|
||||||
def jukebox(self, blockid, data):
|
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"))
|
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
|
# nether and normal fences
|
||||||
# uses pseudo-ancildata found in iterate.c
|
# 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):
|
def fence(self, blockid, data):
|
||||||
# no need for rotations, it uses pseudo data.
|
# no need for rotations, it uses pseudo data.
|
||||||
# create needed images for Big stick fence
|
# create needed images for Big stick fence
|
||||||
@@ -3082,7 +3095,7 @@ def fence(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# pumpkin
|
# 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
|
def pumpkin(self, blockid, data): # pumpkins, jack-o-lantern
|
||||||
# rotation
|
# rotation
|
||||||
if self.rotation == 1:
|
if self.rotation == 1:
|
||||||
@@ -3149,7 +3162,7 @@ def portal(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# cake!
|
# 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):
|
def cake(self, blockid, data):
|
||||||
|
|
||||||
# cake textures
|
# cake textures
|
||||||
@@ -3273,7 +3286,7 @@ def cake(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# redstone repeaters ON and OFF
|
# 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):
|
def repeater(self, blockid, data):
|
||||||
# rotation
|
# rotation
|
||||||
# Masked to not clobber delay info
|
# Masked to not clobber delay info
|
||||||
@@ -3418,7 +3431,7 @@ def repeater(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# redstone comparator (149 is inactive, 150 is active)
|
# 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):
|
def comparator(self, blockid, data):
|
||||||
|
|
||||||
# rotation
|
# rotation
|
||||||
@@ -3483,7 +3496,7 @@ def comparator(self, blockid, data):
|
|||||||
|
|
||||||
# trapdoor
|
# trapdoor
|
||||||
# the trapdoor is looks like a sprite when opened, that's not good
|
# 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):
|
def trapdoor(self, blockid, data):
|
||||||
|
|
||||||
# rotation
|
# rotation
|
||||||
@@ -3539,7 +3552,7 @@ def trapdoor(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# block with hidden silverfish (stone, cobblestone and stone brick)
|
# 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):
|
def hidden_silverfish(self, blockid, data):
|
||||||
if data == 0: # stone
|
if data == 0: # stone
|
||||||
t = self.load_image_texture("assets/minecraft/textures/block/stone.png")
|
t = self.load_image_texture("assets/minecraft/textures/block/stone.png")
|
||||||
@@ -3553,7 +3566,7 @@ def hidden_silverfish(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# stone brick
|
# 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):
|
def stone_brick(self, blockid, data):
|
||||||
if data == 0: # normal
|
if data == 0: # normal
|
||||||
t = self.load_image_texture("assets/minecraft/textures/block/stone_bricks.png")
|
t = self.load_image_texture("assets/minecraft/textures/block/stone_bricks.png")
|
||||||
@@ -3569,7 +3582,7 @@ def stone_brick(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# huge brown and red mushroom
|
# 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):
|
def huge_mushroom(self, blockid, data):
|
||||||
# rotation
|
# rotation
|
||||||
if self.rotation == 1:
|
if self.rotation == 1:
|
||||||
@@ -3653,7 +3666,7 @@ def huge_mushroom(self, blockid, data):
|
|||||||
# iron bars and glass pane
|
# iron bars and glass pane
|
||||||
# TODO glass pane is not a sprite, it has a texture for the side,
|
# TODO glass pane is not a sprite, it has a texture for the side,
|
||||||
# at the moment is not used
|
# 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):
|
def panes(self, blockid, data):
|
||||||
# no rotation, uses pseudo data
|
# no rotation, uses pseudo data
|
||||||
if blockid == 101:
|
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:
|
# 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,
|
# once fully grown the stem bends to the melon/pumpkin block,
|
||||||
# at the moment only render the growing stem
|
# 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):
|
def stem(self, blockid, data):
|
||||||
# the ancildata value indicates how much of the texture
|
# the ancildata value indicates how much of the texture
|
||||||
# is shown.
|
# is shown.
|
||||||
@@ -3725,7 +3738,7 @@ def stem(self, blockid, data):
|
|||||||
|
|
||||||
|
|
||||||
# vines
|
# vines
|
||||||
@material(blockid=106, data=range(16), transparent=True)
|
@material(blockid=106, data=list(range(16)), transparent=True)
|
||||||
def vines(self, blockid, data):
|
def vines(self, blockid, data):
|
||||||
# rotation
|
# rotation
|
||||||
# vines data is bit coded. decode it first.
|
# vines data is bit coded. decode it first.
|
||||||
@@ -3766,7 +3779,7 @@ def vines(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# fence gates
|
# 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):
|
def fence_gate(self, blockid, data):
|
||||||
|
|
||||||
# rotation
|
# 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
|
# 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
|
# orientation depends on their position on the map. So it uses pseudo
|
||||||
# ancildata.
|
# ancildata.
|
||||||
@material(blockid=111, data=range(4), transparent=True)
|
@material(blockid=111, data=list(range(4)), transparent=True)
|
||||||
def lilypad(self, blockid, data):
|
def lilypad(self, blockid, data):
|
||||||
t = self.load_image_texture("assets/minecraft/textures/block/lily_pad.png").copy()
|
t = self.load_image_texture("assets/minecraft/textures/block/lily_pad.png").copy()
|
||||||
if data == 0:
|
if data == 0:
|
||||||
@@ -3888,7 +3901,7 @@ def lilypad(self, blockid, data):
|
|||||||
block(blockid=112, top_image="assets/minecraft/textures/block/nether_bricks.png")
|
block(blockid=112, top_image="assets/minecraft/textures/block/nether_bricks.png")
|
||||||
|
|
||||||
# nether wart
|
# 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):
|
def nether_wart(self, blockid, data):
|
||||||
if data == 0: # just come up
|
if data == 0: # just come up
|
||||||
t = self.load_image_texture("assets/minecraft/textures/block/nether_wart_stage0.png")
|
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
|
# brewing stand
|
||||||
# TODO this is a place holder, is a 2d image pasted
|
# 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):
|
def brewing_stand(self, blockid, data):
|
||||||
base = self.load_image_texture("assets/minecraft/textures/block/brewing_stand_base.png")
|
base = self.load_image_texture("assets/minecraft/textures/block/brewing_stand_base.png")
|
||||||
img = self.build_full_block(None, None, None, None, None, base)
|
img = self.build_full_block(None, None, None, None, None, base)
|
||||||
@@ -3925,7 +3938,7 @@ def brewing_stand(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# cauldron
|
# cauldron
|
||||||
@material(blockid=118, data=range(4), transparent=True)
|
@material(blockid=118, data=list(range(4)), transparent=True)
|
||||||
def cauldron(self, blockid, data):
|
def cauldron(self, blockid, data):
|
||||||
side = self.load_image_texture("assets/minecraft/textures/block/cauldron_side.png")
|
side = self.load_image_texture("assets/minecraft/textures/block/cauldron_side.png")
|
||||||
top = self.load_image_texture("assets/minecraft/textures/block/cauldron_top.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
|
return img
|
||||||
|
|
||||||
# end portal frame (data range 8 to get all orientations of filled)
|
# 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):
|
def end_portal_frame(self, blockid, data):
|
||||||
# The bottom 2 bits are oritation info but seems there is no
|
# The bottom 2 bits are oritation info but seems there is no
|
||||||
# graphical difference between orientations
|
# graphical difference between orientations
|
||||||
@@ -4046,7 +4059,7 @@ def daylight_sensor(self, blockid, data):
|
|||||||
# wooden double and normal slabs
|
# wooden double and normal slabs
|
||||||
# these are the new wooden slabs, blockids 43 44 still have wooden
|
# these are the new wooden slabs, blockids 43 44 still have wooden
|
||||||
# slabs, but those are unobtainable without cheating
|
# 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):
|
def wooden_slabs(self, blockid, data):
|
||||||
texture = data & 7
|
texture = data & 7
|
||||||
if texture== 0: # oak
|
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")
|
block(blockid=133, top_image="assets/minecraft/textures/block/emerald_block.png")
|
||||||
|
|
||||||
# cocoa plant
|
# 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):
|
def cocoa_plant(self, blockid, data):
|
||||||
orientation = data & 3
|
orientation = data & 3
|
||||||
# rotation
|
# rotation
|
||||||
@@ -4198,7 +4211,7 @@ def beacon(self, blockid, data):
|
|||||||
|
|
||||||
# cobblestone and mossy cobblestone walls, chorus plants
|
# cobblestone and mossy cobblestone walls, chorus plants
|
||||||
# one additional bit of data value added for mossy and cobblestone
|
# 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):
|
def cobblestone_wall(self, blockid, data):
|
||||||
# chorus plants
|
# chorus plants
|
||||||
if blockid == 199:
|
if blockid == 199:
|
||||||
@@ -4329,7 +4342,7 @@ def cobblestone_wall(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# carrots, potatoes
|
# 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):
|
def crops4(self, blockid, data):
|
||||||
# carrots and potatoes have 8 data, but only 4 visual stages
|
# carrots and potatoes have 8 data, but only 4 visual stages
|
||||||
stage = {0:0,
|
stage = {0:0,
|
||||||
@@ -4355,7 +4368,7 @@ def crops4(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# anvils
|
# anvils
|
||||||
@material(blockid=145, data=range(12), transparent=True)
|
@material(blockid=145, data=list(range(12)), transparent=True)
|
||||||
def anvil(self, blockid, data):
|
def anvil(self, blockid, data):
|
||||||
|
|
||||||
# anvils only have two orientations, invert it for rotations 1 and 3
|
# 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(blockid=153, top_image="assets/minecraft/textures/block/nether_quartz_ore.png")
|
||||||
|
|
||||||
# block of quartz
|
# 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):
|
def quartz_block(self, blockid, data):
|
||||||
|
|
||||||
if data in (0,1): # normal and chiseled quartz block
|
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))
|
return self.build_full_block(side.rotate(90), None, None, top, side.rotate(90))
|
||||||
|
|
||||||
# hopper
|
# hopper
|
||||||
@material(blockid=154, data=range(4), transparent=True)
|
@material(blockid=154, data=list(range(4)), transparent=True)
|
||||||
def hopper(self, blockid, data):
|
def hopper(self, blockid, data):
|
||||||
#build the top
|
#build the top
|
||||||
side = self.load_image_texture("assets/minecraft/textures/block/hopper_outside.png")
|
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")
|
block(blockid=165, top_image="assets/minecraft/textures/block/slime_block.png")
|
||||||
|
|
||||||
# prismarine block
|
# 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):
|
def prismarine_block(self, blockid, data):
|
||||||
|
|
||||||
if data == 0: # prismarine
|
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")
|
block(blockid=169, top_image="assets/minecraft/textures/block/sea_lantern.png")
|
||||||
|
|
||||||
# hay block
|
# hay block
|
||||||
@material(blockid=170, data=range(9), solid=True)
|
@material(blockid=170, data=list(range(9)), solid=True)
|
||||||
def hayblock(self, blockid, data):
|
def hayblock(self, blockid, data):
|
||||||
top = self.load_image_texture("assets/minecraft/textures/block/hay_block_top.png")
|
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")
|
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?
|
# 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):
|
def carpet(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_wool.png" % color_map[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")
|
block(blockid=172, top_image="assets/minecraft/textures/block/terracotta.png")
|
||||||
|
|
||||||
#stained hardened clay
|
#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):
|
def stained_clay(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_terracotta.png" % color_map[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=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")
|
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):
|
def flower(self, blockid, data):
|
||||||
double_plant_map = ["sunflower", "lilac", "tall_grass", "large_fern", "rose_bush", "peony", "peony", "peony"]
|
double_plant_map = ["sunflower", "lilac", "tall_grass", "large_fern", "rose_bush", "peony", "peony", "peony"]
|
||||||
plant = double_plant_map[data & 0x7]
|
plant = double_plant_map[data & 0x7]
|
||||||
@@ -4608,7 +4621,7 @@ def flower(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# chorus flower
|
# 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):
|
def chorus_flower(self, blockid, data):
|
||||||
# aged 5, dead
|
# aged 5, dead
|
||||||
if data == 5:
|
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")
|
block(blockid=201, top_image="assets/minecraft/textures/block/purpur_block.png")
|
||||||
|
|
||||||
# purpur pilar
|
# 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):
|
def purpur_pillar(self, blockid, data):
|
||||||
pillar_orientation = data & 12
|
pillar_orientation = data & 12
|
||||||
top=self.load_image_texture("assets/minecraft/textures/block/purpur_pillar_top.png")
|
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")
|
block(blockid=206, top_image="assets/minecraft/textures/block/end_stone_bricks.png")
|
||||||
|
|
||||||
# frosted ice
|
# 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):
|
def frosted_ice(self, blockid, data):
|
||||||
img = self.load_image_texture("assets/minecraft/textures/block/frosted_ice_%d.png" % data)
|
img = self.load_image_texture("assets/minecraft/textures/block/frosted_ice_%d.png" % data)
|
||||||
return self.build_block(img, img)
|
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
|
# red nether brick
|
||||||
block(blockid=215, top_image="assets/minecraft/textures/block/red_nether_bricks.png")
|
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):
|
def boneblock(self, blockid, data):
|
||||||
# extract orientation
|
# extract orientation
|
||||||
boneblock_orientation = data & 12
|
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)
|
return self.build_full_block(side, None, None, side.rotate(270), top)
|
||||||
|
|
||||||
# observer
|
# 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):
|
def observer(self, blockid, data):
|
||||||
# first, do the rotation if needed
|
# first, do the rotation if needed
|
||||||
if self.rotation == 1:
|
if self.rotation == 1:
|
||||||
@@ -4718,7 +4731,7 @@ def observer(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# shulker box
|
# 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):
|
def shulker_box(self, blockid, data):
|
||||||
# first, do the rotation if needed
|
# first, do the rotation if needed
|
||||||
data = data & 7
|
data = data & 7
|
||||||
@@ -4741,15 +4754,15 @@ def shulker_box(self, blockid, data):
|
|||||||
color = color_map[blockid - 219]
|
color = color_map[blockid - 219]
|
||||||
shulker_t = self.load_image_texture("assets/minecraft/textures/entity/shulker/shulker_%s.png" % color).copy()
|
shulker_t = self.load_image_texture("assets/minecraft/textures/entity/shulker/shulker_%s.png" % color).copy()
|
||||||
w,h = shulker_t.size
|
w,h = shulker_t.size
|
||||||
res = w / 4
|
res = w // 4
|
||||||
# Cut out the parts of the shulker texture we need for the box
|
# Cut out the parts of the shulker texture we need for the box
|
||||||
top = shulker_t.crop((res,0,res*2,res))
|
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)))
|
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_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_bottom = shulker_t.crop((0, int(res * 2.75), res, int(res * 3.25)))
|
||||||
side = Image.new('RGBA', (res,res))
|
side = Image.new('RGBA', (res, res))
|
||||||
side.paste(side_top, (0,0), side_top)
|
side.paste(side_top, (0, 0), side_top)
|
||||||
side.paste(side_bottom, (0,res/2), side_bottom)
|
side.paste(side_bottom, (0, res // 2), side_bottom)
|
||||||
|
|
||||||
if data == 0: # down
|
if data == 0: # down
|
||||||
side = side.rotate(180)
|
side = side.rotate(180)
|
||||||
@@ -4768,7 +4781,7 @@ def shulker_box(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# structure block
|
# 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):
|
def structure_block(self, blockid, data):
|
||||||
if data == 0:
|
if data == 0:
|
||||||
img = self.load_image_texture("assets/minecraft/textures/block/structure_block_save.png")
|
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)
|
return self.build_block(img, img)
|
||||||
|
|
||||||
# beetroots
|
# 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):
|
def crops(self, blockid, data):
|
||||||
raw_crop = self.load_image_texture("assets/minecraft/textures/block/beetroots_stage%d.png" % data)
|
raw_crop = self.load_image_texture("assets/minecraft/textures/block/beetroots_stage%d.png" % data)
|
||||||
crop1 = self.transform_image_top(raw_crop)
|
crop1 = self.transform_image_top(raw_crop)
|
||||||
@@ -4795,19 +4808,19 @@ def crops(self, blockid, data):
|
|||||||
return img
|
return img
|
||||||
|
|
||||||
# Concrete
|
# Concrete
|
||||||
@material(blockid=251, data=range(16), solid=True)
|
@material(blockid=251, data=list(range(16)), solid=True)
|
||||||
def concrete(self, blockid, data):
|
def concrete(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete.png" % color_map[data])
|
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete.png" % color_map[data])
|
||||||
return self.build_block(texture, texture)
|
return self.build_block(texture, texture)
|
||||||
|
|
||||||
# Concrete Powder
|
# Concrete Powder
|
||||||
@material(blockid=252, data=range(16), solid=True)
|
@material(blockid=252, data=list(range(16)), solid=True)
|
||||||
def concrete(self, blockid, data):
|
def concrete(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete_powder.png" % color_map[data])
|
texture = self.load_image_texture("assets/minecraft/textures/block/%s_concrete_powder.png" % color_map[data])
|
||||||
return self.build_block(texture, texture)
|
return self.build_block(texture, texture)
|
||||||
|
|
||||||
# Glazed Terracotta
|
# 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):
|
def glazed_terracotta(self, blockid, data):
|
||||||
texture = self.load_image_texture("assets/minecraft/textures/block/%s_glazed_terracotta.png" % color_map[blockid - 235])
|
texture = self.load_image_texture("assets/minecraft/textures/block/%s_glazed_terracotta.png" % color_map[blockid - 235])
|
||||||
glazed_terracotta_orientation = data & 3
|
glazed_terracotta_orientation = data & 3
|
||||||
|
|||||||
@@ -26,13 +26,13 @@ import stat
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from itertools import chain, izip, product
|
from itertools import chain, product
|
||||||
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
|
|
||||||
import c_overviewer
|
from . import c_overviewer
|
||||||
import rendermodes
|
from . import rendermodes
|
||||||
from c_overviewer import resize_half
|
from .c_overviewer import resize_half
|
||||||
|
|
||||||
from . import nbt, world
|
from . import nbt, world
|
||||||
from .files import FileReplacer, get_fs_caps
|
from .files import FileReplacer, get_fs_caps
|
||||||
@@ -95,7 +95,7 @@ do_work(workobj)
|
|||||||
# small but useful
|
# small but useful
|
||||||
def iterate_base4(d):
|
def iterate_base4(d):
|
||||||
"""Iterates over a base 4 number with d digits"""
|
"""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
|
# 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()
|
bounds = self._find_chunk_range()
|
||||||
|
|
||||||
# Calculate the depth of the tree
|
# 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?
|
# Will 2^p tiles wide and high suffice?
|
||||||
|
|
||||||
# X has twice as many chunks as tiles, then halved since this is a
|
# 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:
|
if self.treedepth > curdepth:
|
||||||
logging.warning("Your map seems to have expanded beyond its previous bounds.")
|
logging.warning("Your map seems to have expanded beyond its previous bounds.")
|
||||||
logging.warning("Doing some tile re-arrangements... just a sec...")
|
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()
|
self._increase_depth()
|
||||||
elif self.treedepth < curdepth:
|
elif self.treedepth < curdepth:
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"Your map seems to have shrunk. Did you delete some "
|
"Your map seems to have shrunk. Did you delete some "
|
||||||
"chunks? No problem. Re-arranging tiles, just a sec...")
|
"chunks? No problem. Re-arranging tiles, just a sec...")
|
||||||
for _ in xrange(curdepth - self.treedepth):
|
for _ in range(curdepth - self.treedepth):
|
||||||
self._decrease_depth()
|
self._decrease_depth()
|
||||||
logging.info(
|
logging.info(
|
||||||
"There, done. I'm switching to --check-tiles mode for "
|
"There, done. I'm switching to --check-tiles mode for "
|
||||||
@@ -798,12 +798,12 @@ class TileSet(object):
|
|||||||
os.rename(getpath("new3"), getpath("3"))
|
os.rename(getpath("new3"), getpath("3"))
|
||||||
|
|
||||||
# Delete the files in the top directory to make sure they get re-created.
|
# 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]
|
["base." + self.imgextension]
|
||||||
for f in files:
|
for f in files:
|
||||||
try:
|
try:
|
||||||
os.unlink(getpath(f))
|
os.unlink(getpath(f))
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# Ignore file doesn't exist errors
|
# Ignore file doesn't exist errors
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
@@ -964,7 +964,7 @@ class TileSet(object):
|
|||||||
if not quadPath_filtered:
|
if not quadPath_filtered:
|
||||||
try:
|
try:
|
||||||
os.unlink(imgpath)
|
os.unlink(imgpath)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# Ignore errors if it's "file doesn't exist"
|
# Ignore errors if it's "file doesn't exist"
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
@@ -988,14 +988,14 @@ class TileSet(object):
|
|||||||
quad = Image.new("RGBA", (192, 192), self.options['bgcolor'])
|
quad = Image.new("RGBA", (192, 192), self.options['bgcolor'])
|
||||||
resize_half(quad, src)
|
resize_half(quad, src)
|
||||||
img.paste(quad, path[0])
|
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("Couldn't open %s. It may be corrupt. Error was '%s'.", path[1], e)
|
||||||
logging.warning(
|
logging.warning(
|
||||||
"I'm going to try and delete it. You will need to run "
|
"I'm going to try and delete it. You will need to run "
|
||||||
"the render again and with --check-tiles.")
|
"the render again and with --check-tiles.")
|
||||||
try:
|
try:
|
||||||
os.unlink(path[1])
|
os.unlink(path[1])
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logging.error(
|
logging.error(
|
||||||
"While attempting to delete corrupt image %s, an error was encountered. "
|
"While attempting to delete corrupt image %s, an error was encountered. "
|
||||||
"You will need to delete it yourself. Error was '%s'", path[1], e)
|
"You will need to delete it yourself. Error was '%s'", path[1], e)
|
||||||
@@ -1016,7 +1016,7 @@ class TileSet(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
os.utime(tmppath, (max_mtime, max_mtime))
|
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
|
# Ignore errno ENOENT: file does not exist. Due to a race
|
||||||
# condition, two processes could conceivably try and update
|
# condition, two processes could conceivably try and update
|
||||||
# the same temp file at the same time
|
# the same temp file at the same time
|
||||||
@@ -1049,7 +1049,7 @@ class TileSet(object):
|
|||||||
"This may be a bug.", tile)
|
"This may be a bug.", tile)
|
||||||
try:
|
try:
|
||||||
os.unlink(imgpath)
|
os.unlink(imgpath)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# ignore only if the error was "file not found"
|
# ignore only if the error was "file not found"
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
@@ -1062,7 +1062,7 @@ class TileSet(object):
|
|||||||
if not os.path.exists(dirdest):
|
if not os.path.exists(dirdest):
|
||||||
try:
|
try:
|
||||||
os.makedirs(dirdest)
|
os.makedirs(dirdest)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
# Ignore errno EEXIST: file exists. Due to a race condition,
|
# Ignore errno EEXIST: file exists. Due to a race condition,
|
||||||
# two processes could conceivably try and create the same
|
# two processes could conceivably try and create the same
|
||||||
# directory at the same time
|
# directory at the same time
|
||||||
@@ -1098,7 +1098,7 @@ class TileSet(object):
|
|||||||
# Some chunks are present on disk but not fully initialized.
|
# Some chunks are present on disk but not fully initialized.
|
||||||
# This is okay.
|
# This is okay.
|
||||||
pass
|
pass
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logging.error("Could not render chunk %s,%s for some reason. "
|
logging.error("Could not render chunk %s,%s for some reason. "
|
||||||
"This is likely a render primitive option error.", chunkx, chunkz)
|
"This is likely a render primitive option error.", chunkx, chunkz)
|
||||||
logging.error("Full error was:", exc_info=1)
|
logging.error("Full error was:", exc_info=1)
|
||||||
@@ -1154,7 +1154,7 @@ class TileSet(object):
|
|||||||
imgpath = tileobj.get_filepath(self.outputdir, self.imgextension)
|
imgpath = tileobj.get_filepath(self.outputdir, self.imgextension)
|
||||||
try:
|
try:
|
||||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
tile_mtime = 0
|
tile_mtime = 0
|
||||||
@@ -1198,7 +1198,7 @@ class TileSet(object):
|
|||||||
max_child_mtime = 0
|
max_child_mtime = 0
|
||||||
|
|
||||||
# First, recurse to each of our children
|
# First, recurse to each of our children
|
||||||
for childnum in xrange(4):
|
for childnum in range(4):
|
||||||
childpath = path + (childnum,)
|
childpath = path + (childnum,)
|
||||||
|
|
||||||
# Check if this sub-tree should actually exist, so that we only
|
# 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)
|
logging.debug("Testing mtime for composite-tile %s", imgpath)
|
||||||
try:
|
try:
|
||||||
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
tile_mtime = os.stat(imgpath)[stat.ST_MTIME]
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
if e.errno != errno.ENOENT:
|
if e.errno != errno.ENOENT:
|
||||||
raise
|
raise
|
||||||
tile_mtime = 0
|
tile_mtime = 0
|
||||||
@@ -1296,7 +1296,7 @@ def unconvert_coords(col, row):
|
|||||||
|
|
||||||
# col + row = chunkz + chunkz => (col + row)/2 = chunkz
|
# col + row = chunkz + chunkz => (col + row)/2 = chunkz
|
||||||
# col - row = chunkx + chunkx => (col - row)/2 = chunkx
|
# 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
|
# tile above it as well. Also touches the next 4 tiles down (16
|
||||||
# rows)
|
# rows)
|
||||||
if chunkrow % 4 == 0:
|
if chunkrow % 4 == 0:
|
||||||
rowrange = xrange(tilerow - 4, tilerow + 32 + 1, 4)
|
rowrange = range(tilerow - 4, tilerow + 32 + 1, 4)
|
||||||
else:
|
else:
|
||||||
rowrange = xrange(tilerow, tilerow + 32 + 1, 4)
|
rowrange = range(tilerow, tilerow + 32 + 1, 4)
|
||||||
|
|
||||||
return product(colrange, rowrange)
|
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
|
# First do the odd. For each chunk in the tile's odd column the tile
|
||||||
# "passes through" three chunk sections.
|
# "passes through" three chunk sections.
|
||||||
oddcol_sections = []
|
oddcol_sections = []
|
||||||
for i, y in enumerate(reversed(xrange(16))):
|
for i, y in enumerate(reversed(range(16))):
|
||||||
for row in xrange(tile.row + 3 - i * 2, tile.row - 2 - i * 2, -2):
|
for row in range(tile.row + 3 - i * 2, tile.row - 2 - i * 2, -2):
|
||||||
oddcol_sections.append((tile.col + 1, row, y))
|
oddcol_sections.append((tile.col + 1, row, y))
|
||||||
|
|
||||||
evencol_sections = []
|
evencol_sections = []
|
||||||
for i, y in enumerate(reversed(xrange(16))):
|
for i, y in enumerate(reversed(range(16))):
|
||||||
for row in xrange(tile.row + 4 - i * 2, tile.row - 3 - i * 2, -2):
|
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 + 2, row, y))
|
||||||
evencol_sections.append((tile.col, 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.
|
# or more of the children down the tree are True.
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def __nonzero__(self):
|
def __bool__(self):
|
||||||
"""Returns the boolean context of this particular node. If any
|
"""Returns the boolean context of this particular node. If any
|
||||||
descendent of this node is True return True. Otherwise, False.
|
descendent of this node is True return True. Otherwise, False.
|
||||||
|
|
||||||
@@ -1604,8 +1604,8 @@ class RendertileSet(object):
|
|||||||
# XXX There seems to be something wrong with the num_tiles calculation.
|
# 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
|
# Calculate the number of tiles by iteration and emit a warning if it
|
||||||
# does not match.
|
# 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:
|
if num != self.num_tiles:
|
||||||
logging.error("Please report this to the developers: RendertileSet num_tiles=%r, "
|
logging.error("Please report this to the developers: RendertileSet num_tiles=%r, "
|
||||||
"count=%r, children=%r", self.num_tiles, num, self.children)
|
"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.
|
# 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
|
# Calculate the number of tiles by iteration and emit a warning if it
|
||||||
# does not match.
|
# 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:
|
if num != self.num_tiles_all:
|
||||||
logging.error("Please report this to the developers: RendertileSet num_tiles_all=%r, "
|
logging.error("Please report this to the developers: RendertileSet num_tiles_all=%r, "
|
||||||
"count_all=%r, children=%r", self.num_tiles, num, self.children)
|
"count_all=%r, children=%r", self.num_tiles, num, self.children)
|
||||||
return num
|
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 = []
|
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
|
x = off_x * 2 + dx
|
||||||
y = off_y * 2 + dy
|
y = off_y * 2 + dy
|
||||||
order.append((child, (x, y)))
|
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):
|
class RenderTile(object):
|
||||||
@@ -1733,7 +1734,7 @@ class RenderTile(object):
|
|||||||
|
|
||||||
path = []
|
path = []
|
||||||
|
|
||||||
for level in xrange(depth):
|
for level in range(depth):
|
||||||
# Strategy: Find the midpoint of this level, and determine which
|
# Strategy: Find the midpoint of this level, and determine which
|
||||||
# quadrant this row/col is in. Then set the bounds to that level
|
# quadrant this row/col is in. Then set the bounds to that level
|
||||||
# and repeat
|
# and repeat
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ def findGitHash():
|
|||||||
return line
|
return line
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
import overviewer_version
|
from . import overviewer_version
|
||||||
return overviewer_version.HASH
|
return overviewer_version.HASH
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
@@ -77,7 +77,7 @@ def findGitVersion():
|
|||||||
return line
|
return line
|
||||||
except Exception:
|
except Exception:
|
||||||
try:
|
try:
|
||||||
import overviewer_version
|
from . import overviewer_version
|
||||||
return overviewer_version.VERSION
|
return overviewer_version.VERSION
|
||||||
except Exception:
|
except Exception:
|
||||||
return "unknown"
|
return "unknown"
|
||||||
@@ -108,7 +108,7 @@ def nice_exit(ret=0):
|
|||||||
if ret and is_bare_console():
|
if ret and is_bare_console():
|
||||||
print("")
|
print("")
|
||||||
print("Press [Enter] to close this window.")
|
print("Press [Enter] to close this window.")
|
||||||
raw_input()
|
input()
|
||||||
sys.exit(ret)
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ def roundrobin(iterables):
|
|||||||
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
|
"roundrobin('ABC', 'D', 'EF') --> A D E B F C"
|
||||||
# Recipe credited to George Sakkis
|
# Recipe credited to George Sakkis
|
||||||
pending = len(iterables)
|
pending = len(iterables)
|
||||||
nexts = cycle(iter(it).next for it in iterables)
|
nexts = cycle(iter(it).__next__ for it in iterables)
|
||||||
while pending:
|
while pending:
|
||||||
try:
|
try:
|
||||||
for next in nexts:
|
for next in nexts:
|
||||||
@@ -136,281 +136,13 @@ def dict_subset(d, keys):
|
|||||||
return n
|
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
|
def pid_exists(pid): # http://stackoverflow.com/a/6940314/1318435
|
||||||
"""Check whether pid exists in the current process table."""
|
"""Check whether pid exists in the current process table."""
|
||||||
if pid < 0:
|
if pid < 0:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
os.kill(pid, 0)
|
os.kill(pid, 0)
|
||||||
except OSError, e:
|
except OSError as e:
|
||||||
return e.errno != errno.ESRCH
|
return e.errno != errno.ESRCH
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ def log_other_exceptions(func):
|
|||||||
return func(*args)
|
return func(*args)
|
||||||
except ChunkDoesntExist:
|
except ChunkDoesntExist:
|
||||||
raise
|
raise
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
logging.exception("%s raised this exception", func.func_name)
|
logging.exception("%s raised this exception", func.func_name)
|
||||||
raise
|
raise
|
||||||
return newfunc
|
return newfunc
|
||||||
@@ -1139,7 +1139,7 @@ class RegionSet(object):
|
|||||||
try:
|
try:
|
||||||
region = self._get_regionobj(regionfile)
|
region = self._get_regionobj(regionfile)
|
||||||
data = region.load_chunk(x, z)
|
data = region.load_chunk(x, z)
|
||||||
except nbt.CorruptionError, e:
|
except nbt.CorruptionError as e:
|
||||||
tries -= 1
|
tries -= 1
|
||||||
if tries > 0:
|
if tries > 0:
|
||||||
# Flush the region cache to possibly read a new region file
|
# 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:
|
try:
|
||||||
mcr = self._get_regionobj(regionfile)
|
mcr = self._get_regionobj(regionfile)
|
||||||
except nbt.CorruptRegionError:
|
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! """
|
""" SKIP LOADING A REGION WHICH HAS NOT BEEN MODIFIED! """
|
||||||
if (filemtime < mtime):
|
if (filemtime < mtime):
|
||||||
continue
|
continue
|
||||||
@@ -1561,7 +1561,6 @@ def get_worlds():
|
|||||||
"Returns {world # or name : level.dat information}"
|
"Returns {world # or name : level.dat information}"
|
||||||
ret = {}
|
ret = {}
|
||||||
save_dir = get_save_dir()
|
save_dir = get_save_dir()
|
||||||
loc = locale.getpreferredencoding()
|
|
||||||
|
|
||||||
# No dirs found - most likely not running from inside minecraft-dir
|
# No dirs found - most likely not running from inside minecraft-dir
|
||||||
if not save_dir is None:
|
if not save_dir is None:
|
||||||
@@ -1571,11 +1570,12 @@ def get_worlds():
|
|||||||
if not os.path.exists(world_dat): continue
|
if not os.path.exists(world_dat): continue
|
||||||
try:
|
try:
|
||||||
info = nbt.load(world_dat)[1]
|
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():
|
if 'LevelName' in info['Data'].keys():
|
||||||
ret[info['Data']['LevelName']] = info['Data']
|
ret[info['Data']['LevelName']] = info['Data']
|
||||||
except nbt.CorruptNBTError:
|
except nbt.CorruptNBTError:
|
||||||
ret[os.path.basename(world_path).decode(loc) + " (corrupt)"] = {'path': world_path.decode(loc),
|
ret[os.path.basename(world_path) + " (corrupt)"] = {
|
||||||
|
'path': world_path,
|
||||||
'LastPlayed': 0,
|
'LastPlayed': 0,
|
||||||
'Time': 0,
|
'Time': 0,
|
||||||
'IsCorrupt': True}
|
'IsCorrupt': True}
|
||||||
|
|||||||
16
setup.py
16
setup.py
@@ -1,15 +1,15 @@
|
|||||||
#!/usr/bin/env python2
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
# quick version check
|
# quick version check
|
||||||
if not (sys.version_info[0] == 2 and sys.version_info[1] >= 6):
|
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 2.6 to run")
|
print("Sorry, the Overviewer requires at least Python 3.4 to run.")
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
print("and will not run on Python 3.0 or later")
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
from distutils.core import setup
|
from distutils.core import setup
|
||||||
from distutils.extension import Extension
|
from distutils.extension import Extension
|
||||||
from distutils.command.build import build
|
from distutils.command.build import build
|
||||||
@@ -176,12 +176,12 @@ for name in glob.glob("overviewer_core/src/primitives/*.c"):
|
|||||||
primitives.append(name)
|
primitives.append(name)
|
||||||
|
|
||||||
c_overviewer_files = ['main.c', 'composite.c', 'iterate.c', 'endian.c', 'rendermodes.c']
|
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_files += ['Draw.c']
|
||||||
c_overviewer_includes = ['overviewer.h', 'rendermodes.h']
|
c_overviewer_includes = ['overviewer.h', 'rendermodes.h']
|
||||||
|
|
||||||
c_overviewer_files = map(lambda s: 'overviewer_core/src/'+s, c_overviewer_files)
|
c_overviewer_files = ['overviewer_core/src/' + s for s in c_overviewer_files]
|
||||||
c_overviewer_includes = map(lambda s: 'overviewer_core/src/'+s, c_overviewer_includes)
|
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=[]))
|
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
|
import unittest
|
||||||
|
|
||||||
# For convenience
|
# For convenience
|
||||||
|
|||||||
@@ -9,15 +9,15 @@ class TestLRU(unittest.TestCase):
|
|||||||
|
|
||||||
def test_single_insert(self):
|
def test_single_insert(self):
|
||||||
self.lru[1] = 2
|
self.lru[1] = 2
|
||||||
self.assertEquals(self.lru[1], 2)
|
self.assertEqual(self.lru[1], 2)
|
||||||
|
|
||||||
def test_multiple_insert(self):
|
def test_multiple_insert(self):
|
||||||
self.lru[1] = 2
|
self.lru[1] = 2
|
||||||
self.lru[3] = 4
|
self.lru[3] = 4
|
||||||
self.lru[5] = 6
|
self.lru[5] = 6
|
||||||
self.assertEquals(self.lru[1], 2)
|
self.assertEqual(self.lru[1], 2)
|
||||||
self.assertEquals(self.lru[3], 4)
|
self.assertEqual(self.lru[3], 4)
|
||||||
self.assertEquals(self.lru[5], 6)
|
self.assertEqual(self.lru[5], 6)
|
||||||
|
|
||||||
def test_full(self):
|
def test_full(self):
|
||||||
self.lru[1] = 'asdf'
|
self.lru[1] = 'asdf'
|
||||||
@@ -27,11 +27,11 @@ class TestLRU(unittest.TestCase):
|
|||||||
self.lru[5] = 'asdf'
|
self.lru[5] = 'asdf'
|
||||||
self.lru[6] = 'asdf'
|
self.lru[6] = 'asdf'
|
||||||
self.assertRaises(KeyError, self.lru.__getitem__, 1)
|
self.assertRaises(KeyError, self.lru.__getitem__, 1)
|
||||||
self.assertEquals(self.lru[2], 'asdf')
|
self.assertEqual(self.lru[2], 'asdf')
|
||||||
self.assertEquals(self.lru[3], 'asdf')
|
self.assertEqual(self.lru[3], 'asdf')
|
||||||
self.assertEquals(self.lru[4], 'asdf')
|
self.assertEqual(self.lru[4], 'asdf')
|
||||||
self.assertEquals(self.lru[5], 'asdf')
|
self.assertEqual(self.lru[5], 'asdf')
|
||||||
self.assertEquals(self.lru[6], 'asdf')
|
self.assertEqual(self.lru[6], 'asdf')
|
||||||
|
|
||||||
def test_lru(self):
|
def test_lru(self):
|
||||||
self.lru[1] = 'asdf'
|
self.lru[1] = 'asdf'
|
||||||
@@ -40,17 +40,17 @@ class TestLRU(unittest.TestCase):
|
|||||||
self.lru[4] = 'asdf'
|
self.lru[4] = 'asdf'
|
||||||
self.lru[5] = 'asdf'
|
self.lru[5] = 'asdf'
|
||||||
|
|
||||||
self.assertEquals(self.lru[1], 'asdf')
|
self.assertEqual(self.lru[1], 'asdf')
|
||||||
self.assertEquals(self.lru[2], 'asdf')
|
self.assertEqual(self.lru[2], 'asdf')
|
||||||
self.assertEquals(self.lru[4], 'asdf')
|
self.assertEqual(self.lru[4], 'asdf')
|
||||||
self.assertEquals(self.lru[5], 'asdf')
|
self.assertEqual(self.lru[5], 'asdf')
|
||||||
|
|
||||||
# 3 should be evicted now
|
# 3 should be evicted now
|
||||||
self.lru[6] = 'asdf'
|
self.lru[6] = 'asdf'
|
||||||
|
|
||||||
self.assertRaises(KeyError, self.lru.__getitem__, 3)
|
self.assertRaises(KeyError, self.lru.__getitem__, 3)
|
||||||
self.assertEquals(self.lru[1], 'asdf')
|
self.assertEqual(self.lru[1], 'asdf')
|
||||||
self.assertEquals(self.lru[2], 'asdf')
|
self.assertEqual(self.lru[2], 'asdf')
|
||||||
self.assertEquals(self.lru[4], 'asdf')
|
self.assertEqual(self.lru[4], 'asdf')
|
||||||
self.assertEquals(self.lru[5], 'asdf')
|
self.assertEqual(self.lru[5], 'asdf')
|
||||||
self.assertEquals(self.lru[6], 'asdf')
|
self.assertEqual(self.lru[6], 'asdf')
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from itertools import chain, izip
|
from itertools import chain
|
||||||
|
|
||||||
from overviewer_core.tileset import iterate_base4, RendertileSet
|
from overviewer_core.tileset import iterate_base4, RendertileSet
|
||||||
from overviewer_core.util import roundrobin
|
from overviewer_core.util import roundrobin
|
||||||
@@ -150,7 +150,7 @@ class RendertileSetTest(unittest.TestCase):
|
|||||||
self.assertRaises(AssertionError, self.test_iterate)
|
self.assertRaises(AssertionError, self.test_iterate)
|
||||||
|
|
||||||
def test_count(self):
|
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):
|
def test_bool(self):
|
||||||
"Tests the boolean status of a node"
|
"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"""
|
"""Test a post-traversal of the tree's dirty tiles"""
|
||||||
# Expect the results in this proper order.
|
# Expect the results in this proper order.
|
||||||
iterator = iter(self.tree.posttraversal())
|
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.assertEqual(actual, expected)
|
||||||
|
|
||||||
self.assertRaises(StopIteration, next, iterator)
|
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"""
|
"""Test a round-robin post-traversal of the tree's dirty tiles"""
|
||||||
# Expect the results in this proper order.
|
# Expect the results in this proper order.
|
||||||
iterator = iter(self.tree.posttraversal(robin=True))
|
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.assertEqual(actual, expected)
|
||||||
|
|
||||||
self.assertRaises(StopIteration, next, iterator)
|
self.assertRaises(StopIteration, next, iterator)
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
from collections import OrderedDict
|
||||||
|
|
||||||
from overviewer_core import configParser
|
from overviewer_core import configParser
|
||||||
from overviewer_core.settingsValidators import ValidationException
|
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 world
|
||||||
from overviewer_core import rendermodes
|
from overviewer_core import rendermodes
|
||||||
|
|
||||||
from overviewer_core.util import OrderedDict
|
|
||||||
|
|
||||||
class SettingsTest(unittest.TestCase):
|
class SettingsTest(unittest.TestCase):
|
||||||
|
|
||||||
@@ -23,12 +23,12 @@ class SettingsTest(unittest.TestCase):
|
|||||||
# no exceptions so far. that's a good thing
|
# no exceptions so far. that's a good thing
|
||||||
|
|
||||||
# Test the default
|
# 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
|
# 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)
|
world.UPPER_LEFT)
|
||||||
|
|
||||||
def test_rendermode_validation(self):
|
def test_rendermode_validation(self):
|
||||||
@@ -63,7 +63,7 @@ class SettingsTest(unittest.TestCase):
|
|||||||
}),
|
}),
|
||||||
]))
|
]))
|
||||||
self.s.set_config_item("outputdir", "/tmp/fictional/outputdir")
|
self.s.set_config_item("outputdir", "/tmp/fictional/outputdir")
|
||||||
self.assertEquals(fromfile.get_validated_config(), self.s.get_validated_config())
|
self.assertEqual(fromfile.get_validated_config(), self.s.get_validated_config())
|
||||||
|
|
||||||
def test_rendermode_string(self):
|
def test_rendermode_string(self):
|
||||||
self.s.set_config_item("worlds", {
|
self.s.set_config_item("worlds", {
|
||||||
@@ -79,7 +79,7 @@ class SettingsTest(unittest.TestCase):
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
p = self.s.get_validated_config()
|
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__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ class FakeRegionset(object):
|
|||||||
return NotImplementedError()
|
return NotImplementedError()
|
||||||
|
|
||||||
def iterate_chunks(self):
|
def iterate_chunks(self):
|
||||||
for (x,z),mtime in self.chunks.iteritems():
|
for (x,z),mtime in self.chunks.items():
|
||||||
yield x,z,mtime
|
yield x,z,mtime
|
||||||
|
|
||||||
def iterate_newer_chunks(self, filemtime):
|
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
|
yield x,z,mtime
|
||||||
|
|
||||||
def get_chunk_mtime(self, x, z):
|
def get_chunk_mtime(self, x, z):
|
||||||
@@ -77,7 +77,7 @@ def get_tile_set(chunks):
|
|||||||
the compare_iterate_to_expected() method.
|
the compare_iterate_to_expected() method.
|
||||||
"""
|
"""
|
||||||
tile_set = defaultdict(int)
|
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)
|
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)
|
tile_set[tile.path] = max(tile_set[tile.path], chunkmtime)
|
||||||
|
|
||||||
# At this point, tile_set holds all the render-tiles
|
# At this point, tile_set holds all the render-tiles
|
||||||
for tile, tile_mtime in tile_set.copy().iteritems():
|
for tile, tile_mtime in tile_set.copy().items():
|
||||||
# All render-tiles are length 5. Hard-code its upper tiles
|
# 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)
|
tile_set[tile[:i]] = max(tile_set[tile[:i]], tile_mtime)
|
||||||
return dict(tile_set)
|
return dict(tile_set)
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ def create_fakedir(outputdir, tiles):
|
|||||||
files) and sets mtimes appropriately
|
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]))
|
dirpath = os.path.join(outputdir, *(str(x) for x in tilepath[:-1]))
|
||||||
if len(tilepath) == 0:
|
if len(tilepath) == 0:
|
||||||
imgname = "base.png"
|
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))
|
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
|
# 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))
|
self.assertTrue(tilepath in paths, "%s was expected to be returned but wasn't: %s" % (tilepath, paths))
|
||||||
|
|
||||||
def test_get_phase_length(self):
|
def test_get_phase_length(self):
|
||||||
@@ -215,7 +215,7 @@ class TilesetTest(unittest.TestCase):
|
|||||||
"""Same as above but with a different set of chunks
|
"""Same as above but with a different set of chunks
|
||||||
"""
|
"""
|
||||||
# Pick 3 random chunks to update
|
# Pick 3 random chunks to update
|
||||||
chunks = self.rs.chunks.keys()
|
chunks = list(self.rs.chunks.keys())
|
||||||
self.r.shuffle(chunks)
|
self.r.shuffle(chunks)
|
||||||
updated_chunks = {}
|
updated_chunks = {}
|
||||||
for key in chunks[:3]:
|
for key in chunks[:3]:
|
||||||
|
|||||||
@@ -17,19 +17,19 @@ class ExampleWorldTest(unittest.TestCase):
|
|||||||
w = world.World("test/data/worlds/exmaple")
|
w = world.World("test/data/worlds/exmaple")
|
||||||
|
|
||||||
regionsets = w.get_regionsets()
|
regionsets = w.get_regionsets()
|
||||||
self.assertEquals(len(regionsets), 3)
|
self.assertEqual(len(regionsets), 3)
|
||||||
|
|
||||||
regionset = regionsets[0]
|
regionset = regionsets[0]
|
||||||
self.assertEquals(regionset.get_region_path(0,0), 'test/data/worlds/exmaple/DIM-1/region/r.0.0.mcr')
|
self.assertEqual(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.assertEqual(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.assertEqual(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(35,35), None)
|
||||||
|
|
||||||
# a few random chunks. reference timestamps fetched with libredstone
|
# a few random chunks. reference timestamps fetched with libredstone
|
||||||
self.assertEquals(regionset.get_chunk_mtime(0,0), 1316728885)
|
self.assertEqual(regionset.get_chunk_mtime(0,0), 1316728885)
|
||||||
self.assertEquals(regionset.get_chunk_mtime(-1,-1), 1316728886)
|
self.assertEqual(regionset.get_chunk_mtime(-1,-1), 1316728886)
|
||||||
self.assertEquals(regionset.get_chunk_mtime(5,0), 1316728905)
|
self.assertEqual(regionset.get_chunk_mtime(5,0), 1316728905)
|
||||||
self.assertEquals(regionset.get_chunk_mtime(-22,16), 1316786786)
|
self.assertEqual(regionset.get_chunk_mtime(-22,16), 1316786786)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user