From 07145bef3b1175bd327000373057ac0d098056a0 Mon Sep 17 00:00:00 2001 From: Ryan Hitchman Date: Tue, 21 Sep 2010 15:07:23 -0500 Subject: [PATCH] make it easier for the user to use a map in an expected location, show some information about found saves --- gmap.py | 34 +++++++++++++++++++++++++++++++--- world.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/gmap.py b/gmap.py index 7021daf..aa9c3b4 100755 --- a/gmap.py +++ b/gmap.py @@ -6,12 +6,13 @@ import os.path from optparse import OptionParser import re import multiprocessing +import time import world import quadtree helptext = """ -%prog [-p PROCS] [-d] +%prog [-p PROCS] [-d] """ def main(): @@ -27,18 +28,28 @@ def main(): options, args = parser.parse_args() if len(args) < 1: - print "You need to give me your world directory" + 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 len(args) != 2: parser.error("Where do you want to save the tiles?") destdir = args[1] if options.delete: return delete_all(worlddir, destdir) - # First generate the world's chunk images w = world.WorldRenderer(worlddir) w.go(options.procs) @@ -67,5 +78,22 @@ def delete_all(worlddir, tiledir): print "Deleting {0}".format(filepath) os.unlink(filepath) +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. / 1024.) + print "World %s: %s Playtime: %s Modified: %s" % (num, size, playstamp, timestamp) + + if __name__ == "__main__": main() diff --git a/world.py b/world.py index 9e32e1f..3866491 100644 --- a/world.py +++ b/world.py @@ -6,9 +6,11 @@ import multiprocessing from PIL import Image import chunk +import nbt """ This module has routines related to generating all the chunks for a world +and for extracting information about available worlds """ @@ -119,3 +121,35 @@ class WorldRenderer(object): return results +def get_save_dir(): + """Returns the path to the local saves directory + * On Windows, at %APPDATA%/.minecraft/saves/ + * On Darwin, at $HOME/Library/Application Support/minecraft/saves/ + * at $HOME/.minecraft/saves/ + + """ + + savepaths = [] + if "APPDATA" in os.environ: + savepaths += [os.path.join(os.environ['APPDATA'], ".minecraft", "saves")] + if "HOME" in os.environ: + savepaths += [os.path.join(os.environ['HOME'], "Library", + "Application Support", "minecraft", "saves")] + savepaths += [os.path.join(os.environ['HOME'], ".minecraft", "saves")] + + for path in savepaths: + if os.path.exists(path): + return path + +def get_worlds(): + "Returns {world # : level.dat information}" + ret = {} + save_dir = get_save_dir() + for dir in os.listdir(save_dir): + if dir.startswith("World"): + world_n = int(dir[-1]) + info = nbt.load(os.path.join(save_dir, dir, "level.dat"))[1] + info['Data']['path'] = os.path.join(save_dir, dir) + ret[world_n] = info['Data'] + + return ret