Better error handling of errors when a world fails to open.
A common case is a corrupt (or empty) level.dat file. This condition wasn't properly caught, yielding a less-than-useful stack trace. Even more concerning is that this could happen when a user is just running "overviewer.py" to get a world listing. This has been fixed to improve the user experience
This commit is contained in:
@@ -41,6 +41,7 @@ from overviewer_core import optimizeimages, world
|
||||
from overviewer_core import configParser, tileset, assetmanager, dispatcher
|
||||
from overviewer_core import cache
|
||||
from overviewer_core import observer
|
||||
from overviewer_core.nbt import CorruptNBTError
|
||||
|
||||
helptext = """
|
||||
%prog [--rendermodes=...] [options] <World> <Output Dir>
|
||||
@@ -466,7 +467,12 @@ dir but you forgot to put quotes around the directory, since it contains spaces.
|
||||
try:
|
||||
w = worldcache[render['world']]
|
||||
except KeyError:
|
||||
w = world.World(render['world'])
|
||||
try:
|
||||
w = world.World(render['world'])
|
||||
except CorruptNBTError, e:
|
||||
logging.error("Failed to open world %r", render['world'])
|
||||
raise e
|
||||
|
||||
worldcache[render['world']] = w
|
||||
|
||||
# find or create the textures object
|
||||
@@ -595,10 +601,16 @@ def list_worlds():
|
||||
continue
|
||||
except ValueError:
|
||||
pass
|
||||
timestamp = time.strftime("%Y-%m-%d %H:%M",
|
||||
if info['LastPlayed'] > 0:
|
||||
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)
|
||||
else:
|
||||
timestamp = ""
|
||||
if info['Time'] > 0:
|
||||
playtime = info['Time'] / 20
|
||||
playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
|
||||
else:
|
||||
playstamp = ""
|
||||
path = info['path']
|
||||
print(formatString % (name, playstamp, timestamp, path))
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ class NBTFileReader(object):
|
||||
payload = self._read_tag_compound()
|
||||
|
||||
return (name, payload)
|
||||
except (struct.error, ValueError), e:
|
||||
except (struct.error, ValueError, TypeError), e:
|
||||
raise CorruptNBTError("could not parse nbt: %s" % (str(e),))
|
||||
|
||||
# For reference, the MCR format is outlined at
|
||||
|
||||
@@ -792,9 +792,16 @@ def get_worlds():
|
||||
for dir in os.listdir("."):
|
||||
world_dat = os.path.join(dir, "level.dat")
|
||||
if not os.path.exists(world_dat): continue
|
||||
info = nbt.load(world_dat)[1]
|
||||
info['Data']['path'] = os.path.join(".", dir).decode(loc)
|
||||
if 'LevelName' in info['Data'].keys():
|
||||
ret[info['Data']['LevelName']] = info['Data']
|
||||
world_path = os.path.join(".", dir)
|
||||
try:
|
||||
info = nbt.load(world_dat)[1]
|
||||
info['Data']['path'] = world_path.decode(loc)
|
||||
if 'LevelName' in info['Data'].keys():
|
||||
ret[info['Data']['LevelName']] = info['Data']
|
||||
except nbt.CorruptNBTError:
|
||||
ret[os.path.basename(world_path).decode(loc) + " (corrupt)"] = {'path': world_path.decode(loc),
|
||||
'LastPlayed': 0,
|
||||
'Time': 0,
|
||||
'IsCorrupt': True}
|
||||
|
||||
return ret
|
||||
|
||||
Reference in New Issue
Block a user