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 configParser, tileset, assetmanager, dispatcher
|
||||||
from overviewer_core import cache
|
from overviewer_core import cache
|
||||||
from overviewer_core import observer
|
from overviewer_core import observer
|
||||||
|
from overviewer_core.nbt import CorruptNBTError
|
||||||
|
|
||||||
helptext = """
|
helptext = """
|
||||||
%prog [--rendermodes=...] [options] <World> <Output Dir>
|
%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:
|
try:
|
||||||
w = worldcache[render['world']]
|
w = worldcache[render['world']]
|
||||||
except KeyError:
|
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
|
worldcache[render['world']] = w
|
||||||
|
|
||||||
# find or create the textures object
|
# find or create the textures object
|
||||||
@@ -595,10 +601,16 @@ def list_worlds():
|
|||||||
continue
|
continue
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
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))
|
time.localtime(info['LastPlayed'] / 1000))
|
||||||
playtime = info['Time'] / 20
|
else:
|
||||||
playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
|
timestamp = ""
|
||||||
|
if info['Time'] > 0:
|
||||||
|
playtime = info['Time'] / 20
|
||||||
|
playstamp = '%d:%02d' % (playtime / 3600, playtime / 60 % 60)
|
||||||
|
else:
|
||||||
|
playstamp = ""
|
||||||
path = info['path']
|
path = info['path']
|
||||||
print(formatString % (name, playstamp, timestamp, path))
|
print(formatString % (name, playstamp, timestamp, path))
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class NBTFileReader(object):
|
|||||||
payload = self._read_tag_compound()
|
payload = self._read_tag_compound()
|
||||||
|
|
||||||
return (name, payload)
|
return (name, payload)
|
||||||
except (struct.error, ValueError), e:
|
except (struct.error, ValueError, TypeError), e:
|
||||||
raise CorruptNBTError("could not parse nbt: %s" % (str(e),))
|
raise CorruptNBTError("could not parse nbt: %s" % (str(e),))
|
||||||
|
|
||||||
# For reference, the MCR format is outlined at
|
# For reference, the MCR format is outlined at
|
||||||
|
|||||||
@@ -792,9 +792,16 @@ def get_worlds():
|
|||||||
for dir in os.listdir("."):
|
for dir in os.listdir("."):
|
||||||
world_dat = os.path.join(dir, "level.dat")
|
world_dat = os.path.join(dir, "level.dat")
|
||||||
if not os.path.exists(world_dat): continue
|
if not os.path.exists(world_dat): continue
|
||||||
info = nbt.load(world_dat)[1]
|
world_path = os.path.join(".", dir)
|
||||||
info['Data']['path'] = os.path.join(".", dir).decode(loc)
|
try:
|
||||||
if 'LevelName' in info['Data'].keys():
|
info = nbt.load(world_dat)[1]
|
||||||
ret[info['Data']['LevelName']] = info['Data']
|
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
|
return ret
|
||||||
|
|||||||
Reference in New Issue
Block a user