put everything through pydev's code auto-formatter
This commit is contained in:
parent
6b9e82c2e4
commit
225f813d28
@ -35,7 +35,7 @@ class Torch:
|
|||||||
alphaMaterials.RedstoneTorchOn.ID,
|
alphaMaterials.RedstoneTorchOn.ID,
|
||||||
alphaMaterials.RedstoneTorchOff.ID,
|
alphaMaterials.RedstoneTorchOff.ID,
|
||||||
]
|
]
|
||||||
|
|
||||||
South = 1
|
South = 1
|
||||||
North = 2
|
North = 2
|
||||||
West = 3
|
West = 3
|
||||||
@ -45,7 +45,7 @@ genericFlipRotation(Torch)
|
|||||||
|
|
||||||
class Ladder:
|
class Ladder:
|
||||||
blocktypes = [alphaMaterials.Ladder.ID]
|
blocktypes = [alphaMaterials.Ladder.ID]
|
||||||
|
|
||||||
East = 2
|
East = 2
|
||||||
West = 3
|
West = 3
|
||||||
North = 4
|
North = 4
|
||||||
@ -57,7 +57,7 @@ class Stair:
|
|||||||
alphaMaterials.WoodenStairs.ID,
|
alphaMaterials.WoodenStairs.ID,
|
||||||
alphaMaterials.StoneStairs.ID,
|
alphaMaterials.StoneStairs.ID,
|
||||||
]
|
]
|
||||||
|
|
||||||
South = 0
|
South = 0
|
||||||
North = 1
|
North = 1
|
||||||
West = 2
|
West = 2
|
||||||
@ -66,13 +66,13 @@ genericFlipRotation(Stair)
|
|||||||
|
|
||||||
class WallSign:
|
class WallSign:
|
||||||
blocktypes = [alphaMaterials.WallSign.ID]
|
blocktypes = [alphaMaterials.WallSign.ID]
|
||||||
|
|
||||||
East = 2
|
East = 2
|
||||||
West = 3
|
West = 3
|
||||||
North = 4
|
North = 4
|
||||||
South = 5
|
South = 5
|
||||||
genericFlipRotation(WallSign)
|
genericFlipRotation(WallSign)
|
||||||
|
|
||||||
class Furnace:
|
class Furnace:
|
||||||
blocktypes = [
|
blocktypes = [
|
||||||
alphaMaterials.Furnace.ID,
|
alphaMaterials.Furnace.ID,
|
||||||
@ -87,15 +87,15 @@ genericFlipRotation(Furnace)
|
|||||||
class Dispenser(Furnace):
|
class Dispenser(Furnace):
|
||||||
blocktypes = [
|
blocktypes = [
|
||||||
alphaMaterials.Dispenser.ID,
|
alphaMaterials.Dispenser.ID,
|
||||||
]
|
]
|
||||||
genericFlipRotation(Dispenser)
|
genericFlipRotation(Dispenser)
|
||||||
|
|
||||||
class Pumpkin:
|
class Pumpkin:
|
||||||
blocktypes = [
|
blocktypes = [
|
||||||
alphaMaterials.Pumpkin.ID,
|
alphaMaterials.Pumpkin.ID,
|
||||||
alphaMaterials.JackOLantern.ID,
|
alphaMaterials.JackOLantern.ID,
|
||||||
]
|
]
|
||||||
|
|
||||||
East = 0
|
East = 0
|
||||||
South = 1
|
South = 1
|
||||||
West = 2
|
West = 2
|
||||||
@ -104,14 +104,14 @@ genericFlipRotation(Pumpkin)
|
|||||||
|
|
||||||
class Rail:
|
class Rail:
|
||||||
blocktypes = [alphaMaterials.Rail.ID]
|
blocktypes = [alphaMaterials.Rail.ID]
|
||||||
|
|
||||||
EastWest = 0
|
EastWest = 0
|
||||||
NorthSouth = 1
|
NorthSouth = 1
|
||||||
South = 2
|
South = 2
|
||||||
North = 3
|
North = 3
|
||||||
East = 4
|
East = 4
|
||||||
West = 5
|
West = 5
|
||||||
|
|
||||||
Northeast = 6
|
Northeast = 6
|
||||||
Southeast = 7
|
Southeast = 7
|
||||||
Southwest = 8
|
Southwest = 8
|
||||||
@ -143,7 +143,7 @@ def applyBit8(array):
|
|||||||
def applyBit4(array):
|
def applyBit4(array):
|
||||||
array[4:8] = array[0:4] | 0x4
|
array[4:8] = array[0:4] | 0x4
|
||||||
array[12:16] = array[8:12] | 0x4
|
array[12:16] = array[8:12] | 0x4
|
||||||
|
|
||||||
applyThrownBit = applyBit8
|
applyThrownBit = applyBit8
|
||||||
|
|
||||||
class PoweredDetectorRail(Rail):
|
class PoweredDetectorRail(Rail):
|
||||||
@ -161,7 +161,7 @@ applyThrownBit(PoweredDetectorRail.flipEastWest)
|
|||||||
applyThrownBit(PoweredDetectorRail.flipNorthSouth)
|
applyThrownBit(PoweredDetectorRail.flipNorthSouth)
|
||||||
rotationClasses.append(PoweredDetectorRail)
|
rotationClasses.append(PoweredDetectorRail)
|
||||||
|
|
||||||
|
|
||||||
class Lever:
|
class Lever:
|
||||||
blocktypes = [alphaMaterials.Lever.ID]
|
blocktypes = [alphaMaterials.Lever.ID]
|
||||||
ThrownBit = 0x8
|
ThrownBit = 0x8
|
||||||
@ -199,11 +199,11 @@ rotationClasses.append(Button)
|
|||||||
class SignPost:
|
class SignPost:
|
||||||
blocktypes = [alphaMaterials.Sign.ID]
|
blocktypes = [alphaMaterials.Sign.ID]
|
||||||
#west is 0, increasing clockwise
|
#west is 0, increasing clockwise
|
||||||
|
|
||||||
rotateLeft = arange(16, dtype='uint8')
|
rotateLeft = arange(16, dtype='uint8')
|
||||||
rotateLeft -= 4
|
rotateLeft -= 4
|
||||||
rotateLeft &= 0xf
|
rotateLeft &= 0xf
|
||||||
|
|
||||||
flipEastWest = arange(16, dtype='uint8')
|
flipEastWest = arange(16, dtype='uint8')
|
||||||
flipNorthSouth = arange(16, dtype='uint8')
|
flipNorthSouth = arange(16, dtype='uint8')
|
||||||
pass
|
pass
|
||||||
@ -217,14 +217,14 @@ class Door:
|
|||||||
]
|
]
|
||||||
TopHalfBit = 0x8
|
TopHalfBit = 0x8
|
||||||
SwungCCWBit = 0x4
|
SwungCCWBit = 0x4
|
||||||
|
|
||||||
Northeast = 0
|
Northeast = 0
|
||||||
Southeast = 1
|
Southeast = 1
|
||||||
Southwest = 2
|
Southwest = 2
|
||||||
Northwest = 3
|
Northwest = 3
|
||||||
|
|
||||||
rotateLeft = arange(16, dtype='uint8')
|
rotateLeft = arange(16, dtype='uint8')
|
||||||
|
|
||||||
Door.rotateLeft[Door.Northeast] = Door.Northwest
|
Door.rotateLeft[Door.Northeast] = Door.Northwest
|
||||||
Door.rotateLeft[Door.Southeast] = Door.Northeast
|
Door.rotateLeft[Door.Southeast] = Door.Northeast
|
||||||
Door.rotateLeft[Door.Southwest] = Door.Southeast
|
Door.rotateLeft[Door.Southwest] = Door.Southeast
|
||||||
@ -260,14 +260,14 @@ class RedstoneRepeater:
|
|||||||
blocktypes = [
|
blocktypes = [
|
||||||
alphaMaterials.RedstoneRepeaterOff.ID,
|
alphaMaterials.RedstoneRepeaterOff.ID,
|
||||||
alphaMaterials.RedstoneRepeaterOn.ID,
|
alphaMaterials.RedstoneRepeaterOn.ID,
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
East = 0
|
East = 0
|
||||||
South = 1
|
South = 1
|
||||||
West = 2
|
West = 2
|
||||||
North = 3
|
North = 3
|
||||||
|
|
||||||
genericFlipRotation(RedstoneRepeater)
|
genericFlipRotation(RedstoneRepeater)
|
||||||
|
|
||||||
#high bits of the repeater indicate repeater delay, and should be preserved
|
#high bits of the repeater indicate repeater delay, and should be preserved
|
||||||
@ -285,7 +285,7 @@ applyOpenedBit = applyBit4
|
|||||||
|
|
||||||
class Trapdoor:
|
class Trapdoor:
|
||||||
blocktypes = [alphaMaterials.Trapdoor.ID]
|
blocktypes = [alphaMaterials.Trapdoor.ID]
|
||||||
|
|
||||||
West = 0
|
West = 0
|
||||||
East = 1
|
East = 1
|
||||||
South = 2
|
South = 2
|
||||||
@ -299,7 +299,7 @@ applyOpenedBit(Trapdoor.flipNorthSouth)
|
|||||||
applyPistonBit = applyBit8
|
applyPistonBit = applyBit8
|
||||||
class PistonBody:
|
class PistonBody:
|
||||||
blocktypes = [alphaMaterials.StickyPiston.ID, alphaMaterials.Piston.ID]
|
blocktypes = [alphaMaterials.StickyPiston.ID, alphaMaterials.Piston.ID]
|
||||||
|
|
||||||
East = 2
|
East = 2
|
||||||
West = 3
|
West = 3
|
||||||
North = 4
|
North = 4
|
||||||
@ -308,36 +308,36 @@ genericFlipRotation(PistonBody)
|
|||||||
applyPistonBit(PistonBody.rotateLeft)
|
applyPistonBit(PistonBody.rotateLeft)
|
||||||
applyPistonBit(PistonBody.flipEastWest)
|
applyPistonBit(PistonBody.flipEastWest)
|
||||||
applyPistonBit(PistonBody.flipNorthSouth)
|
applyPistonBit(PistonBody.flipNorthSouth)
|
||||||
|
|
||||||
class PistonHead(PistonBody):
|
class PistonHead(PistonBody):
|
||||||
blocktypes = [alphaMaterials.PistonHead.ID]
|
blocktypes = [alphaMaterials.PistonHead.ID]
|
||||||
rotationClasses.append(PistonHead)
|
rotationClasses.append(PistonHead)
|
||||||
|
|
||||||
def masterRotationTable(rotationFunc):
|
def masterRotationTable(rotationFunc):
|
||||||
# compute a 256x16 table mapping each possible blocktype/data combination to
|
# compute a 256x16 table mapping each possible blocktype/data combination to
|
||||||
# the resulting data when the block is rotated
|
# 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')
|
table[:] = arange(16, dtype='uint8')
|
||||||
for cls in rotationClasses:
|
for cls in rotationClasses:
|
||||||
for blocktype in cls.blocktypes:
|
for blocktype in cls.blocktypes:
|
||||||
table[blocktype] = rotationFunc(cls)
|
table[blocktype] = rotationFunc(cls)
|
||||||
|
|
||||||
return table
|
return table
|
||||||
|
|
||||||
class BlockRotation:
|
class BlockRotation:
|
||||||
rotateLeft = masterRotationTable(lambda cls:cls.rotateLeft);
|
rotateLeft = masterRotationTable(lambda cls:cls.rotateLeft);
|
||||||
flipEastWest = masterRotationTable(lambda cls:cls.flipEastWest);
|
flipEastWest = masterRotationTable(lambda cls:cls.flipEastWest);
|
||||||
flipNorthSouth = masterRotationTable(lambda cls:cls.flipNorthSouth);
|
flipNorthSouth = masterRotationTable(lambda cls:cls.flipNorthSouth);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def FlipNorthSouth(blocks, data):
|
def FlipNorthSouth(blocks, data):
|
||||||
data[:] = BlockRotation.flipNorthSouth[blocks, data]
|
data[:] = BlockRotation.flipNorthSouth[blocks, data]
|
||||||
|
|
||||||
def FlipEastWest(blocks, data):
|
def FlipEastWest(blocks, data):
|
||||||
data[:] = BlockRotation.flipEastWest[blocks, data]
|
data[:] = BlockRotation.flipEastWest[blocks, data]
|
||||||
|
|
||||||
|
|
||||||
def RotateLeft(blocks, data):
|
def RotateLeft(blocks, data):
|
||||||
data[:] = BlockRotation.rotateLeft[blocks, data]
|
data[:] = BlockRotation.rotateLeft[blocks, data]
|
||||||
|
|
||||||
|
18
entity.py
18
entity.py
@ -11,7 +11,7 @@ class TileEntity(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def pos(cls, tag):
|
def pos(cls, tag):
|
||||||
return [tag[a].value for a in 'xyz']
|
return [tag[a].value for a in 'xyz']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setpos(cls, tag, pos):
|
def setpos(cls, tag, pos):
|
||||||
for a, p in zip('xyz', pos):
|
for a, p in zip('xyz', pos):
|
||||||
@ -23,21 +23,21 @@ class Entity(object):
|
|||||||
if "Pos" not in tag:
|
if "Pos" not in tag:
|
||||||
print tag
|
print tag
|
||||||
return [a.value for a in tag["Pos"]]
|
return [a.value for a in tag["Pos"]]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setpos(cls, tag, pos):
|
def setpos(cls, tag, pos):
|
||||||
tag["Pos"] = TAG_List([TAG_Int(p) for p in pos])
|
tag["Pos"] = TAG_List([TAG_Int(p) for p in pos])
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def copyWithOffset(cls, entity, copyOffset):
|
def copyWithOffset(cls, entity, copyOffset):
|
||||||
eTag = deepcopy(entity)
|
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)
|
eTag["Pos"] = TAG_List(positionTags)
|
||||||
|
|
||||||
if eTag["id"].value == "Painting":
|
if eTag["id"].value == "Painting":
|
||||||
eTag["TileX"].value += copyOffset[0]
|
eTag["TileX"].value += copyOffset[0]
|
||||||
eTag["TileY"].value += copyOffset[1]
|
eTag["TileY"].value += copyOffset[1]
|
||||||
eTag["TileZ"].value += copyOffset[2]
|
eTag["TileZ"].value += copyOffset[2]
|
||||||
|
|
||||||
return eTag
|
return eTag
|
||||||
|
160
indev.py
160
indev.py
@ -86,115 +86,115 @@ __all__ = ["MCIndevLevel"]
|
|||||||
|
|
||||||
|
|
||||||
class MCIndevLevel(MCLevel):
|
class MCIndevLevel(MCLevel):
|
||||||
|
|
||||||
""" IMPORTANT: self.Blocks and self.Data are indexed with [x,z,y] via axis
|
""" IMPORTANT: self.Blocks and self.Data are indexed with [x,z,y] via axis
|
||||||
swapping to be consistent with infinite levels."""
|
swapping to be consistent with infinite levels."""
|
||||||
hasEntities = True
|
hasEntities = True
|
||||||
|
|
||||||
def setPlayerSpawnPosition(self, pos, player = None):
|
def setPlayerSpawnPosition(self, pos, player=None):
|
||||||
assert len(pos) == 3
|
assert len(pos) == 3
|
||||||
self.Spawn = array(pos);
|
self.Spawn = array(pos);
|
||||||
|
|
||||||
def playerSpawnPosition(self, player = None):
|
def playerSpawnPosition(self, player=None):
|
||||||
return self.Spawn;
|
return self.Spawn;
|
||||||
|
|
||||||
def setPlayerPosition(self, pos, player = "Ignored"):
|
def setPlayerPosition(self, pos, player="Ignored"):
|
||||||
for x in self.root_tag["Entities"]:
|
for x in self.root_tag["Entities"]:
|
||||||
if x["id"].value == "LocalPlayer":
|
if x["id"].value == "LocalPlayer":
|
||||||
x["Pos"] = TAG_List([TAG_Float(p) for p in pos])
|
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"]:
|
for x in self.root_tag["Entities"]:
|
||||||
if x["id"].value == "LocalPlayer":
|
if x["id"].value == "LocalPlayer":
|
||||||
return array(map(lambda x:x.value, x["Pos"]));
|
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"]:
|
for x in self.root_tag["Entities"]:
|
||||||
if x["id"].value == "LocalPlayer":
|
if x["id"].value == "LocalPlayer":
|
||||||
x["Rotation"] = TAG_List([TAG_Float(p) for p in yp])
|
x["Rotation"] = TAG_List([TAG_Float(p) for p in yp])
|
||||||
|
|
||||||
def playerOrientation(self, player = "Ignored"):
|
def playerOrientation(self, player="Ignored"):
|
||||||
""" returns (yaw, pitch) """
|
""" returns (yaw, pitch) """
|
||||||
for x in self.root_tag["Entities"]:
|
for x in self.root_tag["Entities"]:
|
||||||
if x["id"].value == "LocalPlayer":
|
if x["id"].value == "LocalPlayer":
|
||||||
return array(map(lambda x:x.value, x["Rotation"]));
|
return array(map(lambda x:x.value, x["Rotation"]));
|
||||||
|
|
||||||
def setBlockDataAt(self, x,y,z, newdata):
|
def setBlockDataAt(self, x, y, z, newdata):
|
||||||
if x<0 or y<0 or z<0: return 0
|
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;
|
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
|
||||||
self.Data[x,z,y] = (newdata & 0xf);
|
self.Data[x, z, y] = (newdata & 0xf);
|
||||||
|
|
||||||
def blockDataAt(self, x, y, z):
|
def blockDataAt(self, x, y, z):
|
||||||
if x<0 or y<0 or z<0: return 0
|
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;
|
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
|
||||||
return self.Data[x,z,y];
|
return self.Data[x, z, y];
|
||||||
|
|
||||||
def blockLightAt(self, x, y, z):
|
def blockLightAt(self, x, y, z):
|
||||||
if x<0 or y<0 or z<0: return 0
|
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;
|
if x >= self.Width or y >= self.Height or z >= self.Length: return 0;
|
||||||
return self.BlockLight[x,z,y];
|
return self.BlockLight[x, z, y];
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return u"MCIndevLevel({0}): {1}W {2}L {3}H".format(self.filename, self.Width, self.Length, self.Height)
|
return u"MCIndevLevel({0}): {1}W {2}L {3}H".format(self.filename, self.Width, self.Length, self.Height)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _isTagLevel(cls, root_tag):
|
def _isTagLevel(cls, root_tag):
|
||||||
return "MinecraftLevel" == root_tag.name
|
return "MinecraftLevel" == root_tag.name
|
||||||
|
|
||||||
def __init__(self, root_tag = None, filename = ""):
|
def __init__(self, root_tag=None, filename=""):
|
||||||
self.Width = 0
|
self.Width = 0
|
||||||
self.Height = 0
|
self.Height = 0
|
||||||
self.Length = 0
|
self.Length = 0
|
||||||
self.Blocks = array([], uint8)
|
self.Blocks = array([], uint8)
|
||||||
self.Data = array([], uint8)
|
self.Data = array([], uint8)
|
||||||
self.Spawn = (0,0,0)
|
self.Spawn = (0, 0, 0)
|
||||||
self.filename = filename;
|
self.filename = filename;
|
||||||
|
|
||||||
|
|
||||||
if root_tag:
|
if root_tag:
|
||||||
|
|
||||||
self.root_tag = root_tag;
|
self.root_tag = root_tag;
|
||||||
mapTag = root_tag[Map];
|
mapTag = root_tag[Map];
|
||||||
self.Width = mapTag[Width].value
|
self.Width = mapTag[Width].value
|
||||||
self.Length = mapTag[Length].value
|
self.Length = mapTag[Length].value
|
||||||
self.Height = mapTag[Height].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.BlockLight = self.Data & 0xf
|
||||||
|
|
||||||
self.Data >>= 4
|
self.Data >>= 4
|
||||||
|
|
||||||
self.Spawn = [mapTag[Spawn][i].value for i in range(3)];
|
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();
|
root_tag[Entities] = TAG_List();
|
||||||
self.Entities = root_tag[Entities]
|
self.Entities = root_tag[Entities]
|
||||||
|
|
||||||
if not TileEntities in root_tag:
|
if not TileEntities in root_tag:
|
||||||
root_tag[TileEntities] = TAG_List();
|
root_tag[TileEntities] = TAG_List();
|
||||||
self.TileEntities = root_tag[TileEntities]
|
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['id'] = TAG_String('LocalPlayer')
|
||||||
p['Pos'] = TAG_List([TAG_Float(0.), TAG_Float(64.), TAG_Float(0.)])
|
p['Pos'] = TAG_List([TAG_Float(0.), TAG_Float(64.), TAG_Float(0.)])
|
||||||
p['Rotation'] = TAG_List([TAG_Float(0.), TAG_Float(45.)])
|
p['Rotation'] = TAG_List([TAG_Float(0.), TAG_Float(45.)])
|
||||||
|
|
||||||
root_tag[Entities].append(p)
|
root_tag[Entities].append(p)
|
||||||
#self.saveInPlace();
|
#self.saveInPlace();
|
||||||
|
|
||||||
else:
|
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"
|
raise ValueError, "Can't do that yet"
|
||||||
# self.SurroundingGroundHeight = root_tag[Environment][SurroundingGroundHeight].value
|
# self.SurroundingGroundHeight = root_tag[Environment][SurroundingGroundHeight].value
|
||||||
# self.SurroundingGroundType = root_tag[Environment][SurroundingGroundType].value
|
# self.SurroundingGroundType = root_tag[Environment][SurroundingGroundType].value
|
||||||
@ -212,65 +212,65 @@ class MCIndevLevel(MCLevel):
|
|||||||
# self.Author = self.root_tag[About][Author].value
|
# self.Author = self.root_tag[About][Author].value
|
||||||
# self.CreatedOn = self.root_tag[About][CreatedOn].value
|
# self.CreatedOn = self.root_tag[About][CreatedOn].value
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def rotateLeft(self):
|
def rotateLeft(self):
|
||||||
MCLevel.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,
|
torchRotation = array([0, 4, 3, 1, 2, 5,
|
||||||
6, 7,
|
6, 7,
|
||||||
|
|
||||||
8, 9, 10, 11, 12, 13, 14, 15]);
|
8, 9, 10, 11, 12, 13, 14, 15]);
|
||||||
|
|
||||||
torchIndexes = (self.Blocks == self.materials.Torch.ID)
|
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]]
|
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: filename = self.filename;
|
||||||
if filename == None:
|
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!
|
return; #you fool!
|
||||||
|
|
||||||
self.Data <<= 4;
|
self.Data <<= 4;
|
||||||
self.Data |= (self.BlockLight & 0xf)
|
self.Data |= (self.BlockLight & 0xf)
|
||||||
|
|
||||||
self.Blocks = swapaxes(self.Blocks, 0, 2)
|
self.Blocks = swapaxes(self.Blocks, 0, 2)
|
||||||
self.Data = swapaxes(self.Data, 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[Width] = TAG_Short(self.Width);
|
||||||
mapTag[Height] = TAG_Short(self.Height);
|
mapTag[Height] = TAG_Short(self.Height);
|
||||||
mapTag[Length] = TAG_Short(self.Length);
|
mapTag[Length] = TAG_Short(self.Length);
|
||||||
mapTag[Blocks] = TAG_Byte_Array(self.Blocks);
|
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.Blocks = swapaxes(self.Blocks, 0, 2)
|
||||||
self.Data = swapaxes(self.Data, 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] = mapTag;
|
||||||
self.root_tag[Map]
|
self.root_tag[Map]
|
||||||
#output_file = gzip.open(self.filename, "wb", compresslevel=1)
|
#output_file = gzip.open(self.filename, "wb", compresslevel=1)
|
||||||
try:
|
try:
|
||||||
os.rename(filename, filename + ".old");
|
os.rename(filename, filename + ".old");
|
||||||
except Exception,e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.root_tag.saveGzipped(filename);
|
self.root_tag.saveGzipped(filename);
|
||||||
except:
|
except:
|
||||||
os.rename(filename + ".old", filename);
|
os.rename(filename + ".old", filename);
|
||||||
|
|
||||||
try: os.remove(filename + ".old");
|
try: os.remove(filename + ".old");
|
||||||
except Exception,e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
self.BlockLight = self.Data & 0xf
|
self.BlockLight = self.Data & 0xf
|
||||||
|
|
||||||
self.Data >>= 4
|
self.Data >>= 4
|
||||||
|
|
||||||
|
34
items.py
34
items.py
@ -257,20 +257,20 @@ items_txt = """
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
class ItemType (object):
|
class ItemType (object):
|
||||||
def __init__(self, id, name, imagefile = None, imagecoords = None, maxdamage = 0, damagevalue = 0, stacksize = 64):
|
def __init__(self, id, name, imagefile=None, imagecoords=None, maxdamage=0, damagevalue=0, stacksize=64):
|
||||||
self.id=id
|
self.id = id
|
||||||
self.name=name
|
self.name = name
|
||||||
self.imagefile=imagefile
|
self.imagefile = imagefile
|
||||||
self.imagecoords=imagecoords
|
self.imagecoords = imagecoords
|
||||||
self.maxdamage=maxdamage
|
self.maxdamage = maxdamage
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "ItemType({0}, '{1}')".format(self.id, self.name)
|
return "ItemType({0}, '{1}')".format(self.id, self.name)
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "ItemType {0}: {1}".format(self.id, self.name)
|
return "ItemType {0}: {1}".format(self.id, self.name)
|
||||||
|
|
||||||
class Items (object):
|
class Items (object):
|
||||||
items_txt = items_txt
|
items_txt = items_txt
|
||||||
def __init__(self, filename = None):
|
def __init__(self, filename=None):
|
||||||
if filename is None:
|
if filename is None:
|
||||||
items_txt = self.items_txt
|
items_txt = self.items_txt
|
||||||
else:
|
else:
|
||||||
@ -281,9 +281,9 @@ class Items (object):
|
|||||||
print "Error reading items.txt: ", e;
|
print "Error reading items.txt: ", e;
|
||||||
print "Using internal data."
|
print "Using internal data."
|
||||||
items_txt = self.items_txt
|
items_txt = self.items_txt
|
||||||
|
|
||||||
self.itemtypes = {};
|
self.itemtypes = {};
|
||||||
|
|
||||||
for line in items_txt.split("\n"):
|
for line in items_txt.split("\n"):
|
||||||
try:
|
try:
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
@ -293,7 +293,7 @@ class Items (object):
|
|||||||
stacksize = 64
|
stacksize = 64
|
||||||
damagevalue = None
|
damagevalue = None
|
||||||
maxdamage = 0
|
maxdamage = 0
|
||||||
|
|
||||||
fields = line.split();
|
fields = line.split();
|
||||||
if len(fields) >= 4:
|
if len(fields) >= 4:
|
||||||
maxdamage = None;
|
maxdamage = None;
|
||||||
@ -309,25 +309,25 @@ class Items (object):
|
|||||||
id = int(id);
|
id = int(id);
|
||||||
name = name.replace("_", " ");
|
name = name.replace("_", " ");
|
||||||
imagecoords = imagecoords.split(",");
|
imagecoords = imagecoords.split(",");
|
||||||
|
|
||||||
self.itemtypes[(id, damagevalue)] = ItemType(id, name, imagefile, imagecoords, maxdamage, damagevalue, stacksize)
|
self.itemtypes[(id, damagevalue)] = ItemType(id, name, imagefile, imagecoords, maxdamage, damagevalue, stacksize)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "Error reading line:", e
|
print "Error reading line:", e
|
||||||
print "Line: ", line
|
print "Line: ", line
|
||||||
print
|
print
|
||||||
|
|
||||||
self.names = dict((item.name, item.id) for item in self.itemtypes.itervalues())
|
self.names = dict((item.name, item.id) for item in self.itemtypes.itervalues())
|
||||||
|
|
||||||
def findItem(self, id=0, damage=None):
|
def findItem(self, id=0, damage=None):
|
||||||
item = self.itemtypes.get((id, damage))
|
item = self.itemtypes.get((id, damage))
|
||||||
if item: return item
|
if item: return item
|
||||||
|
|
||||||
item = self.itemtypes.get((id, None))
|
item = self.itemtypes.get((id, None))
|
||||||
if item: return item
|
if item: return item
|
||||||
|
|
||||||
item = self.itemtypes.get((id, 0))
|
item = self.itemtypes.get((id, 0))
|
||||||
if item: return item
|
if item: return item
|
||||||
|
|
||||||
raise ItemNotFound, "Item {0}:{1} not found".format(id, damage)
|
raise ItemNotFound, "Item {0}:{1} not found".format(id, damage)
|
||||||
|
|
||||||
class ItemNotFound(KeyError): pass
|
class ItemNotFound(KeyError): pass
|
||||||
|
576
materials.py
576
materials.py
File diff suppressed because it is too large
Load Diff
86
mclevel.py
86
mclevel.py
@ -192,12 +192,12 @@ import sys
|
|||||||
|
|
||||||
# we need to decode file paths from environment variables or else we get an error
|
# 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 they are formatted or joined to a unicode string
|
||||||
|
|
||||||
if sys.platform == "win32":
|
if sys.platform == "win32":
|
||||||
#not sure why win32com is needed if the %APPDATA% var is available
|
#not sure why win32com is needed if the %APPDATA% var is available
|
||||||
try:
|
try:
|
||||||
import win32com.client
|
import win32com.client
|
||||||
|
|
||||||
objShell = win32com.client.Dispatch("WScript.Shell")
|
objShell = win32com.client.Dispatch("WScript.Shell")
|
||||||
minecraftDir = os.path.join(objShell.SpecialFolders("AppData"), u".minecraft")
|
minecraftDir = os.path.join(objShell.SpecialFolders("AppData"), u".minecraft")
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@ -211,9 +211,9 @@ elif sys.platform == "darwin":
|
|||||||
else:
|
else:
|
||||||
minecraftDir = os.path.expanduser("~/.minecraft")
|
minecraftDir = os.path.expanduser("~/.minecraft")
|
||||||
minecraftDir.decode(sys.getfilesystemencoding());
|
minecraftDir.decode(sys.getfilesystemencoding());
|
||||||
|
|
||||||
saveFileDir = os.path.join(minecraftDir, u"saves")
|
saveFileDir = os.path.join(minecraftDir, u"saves")
|
||||||
|
|
||||||
#if sys.platform == "win32":
|
#if sys.platform == "win32":
|
||||||
# from win32com.shell import shell, shellcon
|
# from win32com.shell import shell, shellcon
|
||||||
# saveFileDir = shell.SHGetPathFromIDListEx (
|
# saveFileDir = shell.SHGetPathFromIDListEx (
|
||||||
@ -221,53 +221,53 @@ saveFileDir = os.path.join(minecraftDir, u"saves")
|
|||||||
# )
|
# )
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def fromFile(filename, loadInfinite=True):
|
def fromFile(filename, loadInfinite=True):
|
||||||
''' The preferred method for loading Minecraft levels of any type.
|
''' The preferred method for loading Minecraft levels of any type.
|
||||||
pass False to loadInfinite if you'd rather not load infdev levels.
|
pass False to loadInfinite if you'd rather not load infdev levels.
|
||||||
'''
|
'''
|
||||||
info( u"Identifying " + filename )
|
info(u"Identifying " + filename)
|
||||||
|
|
||||||
class LoadingError(RuntimeError): pass
|
class LoadingError(RuntimeError): pass
|
||||||
|
|
||||||
|
|
||||||
if not filename:
|
if not filename:
|
||||||
raise IOError, "File not found: "+filename
|
raise IOError, "File not found: " + filename
|
||||||
if not os.path.exists(filename):
|
if not os.path.exists(filename):
|
||||||
raise IOError, "File not found: "+filename
|
raise IOError, "File not found: " + filename
|
||||||
|
|
||||||
if (ZipSchematic._isLevel(filename)):
|
if (ZipSchematic._isLevel(filename)):
|
||||||
info( "Zipfile found, attempting zipped infinite level" )
|
info("Zipfile found, attempting zipped infinite level")
|
||||||
lev = ZipSchematic(filename);
|
lev = ZipSchematic(filename);
|
||||||
info( "Detected zipped Infdev level" )
|
info("Detected zipped Infdev level")
|
||||||
return lev
|
return lev
|
||||||
|
|
||||||
if (MCInfdevOldLevel._isLevel(filename)):
|
if (MCInfdevOldLevel._isLevel(filename)):
|
||||||
info( u"Detected Infdev level.dat" )
|
info(u"Detected Infdev level.dat")
|
||||||
if (loadInfinite):
|
if (loadInfinite):
|
||||||
return MCInfdevOldLevel(filename=filename);
|
return MCInfdevOldLevel(filename=filename);
|
||||||
else:
|
else:
|
||||||
raise ValueError, "Asked to load {0} which is an infinite level, loadInfinite was False".format(os.path.basename(filename));
|
raise ValueError, "Asked to load {0} which is an infinite level, loadInfinite was False".format(os.path.basename(filename));
|
||||||
|
|
||||||
if os.path.isdir(filename):
|
if os.path.isdir(filename):
|
||||||
raise ValueError, "Folder {0} was not identified as a Minecraft level.".format(os.path.basename(filename));
|
raise ValueError, "Folder {0} was not identified as a Minecraft level.".format(os.path.basename(filename));
|
||||||
|
|
||||||
f = file(filename, 'rb');
|
f = file(filename, 'rb');
|
||||||
rawdata = f.read()
|
rawdata = f.read()
|
||||||
f.close()
|
f.close()
|
||||||
if len(rawdata) < 4:
|
if len(rawdata) < 4:
|
||||||
raise ValueError, "{0} is too small! ({1}) ".format(filename, len(rawdata))
|
raise ValueError, "{0} is too small! ({1}) ".format(filename, len(rawdata))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data = fromstring(rawdata, dtype='uint8')
|
data = fromstring(rawdata, dtype='uint8')
|
||||||
if not data.any():
|
if not data.any():
|
||||||
raise ValueError, "{0} contains only zeroes. This file is damaged beyond repair."
|
raise ValueError, "{0} contains only zeroes. This file is damaged beyond repair."
|
||||||
|
|
||||||
|
|
||||||
if MCJavaLevel._isDataLevel(data):
|
if MCJavaLevel._isDataLevel(data):
|
||||||
info( u"Detected Java-style level" )
|
info(u"Detected Java-style level")
|
||||||
lev = MCJavaLevel(filename, data);
|
lev = MCJavaLevel(filename, data);
|
||||||
lev.compressed = False;
|
lev.compressed = False;
|
||||||
return lev;
|
return lev;
|
||||||
@ -277,16 +277,16 @@ def fromFile(filename, loadInfinite=True):
|
|||||||
unzippedData = None;
|
unzippedData = None;
|
||||||
try:
|
try:
|
||||||
unzippedData = gunzip(rawdata)
|
unzippedData = gunzip(rawdata)
|
||||||
except Exception,e:
|
except Exception, e:
|
||||||
info( u"Exception during Gzip operation, assuming {0} uncompressed: {1!r}".format(filename, e) )
|
info(u"Exception during Gzip operation, assuming {0} uncompressed: {1!r}".format(filename, e))
|
||||||
if unzippedData is None:
|
if unzippedData is None:
|
||||||
compressed = False;
|
compressed = False;
|
||||||
unzippedData = rawdata
|
unzippedData = rawdata
|
||||||
|
|
||||||
data = fromstring(unzippedData, dtype='uint8')
|
data = fromstring(unzippedData, dtype='uint8')
|
||||||
|
|
||||||
if MCJavaLevel._isDataLevel(data):
|
if MCJavaLevel._isDataLevel(data):
|
||||||
info( u"Detected compressed Java-style level" )
|
info(u"Detected compressed Java-style level")
|
||||||
lev = MCJavaLevel(filename, data);
|
lev = MCJavaLevel(filename, data);
|
||||||
lev.compressed = compressed;
|
lev.compressed = compressed;
|
||||||
return lev;
|
return lev;
|
||||||
@ -294,37 +294,37 @@ def fromFile(filename, loadInfinite=True):
|
|||||||
try:
|
try:
|
||||||
root_tag = nbt.load(buf=data);
|
root_tag = nbt.load(buf=data);
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
info( u"Error during NBT load: {0!r}".format(e) )
|
info(u"Error during NBT load: {0!r}".format(e))
|
||||||
info( u"Fallback: Detected compressed flat block array, yzx ordered " )
|
info(u"Fallback: Detected compressed flat block array, yzx ordered ")
|
||||||
try:
|
try:
|
||||||
lev = MCJavaLevel(filename, data);
|
lev = MCJavaLevel(filename, data);
|
||||||
lev.compressed = compressed;
|
lev.compressed = compressed;
|
||||||
return lev;
|
return lev;
|
||||||
except Exception, e2:
|
except Exception, e2:
|
||||||
raise LoadingError, ("Multiple errors encountered", e, e2)
|
raise LoadingError, ("Multiple errors encountered", e, e2)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if(MCIndevLevel._isTagLevel(root_tag)):
|
if(MCIndevLevel._isTagLevel(root_tag)):
|
||||||
info( u"Detected Indev .mclevel" )
|
info(u"Detected Indev .mclevel")
|
||||||
return MCIndevLevel(root_tag, filename)
|
return MCIndevLevel(root_tag, filename)
|
||||||
if(MCSchematic._isTagLevel(root_tag)):
|
if(MCSchematic._isTagLevel(root_tag)):
|
||||||
info( u"Detected Schematic." )
|
info(u"Detected Schematic.")
|
||||||
return MCSchematic(root_tag=root_tag, filename=filename)
|
return MCSchematic(root_tag=root_tag, filename=filename)
|
||||||
|
|
||||||
if (INVEditChest._isTagLevel(root_tag)):
|
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);
|
return INVEditChest(root_tag=root_tag, filename=filename);
|
||||||
|
|
||||||
|
|
||||||
#it must be a plain array of blocks. see if MCJavaLevel handles it.
|
#it must be a plain array of blocks. see if MCJavaLevel handles it.
|
||||||
|
|
||||||
raise IOError, "Cannot detect file type."
|
raise IOError, "Cannot detect file type."
|
||||||
|
|
||||||
|
|
||||||
def loadWorld(name):
|
def loadWorld(name):
|
||||||
filename = os.path.join(saveFileDir, name)
|
filename = os.path.join(saveFileDir, name)
|
||||||
return fromFile(filename)
|
return fromFile(filename)
|
||||||
|
|
||||||
def loadWorldNumber(i):
|
def loadWorldNumber(i):
|
||||||
#deprecated
|
#deprecated
|
||||||
filename = u"{0}{1}{2}{3}{1}".format(saveFileDir, os.sep, u"World", i)
|
filename = u"{0}{1}{2}{3}{1}".format(saveFileDir, os.sep, u"World", i)
|
||||||
|
@ -60,8 +60,8 @@ def unpack_first(func):
|
|||||||
return func(self, *args, **kw);
|
return func(self, *args, **kw);
|
||||||
upk_first.__doc__ = func.__doc__
|
upk_first.__doc__ = func.__doc__
|
||||||
return upk_first
|
return upk_first
|
||||||
|
|
||||||
class PlayerNotFound(Exception): pass
|
class PlayerNotFound(Exception): pass
|
||||||
class ChunkNotPresent(Exception): pass
|
class ChunkNotPresent(Exception): pass
|
||||||
class RegionMalformed(Exception): pass
|
class RegionMalformed(Exception): pass
|
||||||
class ChunkMalformed(ChunkNotPresent): pass
|
class ChunkMalformed(ChunkNotPresent): pass
|
||||||
|
248
nbt.py
248
nbt.py
@ -33,17 +33,17 @@ class NBTFormatError(RuntimeError): pass
|
|||||||
class TAG_Value(object):
|
class TAG_Value(object):
|
||||||
"""Simple values. Subclasses override fmt to change the type and size.
|
"""Simple values. Subclasses override fmt to change the type and size.
|
||||||
Subclasses may set dataType instead of overriding setValue for automatic data type coercion"""
|
Subclasses may set dataType instead of overriding setValue for automatic data type coercion"""
|
||||||
|
|
||||||
fmt = ">b";
|
fmt = ">b";
|
||||||
tag = -1; #error!
|
tag = -1; #error!
|
||||||
|
|
||||||
_value = None
|
_value = None
|
||||||
def getValue(self):
|
def getValue(self):
|
||||||
return self._value
|
return self._value
|
||||||
def setValue(self, newVal):
|
def setValue(self, newVal):
|
||||||
self._value = self.dataType(newVal)
|
self._value = self.dataType(newVal)
|
||||||
value = property(getValue, setValue, None, "Change the TAG's value. Data types are checked and coerced if needed.")
|
value = property(getValue, setValue, None, "Change the TAG's value. Data types are checked and coerced if needed.")
|
||||||
|
|
||||||
_name = None
|
_name = None
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return self._name
|
return self._name
|
||||||
@ -52,29 +52,29 @@ class TAG_Value(object):
|
|||||||
def delName(self):
|
def delName(self):
|
||||||
self._name = ""
|
self._name = ""
|
||||||
name = property(getName, setName, delName, "Change the TAG's name. Coerced to a string.")
|
name = property(getName, setName, delName, "Change the TAG's name. Coerced to a string.")
|
||||||
|
|
||||||
def __init__(self, value=0, name=None, data=""):
|
def __init__(self, value=0, name=None, data=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
if(data == ""):
|
if(data == ""):
|
||||||
self.value = value
|
self.value = value
|
||||||
else:
|
else:
|
||||||
(self.value,) = struct.unpack_from(self.fmt, data);
|
(self.value,) = struct.unpack_from(self.fmt, data);
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s( \"%s\" ): %s" % (str(self.__class__), self.name, repr(self.value))
|
return "%s( \"%s\" ): %s" % (str(self.__class__), self.name, repr(self.value))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.pretty_string()
|
return self.pretty_string()
|
||||||
|
|
||||||
def pretty_string(self, indent=0):
|
def pretty_string(self, indent=0):
|
||||||
if self.name:
|
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:
|
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):
|
def nbt_length(self):
|
||||||
return struct.calcsize(self.fmt);
|
return struct.calcsize(self.fmt);
|
||||||
|
|
||||||
def write_tag(self, buf):
|
def write_tag(self, buf):
|
||||||
buf.write(struct.pack(TAGfmt, self.tag))
|
buf.write(struct.pack(TAGfmt, self.tag))
|
||||||
def write_name(self, buf):
|
def write_name(self, buf):
|
||||||
@ -82,7 +82,7 @@ class TAG_Value(object):
|
|||||||
TAG_String(self.name).write_value(buf)
|
TAG_String(self.name).write_value(buf)
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
buf.write(struct.pack(self.fmt, self.value))
|
buf.write(struct.pack(self.fmt, self.value))
|
||||||
|
|
||||||
def save(self, filename="", buf=None):
|
def save(self, filename="", buf=None):
|
||||||
if(filename):
|
if(filename):
|
||||||
self.saveGzipped(filename);
|
self.saveGzipped(filename);
|
||||||
@ -100,7 +100,7 @@ class TAG_Value(object):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
#print "Atomic Save: No existing file to rename"
|
#print "Atomic Save: No existing file to rename"
|
||||||
pass
|
pass
|
||||||
|
|
||||||
with closing(gzip.GzipFile(fileobj=sio, mode="wb", compresslevel=compresslevel)) as outputGz:
|
with closing(gzip.GzipFile(fileobj=sio, mode="wb", compresslevel=compresslevel)) as outputGz:
|
||||||
self.save(buf=outputGz);
|
self.save(buf=outputGz);
|
||||||
outputGz.flush();
|
outputGz.flush();
|
||||||
@ -115,27 +115,27 @@ class TAG_Value(object):
|
|||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e;
|
print e;
|
||||||
return
|
return
|
||||||
|
|
||||||
try: os.remove(filename + ".old");
|
try: os.remove(filename + ".old");
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
#print "Atomic Save: No old file to remove"
|
#print "Atomic Save: No old file to remove"
|
||||||
pass;
|
pass;
|
||||||
|
|
||||||
class TAG_Byte(TAG_Value):
|
class TAG_Byte(TAG_Value):
|
||||||
tag = 1;
|
tag = 1;
|
||||||
fmt = ">b";
|
fmt = ">b";
|
||||||
dataType = int
|
dataType = int
|
||||||
|
|
||||||
class TAG_Short(TAG_Value):
|
class TAG_Short(TAG_Value):
|
||||||
tag = 2;
|
tag = 2;
|
||||||
fmt = ">h";
|
fmt = ">h";
|
||||||
dataType = int
|
dataType = int
|
||||||
|
|
||||||
class TAG_Int(TAG_Value):
|
class TAG_Int(TAG_Value):
|
||||||
tag = 3;
|
tag = 3;
|
||||||
fmt = ">i";
|
fmt = ">i";
|
||||||
dataType = int
|
dataType = int
|
||||||
|
|
||||||
class TAG_Long(TAG_Value):
|
class TAG_Long(TAG_Value):
|
||||||
tag = 4;
|
tag = 4;
|
||||||
fmt = ">q";
|
fmt = ">q";
|
||||||
@ -146,7 +146,7 @@ class TAG_Float(TAG_Value):
|
|||||||
fmt = ">f";
|
fmt = ">f";
|
||||||
dataType = float
|
dataType = float
|
||||||
|
|
||||||
|
|
||||||
class TAG_Double(TAG_Value):
|
class TAG_Double(TAG_Value):
|
||||||
tag = 6;
|
tag = 6;
|
||||||
fmt = ">d";
|
fmt = ">d";
|
||||||
@ -162,22 +162,22 @@ class TAG_Byte_Array(TAG_Value):
|
|||||||
|
|
||||||
def dataType(self, value):
|
def dataType(self, value):
|
||||||
return array(value, uint8)
|
return array(value, uint8)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<%s: length %d> ( %s )" % (self.__class__, len(self.value), self.name)
|
return "<%s: length %d> ( %s )" % (self.__class__, len(self.value), self.name)
|
||||||
|
|
||||||
|
|
||||||
def pretty_string(self, indent=0):
|
def pretty_string(self, indent=0):
|
||||||
if self.name:
|
if self.name:
|
||||||
return " "*indent + "%s( \"%s\" ): shape=%s dtype=%s %s" % (
|
return " " * indent + "%s( \"%s\" ): shape=%s dtype=%s %s" % (
|
||||||
str(self.__class__.__name__),
|
str(self.__class__.__name__),
|
||||||
self.name,
|
self.name,
|
||||||
str(self.value.shape),
|
str(self.value.shape),
|
||||||
str(self.value.dtype),
|
str(self.value.dtype),
|
||||||
self.value)
|
self.value)
|
||||||
else:
|
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=""):
|
def __init__(self, value=zeros(0, uint8), name=None, data=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
if(data == ""):
|
if(data == ""):
|
||||||
@ -185,21 +185,21 @@ class TAG_Byte_Array(TAG_Value):
|
|||||||
else:
|
else:
|
||||||
(string_len,) = struct.unpack_from(">I", data);
|
(string_len,) = struct.unpack_from(">I", data);
|
||||||
self.value = fromstring(data[4:string_len + 4], 'uint8');
|
self.value = fromstring(data[4:string_len + 4], 'uint8');
|
||||||
|
|
||||||
def nbt_length(self) :
|
def nbt_length(self) :
|
||||||
return len(self.value) + 4;
|
return len(self.value) + 4;
|
||||||
|
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
#print self.value
|
#print self.value
|
||||||
valuestr = self.value.tostring()
|
valuestr = self.value.tostring()
|
||||||
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr), valuestr))
|
buf.write(struct.pack(self.fmt % (len(valuestr),), len(valuestr), valuestr))
|
||||||
|
|
||||||
class TAG_Int_Array(TAG_Byte_Array):
|
class TAG_Int_Array(TAG_Byte_Array):
|
||||||
"""An array of ints"""
|
"""An array of ints"""
|
||||||
tag = 11;
|
tag = 11;
|
||||||
def dataType(self, value):
|
def dataType(self, value):
|
||||||
return array(value, '>u4')
|
return array(value, '>u4')
|
||||||
|
|
||||||
def __init__(self, value=zeros(0, ">u4"), name=None, data=""):
|
def __init__(self, value=zeros(0, ">u4"), name=None, data=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
if(data == ""):
|
if(data == ""):
|
||||||
@ -207,22 +207,22 @@ class TAG_Int_Array(TAG_Byte_Array):
|
|||||||
else:
|
else:
|
||||||
(string_len,) = struct.unpack_from(">I", data);
|
(string_len,) = struct.unpack_from(">I", data);
|
||||||
self.value = fromstring(data[4:string_len * 4 + 4], '>u4')
|
self.value = fromstring(data[4:string_len * 4 + 4], '>u4')
|
||||||
|
|
||||||
|
|
||||||
def nbt_length(self) :
|
def nbt_length(self) :
|
||||||
return len(self.value) * 4 + 4;
|
return len(self.value) * 4 + 4;
|
||||||
|
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
#print self.value
|
#print self.value
|
||||||
valuestr = self.value.tostring()
|
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):
|
class TAG_Short_Array(TAG_Int_Array):
|
||||||
"""An array of ints"""
|
"""An array of ints"""
|
||||||
tag = 12;
|
tag = 12;
|
||||||
def dataType(self, value):
|
def dataType(self, value):
|
||||||
return array(value, '>u2')
|
return array(value, '>u2')
|
||||||
|
|
||||||
def __init__(self, value=zeros(0, ">u2"), name=None, data=""):
|
def __init__(self, value=zeros(0, ">u2"), name=None, data=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
if(data == ""):
|
if(data == ""):
|
||||||
@ -230,25 +230,25 @@ class TAG_Short_Array(TAG_Int_Array):
|
|||||||
else:
|
else:
|
||||||
(string_len,) = struct.unpack_from(">I", data);
|
(string_len,) = struct.unpack_from(">I", data);
|
||||||
self.value = fromstring(data[4:string_len * 2 + 4], '>u2')
|
self.value = fromstring(data[4:string_len * 2 + 4], '>u2')
|
||||||
|
|
||||||
|
|
||||||
def nbt_length(self) :
|
def nbt_length(self) :
|
||||||
return len(self.value) * 2 + 4;
|
return len(self.value) * 2 + 4;
|
||||||
|
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
#print self.value
|
#print self.value
|
||||||
valuestr = self.value.tostring()
|
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):
|
class TAG_String(TAG_Value):
|
||||||
"""String in UTF-8
|
"""String in UTF-8
|
||||||
The data parameter should either be a 'unicode' or an ascii-encoded 'str'
|
The data parameter should either be a 'unicode' or an ascii-encoded 'str'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
tag = 8;
|
tag = 8;
|
||||||
fmt = ">h%ds"
|
fmt = ">h%ds"
|
||||||
dataType = unicode
|
dataType = unicode
|
||||||
|
|
||||||
def __init__(self, value="", name=None, data=""):
|
def __init__(self, value="", name=None, data=""):
|
||||||
self.name = name
|
self.name = name
|
||||||
if(data == ""):
|
if(data == ""):
|
||||||
@ -263,7 +263,7 @@ class TAG_String(TAG_Value):
|
|||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
u8value = self.value.encode('utf-8')
|
u8value = self.value.encode('utf-8')
|
||||||
buf.write(struct.pack(self.fmt % (len(u8value),), len(u8value), u8value))
|
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."""
|
operator []. This will automatically name the tags."""
|
||||||
|
|
||||||
tag = 10;
|
tag = 10;
|
||||||
|
|
||||||
def dataType(self, val):
|
def dataType(self, val):
|
||||||
for i in val:
|
for i in val:
|
||||||
assert isinstance(i, TAG_Value)
|
assert isinstance(i, TAG_Value)
|
||||||
assert i.name
|
assert i.name
|
||||||
return list(val)
|
return list(val)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s( %s ): %s" % (str(self.__class__.__name__), self.name, self.value)
|
return "%s( %s ): %s" % (str(self.__class__.__name__), self.name, self.value)
|
||||||
|
|
||||||
def pretty_string(self, indent=0):
|
def pretty_string(self, indent=0):
|
||||||
if self.name:
|
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:
|
else:
|
||||||
pretty = " "*indent + "%s():\n" % (str(self.__class__.__name__))
|
pretty = " " * indent + "%s():\n" % (str(self.__class__.__name__))
|
||||||
indent += 4
|
indent += 4
|
||||||
for tag in self.value:
|
for tag in self.value:
|
||||||
pretty += tag.pretty_string(indent) + "\n"
|
pretty += tag.pretty_string(indent) + "\n"
|
||||||
return pretty
|
return pretty
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, value=[], name="", data=""):
|
def __init__(self, value=[], name="", data=""):
|
||||||
|
|
||||||
self.name = name;
|
self.name = name;
|
||||||
if value.__class__ == ''.__class__:
|
if value.__class__ == ''.__class__:
|
||||||
self.name = value;
|
self.name = value;
|
||||||
@ -306,7 +306,7 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
|
|||||||
else:
|
else:
|
||||||
|
|
||||||
data_cursor = 0;
|
data_cursor = 0;
|
||||||
|
|
||||||
while data_cursor < len(data):
|
while data_cursor < len(data):
|
||||||
tag_type = data[data_cursor];
|
tag_type = data[data_cursor];
|
||||||
data_cursor += 1;
|
data_cursor += 1;
|
||||||
@ -314,21 +314,21 @@ class TAG_Compound(TAG_Value, collections.MutableMapping):
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
assert_type(tag_type, data_cursor)
|
assert_type(tag_type, data_cursor)
|
||||||
|
|
||||||
|
|
||||||
data_cursor, tag = load_named(data, data_cursor, tag_type)
|
data_cursor, tag = load_named(data, data_cursor, tag_type)
|
||||||
|
|
||||||
self.value.append(tag);
|
self.value.append(tag);
|
||||||
|
|
||||||
|
|
||||||
def nbt_length(self):
|
def nbt_length(self):
|
||||||
return sum(x.nbt_length() + len(x.name) + 3 for x in self.value) + 1;
|
return sum(x.nbt_length() + len(x.name) + 3 for x in self.value) + 1;
|
||||||
|
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
for i in self.value:
|
for i in self.value:
|
||||||
i.save(buf=buf)
|
i.save(buf=buf)
|
||||||
buf.write("\x00")
|
buf.write("\x00")
|
||||||
|
|
||||||
"collection functions"
|
"collection functions"
|
||||||
def __getitem__(self, k):
|
def __getitem__(self, k):
|
||||||
#hits=filter(lambda x:x.name==k, self.value);
|
#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:
|
for key in self.value:
|
||||||
if key.name == k: return key
|
if key.name == k: return key
|
||||||
raise KeyError("Key {0} not found".format(k));
|
raise KeyError("Key {0} not found".format(k));
|
||||||
|
|
||||||
def __iter__(self): return itertools.imap(lambda x:x.name, self.value);
|
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 __contains__(self, k):return k in map(lambda x:x.name, self.value);
|
||||||
def __len__(self): return self.value.__len__()
|
def __len__(self): return self.value.__len__()
|
||||||
|
|
||||||
|
|
||||||
def __setitem__(self, k, v):
|
def __setitem__(self, k, v):
|
||||||
if not (v.__class__ in tag_handlers.values()): raise TypeError("Invalid type %s for TAG_Compound" % (v.__class__))
|
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)
|
for i in olditems: self.value.remove(i)
|
||||||
self.value.append(v);
|
self.value.append(v);
|
||||||
v.name = k;
|
v.name = k;
|
||||||
|
|
||||||
def __delitem__(self, k): self.value.__delitem__(self.value.index(self[k]));
|
def __delitem__(self, k): self.value.__delitem__(self.value.index(self[k]));
|
||||||
|
|
||||||
def add(self, v):
|
def add(self, v):
|
||||||
self[v.name] = v;
|
self[v.name] = v;
|
||||||
|
|
||||||
class TAG_List(TAG_Value, collections.MutableSequence):
|
class TAG_List(TAG_Value, collections.MutableSequence):
|
||||||
|
|
||||||
"""A homogenous list of unnamed data of a single TAG_* type.
|
"""A homogenous list of unnamed data of a single TAG_* type.
|
||||||
Once created, the type can only be changed by emptying the list
|
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,
|
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?
|
# 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)
|
assert all(isinstance(x, listType) and x.name in ("", "None") for x in val)
|
||||||
return list(val)
|
return list(val)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "%s( %s ): %s" % (self.__class__.__name__, self.name, self.value)
|
return "%s( %s ): %s" % (self.__class__.__name__, self.name, self.value)
|
||||||
|
|
||||||
|
|
||||||
def pretty_string(self, indent=0):
|
def pretty_string(self, indent=0):
|
||||||
if self.name:
|
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:
|
else:
|
||||||
pretty = " "*indent + "%s():\n" % (str(self.__class__.__name__), )
|
pretty = " " * indent + "%s():\n" % (str(self.__class__.__name__),)
|
||||||
|
|
||||||
indent += 4
|
indent += 4
|
||||||
for tag in self.value:
|
for tag in self.value:
|
||||||
pretty += tag.pretty_string(indent) + "\n"
|
pretty += tag.pretty_string(indent) + "\n"
|
||||||
return pretty
|
return pretty
|
||||||
|
|
||||||
def __init__(self, value=[], name=None, data=None, list_type=TAG_Compound):
|
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
|
#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
|
#name, or created from raw tag data, or created with list_type
|
||||||
#taken from a TAG class or instance
|
#taken from a TAG class or instance
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
self.value = [];
|
self.value = [];
|
||||||
self.list_type = list_type.tag
|
self.list_type = list_type.tag
|
||||||
|
|
||||||
if(data == None):
|
if(data == None):
|
||||||
if(len(value)):
|
if(len(value)):
|
||||||
self.list_type = value[0].tag;
|
self.list_type = value[0].tag;
|
||||||
value = filter(lambda x:x.__class__ == value[0].__class__, value)
|
value = filter(lambda x:x.__class__ == value[0].__class__, value)
|
||||||
|
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
else:
|
else:
|
||||||
data_cursor = 0;
|
data_cursor = 0;
|
||||||
|
|
||||||
self.list_type = data[data_cursor];
|
self.list_type = data[data_cursor];
|
||||||
assert_type(self.list_type, data_cursor);
|
assert_type(self.list_type, data_cursor);
|
||||||
|
|
||||||
data_cursor += 1;
|
data_cursor += 1;
|
||||||
|
|
||||||
list_length = TAG_Int(data=data[data_cursor:])
|
list_length = TAG_Int(data=data[data_cursor:])
|
||||||
data_cursor += list_length.nbt_length()
|
data_cursor += list_length.nbt_length()
|
||||||
list_length = list_length.value
|
list_length = list_length.value
|
||||||
|
|
||||||
|
|
||||||
for i in range(list_length):
|
for i in range(list_length):
|
||||||
|
|
||||||
tag = tag_handlers[self.list_type](data=data[data_cursor:])
|
tag = tag_handlers[self.list_type](data=data[data_cursor:])
|
||||||
self.append(tag);
|
self.append(tag);
|
||||||
data_cursor += tag.nbt_length()
|
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 __contains__(self, k):return k in self.value;
|
||||||
def __getitem__(self, i): return self.value[i];
|
def __getitem__(self, i): return self.value[i];
|
||||||
def __len__(self): return len(self.value)
|
def __len__(self): return len(self.value)
|
||||||
|
|
||||||
def __setitem__(self, i, v):
|
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]))
|
raise TypeError("Invalid type %s for TAG_List(%s)" % (v.__class__, tag_handlers[self.list_type]))
|
||||||
v.name = ""
|
v.name = ""
|
||||||
self.value[i] = v;
|
self.value[i] = v;
|
||||||
|
|
||||||
def __delitem__(self, i):
|
def __delitem__(self, i):
|
||||||
del self.value[i]
|
del self.value[i]
|
||||||
|
|
||||||
def insert(self, i, v):
|
def insert(self, i, v):
|
||||||
if not v.tag in tag_handlers: raise TypeError("Not a tag type: %s" % (v,))
|
if not v.tag in tag_handlers: raise TypeError("Not a tag type: %s" % (v,))
|
||||||
if len(self) == 0:
|
if len(self) == 0:
|
||||||
self.list_type = v.tag
|
self.list_type = v.tag
|
||||||
else:
|
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]))
|
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 = ""
|
v.name = ""
|
||||||
self.value.insert(i, v);
|
self.value.insert(i, v);
|
||||||
|
|
||||||
def nbt_length(self):
|
def nbt_length(self):
|
||||||
return 5 + sum(x.nbt_length() for x in self.value)
|
return 5 + sum(x.nbt_length() for x in self.value)
|
||||||
|
|
||||||
def write_value(self, buf):
|
def write_value(self, buf):
|
||||||
buf.write(struct.pack(TAGfmt, self.list_type))
|
buf.write(struct.pack(TAGfmt, self.list_type))
|
||||||
TAG_Int(len(self)).write_value(buf)
|
TAG_Int(len(self)).write_value(buf)
|
||||||
for i in self.value:
|
for i in self.value:
|
||||||
i.write_value(buf)
|
i.write_value(buf)
|
||||||
|
|
||||||
|
|
||||||
tag_handlers = {
|
tag_handlers = {
|
||||||
1 : TAG_Byte,
|
1 : TAG_Byte,
|
||||||
@ -476,11 +476,11 @@ tag_handlers = {
|
|||||||
def assert_type(t, offset) :
|
def assert_type(t, offset) :
|
||||||
if not t in tag_handlers: raise ValueError("Unexpected tag type %d at %d" % (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):
|
def gunzip(data):
|
||||||
#strip off the header and use negative WBITS to tell zlib there's no header
|
#strip off the header and use negative WBITS to tell zlib there's no header
|
||||||
return zlib.decompress(data[10:], -zlib.MAX_WBITS)
|
return zlib.decompress(data[10:], -zlib.MAX_WBITS)
|
||||||
|
|
||||||
def loadFile(filename):
|
def loadFile(filename):
|
||||||
#sio = StringIO.StringIO();
|
#sio = StringIO.StringIO();
|
||||||
with file(filename, "rb") as f:
|
with file(filename, "rb") as f:
|
||||||
@ -491,14 +491,14 @@ def loadFile(filename):
|
|||||||
data = gunzip(inputdata)
|
data = gunzip(inputdata)
|
||||||
except IOError:
|
except IOError:
|
||||||
print "File %s not zipped" % filename
|
print "File %s not zipped" % filename
|
||||||
|
|
||||||
return load(buf=fromstring(data, 'uint8'));
|
return load(buf=fromstring(data, 'uint8'));
|
||||||
|
|
||||||
def load_named(data, data_cursor, tag_type):
|
def load_named(data, data_cursor, tag_type):
|
||||||
tag_name = TAG_String(data=data[data_cursor:])
|
tag_name = TAG_String(data=data[data_cursor:])
|
||||||
data_cursor += tag_name.nbt_length()
|
data_cursor += tag_name.nbt_length()
|
||||||
tag_name = tag_name.value
|
tag_name = tag_name.value
|
||||||
|
|
||||||
tag = tag_handlers[tag_type](data=data[data_cursor:], name=tag_name)
|
tag = tag_handlers[tag_type](data=data[data_cursor:], name=tag_name)
|
||||||
data_cursor += tag.nbt_length()
|
data_cursor += tag.nbt_length()
|
||||||
return data_cursor, tag
|
return data_cursor, tag
|
||||||
@ -507,7 +507,7 @@ def load(filename="", buf=None):
|
|||||||
"""Unserialize data from an entire NBT file and return the
|
"""Unserialize data from an entire NBT file and return the
|
||||||
root TAG_Compound object. Argument can be a string containing a
|
root TAG_Compound object. Argument can be a string containing a
|
||||||
filename or an array of integers containing TAG_Compound data. """
|
filename or an array of integers containing TAG_Compound data. """
|
||||||
|
|
||||||
if filename and isinstance(filename, (str, unicode)):
|
if filename and isinstance(filename, (str, unicode)):
|
||||||
return loadFile(filename)
|
return loadFile(filename)
|
||||||
if isinstance(buf, str): buf = fromstring(buf, uint8)
|
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."""
|
"""Use the [] operator to look up subtags of a TAG_Compound."""
|
||||||
print level["Environment"]["SurroundingGroundHeight"].value;
|
print level["Environment"]["SurroundingGroundHeight"].value;
|
||||||
|
|
||||||
|
|
||||||
"""Numeric, string, and bytearray types have a value
|
"""Numeric, string, and bytearray types have a value
|
||||||
that can be accessed and changed. """
|
that can be accessed and changed. """
|
||||||
print level["Map"]["Blocks"].value
|
print level["Map"]["Blocks"].value
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
|
|
||||||
def createtest():
|
def createtest():
|
||||||
"Create an indev level."
|
"Create an indev level."
|
||||||
|
|
||||||
"The root of an NBT file is always a TAG_Compound."
|
"The root of an NBT file is always a TAG_Compound."
|
||||||
level = TAG_Compound(name="MinecraftLevel")
|
level = TAG_Compound(name="MinecraftLevel")
|
||||||
|
|
||||||
@ -558,52 +558,52 @@ def createtest():
|
|||||||
level["Environment"] = TAG_Compound()
|
level["Environment"] = TAG_Compound()
|
||||||
level["Environment"]["SkyBrightness"] = TAG_Byte(16)
|
level["Environment"]["SkyBrightness"] = TAG_Byte(16)
|
||||||
level["Environment"]["SurroundingWaterHeight"] = TAG_Short(32)
|
level["Environment"]["SurroundingWaterHeight"] = TAG_Short(32)
|
||||||
|
|
||||||
"You can also create and name a tag before adding it to the compound."
|
"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 = TAG_List((TAG_Short(100), TAG_Short(45), TAG_Short(55)))
|
||||||
spawn.name = "Spawn"
|
spawn.name = "Spawn"
|
||||||
|
|
||||||
mapTag = TAG_Compound()
|
mapTag = TAG_Compound()
|
||||||
mapTag.add(spawn);
|
mapTag.add(spawn);
|
||||||
mapTag.name = "Map"
|
mapTag.name = "Map"
|
||||||
level.add(mapTag)
|
level.add(mapTag)
|
||||||
|
|
||||||
"I think it looks more familiar with [] syntax."
|
"I think it looks more familiar with [] syntax."
|
||||||
|
|
||||||
l, w, h = 128, 128, 128
|
l, w, h = 128, 128, 128
|
||||||
mapTag["Height"] = TAG_Short(h) # y dimension
|
mapTag["Height"] = TAG_Short(h) # y dimension
|
||||||
mapTag["Length"] = TAG_Short(l) # z dimension
|
mapTag["Length"] = TAG_Short(l) # z dimension
|
||||||
mapTag["Width"] = TAG_Short(w) # x dimension
|
mapTag["Width"] = TAG_Short(w) # x dimension
|
||||||
|
|
||||||
"Byte arrays are stored as numpy.uint8 arrays. "
|
"Byte arrays are stored as numpy.uint8 arrays. "
|
||||||
|
|
||||||
mapTag["Blocks"] = TAG_Byte_Array()
|
mapTag["Blocks"] = TAG_Byte_Array()
|
||||||
mapTag["Blocks"].value = zeros(l * w * h, dtype=uint8) #create lots of air!
|
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"
|
"The blocks array is indexed (y,z,x) for indev levels, so reshape the blocks"
|
||||||
mapTag["Blocks"].value.shape = (h, l, w);
|
mapTag["Blocks"].value.shape = (h, l, w);
|
||||||
|
|
||||||
"Replace the bottom layer of the indev level with wood"
|
"Replace the bottom layer of the indev level with wood"
|
||||||
mapTag["Blocks"].value[0, :, :] = 5;
|
mapTag["Blocks"].value[0, :, :] = 5;
|
||||||
|
|
||||||
"This is a great way to learn the power of numpy array slicing and indexing."
|
"This is a great way to learn the power of numpy array slicing and indexing."
|
||||||
|
|
||||||
|
|
||||||
return level;
|
return level;
|
||||||
|
|
||||||
def modifytest():
|
def modifytest():
|
||||||
level = createtest();
|
level = createtest();
|
||||||
|
|
||||||
"Most of the value types work as expected. Here, we replace the entire tag with a TAG_String"
|
"Most of the value types work as expected. Here, we replace the entire tag with a TAG_String"
|
||||||
level["About"]["Author"] = TAG_String("YARRR~!");
|
level["About"]["Author"] = TAG_String("YARRR~!");
|
||||||
|
|
||||||
"Because the tag type usually doesn't change, "
|
"Because the tag type usually doesn't change, "
|
||||||
"we can replace the string tag's value instead of replacing the entire tag."
|
"we can replace the string tag's value instead of replacing the entire tag."
|
||||||
level["About"]["Author"].value = "Stew Pickles"
|
level["About"]["Author"].value = "Stew Pickles"
|
||||||
|
|
||||||
"Remove members of a TAG_Compound using del, similar to a python dict."
|
"Remove members of a TAG_Compound using del, similar to a python dict."
|
||||||
del(level["About"]);
|
del(level["About"]);
|
||||||
|
|
||||||
"Replace all of the wood blocks with gold using a boolean index array"
|
"Replace all of the wood blocks with gold using a boolean index array"
|
||||||
blocks = level["Map"]["Blocks"].value
|
blocks = level["Map"]["Blocks"].value
|
||||||
blocks[blocks == 5] = 41;
|
blocks[blocks == 5] = 41;
|
||||||
@ -613,10 +613,10 @@ def savetest():
|
|||||||
|
|
||||||
level = createtest()
|
level = createtest()
|
||||||
level["Environment"]["SurroundingWaterHeight"].value += 6;
|
level["Environment"]["SurroundingWaterHeight"].value += 6;
|
||||||
|
|
||||||
"Save the entire TAG structure to a different file."
|
"Save the entire TAG structure to a different file."
|
||||||
level.save("atlantis.mclevel")
|
level.save("atlantis.mclevel")
|
||||||
|
|
||||||
level = createtest();
|
level = createtest();
|
||||||
level.save("synthetic.mclevel");
|
level.save("synthetic.mclevel");
|
||||||
|
|
||||||
@ -626,7 +626,7 @@ def abusetest():
|
|||||||
named list elements are not allowed by the NBT spec,
|
named list elements are not allowed by the NBT spec,
|
||||||
so we must discard any names when writing a list.
|
so we must discard any names when writing a list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
level = createtest();
|
level = createtest();
|
||||||
level["Map"]["Spawn"][0].name = "Torg Potter"
|
level["Map"]["Spawn"][0].name = "Torg Potter"
|
||||||
sio = StringIO.StringIO()
|
sio = StringIO.StringIO()
|
||||||
@ -647,9 +647,9 @@ def abusetest():
|
|||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
assert False
|
assert False
|
||||||
|
|
||||||
|
|
||||||
def runtests():
|
def runtests():
|
||||||
loadtest();
|
loadtest();
|
||||||
createtest();
|
createtest();
|
||||||
modifytest();
|
modifytest();
|
||||||
@ -661,5 +661,5 @@ if(__name__ == "__main__") :
|
|||||||
runtests()
|
runtests()
|
||||||
|
|
||||||
__all__ = [a.__name__ for a in tag_handlers.itervalues()] + ["loadFile", "gunzip"]
|
__all__ = [a.__name__ for a in tag_handlers.itervalues()] + ["loadFile", "gunzip"]
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ def generate_file_list(directory):
|
|||||||
yield os.path.join(dirpath, filename)
|
yield os.path.join(dirpath, filename)
|
||||||
|
|
||||||
def sha1_file(name, checksum=None):
|
def sha1_file(name, checksum=None):
|
||||||
CHUNKSIZE=1024
|
CHUNKSIZE = 1024
|
||||||
if checksum is None:
|
if checksum is None:
|
||||||
checksum = hashlib.sha1()
|
checksum = hashlib.sha1()
|
||||||
if fnmatch.fnmatch(name, "*.dat"):
|
if fnmatch.fnmatch(name, "*.dat"):
|
||||||
@ -71,17 +71,17 @@ def untared_content(src):
|
|||||||
f.extractall(dest)
|
f.extractall(dest)
|
||||||
yield 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
|
#my python breaks with an empty environ, i think it wants PATH
|
||||||
#if sys.platform == "win32":
|
#if sys.platform == "win32":
|
||||||
newenv = {}
|
newenv = {}
|
||||||
newenv.update(os.environ)
|
newenv.update(os.environ)
|
||||||
newenv.update(env);
|
newenv.update(env);
|
||||||
|
|
||||||
proc = subprocess.Popen((["python.exe"] if sys.platform == "win32" else []) + [
|
proc = subprocess.Popen((["python.exe"] if sys.platform == "win32" else []) + [
|
||||||
"./mce.py",
|
"./mce.py",
|
||||||
directory] + arguments, stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=newenv)
|
directory] + arguments, stdin=subprocess.PIPE, stdout=subprocess.PIPE, env=newenv)
|
||||||
|
|
||||||
return proc
|
return proc
|
||||||
|
|
||||||
class RegressionError(Exception): pass
|
class RegressionError(Exception): pass
|
||||||
@ -129,7 +129,7 @@ def do_test_match_output(test_data, result_check, arguments=[]):
|
|||||||
proc.stdin.close()
|
proc.stdin.close()
|
||||||
output = proc.stdout.read()
|
output = proc.stdout.read()
|
||||||
proc.wait()
|
proc.wait()
|
||||||
|
|
||||||
if proc.returncode:
|
if proc.returncode:
|
||||||
raise RegressionError("Program execution failed!")
|
raise RegressionError("Program execution failed!")
|
||||||
|
|
||||||
@ -146,13 +146,13 @@ def do_test_match_output(test_data, result_check, arguments=[]):
|
|||||||
|
|
||||||
|
|
||||||
alpha_tests = [
|
alpha_tests = [
|
||||||
(do_test, 'baseline', '9e7460d39c8e0456789cf89fee45276db2719aaa', []),
|
(do_test, 'baseline', '9e7460d39c8e0456789cf89fee45276db2719aaa', []),
|
||||||
(do_test, 'degrief', '403e6c6147cf1f8d73377b18bbf5e4973606a311', ['degrief']),
|
(do_test, 'degrief', '403e6c6147cf1f8d73377b18bbf5e4973606a311', ['degrief']),
|
||||||
(do_test_match_output, 'analyze', '89ae362dec7f6c0fd743d6ed4e3957459cb3c34d', ['analyze']),
|
(do_test_match_output, 'analyze', '89ae362dec7f6c0fd743d6ed4e3957459cb3c34d', ['analyze']),
|
||||||
(do_test, 'relight', 'e0cf60c62adfdb313f198af5314c31f89d158c12', ['relight']),
|
(do_test, 'relight', 'e0cf60c62adfdb313f198af5314c31f89d158c12', ['relight']),
|
||||||
(do_test, 'replace', 'd73767293e903b6d1c49c1838eb1849b69d83ad8', ['replace', 'Water (active)', 'with', 'Lava (active)']),
|
(do_test, 'replace', 'd73767293e903b6d1c49c1838eb1849b69d83ad8', ['replace', 'Water (active)', 'with', 'Lava (active)']),
|
||||||
(do_test, 'fill', 'f4f57c3d902b6894031d416cb9279232e7e24bd7', ['fill', 'Water (active)']),
|
(do_test, 'fill', 'f4f57c3d902b6894031d416cb9279232e7e24bd7', ['fill', 'Water (active)']),
|
||||||
(do_test, 'heightmap', '9e7460d39c8e0456789cf89fee45276db2719aaa', ['heightmap', 'regression_test/mars.png']),
|
(do_test, 'heightmap', '9e7460d39c8e0456789cf89fee45276db2719aaa', ['heightmap', 'regression_test/mars.png']),
|
||||||
]
|
]
|
||||||
|
|
||||||
import optparse
|
import optparse
|
||||||
@ -172,26 +172,26 @@ def main(argv):
|
|||||||
test_data = os.path.join(directory, "alpha")
|
test_data = os.path.join(directory, "alpha")
|
||||||
passes = []
|
passes = []
|
||||||
fails = []
|
fails = []
|
||||||
|
|
||||||
for func, name, sha, args in alpha_tests:
|
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 any(fnmatch.fnmatch(name, x) for x in do_these_regressions):
|
||||||
if options.profile:
|
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
|
os.environ['MCE_PROFILE'] = '%s.profile' % name
|
||||||
try:
|
try:
|
||||||
func(test_data, sha, args)
|
func(test_data, sha, args)
|
||||||
except RegressionError, e:
|
except RegressionError, e:
|
||||||
fails.append( "Regression {0} failed: {1}".format(name, e) )
|
fails.append("Regression {0} failed: {1}".format(name, e))
|
||||||
print fails[-1]
|
print fails[-1]
|
||||||
else:
|
else:
|
||||||
passes.append( "Regression {0!r} complete.".format(name) )
|
passes.append("Regression {0!r} complete.".format(name))
|
||||||
print passes[-1]
|
print passes[-1]
|
||||||
|
|
||||||
print "{0} tests passed.".format(len(passes))
|
print "{0} tests passed.".format(len(passes))
|
||||||
for line in fails: print line;
|
for line in fails: print line;
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
sys.exit(main(sys.argv))
|
sys.exit(main(sys.argv))
|
||||||
|
@ -468,6 +468,7 @@ def extractSchematicFrom(sourceLevel, box):
|
|||||||
|
|
||||||
return tempSchematic
|
return tempSchematic
|
||||||
|
|
||||||
|
import tempfile
|
||||||
def extractZipSchematicFrom(sourceLevel, box, zipfilename):
|
def extractZipSchematicFrom(sourceLevel, box, zipfilename):
|
||||||
#converts classic blocks to alpha
|
#converts classic blocks to alpha
|
||||||
#probably should only apply to alpha levels
|
#probably should only apply to alpha levels
|
||||||
|
Reference in New Issue
Block a user