0

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:
Andrew Chin
2016-12-19 10:50:01 -05:00
parent b81661dc94
commit 3938d1889c
3 changed files with 28 additions and 9 deletions

View File

@@ -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))

View File

@@ -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

View File

@@ -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