Skip to content

Instantly share code, notes, and snippets.

@fernferret
Created November 30, 2011 02:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fernferret/1407699 to your computer and use it in GitHub Desktop.
Save fernferret/1407699 to your computer and use it in GitHub Desktop.
This file can fix (or break) Worlds that won't load in Minecraft
#!/usr/bin/python
"""A small nbt fixer for bukkit multiworld worlds.
A problem has been identified that when a world (that's not imported by the minecraft server) tries to be imported by bukkit, the server hangs.
The issue is that for some reason, having rain and thunder both set to 1 causes the hang. This utility will set these to default for you.
That's seriously all it does, and if you're on Windows you may prefer to use a GUI editor.
I was too lazy to install mono and NEINedit didn't save the files for me. So...
This class requires you have the NBT Python Library. To run it:
1 Download (or clone) NBT for Python: https://github.com/twoolie/NBT
2 Place this file inside the unzipped directory. It should sit at the same level as the README
3 cd to this directory in a terminal and run: ./fixnbt.py -w /path/to/the/broken/level.dat
4 Done! By default this script backs up your level.dat
If you want to see all the help simply use:
./fixnbt.py -h
Cheers!
Special thanks to MidnightLightning and Fenixin for the awesome python lib! You guys rock!
--FernFerret
a Multiverse 2 Dev
"""
import nbt.nbt
import sys, optparse
class NBTFixer(object):
"""This class is specifically targeted at setting weather and rain.
You could potentially update it for other functions, but really this is a quick fix tool.
"""
def __init__(self, filename, backup = True, makeChanges = False):
self.nbtfile = nbt.NBTFile(filename,'rb')
print "Backing up NBT..."
def show_file(self):
print self.nbtfile.pretty_tree()
def write_file(self, backup = True):
if backup:
self.nbtfile.write_file(name + "_backup")
else:
self.nbtfile.write_file()
def set_thunder(self, value):
try:
print "Thundering: " + str(self.nbtfile["Data"]["thundering"])
if value == 0 or value == 1:
self.nbtfile["Data"]["thundering"].value = value
return True
except:
print "This is NOT a level.dat file :("
return False
def set_rain(self, value):
try:
print "Raining: " + str(self.nbtfile["Data"]["raining"])
if value == 0 or value == 1:
self.nbtfile["Data"]["raining"].value = value
return True
except:
print "This is NOT a level.dat file 2 :("
return False
def set_value(self, key, value):
try:
self.nbtfile['Data'][key].value = value
except:
print "oops... I couldn't set that :("
return False
if __name__ == "__main__":
op = optparse.OptionParser()
op.add_option("-w", "--write", action="store_true", default=False, help="Actually write changes to the NBT file, don't just print.")
op.add_option("-b", "--backup", action="store_true", default=False, help="Create a backup in the same folder called {nbtname.nbt}_backup")
op.add_option("-d", "--disp", action="store_true", default=False, help="Display the NBT and quit.")
op.add_option("--breakit", action="store_true", default=False, help="Attempts to 'break' a world. This sets the rain and thunder to 1.")
(options, args) = op.parse_args()
if len(args) > 0:
name = args[0]
else:
name = raw_input("Where is the level.dat file located?\n")
fixer = NBTFixer(name)
if options.disp:
fixer.show_file()
sys.exit(0)
if options.backup:
print "Writing backup..."
fixer.write_file(True)
value = 0
if options.breakit:
value = 1
print "Setting them to: ", value
fixer.set_thunder(value)
fixer.set_rain(value)
if options.write:
print "Writing file..."
fixer.write_file(False)
else:
print "NOT writing to file. Add the --write flag. Use --help for help."
@fernferret
Copy link
Author

This does not have a lot of error checking as it's just meant to help solve a temp problem.

Here's a sample run:

[688] [fernferret@~/nbt] % ls
CONTRIBUTORS.txt PKG-INFO         bigtest.nbt      examples         fixnbt.pyc       setup.py
LICENSE.txt      README.txt       doc              fixnbt.py        nbt              tests.py
[689] [fernferret@~/nbt] % ./fixnbt.py /Users/fernferret/Documents/minecraftdev/TestServers/WorldCorrupt/world_suk/level.dat
Backing up NBT...
Setting them to:  0
Thundering: 1
Raining: 1
NOT writing to file. Add the --write flag. Use --help for help.
[690] [fernferret@~/nbt] % ./fixnbt.py /Users/fernferret/Documents/minecraftdev/TestServers/WorldCorrupt/world_suk/level.dat -w
Backing up NBT...
Setting them to:  0
Thundering: 1
Raining: 1
Writing file...
[691] [fernferret@~/nbt] % ./fixnbt.py /Users/fernferret/Documents/minecraftdev/TestServers/WorldCorrupt/world_suk/level.dat   
Backing up NBT...
Setting them to:  0
Thundering: 0
Raining: 0
NOT writing to file. Add the --write flag. Use --help for help.
[692] [fernferret@~/nbt] % ./fixnbt.py /Users/fernferret/Documents/minecraftdev/TestServers/WorldCorrupt/world_suk/level.dat -d
Backing up NBT...
TAG_Compound: 1 Entries
{
    TAG_Compound("Data"): 16 Entries
    {
        TAG_Byte("thundering"): 0
        TAG_Long("LastPlayed"): 1322292776998
        TAG_Long("RandomSeed"): -1623774494
        TAG_Int("GameType"): 0
        TAG_Byte("MapFeatures"): 1
        TAG_Int("version"): 19132
        TAG_Long("Time"): 31566352
        TAG_Byte("raining"): 0
        TAG_Int("thunderTime"): 5522
        TAG_Int("SpawnX"): -2
        TAG_Byte("hardcore"): 0
        TAG_Int("SpawnY"): 69
        TAG_Int("SpawnZ"): 0
        TAG_String("LevelName"): world_suk
        TAG_Long("SizeOnDisk"): 6369280
        TAG_Int("rainTime"): 13572
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment