0

overviewer: code style and consistency fixes

A good sprinkling of PEP8 fixes. We're also getting rid of some
odd manual linebreaks in the output messages, and making sure to
end sentences with a period where appropriate. Help messages have
also been made more consistent, e.g. "Tries" -> "Try" and so forth.
This commit is contained in:
Nicolas F
2019-03-06 14:27:04 +01:00
parent 4ffa0be456
commit ef66efd140

View File

@@ -47,6 +47,7 @@ helptext = """
%prog [--rendermodes=...] [options] <World> <Output Dir> %prog [--rendermodes=...] [options] <World> <Output Dir>
%prog --config=<config file> [options]""" %prog --config=<config file> [options]"""
def main(): def main():
# bootstrap the logger with defaults # bootstrap the logger with defaults
logger.configure() logger.configure()
@@ -66,57 +67,65 @@ def main():
except NotImplementedError: except NotImplementedError:
cpus = 1 cpus = 1
#avail_rendermodes = c_overviewer.get_render_modes()
avail_north_dirs = ['lower-left', 'upper-left', 'upper-right', 'lower-right', 'auto'] avail_north_dirs = ['lower-left', 'upper-left', 'upper-right', 'lower-right', 'auto']
# Parse for basic options # Parse for basic options
parser = OptionParser(usage=helptext, add_help_option=False) parser = OptionParser(usage=helptext, add_help_option=False)
parser.add_option("-h", "--help", dest="help", action="store_true", parser.add_option("-h", "--help", dest="help", action="store_true",
help="show this help message and exit") help="Show this help message and exit.")
parser.add_option("-c", "--config", dest="config", action="store", help="Specify the config file to use.") parser.add_option("-c", "--config", dest="config", action="store",
help="Specify the config file to use.")
parser.add_option("-p", "--processes", dest="procs", action="store", type="int", parser.add_option("-p", "--processes", dest="procs", action="store", type="int",
help="The number of local worker processes to spawn. Defaults to the number of CPU cores your computer has") help="The number of local worker processes to spawn. Defaults to the number "
"of CPU cores your computer has.")
parser.add_option("--pid", dest="pid", action="store", help="Specify the pid file to use.") parser.add_option("--pid", dest="pid", action="store", help="Specify the pid file to use.")
# Options that only apply to the config-less render usage # Options that only apply to the config-less render usage
parser.add_option("--rendermodes", dest="rendermodes", action="store", parser.add_option("--rendermodes", dest="rendermodes", action="store",
help="If you're not using a config file, specify which rendermodes to render with this option. This is a comma-separated list.") help="If you're not using a config file, specify which rendermodes to "
"render with this option. This is a comma-separated list.")
# Useful one-time render modifiers: # Useful one-time render modifiers:
parser.add_option("--forcerender", dest="forcerender", action="store_true", parser.add_option("--forcerender", dest="forcerender", action="store_true",
help="Force re-rendering the entire map.") help="Force re-render the entire map.")
parser.add_option("--check-tiles", dest="checktiles", action="store_true", parser.add_option("--check-tiles", dest="checktiles", action="store_true",
help="Check each tile on disk and re-render old tiles") help="Check each tile on disk and re-render old tiles.")
parser.add_option("--no-tile-checks", dest="notilechecks", action="store_true", parser.add_option("--no-tile-checks", dest="notilechecks", action="store_true",
help="Only render tiles that come from chunks that have changed since the last render (the default)") help="Only render tiles that come from chunks that have changed since the "
"last render (the default).")
# Useful one-time debugging options: # Useful one-time debugging options:
parser.add_option("--check-terrain", dest="check_terrain", action="store_true", parser.add_option("--check-terrain", dest="check_terrain", action="store_true",
help="Tries to locate the texture files. Useful for debugging texture problems.") help="Try to locate the texture files. Useful for debugging texture"
" problems.")
parser.add_option("-V", "--version", dest="version", parser.add_option("-V", "--version", dest="version",
help="Displays version information and then exits", action="store_true") help="Display version information and then exits.", action="store_true")
parser.add_option("--check-version", dest="checkversion", parser.add_option("--check-version", dest="checkversion",
help="Fetchs information about the latest version of Overviewer", action="store_true") help="Fetch information about the latest version of Overviewer.",
action="store_true")
parser.add_option("--update-web-assets", dest='update_web_assets', action="store_true", parser.add_option("--update-web-assets", dest='update_web_assets', action="store_true",
help="Update web assets. Will *not* render tiles or update overviewerConfig.js") help="Update web assets. Will *not* render tiles or update "
"overviewerConfig.js.")
# Log level options: # Log level options:
parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0, parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0,
help="Print less output. You can specify this option multiple times.") help="Print less output. You can specify this option multiple times.")
parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0, parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0,
help="Print more output. You can specify this option multiple times.") help="Print more output. You can specify this option multiple times.")
parser.add_option("--simple-output", dest="simple", action="store_true", default=False, parser.add_option("--simple-output", dest="simple", action="store_true", default=False,
help="Use a simple output format, with no colors or progress bars") help="Use a simple output format, with no colors or progress bars.")
# create a group for "plugin exes" (the concept of a plugin exe is only loosly defined at this point) # create a group for "plugin exes"
# (the concept of a plugin exe is only loosely defined at this point)
exegroup = OptionGroup(parser, "Other Scripts", exegroup = OptionGroup(parser, "Other Scripts",
"These scripts may accept different arguments than the ones listed above") "These scripts may accept different arguments than the ones "
"listed above")
exegroup.add_option("--genpoi", dest="genpoi", action="store_true", exegroup.add_option("--genpoi", dest="genpoi", action="store_true",
help="Runs the genPOI script") help="Run the genPOI script.")
exegroup.add_option("--skip-scan", dest="skipscan", action="store_true", exegroup.add_option("--skip-scan", dest="skipscan", action="store_true",
help="When running GenPOI, don't scan for entities") help="When running GenPOI, don't scan for entities.")
exegroup.add_option("--skip-players", dest="skipplayers", action="store_true", exegroup.add_option("--skip-players", dest="skipplayers", action="store_true",
help="When running GenPOI, don't get player data") help="When running GenPOI, don't scan player data.")
parser.add_option_group(exegroup) parser.add_option_group(exegroup)
@@ -126,7 +135,6 @@ def main():
if options.genpoi: if options.genpoi:
# remove the "--genpoi" option from sys.argv before running genPI # remove the "--genpoi" option from sys.argv before running genPI
sys.argv.remove("--genpoi") sys.argv.remove("--genpoi")
#sys.path.append(".")
g = __import__("overviewer_core.aux_files", {}, {}, ["genPOI"]) g = __import__("overviewer_core.aux_files", {}, {}, ["genPOI"])
g.genPOI.main() g.genPOI.main()
return 0 return 0
@@ -135,9 +143,8 @@ def main():
return 0 return 0
# re-configure the logger now that we've processed the command line options # re-configure the logger now that we've processed the command line options
logger.configure(logging.INFO + 10*options.quiet - 10*options.verbose, logger.configure(logging.INFO + 10 * options.quiet - 10 * options.verbose,
verbose=options.verbose > 0, verbose=options.verbose > 0, simple=options.simple)
simple=options.simple)
########################################################################## ##########################################################################
# This section of main() runs in response to any one-time options we have, # This section of main() runs in response to any one-time options we have,
@@ -149,8 +156,9 @@ def main():
import overviewer_core.overviewer_version as overviewer_version import overviewer_core.overviewer_version as overviewer_version
print("built on %s" % overviewer_version.BUILD_DATE) print("built on %s" % overviewer_version.BUILD_DATE)
if options.verbose > 0: if options.verbose > 0:
print("Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM, overviewer_version.BUILD_OS)) print("Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM,
print("Read version information from %r"% overviewer_version.__file__) overviewer_version.BUILD_OS))
print("Read version information from %r" % overviewer_version.__file__)
except ImportError: except ImportError:
print("(build info not found)") print("(build info not found)")
if options.verbose > 0: if options.verbose > 0:
@@ -164,31 +172,32 @@ def main():
try: try:
import urllib import urllib
import json import json
latest_ver = json.loads(urllib.urlopen("http://overviewer.org/download.json").read())['src'] latest_ver = json.loads(urllib.urlopen("http://overviewer.org/download.json")
print("Latest version of Minecraft Overviewer %s (%s)" % (latest_ver['version'], latest_ver['commit'][:7])) .read())['src']
print("See http://overviewer.org/downloads for more information") print("Latest version of Minecraft Overviewer %s (%s)" % (latest_ver['version'],
latest_ver['commit'][:7]))
print("See https://overviewer.org/downloads for more information.")
except Exception: except Exception:
print("Failed to fetch latest version info.") print("Failed to fetch latest version info.")
if options.verbose > 0: if options.verbose > 0:
import traceback import traceback
traceback.print_exc() traceback.print_exc()
else: else:
print("Re-run with --verbose for more details") print("Re-run with --verbose for more details.")
return 1 return 1
return 0 return 0
if options.pid: if options.pid:
if os.path.exists(options.pid): if os.path.exists(options.pid):
try: try:
with open(options.pid, 'r') as fpid: with open(options.pid, 'r') as fpid:
pid = int(fpid.read()) pid = int(fpid.read())
if util.pid_exists(pid): if util.pid_exists(pid):
print("Already running (pid exists) - exiting..") print("Overviewer is already running (pid exists) - exiting.")
return 0 return 0
except (IOError, ValueError): except (IOError, ValueError):
pass pass
with open(options.pid,"w") as f: with open(options.pid, "w") as f:
f.write(str(os.getpid())) f.write(str(os.getpid()))
# if --check-terrain was specified, but we have NO config file, then we cannot # if --check-terrain was specified, but we have NO config file, then we cannot
# operate on a custom texture path. we do terrain checking with a custom texture # operate on a custom texture path. we do terrain checking with a custom texture
@@ -225,7 +234,8 @@ def main():
else: else:
# more helpful message for users who know what they're doing # more helpful message for users who know what they're doing
logging.error("You must either specify --config or give me a world directory and output directory") logging.error("You must either specify --config or give me a world directory "
"and output directory.")
parser.print_help() parser.print_help()
list_worlds() list_worlds()
return 1 return 1
@@ -236,13 +246,14 @@ def main():
# given, and vice versa # given, and vice versa
if options.config and args: if options.config and args:
print() print()
print("If you specify --config, you need to specify the world to render as well as") print("If you specify --config, you need to specify the world to render as well as "
print("the destination in the config file, not on the command line.") "the destination in the config file, not on the command line.")
print("Put something like this in your config file:") print("Put something like this in your config file:")
print("worlds['myworld'] = %r" % args[0]) print("worlds['myworld'] = %r" % args[0])
print("outputdir = %r" % (args[1] if len(args) > 1 else "/path/to/output")) print("outputdir = %r" % (args[1] if len(args) > 1 else "/path/to/output"))
print() print()
logging.error("Cannot specify both --config AND a world + output directory on the command line.") logging.error("You cannot specify both --config AND a world + output directory on the "
"command line.")
parser.print_help() parser.print_help()
return 1 return 1
@@ -255,10 +266,12 @@ def main():
# properly escape it attempt to detect this case # properly escape it attempt to detect this case
for start in range(len(args)): for start in range(len(args)):
if not os.path.exists(args[start]): if not os.path.exists(args[start]):
for end in range(start+1, len(args)+1): for end in range(start + 1, len(args) + 1):
if os.path.exists(" ".join(args[start:end])): if os.path.exists(" ".join(args[start:end])):
logging.warning("It looks like you meant to specify \"%s\" as your world dir or your output\n\ logging.warning(
dir but you forgot to put quotes around the directory, since it contains spaces." % " ".join(args[start:end])) "It looks like you meant to specify \"%s\" as your world dir or your "
"output dir but you forgot to put quotes around the directory, since "
"it contains spaces." % " ".join(args[start:end]))
return 1 return 1
logging.error("Too many command line arguments") logging.error("Too many command line arguments")
parser.print_help() parser.print_help()
@@ -280,21 +293,22 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
rendermodes = ['lighting'] rendermodes = ['lighting']
if options.rendermodes: if options.rendermodes:
rendermodes = options.rendermodes.replace("-","_").split(",") rendermodes = options.rendermodes.replace("-", "_").split(",")
# Now for some good defaults # Now for some good defaults
renders = util.OrderedDict() renders = util.OrderedDict()
for rm in rendermodes: for rm in rendermodes:
renders["world-" + rm] = { renders["world-" + rm] = {
"world": "world", "world": "world",
"title": "Overviewer Render (%s)" % rm, "title": "Overviewer Render (%s)" % rm,
"rendermode": rm, "rendermode": rm,
} }
mw_parser.set_config_item("renders", renders) mw_parser.set_config_item("renders", renders)
else: else:
if options.rendermodes: if options.rendermodes:
logging.error("You cannot specify --rendermodes if you give a config file. Configure your rendermodes in the config file instead") logging.error("You cannot specify --rendermodes if you give a config file. "
"Configure your rendermodes in the config file instead.")
parser.print_help() parser.print_help()
return 1 return 1
@@ -316,16 +330,17 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
config = mw_parser.get_validated_config() config = mw_parser.get_validated_config()
except Exception as ex: except Exception as ex:
if options.verbose: if options.verbose:
logging.exception("An error was encountered with your configuration. See the info below.") logging.exception("An error was encountered with your configuration. "
else: # no need to print scary traceback! just "See the information below.")
else: # no need to print scary traceback!
logging.error("An error was encountered with your configuration.") logging.error("An error was encountered with your configuration.")
logging.error(str(ex)) logging.error(str(ex))
return 1 return 1
if options.check_terrain: # we are already in the "if configfile" branch if options.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'].iteritems():
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
texopts = util.dict_subset(render, ["texturepath"]) texopts = util.dict_subset(render, ["texturepath"])
@@ -340,40 +355,42 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
############################################################ ############################################################
# Final validation steps and creation of the destination directory # Final validation steps and creation of the destination directory
logging.info("Welcome to Minecraft Overviewer!") logging.info("Welcome to Minecraft Overviewer!")
logging.debug("Current log level: {0}".format(logging.getLogger().level)) logging.debug("Current log level: {0}.".format(logging.getLogger().level))
# Override some render configdict options depending on one-time command line # Override some render configdict options depending on one-time command line
# modifiers # modifiers
if ( if (
bool(options.forcerender) + bool(options.forcerender) +
bool(options.checktiles) + bool(options.checktiles) +
bool(options.notilechecks) bool(options.notilechecks)
) > 1: ) > 1:
logging.error("You cannot specify more than one of --forcerender, "+ logging.error("You cannot specify more than one of --forcerender, "
"--check-tiles, and --no-tile-checks. These options conflict.") "--check-tiles, and --no-tile-checks. These options conflict.")
parser.print_help() parser.print_help()
return 1 return 1
def set_renderchecks(checkname, num): def set_renderchecks(checkname, num):
for name, render in config['renders'].iteritems(): for name, render in config['renders'].iteritems():
if render.get('renderchecks', 0) == 3: if render.get('renderchecks', 0) == 3:
logging.warning(checkname + " ignoring render " + repr(name) + " since it's marked as \"don't render\".") logging.warning(checkname + " ignoring render " + repr(name) + " since it's "
"marked as \"don't render\".")
else: else:
render['renderchecks'] = num render['renderchecks'] = num
if options.forcerender: if options.forcerender:
logging.info("Forcerender mode activated. ALL tiles will be rendered") logging.info("Forcerender mode activated. ALL tiles will be rendered.")
set_renderchecks("forcerender", 2) set_renderchecks("forcerender", 2)
elif options.checktiles: elif options.checktiles:
logging.info("Checking all tiles for updates manually.") logging.info("Checking all tiles for updates manually.")
set_renderchecks("checktiles", 1) set_renderchecks("checktiles", 1)
elif options.notilechecks: elif options.notilechecks:
logging.info("Disabling all tile mtime checks. Only rendering tiles "+ logging.info("Disabling all tile mtime checks. Only rendering tiles "
"that need updating since last render") "that need updating since last render.")
set_renderchecks("notilechecks", 0) set_renderchecks("notilechecks", 0)
if not config['renders']: if not config['renders']:
logging.error("You must specify at least one render in your config file. See the docs if you're having trouble") logging.error("You must specify at least one render in your config file. Check the "
"documentation at http://docs.overviewer.org if you're having trouble.")
return 1 return 1
##################### #####################
@@ -384,8 +401,8 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
try: try:
worldpath = config['worlds'][render['world']] worldpath = config['worlds'][render['world']]
except KeyError: except KeyError:
logging.error("Render %s's world is '%s', but I could not find a corresponding entry in the worlds dictionary.", logging.error("Render %s's world is '%s', but I could not find a corresponding entry "
rname, render['world']) "in the worlds dictionary.", rname, render['world'])
return 1 return 1
render['worldname_orig'] = render['world'] render['worldname_orig'] = render['world']
render['world'] = worldpath render['world'] = worldpath
@@ -401,8 +418,8 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
try: try:
renderLink = config['renders'][x] renderLink = config['renders'][x]
except KeyError: except KeyError:
logging.error("Render %s's overlay is '%s', but I could not find a corresponding entry in the renders dictionary.", logging.error("Render %s's overlay is '%s', but I could not find a "
rname, x) "corresponding entry in the renders dictionary.", rname, x)
return 1 return 1
else: else:
logging.error("Render %s's overlay contains itself.", rname) logging.error("Render %s's overlay contains itself.", rname)
@@ -426,10 +443,10 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
# create our asset manager... ASSMAN # create our asset manager... ASSMAN
assetMrg = assetmanager.AssetManager(destdir, config.get('customwebassets', None)) assetMrg = assetmanager.AssetManager(destdir, config.get('customwebassets', None))
# If we've been asked to update web assets, do that and then exit # If we've been asked to update web assets, do that and then exit
if options.update_web_assets: if options.update_web_assets:
assetMrg.output_noconfig() assetMrg.output_noconfig()
logging.info("Web assets have been updated") logging.info("Web assets have been updated.")
return 0 return 0
# The changelist support. # The changelist support.
@@ -439,7 +456,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
path = render['changelist'] path = render['changelist']
if path not in changelists: if path not in changelists:
out = open(path, "w") out = open(path, "w")
logging.debug("Opening changelist %s (%s)", out, out.fileno()) logging.debug("Opening changelist %s (%s).", out, out.fileno())
changelists[path] = out changelists[path] = out
else: else:
out = changelists[path] out = changelists[path]
@@ -468,7 +485,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
try: try:
w = world.World(render['world']) w = world.World(render['world'])
except CorruptNBTError, e: except CorruptNBTError, e:
logging.error("Failed to open world %r", render['world']) logging.error("Failed to open world %r.", render['world'])
raise e raise e
except world.UnsupportedVersion, e: except world.UnsupportedVersion, e:
for ln in str(e).split('\n'): for ln in str(e).split('\n'):
@@ -484,19 +501,21 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
tex = textures.Textures(**texopts) tex = textures.Textures(**texopts)
logging.info("Generating textures...") logging.info("Generating textures...")
tex.generate() tex.generate()
logging.debug("Finished generating textures") logging.debug("Finished generating textures.")
texcache[texopts_key] = tex texcache[texopts_key] = tex
else: else:
tex = texcache[texopts_key] tex = texcache[texopts_key]
try: try:
logging.debug("Asking for regionset %r" % render['dimension'][1]) logging.debug("Asking for regionset %r." % render['dimension'][1])
rset = w.get_regionset(render['dimension'][1]) rset = w.get_regionset(render['dimension'][1])
except IndexError: except IndexError:
logging.error("Sorry, I can't find anything to render! Are you sure there are .mca files in the world directory?") logging.error("Sorry, I can't find anything to render! Are you sure there are .mca "
"files in the world directory?")
return 1 return 1
if rset == None: # indicates no such dimension was found: if rset is None: # indicates no such dimension was found
logging.warn("Sorry, you requested dimension '%s' for %s, but I couldn't find it", render['dimension'][0], render_name) logging.warn("Sorry, you requested dimension '%s' for %s, but I couldn't find it.",
render['dimension'][0], render_name)
continue continue
################# #################
@@ -532,23 +551,22 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
tileset_dir = os.path.abspath(os.path.join(destdir, render_name)) tileset_dir = os.path.abspath(os.path.join(destdir, render_name))
# only pass to the TileSet the options it really cares about # only pass to the TileSet the options it really cares about
render['name'] = render_name # perhaps a hack. This is stored here for the asset manager render['name'] = render_name # perhaps a hack. This is stored here for the asset manager
tileSetOpts = util.dict_subset(render, [ tileSetOpts = util.dict_subset(render, [
"name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom", "name", "imgformat", "renderchecks", "rerenderprob", "bgcolor", "defaultzoom",
"imgquality", "imglossless", "optimizeimg", "rendermode", "worldname_orig", "title", "imgquality", "imglossless", "optimizeimg", "rendermode", "worldname_orig", "title",
"dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom", "dimension", "changelist", "showspawn", "overlay", "base", "poititle", "maxzoom",
"showlocationmarker", "minzoom"]) "showlocationmarker", "minzoom"])
tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this tileSetOpts.update({"spawn": w.find_true_spawn()}) # TODO find a better way to do this
for rset in rsets: for rset in rsets:
tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir) tset = tileset.TileSet(w, rset, assetMrg, tex, tileSetOpts, tileset_dir)
tilesets.append(tset) tilesets.append(tset)
# If none of the requested dimenstions exist, tilesets will be empty # If none of the requested dimenstions exist, tilesets will be empty
if not tilesets: if not tilesets:
logging.error("There are no tilesets to render! There's nothing to do, so exiting.") logging.error("There are no tilesets to render! There's nothing to do, so exiting.")
return 1 return 1
# Do tileset preprocessing here, before we start dispatching jobs # Do tileset preprocessing here, before we start dispatching jobs
logging.info("Preprocessing...") logging.info("Preprocessing...")
for ts in tilesets: for ts in tilesets:
@@ -569,7 +587,7 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
assetMrg.finalize(tilesets) assetMrg.finalize(tilesets)
for out in changelists.itervalues(): for out in changelists.itervalues():
logging.debug("Closing %s (%s)", out, out.fileno()) logging.debug("Closing %s (%s).", out, out.fileno())
out.close() out.close()
if config['processes'] == 1: if config['processes'] == 1:
@@ -579,16 +597,17 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
if options.pid: if options.pid:
os.remove(options.pid) os.remove(options.pid)
logging.info("Your render has been written to '%s', open index.html to view it" % destdir) logging.info("Your render has been written to '%s', open index.html to view it." % destdir)
return 0 return 0
def list_worlds(): def list_worlds():
"Prints out a brief summary of saves found in the default directory" "Prints out a brief summary of saves found in the default directory"
print print
worlds = world.get_worlds() worlds = world.get_worlds()
if not worlds: if not worlds:
print('No world saves found in the usual place') print('No world saves found in the usual place.')
return return
print("Detected saves:") print("Detected saves:")
@@ -597,7 +616,7 @@ 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.iteritems()):
if isinstance(name, basestring) and name.startswith("World") and len(name) == 6: if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
try: try:
@@ -608,8 +627,7 @@ def list_worlds():
except ValueError: except ValueError:
pass pass
if info['LastPlayed'] > 0: if info['LastPlayed'] > 0:
timestamp = time.strftime("%Y-%m-%d %H:%M", timestamp = time.strftime("%Y-%m-%d %H:%M", time.localtime(info['LastPlayed'] / 1000))
time.localtime(info['LastPlayed'] / 1000))
else: else:
timestamp = "" timestamp = ""
if info['Time'] > 0: if info['Time'] > 0:
@@ -623,8 +641,9 @@ def list_worlds():
if found_corrupt: if found_corrupt:
print("") print("")
print("An error has been detected in one or more of your worlds (see the above table).") print("An error has been detected in one or more of your worlds (see the above table).")
print("This is usually due to a corrupt level.dat file. Corrupt worlds need to be") print("This is usually due to a corrupt level.dat file. Corrupt worlds need to be "
print("repaired before Overviewer can render them.") "repaired before Overviewer can render them.")
if __name__ == "__main__": if __name__ == "__main__":
multiprocessing.freeze_support() multiprocessing.freeze_support()