def list_worlds():
    "Prints out a brief summary of saves found in the default directory"
    print
    worlds = world.get_worlds()
    if not worlds:
        print 'No world saves found in the usual place'
        return
    print "Detected saves:"
    for name, info in sorted(worlds.iteritems()):
        if isinstance(
                name,
                basestring) and name.startswith("World") and len(name) == 6:
            try:
                world_n = int(name[-1])
                # we'll catch this one later, when it shows up as an
                # integer key
                continue
            except ValueError:
                pass
        timestamp = time.strftime("%Y-%m-%d %H:%M",
                                  time.localtime(info['LastPlayed'] / 1000))
        playtime = info['Time'] / 20
        playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
        size = "%.2fMB" % (info['SizeOnDisk'] / 1024. / 1024.)
        print "World %s: %s Playtime: %s Modified: %s" % (name, size,
                                                          playstamp, timestamp)
def list_worlds():
    "Prints out a brief summary of saves found in the default directory"
    print
    worlds = world.get_worlds()
    if not worlds:
        print "No world saves found in the usual place"
        return
    print "Detected saves:"
    for num, info in sorted(worlds.iteritems()):
        timestamp = time.strftime("%Y-%m-%d %H:%M", time.localtime(info["LastPlayed"] / 1000))
        playtime = info["Time"] / 20
        playstamp = "%d:%02d" % (playtime / 3600, playtime / 60 % 60)
        size = "%.2fMB" % (info["SizeOnDisk"] / 1024.0 / 1024.0)
        print "World %s: %s Playtime: %s Modified: %s" % (num, size, playstamp, timestamp)
def list_worlds():
    "Prints out a brief summary of saves found in the default directory"
    print
    worlds = world.get_worlds()
    if not worlds:
        print "No world saves found in the usual place"
        return
    print "Detected saves:"
    for name, info in sorted(worlds.iteritems()):
        if isinstance(name, basestring) and name.startswith("World") and len(name) == 6:
            try:
                world_n = int(name[-1])
                # we'll catch this one later, when it shows up as an
                # integer key
                continue
            except ValueError:
                pass
        timestamp = time.strftime("%Y-%m-%d %H:%M", time.localtime(info["LastPlayed"] / 1000))
        playtime = info["Time"] / 20
        playstamp = "%d:%02d" % (playtime / 3600, playtime / 60 % 60)
        size = "%.2fMB" % (info["SizeOnDisk"] / 1024.0 / 1024.0)
        print "World %s: %s Playtime: %s Modified: %s" % (name, size, playstamp, timestamp)
Exemple #4
0
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1
    parser = OptionParser(usage=helptext)
    parser.add_option("-p", "--processes", dest="procs", help="How many worker processes to start. Default %s" % cpus, default=cpus, action="store", type="int")
    parser.add_option("-z", "--zoom", dest="zoom", help="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles", action="store", type="int")
    parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true")
    parser.add_option("--cachedir", dest="cachedir", help="Sets the directory where the Overviewer will save chunk images, which is an intermediate step before the tiles are generated. You must use the same directory each time to gain any benefit from the cache. If not set, this defaults to your world directory.")
    parser.add_option("--chunklist", dest="chunklist", help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.")
    parser.add_option("--lighting", dest="lighting", help="Renders shadows using light data from each chunk.", action="store_true")
    parser.add_option("--night", dest="night", help="Renders shadows using light data from each chunk, as if it were night. Implies --lighting.", action="store_true")
    parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format.")
    parser.add_option("--optimize-img", dest="optimizeimg", help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%")
    parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0, help="Print less output. You can specify this option multiple times.")
    parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0, help="Print more output. You can specify this option multiple times.")
    parser.add_option("--skip-js", dest="skipjs", action="store_true", help="Don't output marker.js or regions.js")

    options, args = parser.parse_args()

    if len(args) < 1:
        print "You need to give me your world number or directory"
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        try:
            worldnum = int(worlddir)
            worlddir = world.get_worlds()[worldnum]['path']
        except (ValueError, KeyError):
            print "Invalid world number or directory"
            parser.print_help()
            sys.exit(1)

    if not options.cachedir:
        cachedir = worlddir
    else:
        cachedir = options.cachedir

    if len(args) != 2:
        if options.delete:
            return delete_all(cachedir, None)
        parser.error("Where do you want to save the tiles?")

    destdir = args[1]

    if options.delete:
        return delete_all(cachedir, destdir)

    if options.chunklist:
        chunklist = open(options.chunklist, 'r')
    else:
        chunklist = None

    if options.imgformat:
        if options.imgformat not in ('jpg','png'):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = 'png'

    if options.optimizeimg:
        optimizeimg = options.optimizeimg
    else:
        optimizeimg = None

    logging.getLogger().setLevel(
        logging.getLogger().level + 10*options.quiet)
    logging.getLogger().setLevel(
        logging.getLogger().level - 10*options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    
    useBiomeData = os.path.exists(os.path.join(worlddir, 'EXTRACTEDBIOMES'))
    if not useBiomeData:
        logging.info("Notice: Not using biome data for tinting")

    # First generate the world's chunk images
    w = world.WorldRenderer(worlddir, cachedir, chunklist=chunklist, lighting=options.lighting, night=options.night, useBiomeData=useBiomeData)
    w.go(options.procs)

    # Now generate the tiles
    q = quadtree.QuadtreeGen(w, destdir, depth=options.zoom, imgformat=imgformat, optimizeimg=optimizeimg)
    q.write_html(options.skipjs)
    q.go(options.procs)
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1

    avail_rendermodes = c_overviewer.get_render_modes()

    parser = ConfigOptionParser(usage=helptext, config="settings.py")
    parser.add_option(
        "-V", "--version", dest="version", help="Displays version information and then exits", action="store_true"
    )
    parser.add_option(
        "-p",
        "--processes",
        dest="procs",
        help="How many worker processes to start. Default %s" % cpus,
        default=cpus,
        action="store",
        type="int",
    )
    parser.add_option(
        "-z",
        "--zoom",
        dest="zoom",
        help="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles",
        action="store",
        type="int",
        configFileOnly=True,
    )
    parser.add_option(
        "-d",
        "--delete",
        dest="delete",
        help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.",
        action="store_true",
        commandLineOnly=True,
    )
    parser.add_option(
        "--chunklist",
        dest="chunklist",
        help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.",
    )
    parser.add_option(
        "--rendermodes",
        dest="rendermode",
        help="Specifies the render types, separated by commas. Use --list-rendermodes to list them all.",
        type="choice",
        choices=avail_rendermodes,
        required=True,
        default=avail_rendermodes[0],
        listify=True,
    )
    parser.add_option(
        "--list-rendermodes",
        dest="list_rendermodes",
        action="store_true",
        help="List available render modes and exit.",
        commandLineOnly=True,
    )
    parser.add_option(
        "--imgformat",
        dest="imgformat",
        help="The image output format to use. Currently supported: png(default), jpg.",
        configFileOnly=True,
    )
    parser.add_option(
        "--imgquality",
        dest="imgquality",
        default=95,
        help='Specify the quality of image output when using imgformat="jpg".',
        type="int",
        configFileOnly=True,
    )
    parser.add_option(
        "--bg_color",
        dest="bg_color",
        help="Configures the background color for the GoogleMap output.  Specify in #RRGGBB format",
        configFileOnly=True,
        type="string",
        default="#1A1A1A",
    )
    parser.add_option(
        "--optimize-img",
        dest="optimizeimg",
        help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%",
        configFileOnly=True,
    )
    parser.add_option(
        "--web-assets-hook",
        dest="web_assets_hook",
        help="If provided, run this function after the web assets have been copied, but before actual tile rendering begins. It should accept a QuadtreeGen object as its only argument.",
        action="store",
        metavar="SCRIPT",
        type="function",
        configFileOnly=True,
    )
    parser.add_option(
        "--web-assets-path",
        dest="web_assets_path",
        help="Specifies a non-standard web_assets directory to use. Files here will overwrite the default web assets.",
        metavar="PATH",
        type="string",
        configFileOnly=True,
    )
    parser.add_option(
        "--textures-path",
        dest="textures_path",
        help="Specifies a non-standard textures path, from which terrain.png and other textures are loaded.",
        metavar="PATH",
        type="string",
        configFileOnly=True,
    )
    parser.add_option(
        "-q",
        "--quiet",
        dest="quiet",
        action="count",
        default=0,
        help="Print less output. You can specify this option multiple times.",
    )
    parser.add_option(
        "-v",
        "--verbose",
        dest="verbose",
        action="count",
        default=0,
        help="Print more output. You can specify this option multiple times.",
    )
    parser.add_option("--skip-js", dest="skipjs", action="store_true", help="Don't output marker.js or regions.js")
    parser.add_option(
        "--display-config",
        dest="display_config",
        action="store_true",
        help="Display the configuration parameters, but don't render the map.  Requires all required options to be specified",
        commandLineOnly=True,
    )
    # parser.add_option("--write-config", dest="write_config", action="store_true", help="Writes out a sample config file", commandLineOnly=True)

    options, args = parser.parse_args()

    if options.version:
        print "Minecraft-Overviewer"
        print "Git version: %s" % util.findGitVersion()
        try:
            import overviewer_version

            if hasattr(sys, "frozen"):
                print "py2exe version build on %s" % overviewer_version.BUILD_DATE
                print "Build machine: %s %s" % (overviewer_version.BUILD_PLATFORM, overviewer_version.BUILD_OS)
        except:
            pass
        sys.exit(0)

    if options.list_rendermodes:
        rendermode_info = map(c_overviewer.get_render_mode_info, avail_rendermodes)
        name_width = max(map(lambda i: len(i["name"]), rendermode_info))
        for info in rendermode_info:
            print "{name:{0}} {description}".format(name_width, **info)
        sys.exit(0)

    if len(args) < 1:
        logging.error("You need to give me your world number or directory")
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        # world given is either world number, or name
        worlds = world.get_worlds()

        # if there are no worlds found at all, exit now
        if not worlds:
            parser.print_help()
            logging.error("Invalid world path")
            sys.exit(1)

        try:
            worldnum = int(worlddir)
            worlddir = worlds[worldnum]["path"]
        except ValueError:
            # it wasn't a number or path, try using it as a name
            try:
                worlddir = worlds[worlddir]["path"]
            except KeyError:
                # it's not a number, name, or path
                parser.print_help()
                logging.error("Invalid world name or path")
                sys.exit(1)
        except KeyError:
            # it was an invalid number
            parser.print_help()
            logging.error("Invalid world number")
            sys.exit(1)

    if len(args) < 2:
        if options.delete:
            return delete_all(worlddir, None)
        logging.error("Where do you want to save the tiles?")
        sys.exit(1)
    elif len(args) > 2:
        if options.delete:
            return delete_all(worlddir, None)
        parser.print_help()
        logging.error("Sorry, you specified too many arguments")
        sys.exit(1)

    destdir = args[1]
    if options.display_config:
        # just display the config file and exit
        parser.display_config()
        sys.exit(0)

    if options.delete:
        return delete_all(worlddir, destdir)

    if options.chunklist:
        chunklist = open(options.chunklist, "r")
    else:
        chunklist = None

    if options.imgformat:
        if options.imgformat not in ("jpg", "png"):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = "png"

    if options.optimizeimg:
        optimizeimg = int(options.optimizeimg)
        optimizeimages.check_programs(optimizeimg)
    else:
        optimizeimg = None

    logging.getLogger().setLevel(logging.getLogger().level + 10 * options.quiet)
    logging.getLogger().setLevel(logging.getLogger().level - 10 * options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    useBiomeData = os.path.exists(os.path.join(worlddir, "biomes"))
    if not useBiomeData:
        logging.info("Notice: Not using biome data for tinting")

    # First do world-level preprocessing
    w = world.World(worlddir, useBiomeData=useBiomeData)
    w.go(options.procs)

    logging.info("Rending the following tilesets: %s", ",".join(options.rendermode))

    bgcolor = (int(options.bg_color[1:3], 16), int(options.bg_color[3:5], 16), int(options.bg_color[5:7], 16), 0)

    # create the quadtrees
    # TODO chunklist
    q = []
    qtree_args = {
        "depth": options.zoom,
        "imgformat": imgformat,
        "imgquality": options.imgquality,
        "optimizeimg": optimizeimg,
        "bgcolor": bgcolor,
    }
    for rendermode in options.rendermode:
        if rendermode == "normal":
            qtree = quadtree.QuadtreeGen(w, destdir, rendermode=rendermode, tiledir="tiles", **qtree_args)
        else:
            qtree = quadtree.QuadtreeGen(w, destdir, rendermode=rendermode, **qtree_args)
        q.append(qtree)

    # do quadtree-level preprocessing
    for qtree in q:
        qtree.go(options.procs)

    # create the distributed render
    r = rendernode.RenderNode(q, options)

    # write out the map and web assets
    m = googlemap.MapGen(q, configInfo=options)
    m.go(options.procs)

    # render the tiles!
    r.go(options.procs)

    # finish up the map
    m.finalize()
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1
    parser = OptionParser(usage=helptext)
    parser.add_option("-p",
                      "--processes",
                      dest="procs",
                      help="How many worker processes to start. Default %s" %
                      cpus,
                      default=cpus,
                      action="store",
                      type="int")
    parser.add_option(
        "-z",
        "--zoom",
        dest="zoom",
        help=
        "Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles",
        action="store",
        type="int")
    parser.add_option(
        "-d",
        "--delete",
        dest="delete",
        help=
        "Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.",
        action="store_true")
    parser.add_option(
        "--cachedir",
        dest="cachedir",
        help=
        "Sets the directory where the Overviewer will save chunk images, which is an intermediate step before the tiles are generated. You must use the same directory each time to gain any benefit from the cache. If not set, this defaults to your world directory."
    )
    parser.add_option(
        "--chunklist",
        dest="chunklist",
        help=
        "A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply."
    )
    parser.add_option("--lighting",
                      dest="lighting",
                      help="Renders shadows using light data from each chunk.",
                      action="store_true")
    parser.add_option(
        "--night",
        dest="night",
        help=
        "Renders shadows using light data from each chunk, as if it were night. Implies --lighting.",
        action="store_true")
    parser.add_option(
        "--spawn",
        dest="spawn",
        help=
        "Renders shadows using light data from each chunk, as if it were night, while also highlighting areas that are dark enough to spawn mobs. Implies --lighting and --night.",
        action="store_true")
    parser.add_option(
        "--imgformat",
        dest="imgformat",
        help=
        "The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format."
    )
    parser.add_option(
        "--optimize-img",
        dest="optimizeimg",
        help=
        "If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%"
    )
    parser.add_option(
        "-q",
        "--quiet",
        dest="quiet",
        action="count",
        default=0,
        help="Print less output. You can specify this option multiple times.")
    parser.add_option(
        "-v",
        "--verbose",
        dest="verbose",
        action="count",
        default=0,
        help="Print more output. You can specify this option multiple times.")
    parser.add_option("--skip-js",
                      dest="skipjs",
                      action="store_true",
                      help="Don't output marker.js or regions.js")

    options, args = parser.parse_args()

    if len(args) < 1:
        print "You need to give me your world number or directory"
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        # world given is either world number, or name
        worlds = world.get_worlds()

        # if there are no worlds found at all, exit now
        if not worlds:
            parser.print_help()
            print "\nInvalid world path"
            sys.exit(1)

        try:
            worldnum = int(worlddir)
            worlddir = worlds[worldnum]['path']
        except ValueError:
            # it wasn't a number or path, try using it as a name
            try:
                worlddir = worlds[worlddir]['path']
            except KeyError:
                # it's not a number, name, or path
                parser.print_help()
                print "Invalid world name or path"
                sys.exit(1)
        except KeyError:
            # it was an invalid number
            parser.print_help()
            print "Invalid world number"
            sys.exit(1)

    if not options.cachedir:
        cachedir = worlddir
    else:
        cachedir = options.cachedir

    if len(args) != 2:
        if options.delete:
            return delete_all(cachedir, None)
        parser.error("Where do you want to save the tiles?")

    destdir = args[1]

    if options.delete:
        return delete_all(cachedir, destdir)

    if options.chunklist:
        chunklist = open(options.chunklist, 'r')
    else:
        chunklist = None

    if options.imgformat:
        if options.imgformat not in ('jpg', 'png'):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = 'png'

    if options.optimizeimg:
        optimizeimg = int(options.optimizeimg)
        optimizeimages.check_programs(optimizeimg)
    else:
        optimizeimg = None

    logging.getLogger().setLevel(logging.getLogger().level +
                                 10 * options.quiet)
    logging.getLogger().setLevel(logging.getLogger().level -
                                 10 * options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    if not composite.extension_alpha_over:
        logging.info(
            "Notice: alpha_over extension not found; using default PIL paste()"
        )

    useBiomeData = os.path.exists(os.path.join(worlddir, 'biomes'))
    if not useBiomeData:
        logging.info("Notice: Not using biome data for tinting")

    # First generate the world's chunk images
    w = world.WorldRenderer(worlddir,
                            cachedir,
                            chunklist=chunklist,
                            lighting=options.lighting,
                            night=options.night,
                            spawn=options.spawn,
                            useBiomeData=useBiomeData)

    w.go(options.procs)

    # Now generate the tiles
    q = quadtree.QuadtreeGen(w,
                             destdir,
                             depth=options.zoom,
                             imgformat=imgformat,
                             optimizeimg=optimizeimg)
    q.write_html(options.skipjs)
    q.go(options.procs)
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1
    parser = OptionParser(usage=helptext)
    parser.add_option("-p", "--processes", dest="procs", help="How many worker processes to start. Default %s" % cpus, default=cpus, action="store", type="int")
    parser.add_option("-z", "--zoom", dest="zoom", help="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles", action="store", type="int")
    parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true")
    parser.add_option("--cachedir", dest="cachedir", help="Sets the directory where the Overviewer will save chunk images, which is an intermediate step before the tiles are generated. You must use the same directory each time to gain any benefit from the cache. If not set, this defaults to your world directory.")
    parser.add_option("--queuedir", dest="queuedir", help="Sets the directory where the Overviewer will load the chunk queue from")
    parser.add_option("--all-branches", dest="allbranches", help="Renders all three lighting branches", action="store_true")
    parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format.")
    parser.add_option("--optimize-img", dest="optimizeimg", help="If using png, perform image file size optimizations on the output. Specify 1 for pngcrush, 2 for pngcrush+optipng+advdef. This may double (or more) render times, but will produce up to 30% smaller images. NOTE: requires corresponding programs in $PATH or %PATH%")
    parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0, help="Print less output. You can specify this option multiple times.")
    parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0, help="Print more output. You can specify this option multiple times.")
    
    options, args = parser.parse_args()

    if len(args) < 1:
        print "You need to give me your world number or directory"
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        try:
            worldnum = int(worlddir)
            worlddir = world.get_worlds()[worldnum]['path']
        except (ValueError, KeyError):
            print "Invalid world number or directory"
            parser.print_help()
            sys.exit(1)

    if not options.cachedir:
        cachedir = worlddir
    else:
        cachedir = options.cachedir

    if not options.queuedir:
        queuedir = cachedir
    else:
        queuedir = options.queuedir
        
        
    if len(args) != 2:
        if options.delete:
            return delete_all(cachedir, None)
        parser.error("Where do you want to save the tiles?")

    destdir = args[1]

    if options.delete:
        return delete_all(cachedir, destdir)

    if options.imgformat:
        if options.imgformat not in ('jpg','png'):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = 'png'

    if options.optimizeimg:
        optimizeimg = options.optimizeimg
    else:
        optimizeimg = None

    
    
    logging.getLogger().setLevel(logging.getLogger().level + 10*options.quiet)
    logging.getLogger().setLevel(logging.getLogger().level - 10*options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    # Load the full world queue from disk, or generate if its the first time
    w = world.WorldRenderer(worlddir, cachedir, allbranches=options.allbranches)
    w.renderChunkset(options.procs, True) #!TODO!Make initial render optional (ie fill blank tiles)
    #!TODO!render spawn initially
    
    # Generate the initial tiles
    q = quadtree.QuadtreeGen(w, destdir, depth=options.zoom, imgformat=imgformat, optimizeimg=optimizeimg)
    q.write_html(worlddir=worlddir) #!TODO!Clean up this function
    q.renderChunkset(options.procs)
    
    # Load the standard and priority queues from disk if they exist
    #w.loadQueues(params)
    
    # Start a thread to populate input queue from file contents and process
    #startInputQueue(w)
    
    # Loop to render chunks pulled from first available location
    keepgoing = True
    while keepgoing:
        chunkset = None
        # Check for standard queue
        queuefile = os.path.join(queuedir,'queue')
        if os.path.exists(queuefile):
            chunklist = open(queuefile, 'r')
            os.unlink(queuefile)
            chunkset = world.get_chunk_renderset(chunklist)
        # Check for world queue
        else:
            chunkset = w.getQueueTop(number=50)
        
        if chunkset:
            # Render chunks to cache
            w.renderChunkset(options.procs, False, chunkset=chunkset)
        
            # Just need to set q.chunkset to (col,row) of chunks from queue
            q.renderChunkset(options.procs, chunkset)
            q.write_html(worlddir=worlddir,onlyindex=True)
def main():
    try:
        cpus = multiprocessing.cpu_count()
    except NotImplementedError:
        cpus = 1
    parser = OptionParser(usage=helptext)
    parser.add_option("-p", "--processes", dest="procs", help="How many worker processes to start. Default %s" % cpus, default=cpus, action="store", type="int")
    parser.add_option("-z", "--zoom", dest="zoom", help="Sets the zoom level manually instead of calculating it. This can be useful if you have outlier chunks that make your world too big. This value will make the highest zoom level contain (2**ZOOM)^2 tiles", action="store", type="int")
    parser.add_option("-d", "--delete", dest="delete", help="Clear all caches. Next time you render your world, it will have to start completely over again. This is probably not a good idea for large worlds. Use this if you change texture packs and want to re-render everything.", action="store_true")
    parser.add_option("--cachedir", dest="cachedir", help="Sets the directory where the Overviewer will save chunk images, which is an intermediate step before the tiles are generated. You must use the same directory each time to gain any benefit from the cache. If not set, this defaults to your world directory.")
    parser.add_option("--chunklist", dest="chunklist", help="A file containing, on each line, a path to a chunkfile to update. Instead of scanning the world directory for chunks, it will just use this list. Normal caching rules still apply.")
    parser.add_option("--imgformat", dest="imgformat", help="The image output format to use. Currently supported: png(default), jpg. NOTE: png will always be used as the intermediate image format.")
    parser.add_option("-q", "--quiet", dest="quiet", action="count", default=0, help="Print less output. You can specify this option multiple times.")
    parser.add_option("-v", "--verbose", dest="verbose", action="count", default=0, help="Print more output. You can specify this option multiple times.")

    options, args = parser.parse_args()

    if len(args) < 1:
        print "You need to give me your world number or directory"
        parser.print_help()
        list_worlds()
        sys.exit(1)
    worlddir = args[0]

    if not os.path.exists(worlddir):
        try:
            worldnum = int(worlddir)
            worlddir = world.get_worlds()[worldnum]['path']
        except (ValueError, KeyError):
            print "Invalid world number or directory"
            parser.print_help()
            sys.exit(1)

    if not options.cachedir:
        cachedir = worlddir
    else:
        cachedir = options.cachedir

    if len(args) != 2:
        if options.delete:
            return delete_all(cachedir, None)
        parser.error("Where do you want to save the tiles?")

    destdir = args[1]

    if options.delete:
        return delete_all(cachedir, destdir)

    if options.chunklist:
        chunklist = open(options.chunklist, 'r')
    else:
        chunklist = None

    if options.imgformat:
        if options.imgformat not in ('jpg','png'):
            parser.error("Unknown imgformat!")
        else:
            imgformat = options.imgformat
    else:
        imgformat = 'png'

    logging.getLogger().setLevel(
        logging.getLogger().level + 10*options.quiet)
    logging.getLogger().setLevel(
        logging.getLogger().level - 10*options.verbose)

    logging.info("Welcome to Minecraft Overviewer!")
    logging.debug("Current log level: {0}".format(logging.getLogger().level))

    # First generate the world's chunk images
    w = world.WorldRenderer(worlddir, cachedir, chunklist=chunklist)
    w.go(options.procs)

    # Now generate the tiles
    q = quadtree.QuadtreeGen(w, destdir, depth=options.zoom, imgformat=imgformat)
    q.go(options.procs)
def main():
    parser = OptionParser(usage=usage, description=description)
    parser.add_option("-d", "--dry-run", dest="dry", action="store_true",
                      help="Don't actually delete anything. Best used with -v.")
    parser.add_option("-k", "--keep-dirs", dest="keep", action="store_true",
                      help="Keep the world directories intact, even if they are empty.")
    parser.add_option("-v", "--verbose", dest="verbose", action="store_true",
                      help="Log each and every file that is deleted.")
    
    opt, args = parser.parse_args()
    
    if not len(args) == 1:
        parser.print_help()
        sys.exit(1)
        
    worlddir = args[0]

    if not os.path.exists(worlddir):
        # world given is either world number, or name
        worlds = world.get_worlds()
        
        # if there are no worlds found at all, exit now
        if not worlds:
            parser.print_help()
            print "\nInvalid world path"
            sys.exit(1)
        
        try:
            worldnum = int(worlddir)
            worlddir = worlds[worldnum]['path']
        except ValueError:
            # it wasn't a number or path, try using it as a name
            try:
                worlddir = worlds[worlddir]['path']
            except KeyError:
                # it's not a number, name, or path
                parser.print_help()
                print "Invalid world name or path"
                sys.exit(1)
        except KeyError:
            # it was an invalid number
            parser.print_help()
            print "Invalid world number"
            sys.exit(1)
    
    files_deleted = 0
    dirs_deleted = 0
    
    imgre = re.compile(r'img\.[^.]+\.[^.]+\.nocave\.\w+\.png$')
    for dirpath, dirnames, filenames in os.walk(worlddir, topdown=False):
        for f in filenames:
            if imgre.match(f):
                filepath = os.path.join(dirpath, f)
                if opt.verbose:
                    print "Deleting %s" % (filepath,)
                if not opt.dry:
                    os.unlink(filepath)
                    files_deleted += 1
        
        if not opt.keep:
            if len(os.listdir(dirpath)) == 0:
                if opt.verbose:
                    print "Deleting %s" % (dirpath,)
                if not opt.dry:
                    os.rmdir(dirpath)
                    dirs_deleted += 1
    
    print "%i files and %i directories deleted." % (files_deleted, dirs_deleted)