put everything through pydev's code auto-formatter

This commit is contained in:
David Vierra 2011-07-23 21:59:18 -10:00
parent 6b9e82c2e4
commit 225f813d28
12 changed files with 1228 additions and 1227 deletions

View File

@ -35,7 +35,7 @@ class Torch:
alphaMaterials.RedstoneTorchOn.ID,
alphaMaterials.RedstoneTorchOff.ID,
]
South = 1
North = 2
West = 3
@ -45,7 +45,7 @@ genericFlipRotation(Torch)
class Ladder:
blocktypes = [alphaMaterials.Ladder.ID]
East = 2
West = 3
North = 4
@ -57,7 +57,7 @@ class Stair:
alphaMaterials.WoodenStairs.ID,
alphaMaterials.StoneStairs.ID,
]
South = 0
North = 1
West = 2
@ -66,13 +66,13 @@ genericFlipRotation(Stair)
class WallSign:
blocktypes = [alphaMaterials.WallSign.ID]
East = 2
West = 3
North = 4
South = 5
genericFlipRotation(WallSign)
class Furnace:
blocktypes = [
alphaMaterials.Furnace.ID,
@ -87,15 +87,15 @@ genericFlipRotation(Furnace)
class Dispenser(Furnace):
blocktypes = [
alphaMaterials.Dispenser.ID,
]
]
genericFlipRotation(Dispenser)
class Pumpkin:
blocktypes = [
alphaMaterials.Pumpkin.ID,
alphaMaterials.JackOLantern.ID,
]
East = 0
South = 1
West = 2
@ -104,14 +104,14 @@ genericFlipRotation(Pumpkin)
class Rail:
blocktypes = [alphaMaterials.Rail.ID]
EastWest = 0
NorthSouth = 1
South = 2
North = 3
East = 4
West = 5
Northeast = 6
Southeast = 7
Southwest = 8
@ -143,7 +143,7 @@ def applyBit8(array):
def applyBit4(array):
array[4:8] = array[0:4] | 0x4
array[12:16] = array[8:12] | 0x4
applyThrownBit = applyBit8
class PoweredDetectorRail(Rail):
@ -161,7 +161,7 @@ applyThrownBit(PoweredDetectorRail.flipEastWest)
applyThrownBit(PoweredDetectorRail.flipNorthSouth)
rotationClasses.append(PoweredDetectorRail)
class Lever:
blocktypes = [alphaMaterials.Lever.ID]
ThrownBit = 0x8
@ -199,11 +199,11 @@ rotationClasses.append(Button)
class SignPost:
blocktypes = [alphaMaterials.Sign.ID]
#west is 0, increasing clockwise
rotateLeft = arange(16, dtype='uint8')
rotateLeft -= 4
rotateLeft &= 0xf
flipEastWest = arange(16, dtype='uint8')
flipNorthSouth = arange(16, dtype='uint8')
pass
@ -217,14 +217,14 @@ class Door:
]
TopHalfBit = 0x8
SwungCCWBit = 0x4
Northeast = 0
Southeast = 1
Southwest = 2
Northwest = 3
rotateLeft = arange(16, dtype='uint8')
Door.rotateLeft[Door.Northeast] = Door.Northwest
Door.rotateLeft[Door.Southeast] = Door.Northeast
Door.rotateLeft[Door.Southwest] = Door.Southeast
@ -260,14 +260,14 @@ class RedstoneRepeater:
blocktypes = [
alphaMaterials.RedstoneRepeaterOff.ID,
alphaMaterials.RedstoneRepeaterOn.ID,
]
East = 0
South = 1
West = 2
North = 3
genericFlipRotation(RedstoneRepeater)
#high bits of the repeater indicate repeater delay, and should be preserved
@ -285,7 +285,7 @@ applyOpenedBit = applyBit4
class Trapdoor:
blocktypes = [alphaMaterials.Trapdoor.ID]
West = 0
East = 1
South = 2
@ -299,7 +299,7 @@ applyOpenedBit(Trapdoor.flipNorthSouth)
applyPistonBit = applyBit8
class PistonBody:
blocktypes = [alphaMaterials.StickyPiston.ID, alphaMaterials.Piston.ID]
East = 2
West = 3
North = 4
@ -308,36 +308,36 @@ genericFlipRotation(PistonBody)
applyPistonBit(PistonBody.rotateLeft)
applyPistonBit(PistonBody.flipEastWest)
applyPistonBit(PistonBody.flipNorthSouth)
class PistonHead(PistonBody):
blocktypes = [alphaMaterials.PistonHead.ID]
rotationClasses.append(PistonHead)
rotationClasses.append(PistonHead)
def masterRotationTable(rotationFunc):
# compute a 256x16 table mapping each possible blocktype/data combination to
# the resulting data when the block is rotated
table = zeros( (256, 16), dtype='uint8')
table = zeros((256, 16), dtype='uint8')
table[:] = arange(16, dtype='uint8')
for cls in rotationClasses:
for blocktype in cls.blocktypes:
table[blocktype] = rotationFunc(cls)
return table
return table
class BlockRotation:
rotateLeft = masterRotationTable(lambda cls:cls.rotateLeft);
flipEastWest = masterRotationTable(lambda cls:cls.flipEastWest);
flipNorthSouth = masterRotationTable(lambda cls:cls.flipNorthSouth);
def FlipNorthSouth(blocks, data):
data[:] = BlockRotation.flipNorthSouth[blocks, data]
def FlipEastWest(blocks, data):
data[:] = BlockRotation.flipEastWest[blocks, data]
def RotateLeft(blocks, data):
data[:] = BlockRotation.rotateLeft[blocks, data]

View File

@ -11,7 +11,7 @@ class TileEntity(object):
@classmethod
def pos(cls, tag):
return [tag[a].value for a in 'xyz']
@classmethod
def setpos(cls, tag, pos):
for a, p in zip('xyz', pos):
@ -23,21 +23,21 @@ class Entity(object):
if "Pos" not in tag:
print tag
return [a.value for a in tag["Pos"]]
@classmethod
def setpos(cls, tag, pos):
tag["Pos"] = TAG_List([TAG_Int(p) for p in pos])
@classmethod
def copyWithOffset(cls, entity, copyOffset):
def copyWithOffset(cls, entity, copyOffset):
eTag = deepcopy(entity)
positionTags = map(lambda p, co: nbt.TAG_Double(p.value+co), eTag["Pos"], copyOffset)
positionTags = map(lambda p, co: nbt.TAG_Double(p.value + co), eTag["Pos"], copyOffset)
eTag["Pos"] = TAG_List(positionTags)
if eTag["id"].value == "Painting":
eTag["TileX"].value += copyOffset[0]
eTag["TileY"].value += copyOffset[1]
eTag["TileZ"].value += copyOffset[2]
return eTag
return eTag

160
indev.py
View File

@ -86,115 +86,115 @@ __all__ = ["MCIndevLevel"]
class MCIndevLevel(MCLevel):
""" IMPORTANT: self.Blocks and self.Data are indexed with [x,z,y] via axis
swapping to be consistent with infinite levels."""
hasEntities = True
def setPlayerSpawnPosition(self, pos, player = None):
def setPlayerSpawnPosition(self, pos, player=None):
assert len(pos) == 3
self.Spawn = array(pos);
def playerSpawnPosition(self, player = None):
def playerSpawnPosition(self, player=None):
return self.Spawn;
def setPlayerPosition(self, pos, player = "Ignored"):
def setPlayerPosition(self, pos, player="Ignored"):
for x in self.root_tag["Entities"]:
if x["id"].value == "LocalPlayer":
x["Pos"] = TAG_List([TAG_Float(p) for p in pos])
def getPlayerPosition(self, player = "Ignored"):
def getPlayerPosition(self, player="Ignored"):
for x in self.root_tag["Entities"]:
if x["id"].value == "LocalPlayer":
return array(map(lambda x:x.value, x["Pos"]));
def setPlayerOrientation(self, yp, player = "Ignored"):
def setPlayerOrientation(self, yp, player="Ignored"):
for x in self.root_tag["Entities"]:
if x["id"].value == "LocalPlayer":
x["Rotation"] = TAG_List([TAG_Float(p) for p in yp])
def playerOrientation(self, player = "Ignored"):
def playerOrientation(self, player="Ignored"):
""" returns (yaw, pitch) """
for x in self.root_tag["Entities"]:
if x["id"].value == "LocalPlayer":
return array(map(lambda x:x.value, x["Rotation"]));
def setBlockDataAt(self, x,y,z, newdata):
if x<0 or y<0 or z<0: return 0
if x>=self.Width or y>=self.Height or z>=self.Length: return 0;
self.Data[x,z,y] = (newdata & 0xf);
def setBlockDataAt(self, x, y, z, newdata):
if x < 0 or y < 0 or z < 0: return 0
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
self.Data[x, z, y] = (newdata & 0xf);
def blockDataAt(self, x, y, z):
if x<0 or y<0 or z<0: return 0
if x>=self.Width or y>=self.Height or z>=self.Length: return 0;
return self.Data[x,z,y];
if x < 0 or y < 0 or z < 0: return 0
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
return self.Data[x, z, y];
def blockLightAt(self, x, y, z):
if x<0 or y<0 or z<0: return 0
if x>=self.Width or y>=self.Height or z>=self.Length: return 0;
return self.BlockLight[x,z,y];
if x < 0 or y < 0 or z < 0: return 0
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
return self.BlockLight[x, z, y];
def __repr__(self):
return u"MCIndevLevel({0}): {1}W {2}L {3}H".format(self.filename, self.Width, self.Length, self.Height)
@classmethod
def _isTagLevel(cls, root_tag):
return "MinecraftLevel" == root_tag.name
def __init__(self, root_tag = None, filename = ""):
def __init__(self, root_tag=None, filename=""):
self.Width = 0
self.Height = 0
self.Length = 0
self.Blocks = array([], uint8)
self.Data = array([], uint8)
self.Spawn = (0,0,0)
self.Spawn = (0, 0, 0)
self.filename = filename;
if root_tag:
self.root_tag = root_tag;
mapTag = root_tag[Map];
self.Width = mapTag[Width].value
self.Length = mapTag[Length].value
self.Height = mapTag[Height].value
mapTag[Blocks].value.shape = (self.Height, self.Length, self.Width)
self.Blocks = swapaxes(mapTag[Blocks].value, 0, 2)
mapTag[Data].value.shape = (self.Height, self.Length, self.Width)
self.Data = swapaxes(mapTag[Data].value, 0, 2)
mapTag[Blocks].value.shape = (self.Height, self.Length, self.Width)
self.Blocks = swapaxes(mapTag[Blocks].value, 0, 2)
mapTag[Data].value.shape = (self.Height, self.Length, self.Width)
self.Data = swapaxes(mapTag[Data].value, 0, 2)
self.BlockLight = self.Data & 0xf
self.Data >>= 4
self.Spawn = [mapTag[Spawn][i].value for i in range(3)];
if not Entities in root_tag:
if not Entities in root_tag:
root_tag[Entities] = TAG_List();
self.Entities = root_tag[Entities]
if not TileEntities in root_tag:
if not TileEntities in root_tag:
root_tag[TileEntities] = TAG_List();
self.TileEntities = root_tag[TileEntities]
if len(filter(lambda x:x['id'].value=='LocalPlayer', root_tag[Entities])) == 0: #omen doesn't make a player entity
p=TAG_Compound()
if len(filter(lambda x:x['id'].value == 'LocalPlayer', root_tag[Entities])) == 0: #omen doesn't make a player entity
p = TAG_Compound()
p['id'] = TAG_String('LocalPlayer')
p['Pos'] = TAG_List([TAG_Float(0.), TAG_Float(64.), TAG_Float(0.)])
p['Rotation'] = TAG_List([TAG_Float(0.), TAG_Float(45.)])
root_tag[Entities].append(p)
#self.saveInPlace();
else:
info( u"Creating new Indev levels is not yet implemented.!" )
info(u"Creating new Indev levels is not yet implemented.!")
raise ValueError, "Can't do that yet"
# self.SurroundingGroundHeight = root_tag[Environment][SurroundingGroundHeight].value
# self.SurroundingGroundType = root_tag[Environment][SurroundingGroundType].value
@ -212,65 +212,65 @@ class MCIndevLevel(MCLevel):
# self.Author = self.root_tag[About][Author].value
# self.CreatedOn = self.root_tag[About][CreatedOn].value
def rotateLeft(self):
MCLevel.rotateLeft(self);
self.Data = swapaxes(self.Data, 1, 0)[:,::-1,:]; #x=y; y=-x
self.Data = swapaxes(self.Data, 1, 0)[:, ::-1, :]; #x=y; y=-x
torchRotation = array([0, 4, 3, 1, 2, 5,
6, 7,
6, 7,
8, 9, 10, 11, 12, 13, 14, 15]);
torchIndexes = (self.Blocks == self.materials.Torch.ID)
info( u"Rotating torches: {0}".format( len(torchIndexes.nonzero()[0]) ) )
info(u"Rotating torches: {0}".format(len(torchIndexes.nonzero()[0])))
self.Data[torchIndexes] = torchRotation[self.Data[torchIndexes]]
def saveToFile(self, filename = None):
def saveToFile(self, filename=None):
if filename == None: filename = self.filename;
if filename == None:
warn( u"Attempted to save an unnamed file in place" )
warn(u"Attempted to save an unnamed file in place")
return; #you fool!
self.Data <<= 4;
self.Data |= (self.BlockLight & 0xf)
self.Blocks = swapaxes(self.Blocks, 0, 2)
self.Data = swapaxes(self.Data, 0, 2)
mapTag = TAG_Compound( name=Map );
mapTag = TAG_Compound(name=Map);
mapTag[Width] = TAG_Short(self.Width);
mapTag[Height] = TAG_Short(self.Height);
mapTag[Length] = TAG_Short(self.Length);
mapTag[Blocks] = TAG_Byte_Array(self.Blocks);
mapTag[Data] = TAG_Byte_Array(self.Data);
mapTag[Data] = TAG_Byte_Array(self.Data);
self.Blocks = swapaxes(self.Blocks, 0, 2)
self.Data = swapaxes(self.Data, 0, 2)
mapTag[Spawn] = TAG_List([TAG_Short(i) for i in self.Spawn])
mapTag[Spawn] = TAG_List([TAG_Short(i) for i in self.Spawn])
self.root_tag[Map] = mapTag;
self.root_tag[Map]
#output_file = gzip.open(self.filename, "wb", compresslevel=1)
try:
os.rename(filename, filename + ".old");
except Exception,e:
except Exception, e:
pass
try:
self.root_tag.saveGzipped(filename);
except:
os.rename(filename + ".old", filename);
try: os.remove(filename + ".old");
except Exception,e:
except Exception, e:
pass
self.BlockLight = self.Data & 0xf
self.Data >>= 4

View File

@ -257,20 +257,20 @@ items_txt = """
"""
class ItemType (object):
def __init__(self, id, name, imagefile = None, imagecoords = None, maxdamage = 0, damagevalue = 0, stacksize = 64):
self.id=id
self.name=name
self.imagefile=imagefile
self.imagecoords=imagecoords
self.maxdamage=maxdamage
def __init__(self, id, name, imagefile=None, imagecoords=None, maxdamage=0, damagevalue=0, stacksize=64):
self.id = id
self.name = name
self.imagefile = imagefile
self.imagecoords = imagecoords
self.maxdamage = maxdamage
def __repr__(self):
return "ItemType({0}, '{1}')".format(self.id, self.name)
def __str__(self):
return "ItemType {0}: {1}".format(self.id, self.name)
class Items (object):
items_txt = items_txt
def __init__(self, filename = None):
def __init__(self, filename=None):
if filename is None:
items_txt = self.items_txt
else:
@ -281,9 +281,9 @@ class Items (object):
print "Error reading items.txt: ", e;
print "Using internal data."
items_txt = self.items_txt
self.itemtypes = {};
for line in items_txt.split("\n"):
try:
line = line.strip()
@ -293,7 +293,7 @@ class Items (object):
stacksize = 64
damagevalue = None
maxdamage = 0
fields = line.split();
if len(fields) >= 4:
maxdamage = None;
@ -309,25 +309,25 @@ class Items (object):
id = int(id);
name = name.replace("_", " ");
imagecoords = imagecoords.split(",");
self.itemtypes[(id, damagevalue)] = ItemType(id, name, imagefile, imagecoords, maxdamage, damagevalue, stacksize)
except Exception, e:
print "Error reading line:", e
print "Line: ", line
print
self.names = dict((item.name, item.id) for item in self.itemtypes.itervalues())
def findItem(self, id=0, damage=None):
item = self.itemtypes.get((id, damage))
if item: return item
item = self.itemtypes.get((id, None))
if item: return item
item = self.itemtypes.get((id, 0))
if item: return item
raise ItemNotFound, "Item {0}:{1} not found".format(id, damage)
class ItemNotFound(KeyError): pass

636
level.py

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

584
mce.py

File diff suppressed because it is too large Load Diff

View File

@ -192,12 +192,12 @@ import sys
# we need to decode file paths from environment variables or else we get an error
# if they are formatted or joined to a unicode string
if sys.platform == "win32":
#not sure why win32com is needed if the %APPDATA% var is available
try:
try:
import win32com.client
objShell = win32com.client.Dispatch("WScript.Shell")
minecraftDir = os.path.join(objShell.SpecialFolders("AppData"), u".minecraft")
except Exception, e:
@ -211,9 +211,9 @@ elif sys.platform == "darwin":
else:
minecraftDir = os.path.expanduser("~/.minecraft")
minecraftDir.decode(sys.getfilesystemencoding());
saveFileDir = os.path.join(minecraftDir, u"saves")
#if sys.platform == "win32":
# from win32com.shell import shell, shellcon
# saveFileDir = shell.SHGetPathFromIDListEx (
@ -221,53 +221,53 @@ saveFileDir = os.path.join(minecraftDir, u"saves")
# )
#
def fromFile(filename, loadInfinite=True):
''' The preferred method for loading Minecraft levels of any type.
pass False to loadInfinite if you'd rather not load infdev levels.
'''
info( u"Identifying " + filename )
info(u"Identifying " + filename)
class LoadingError(RuntimeError): pass
if not filename:
raise IOError, "File not found: "+filename
raise IOError, "File not found: " + filename
if not os.path.exists(filename):
raise IOError, "File not found: "+filename
raise IOError, "File not found: " + filename
if (ZipSchematic._isLevel(filename)):
info( "Zipfile found, attempting zipped infinite level" )
info("Zipfile found, attempting zipped infinite level")
lev = ZipSchematic(filename);
info( "Detected zipped Infdev level" )
info("Detected zipped Infdev level")
return lev
if (MCInfdevOldLevel._isLevel(filename)):
info( u"Detected Infdev level.dat" )
info(u"Detected Infdev level.dat")
if (loadInfinite):
return MCInfdevOldLevel(filename=filename);
else:
raise ValueError, "Asked to load {0} which is an infinite level, loadInfinite was False".format(os.path.basename(filename));
if os.path.isdir(filename):
raise ValueError, "Folder {0} was not identified as a Minecraft level.".format(os.path.basename(filename));
f = file(filename, 'rb');
rawdata = f.read()
f.close()
if len(rawdata) < 4:
raise ValueError, "{0} is too small! ({1}) ".format(filename, len(rawdata))
data = fromstring(rawdata, dtype='uint8')
if not data.any():
raise ValueError, "{0} contains only zeroes. This file is damaged beyond repair."
if MCJavaLevel._isDataLevel(data):
info( u"Detected Java-style level" )
info(u"Detected Java-style level")
lev = MCJavaLevel(filename, data);
lev.compressed = False;
return lev;
@ -277,16 +277,16 @@ def fromFile(filename, loadInfinite=True):
unzippedData = None;
try:
unzippedData = gunzip(rawdata)
except Exception,e:
info( u"Exception during Gzip operation, assuming {0} uncompressed: {1!r}".format(filename, e) )
except Exception, e:
info(u"Exception during Gzip operation, assuming {0} uncompressed: {1!r}".format(filename, e))
if unzippedData is None:
compressed = False;
unzippedData = rawdata
data = fromstring(unzippedData, dtype='uint8')
if MCJavaLevel._isDataLevel(data):
info( u"Detected compressed Java-style level" )
info(u"Detected compressed Java-style level")
lev = MCJavaLevel(filename, data);
lev.compressed = compressed;
return lev;
@ -294,37 +294,37 @@ def fromFile(filename, loadInfinite=True):
try:
root_tag = nbt.load(buf=data);
except Exception, e:
info( u"Error during NBT load: {0!r}".format(e) )
info( u"Fallback: Detected compressed flat block array, yzx ordered " )
info(u"Error during NBT load: {0!r}".format(e))
info(u"Fallback: Detected compressed flat block array, yzx ordered ")
try:
lev = MCJavaLevel(filename, data);
lev.compressed = compressed;
return lev;
except Exception, e2:
raise LoadingError, ("Multiple errors encountered", e, e2)
else:
if(MCIndevLevel._isTagLevel(root_tag)):
info( u"Detected Indev .mclevel" )
info(u"Detected Indev .mclevel")
return MCIndevLevel(root_tag, filename)
if(MCSchematic._isTagLevel(root_tag)):
info( u"Detected Schematic." )
info(u"Detected Schematic.")
return MCSchematic(root_tag=root_tag, filename=filename)
if (INVEditChest._isTagLevel(root_tag)):
info( u"Detected INVEdit inventory file" )
info(u"Detected INVEdit inventory file")
return INVEditChest(root_tag=root_tag, filename=filename);
#it must be a plain array of blocks. see if MCJavaLevel handles it.
raise IOError, "Cannot detect file type."
def loadWorld(name):
filename = os.path.join(saveFileDir, name)
return fromFile(filename)
def loadWorldNumber(i):
#deprecated
filename = u"{0}{1}{2}{3}{1}".format(saveFileDir, os.sep, u"World", i)

View File

@ -60,8 +60,8 @@ def unpack_first(func):
return func(self, *args, **kw);
upk_first.__doc__ = func.__doc__
return upk_first
class PlayerNotFound(Exception): pass
class PlayerNotFound(Exception): pass
class ChunkNotPresent(Exception): pass
class RegionMalformed(Exception): pass
class ChunkMalformed(ChunkNotPresent): pass

248
nbt.py
View File

@ -33,17 +33,17 @@ class NBTFormatError(RuntimeError): pass
class TAG_Value(object):
"""Simple values. Subclasses override fmt to change the type and size.
Subclasses may set dataType instead of overriding setValue for automatic data type coercion"""
fmt = ">b";
tag = -1; #error!
_value = None
def getValue(self):
return self._value
def setValue(self, newVal):
self._value = self.dataType(newVal)
value = property(getValue, setValue, None, "Change the TAG's value. Data types are checked and coerced if needed.")
_name = None
def getName(self):
return self._name
@ -52,29 +52,29 @@ class TAG_Value(object):
def delName(self):
self._name = ""
name = property(getName, setName, delName, "Change the TAG's name. Coerced to a string.")
def __init__(self, value=0, name=None, data=""):
self.name = name
if(data == ""):
self.value = value
else:
else:
(self.value,) = struct.unpack_from(self.fmt, data);
def __repr__(self):
return "%s( \"%s\" ): %s" % (str(self.__class__), self.name, repr(self.value))
def __str__(self):
return self.pretty_string()
def pretty_string(self, indent=0):
if self.name:
return " "*indent + "%s( \"%s\" ): %s" % (str(self.__class__.__name__), self.name, self.value)
return " " * indent + "%s( \"%s\" ): %s" % (str(self.__class__.__name__), self.name, self.value)
else:
return " "*indent + "%s: %s" % (str(self.__class__.__name__), self.value)
return " " * indent + "%s: %s" % (str(self.__class__.__name__), self.value)
def nbt_length(self):
return struct.calcsize(self.fmt);
def write_tag(self, buf):
buf.write(struct.pack(TAGfmt, self.tag))
def write_name(self, buf):
@ -82,7 +82,7 @@ class TAG_Value(object):
TAG_String(self.name).write_value(buf)
def write_value(self, buf):
buf.write(struct.pack(self.fmt, self.value))
def save(self, filename="", buf=None):
if(filename):
self.saveGzipped(filename);
@ -100,7 +100,7 @@ class TAG_Value(object):
except Exception, e:
#print "Atomic Save: No existing file to rename"
pass
with closing(gzip.GzipFile(fileobj=sio, mode="wb", compresslevel=compresslevel)) as outputGz:
self.save(buf=outputGz);
outputGz.flush();
@ -115,27 +115,27 @@ class TAG_Value(object):
except Exception, e:
print e;
return
try: os.remove(filename + ".old");
except Exception, e:
#print "Atomic Save: No old file to remove"
pass;
class TAG_Byte(TAG_Value):
tag = 1;
fmt = ">b";
dataType = int
class TAG_Short(TAG_Value):
tag = 2;
fmt = ">h";
dataType = int
class TAG_Int(TAG_Value):
tag = 3;
fmt = ">i";
dataType = int
class TAG_Long(TAG_Value):
tag = 4;
fmt = ">q";
@ -146,7 +146,7 @@ class TAG_Float(TAG_Value):
fmt = ">f";
dataType = float
class TAG_Double(TAG_Value):
tag = 6;
fmt = ">d";
@ -162,22 +162,22 @@ class TAG_Byte_Array(TAG_Value):
def dataType(self, value):
return array(value, uint8)
def __repr__(self):
return "<%s: length %d> ( %s )" % (self.__class__, len(self.value), self.name)
def pretty_string(self, indent=0):
if self.name:
return " "*indent + "%s( \"%s\" ): shape=%s dtype=%s %s" % (
str(self.__class__.__name__),
self.name,
return " " * indent + "%s( \"%s\" ): shape=%s dtype=%s %s" % (
str(self.__class__.__name__),
self.name,
str(self.value.shape),
str(self.value.dtype),
str(self.value.dtype),
self.value)
else:
return " "*indent + "%s: %s %s" % (str(self.__class__.__name__), str(self.value.shape), self.value)
return " " * indent + "%s: %s %s" % (str(self.__class__.__name__), str(self.value.shape), self.value)
def __init__(self, value=zeros(0, uint8), name=None, data=""):
self.name = name
if(data == ""):
@ -185,21 +185,21 @@ class TAG_Byte_Array(TAG_Value):
else:
(string_len,) = struct.unpack_from(">I", data);
self.value = fromstring(data[4:string_len + 4], 'uint8');
def nbt_length(self) :
return len(self.value) + 4;
def write_value(self, buf):
#print self.value
valuestr = self.value.tostring()
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr), valuestr))
class TAG_Int_Array(TAG_Byte_Array):
"""An array of ints"""
tag = 11;
def dataType(self, value):
return array(value, '>u4')
def __init__(self, value=zeros(0, ">u4"), name=None, data=""):
self.name = name
if(data == ""):
@ -207,22 +207,22 @@ class TAG_Int_Array(TAG_Byte_Array):
else:
(string_len,) = struct.unpack_from(">I", data);
self.value = fromstring(data[4:string_len * 4 + 4], '>u4')
def nbt_length(self) :
return len(self.value) * 4 + 4;
def write_value(self, buf):
#print self.value
valuestr = self.value.tostring()
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr)/4, valuestr))
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr) / 4, valuestr))
class TAG_Short_Array(TAG_Int_Array):
"""An array of ints"""
tag = 12;
def dataType(self, value):
return array(value, '>u2')
def __init__(self, value=zeros(0, ">u2"), name=None, data=""):
self.name = name
if(data == ""):
@ -230,25 +230,25 @@ class TAG_Short_Array(TAG_Int_Array):
else:
(string_len,) = struct.unpack_from(">I", data);
self.value = fromstring(data[4:string_len * 2 + 4], '>u2')
def nbt_length(self) :
return len(self.value) * 2 + 4;
def write_value(self, buf):
#print self.value
valuestr = self.value.tostring()
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr)/2, valuestr))
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr) / 2, valuestr))
class TAG_String(TAG_Value):
"""String in UTF-8
The data parameter should either be a 'unicode' or an ascii-encoded 'str'
"""
tag = 8;
fmt = ">h%ds"
dataType = unicode
def __init__(self, value="", name=None, data=""):
self.name = name
if(data == ""):
@ -263,7 +263,7 @@ class TAG_String(TAG_Value):
def write_value(self, buf):
u8value = self.value.encode('utf-8')
buf.write(struct.pack(self.fmt % (len(u8value),), len(u8value), u8value))
@ -273,29 +273,29 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
operator []. This will automatically name the tags."""
tag = 10;
def dataType(self, val):
for i in val:
assert isinstance(i, TAG_Value)
assert i.name
return list(val)
def __repr__(self):
return "%s( %s ): %s" % (str(self.__class__.__name__), self.name, self.value)
def pretty_string(self, indent=0):
if self.name:
pretty = " "*indent + "%s( \"%s\" ):\n" % (str(self.__class__.__name__), self.name)
pretty = " " * indent + "%s( \"%s\" ):\n" % (str(self.__class__.__name__), self.name)
else:
pretty = " "*indent + "%s():\n" % (str(self.__class__.__name__))
pretty = " " * indent + "%s():\n" % (str(self.__class__.__name__))
indent += 4
for tag in self.value:
pretty += tag.pretty_string(indent) + "\n"
return pretty
def __init__(self, value=[], name="", data=""):
self.name = name;
if value.__class__ == ''.__class__:
self.name = value;
@ -306,7 +306,7 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
else:
data_cursor = 0;
while data_cursor < len(data):
tag_type = data[data_cursor];
data_cursor += 1;
@ -314,21 +314,21 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
break;
assert_type(tag_type, data_cursor)
data_cursor, tag = load_named(data, data_cursor, tag_type)
self.value.append(tag);
def nbt_length(self):
return sum(x.nbt_length() + len(x.name) + 3 for x in self.value) + 1;
def write_value(self, buf):
for i in self.value:
i.save(buf=buf)
buf.write("\x00")
"collection functions"
def __getitem__(self, k):
#hits=filter(lambda x:x.name==k, self.value);
@ -336,11 +336,11 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
for key in self.value:
if key.name == k: return key
raise KeyError("Key {0} not found".format(k));
def __iter__(self): return itertools.imap(lambda x:x.name, self.value);
def __contains__(self, k):return k in map(lambda x:x.name, self.value);
def __len__(self): return self.value.__len__()
def __setitem__(self, k, v):
if not (v.__class__ in tag_handlers.values()): raise TypeError("Invalid type %s for TAG_Compound" % (v.__class__))
@ -349,14 +349,14 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
for i in olditems: self.value.remove(i)
self.value.append(v);
v.name = k;
def __delitem__(self, k): self.value.__delitem__(self.value.index(self[k]));
def add(self, v):
self[v.name] = v;
class TAG_List(TAG_Value, collections.MutableSequence):
"""A homogenous list of unnamed data of a single TAG_* type.
Once created, the type can only be changed by emptying the list
and adding an element of the new type. If created with no arguments,
@ -372,53 +372,53 @@ class TAG_List(TAG_Value, collections.MutableSequence):
# FIXME: This is kinda weird; None as the empty tag name?
assert all(isinstance(x, listType) and x.name in ("", "None") for x in val)
return list(val)
def __repr__(self):
return "%s( %s ): %s" % (self.__class__.__name__, self.name, self.value)
def pretty_string(self, indent=0):
if self.name:
pretty = " "*indent + "%s( \"%s\" ):\n" % (str(self.__class__.__name__), self.name)
pretty = " " * indent + "%s( \"%s\" ):\n" % (str(self.__class__.__name__), self.name)
else:
pretty = " "*indent + "%s():\n" % (str(self.__class__.__name__), )
pretty = " " * indent + "%s():\n" % (str(self.__class__.__name__),)
indent += 4
for tag in self.value:
pretty += tag.pretty_string(indent) + "\n"
return pretty
def __init__(self, value=[], name=None, data=None, list_type=TAG_Compound):
#can be created from a list of tags in value, with an optional
#name, or created from raw tag data, or created with list_type
#taken from a TAG class or instance
self.name = name
self.value = [];
self.list_type = list_type.tag
if(data == None):
if(len(value)):
self.list_type = value[0].tag;
value = filter(lambda x:x.__class__ == value[0].__class__, value)
self.value = value
else:
else:
data_cursor = 0;
self.list_type = data[data_cursor];
assert_type(self.list_type, data_cursor);
data_cursor += 1;
list_length = TAG_Int(data=data[data_cursor:])
data_cursor += list_length.nbt_length()
list_length = list_length.value
for i in range(list_length):
tag = tag_handlers[self.list_type](data=data[data_cursor:])
self.append(tag);
data_cursor += tag.nbt_length()
@ -428,35 +428,35 @@ class TAG_List(TAG_Value, collections.MutableSequence):
def __contains__(self, k):return k in self.value;
def __getitem__(self, i): return self.value[i];
def __len__(self): return len(self.value)
def __setitem__(self, i, v):
if v.__class__ != tag_handlers[self.list_type]:
if v.__class__ != tag_handlers[self.list_type]:
raise TypeError("Invalid type %s for TAG_List(%s)" % (v.__class__, tag_handlers[self.list_type]))
v.name = ""
self.value[i] = v;
def __delitem__(self, i):
def __delitem__(self, i):
del self.value[i]
def insert(self, i, v):
if not v.tag in tag_handlers: raise TypeError("Not a tag type: %s" % (v,))
if len(self) == 0:
self.list_type = v.tag
if len(self) == 0:
self.list_type = v.tag
else:
if v.__class__ != tag_handlers[self.list_type]: raise TypeError("Invalid type %s for TAG_List(%s)" % (v.__class__, tag_handlers[self.list_type]))
v.name = ""
self.value.insert(i, v);
def nbt_length(self):
return 5 + sum(x.nbt_length() for x in self.value)
def write_value(self, buf):
buf.write(struct.pack(TAGfmt, self.list_type))
TAG_Int(len(self)).write_value(buf)
for i in self.value:
i.write_value(buf)
tag_handlers = {
1 : TAG_Byte,
@ -476,11 +476,11 @@ tag_handlers = {
def assert_type(t, offset) :
if not t in tag_handlers: raise ValueError("Unexpected tag type %d at %d" % (t, offset));
import zlib
import zlib
def gunzip(data):
#strip off the header and use negative WBITS to tell zlib there's no header
return zlib.decompress(data[10:], -zlib.MAX_WBITS)
def loadFile(filename):
#sio = StringIO.StringIO();
with file(filename, "rb") as f:
@ -491,14 +491,14 @@ def loadFile(filename):
data = gunzip(inputdata)
except IOError:
print "File %s not zipped" % filename
return load(buf=fromstring(data, 'uint8'));
def load_named(data, data_cursor, tag_type):
tag_name = TAG_String(data=data[data_cursor:])
data_cursor += tag_name.nbt_length()
tag_name = tag_name.value
tag = tag_handlers[tag_type](data=data[data_cursor:], name=tag_name)
data_cursor += tag.nbt_length()
return data_cursor, tag
@ -507,7 +507,7 @@ def load(filename="", buf=None):
"""Unserialize data from an entire NBT file and return the
root TAG_Compound object. Argument can be a string containing a
filename or an array of integers containing TAG_Compound data. """
if filename and isinstance(filename, (str, unicode)):
return loadFile(filename)
if isinstance(buf, str): buf = fromstring(buf, uint8)
@ -537,17 +537,17 @@ def loadtest():
"""Use the [] operator to look up subtags of a TAG_Compound."""
print level["Environment"]["SurroundingGroundHeight"].value;
"""Numeric, string, and bytearray types have a value
that can be accessed and changed. """
print level["Map"]["Blocks"].value
return level;
def createtest():
"Create an indev level."
"The root of an NBT file is always a TAG_Compound."
level = TAG_Compound(name="MinecraftLevel")
@ -558,52 +558,52 @@ def createtest():
level["Environment"] = TAG_Compound()
level["Environment"]["SkyBrightness"] = TAG_Byte(16)
level["Environment"]["SurroundingWaterHeight"] = TAG_Short(32)
"You can also create and name a tag before adding it to the compound."
spawn = TAG_List((TAG_Short(100), TAG_Short(45), TAG_Short(55)))
spawn.name = "Spawn"
mapTag = TAG_Compound()
mapTag.add(spawn);
mapTag.name = "Map"
level.add(mapTag)
"I think it looks more familiar with [] syntax."
l, w, h = 128, 128, 128
mapTag["Height"] = TAG_Short(h) # y dimension
mapTag["Length"] = TAG_Short(l) # z dimension
mapTag["Width"] = TAG_Short(w) # x dimension
"Byte arrays are stored as numpy.uint8 arrays. "
mapTag["Blocks"] = TAG_Byte_Array()
mapTag["Blocks"].value = zeros(l * w * h, dtype=uint8) #create lots of air!
"The blocks array is indexed (y,z,x) for indev levels, so reshape the blocks"
mapTag["Blocks"].value.shape = (h, l, w);
"Replace the bottom layer of the indev level with wood"
mapTag["Blocks"].value[0, :, :] = 5;
"This is a great way to learn the power of numpy array slicing and indexing."
return level;
def modifytest():
level = createtest();
"Most of the value types work as expected. Here, we replace the entire tag with a TAG_String"
level["About"]["Author"] = TAG_String("YARRR~!");
"Because the tag type usually doesn't change, "
"we can replace the string tag's value instead of replacing the entire tag."
level["About"]["Author"].value = "Stew Pickles"
"Remove members of a TAG_Compound using del, similar to a python dict."
del(level["About"]);
"Replace all of the wood blocks with gold using a boolean index array"
blocks = level["Map"]["Blocks"].value
blocks[blocks == 5] = 41;
@ -613,10 +613,10 @@ def savetest():
level = createtest()
level["Environment"]["SurroundingWaterHeight"].value += 6;
"Save the entire TAG structure to a different file."
level.save("atlantis.mclevel")
level = createtest();
level.save("synthetic.mclevel");
@ -626,7 +626,7 @@ def abusetest():
named list elements are not allowed by the NBT spec,
so we must discard any names when writing a list.
"""
level = createtest();
level["Map"]["Spawn"][0].name = "Torg Potter"
sio = StringIO.StringIO()
@ -647,9 +647,9 @@ def abusetest():
pass
else:
assert False
def runtests():
def runtests():
loadtest();
createtest();
modifytest();
@ -661,5 +661,5 @@ if(__name__ == "__main__") :
runtests()
__all__ = [a.__name__ for a in tag_handlers.itervalues()] + ["loadFile", "gunzip"]

View File

@ -19,7 +19,7 @@ def generate_file_list(directory):
yield os.path.join(dirpath, filename)
def sha1_file(name, checksum=None):
CHUNKSIZE=1024
CHUNKSIZE = 1024
if checksum is None:
checksum = hashlib.sha1()
if fnmatch.fnmatch(name, "*.dat"):
@ -71,17 +71,17 @@ def untared_content(src):
f.extractall(dest)
yield dest
def launch_subprocess(directory, arguments, env = {}):
def launch_subprocess(directory, arguments, env={}):
#my python breaks with an empty environ, i think it wants PATH
#if sys.platform == "win32":
newenv = {}
newenv.update(os.environ)
newenv.update(env);
proc = subprocess.Popen((["python.exe"] if sys.platform == "win32" else []) + [
"./mce.py",
directory] + arguments, stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=newenv)
return proc
class RegressionError(Exception): pass
@ -129,7 +129,7 @@ def do_test_match_output(test_data, result_check, arguments=[]):
proc.stdin.close()
output = proc.stdout.read()
proc.wait()
if proc.returncode:
raise RegressionError("Program execution failed!")
@ -146,13 +146,13 @@ def do_test_match_output(test_data, result_check, arguments=[]):
alpha_tests = [
(do_test, 'baseline', '9e7460d39c8e0456789cf89fee45276db2719aaa', []),
(do_test, 'degrief', '403e6c6147cf1f8d73377b18bbf5e4973606a311', ['degrief']),
(do_test_match_output, 'analyze', '89ae362dec7f6c0fd743d6ed4e3957459cb3c34d', ['analyze']),
(do_test, 'relight', 'e0cf60c62adfdb313f198af5314c31f89d158c12', ['relight']),
(do_test, 'replace', 'd73767293e903b6d1c49c1838eb1849b69d83ad8', ['replace', 'Water (active)', 'with', 'Lava (active)']),
(do_test, 'fill', 'f4f57c3d902b6894031d416cb9279232e7e24bd7', ['fill', 'Water (active)']),
(do_test, 'heightmap', '9e7460d39c8e0456789cf89fee45276db2719aaa', ['heightmap', 'regression_test/mars.png']),
(do_test, 'baseline', '9e7460d39c8e0456789cf89fee45276db2719aaa', []),
(do_test, 'degrief', '403e6c6147cf1f8d73377b18bbf5e4973606a311', ['degrief']),
(do_test_match_output, 'analyze', '89ae362dec7f6c0fd743d6ed4e3957459cb3c34d', ['analyze']),
(do_test, 'relight', 'e0cf60c62adfdb313f198af5314c31f89d158c12', ['relight']),
(do_test, 'replace', 'd73767293e903b6d1c49c1838eb1849b69d83ad8', ['replace', 'Water (active)', 'with', 'Lava (active)']),
(do_test, 'fill', 'f4f57c3d902b6894031d416cb9279232e7e24bd7', ['fill', 'Water (active)']),
(do_test, 'heightmap', '9e7460d39c8e0456789cf89fee45276db2719aaa', ['heightmap', 'regression_test/mars.png']),
]
import optparse
@ -172,26 +172,26 @@ def main(argv):
test_data = os.path.join(directory, "alpha")
passes = []
fails = []
for func, name, sha, args in alpha_tests:
print "Starting regression {0} ({1})".format( name, args )
print "Starting regression {0} ({1})".format(name, args)
if any(fnmatch.fnmatch(name, x) for x in do_these_regressions):
if options.profile:
print >>sys.stderr, "Starting to profile to %s.profile" % name
print >> sys.stderr, "Starting to profile to %s.profile" % name
os.environ['MCE_PROFILE'] = '%s.profile' % name
try:
func(test_data, sha, args)
except RegressionError, e:
fails.append( "Regression {0} failed: {1}".format(name, e) )
fails.append("Regression {0} failed: {1}".format(name, e))
print fails[-1]
else:
passes.append( "Regression {0!r} complete.".format(name) )
passes.append("Regression {0!r} complete.".format(name))
print passes[-1]
print "{0} tests passed.".format(len(passes))
for line in fails: print line;
if __name__ == '__main__':
sys.exit(main(sys.argv))

View File

@ -468,6 +468,7 @@ def extractSchematicFrom(sourceLevel, box):
return tempSchematic
import tempfile
def extractZipSchematicFrom(sourceLevel, box, zipfilename):
#converts classic blocks to alpha
#probably should only apply to alpha levels