refactor some entity code out to entity.py
This commit is contained in:
parent
6e7c6f0ab3
commit
b664a2bf73
40
entity.py
40
entity.py
@ -7,7 +7,22 @@ from mclevelbase import *
|
|||||||
|
|
||||||
__all__ = "Entity, TileEntity".split(", ")
|
__all__ = "Entity, TileEntity".split(", ")
|
||||||
|
|
||||||
|
EntityId = "EntityId"
|
||||||
|
id = "id"
|
||||||
|
|
||||||
|
Motion = "Motion"
|
||||||
|
Pos = "Pos"
|
||||||
|
Rotation = "Rotation"
|
||||||
|
|
||||||
class TileEntity(object):
|
class TileEntity(object):
|
||||||
|
knownIDs = "Furnace, Sign, MonsterSpawner, Chest, Music, Trap, RecordPlayer".split(", ")
|
||||||
|
@classmethod
|
||||||
|
def Create(cls, tileEntityID, **kw):
|
||||||
|
tileEntityTag = TAG_Compound()
|
||||||
|
tileEntityTag[id] = TAG_String(tileEntityID)
|
||||||
|
cls.setpos(tileEntityTag, (0, 0, 0))
|
||||||
|
return tileEntityTag
|
||||||
|
|
||||||
@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']
|
||||||
@ -17,12 +32,28 @@ class TileEntity(object):
|
|||||||
for a, p in zip('xyz', pos):
|
for a, p in zip('xyz', pos):
|
||||||
tag[a] = TAG_Int(p)
|
tag[a] = TAG_Int(p)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def copyWithOffset(cls, tileEntity, copyOffset):
|
||||||
|
eTag = deepcopy(tileEntity)
|
||||||
|
eTag['x'] = TAG_Int(tileEntity['x'].value + copyOffset[0])
|
||||||
|
eTag['y'] = TAG_Int(tileEntity['y'].value + copyOffset[1])
|
||||||
|
eTag['z'] = TAG_Int(tileEntity['z'].value + copyOffset[2])
|
||||||
|
return eTag
|
||||||
|
|
||||||
|
|
||||||
class Entity(object):
|
class Entity(object):
|
||||||
|
@classmethod
|
||||||
|
def Create(cls, entityID, **kw):
|
||||||
|
entityTag = TAG_Compound()
|
||||||
|
entityTag[EntityId] = TAG_String(entityID)
|
||||||
|
entityTag[Pos] = [TAG_Int(0) for i in range(3)]
|
||||||
|
return entityTag
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def pos(cls, tag):
|
def pos(cls, tag):
|
||||||
if "Pos" not in tag:
|
if Pos not in tag:
|
||||||
print tag
|
raise InvalidEntity, 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):
|
||||||
@ -41,3 +72,6 @@ class Entity(object):
|
|||||||
eTag["TileZ"].value += copyOffset[2]
|
eTag["TileZ"].value += copyOffset[2]
|
||||||
|
|
||||||
return eTag
|
return eTag
|
||||||
|
|
||||||
|
class InvalidEntity(ValueError): pass
|
||||||
|
class InvalidTileEntity(ValueError): pass
|
||||||
|
@ -1896,22 +1896,21 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
entities = [];
|
entities = [];
|
||||||
if chunk.Entities is None: return entities;
|
if chunk.Entities is None: return entities;
|
||||||
for entity in chunk.Entities:
|
for entity in chunk.Entities:
|
||||||
if map(lambda x:int(x.value), entity[Pos]) == [x, y, z]:
|
if map(lambda x:int(floor(x)), Entity.pos(entity)) == [x, y, z]:
|
||||||
entities.append(entity);
|
entities.append(entity);
|
||||||
|
|
||||||
return entities;
|
return entities;
|
||||||
|
|
||||||
def addEntity(self, entity):
|
def addEntity(self, entityTag):
|
||||||
assert isinstance(entity, TAG_Compound)
|
assert isinstance(entityTag, TAG_Compound)
|
||||||
x = int(entity[Pos][0].value)
|
x, y, z = map(lambda x:int(floor(x)), Entity.pos(entityTag))
|
||||||
z = int(entity[Pos][2].value)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
chunk = self.getChunk(x >> 4, z >> 4)
|
chunk = self.getChunk(x >> 4, z >> 4)
|
||||||
except (ChunkNotPresent, ChunkMalformed), e:
|
except (ChunkNotPresent, ChunkMalformed), e:
|
||||||
return None
|
return None
|
||||||
# raise Error, can't find a chunk?
|
# raise Error, can't find a chunk?
|
||||||
chunk.Entities.append(entity);
|
chunk.Entities.append(entityTag);
|
||||||
chunk.dirty = True
|
chunk.dirty = True
|
||||||
|
|
||||||
def tileEntityAt(self, x, y, z):
|
def tileEntityAt(self, x, y, z):
|
||||||
@ -1931,13 +1930,10 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
return entities[0];
|
return entities[0];
|
||||||
|
|
||||||
|
|
||||||
def addTileEntity(self, entity):
|
def addTileEntity(self, tileEntityTag):
|
||||||
assert isinstance(entity, TAG_Compound)
|
assert isinstance(tileEntityTag, TAG_Compound)
|
||||||
if not 'x' in entity: return
|
if not 'x' in tileEntityTag: return
|
||||||
|
x, y, z = TileEntity.pos(tileEntityTag)
|
||||||
x = int(entity['x'].value)
|
|
||||||
y = int(entity['y'].value)
|
|
||||||
z = int(entity['z'].value)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
chunk = self.getChunk(x >> 4, z >> 4)
|
chunk = self.getChunk(x >> 4, z >> 4)
|
||||||
@ -1945,11 +1941,11 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
return
|
return
|
||||||
# raise Error, can't find a chunk?
|
# raise Error, can't find a chunk?
|
||||||
def differentPosition(a):
|
def differentPosition(a):
|
||||||
return not ((entity is a) or ('x' in a and (a['x'].value == x and a['y'].value == y and a['z'].value == z)))
|
return not ((tileEntityTag is a) or ('x' in a and (a['x'].value == x and a['y'].value == y and a['z'].value == z)))
|
||||||
|
|
||||||
chunk.TileEntities.value[:] = filter(differentPosition, chunk.TileEntities);
|
chunk.TileEntities.value[:] = filter(differentPosition, chunk.TileEntities);
|
||||||
|
|
||||||
chunk.TileEntities.append(entity);
|
chunk.TileEntities.append(tileEntityTag);
|
||||||
chunk.dirty = True
|
chunk.dirty = True
|
||||||
|
|
||||||
def removeEntitiesInBox(self, box):
|
def removeEntitiesInBox(self, box):
|
||||||
|
44
level.py
44
level.py
@ -569,16 +569,6 @@ class MCLevel(object):
|
|||||||
def playerOrientation(self, player="Player"):
|
def playerOrientation(self, player="Player"):
|
||||||
return (-45., 0.)
|
return (-45., 0.)
|
||||||
|
|
||||||
def copyEntityWithOffset(self, entity, copyOffset):
|
|
||||||
return Entity.copyWithOffset(entity, copyOffset)
|
|
||||||
|
|
||||||
|
|
||||||
def copyTileEntityWithOffset(self, tileEntity, copyOffset):
|
|
||||||
eTag = deepcopy(tileEntity)
|
|
||||||
eTag['x'] = TAG_Int(tileEntity['x'].value + copyOffset[0])
|
|
||||||
eTag['y'] = TAG_Int(tileEntity['y'].value + copyOffset[1])
|
|
||||||
eTag['z'] = TAG_Int(tileEntity['z'].value + copyOffset[2])
|
|
||||||
return eTag
|
|
||||||
|
|
||||||
def copyEntitiesFromInfinite(self, sourceLevel, sourceBox, destinationPoint):
|
def copyEntitiesFromInfinite(self, sourceLevel, sourceBox, destinationPoint):
|
||||||
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
||||||
@ -586,29 +576,24 @@ class MCLevel(object):
|
|||||||
for (chunk, slices, point) in chunkIterator:
|
for (chunk, slices, point) in chunkIterator:
|
||||||
#remember, slices are ordered x,z,y so you can subscript them like so: chunk.Blocks[slices]
|
#remember, slices are ordered x,z,y so you can subscript them like so: chunk.Blocks[slices]
|
||||||
cx, cz = chunk.chunkPosition
|
cx, cz = chunk.chunkPosition
|
||||||
wx, wz = cx << 4, cz << 4
|
#wx, wz = cx << 4, cz << 4
|
||||||
|
|
||||||
copyOffset = map(lambda x, y:x - y, destinationPoint, sourceBox.origin)
|
copyOffset = map(lambda x, y:x - y, destinationPoint, sourceBox.origin)
|
||||||
for entity in chunk.Entities:
|
for entityTag in chunk.Entities:
|
||||||
x, y, z = map(lambda x:x.value, entity[Pos])
|
x, y, z = Entity.pos(entityTag)
|
||||||
|
if (x, y, z) not in sourceBox: continue
|
||||||
|
|
||||||
if x - wx < slices[0].start or x - wx >= slices[0].stop: continue
|
eTag = Entity.copyWithOffset(entityTag, copyOffset)
|
||||||
if y < slices[2].start or y >= slices[2].stop: continue
|
|
||||||
if z - wz < slices[1].start or z - wz >= slices[1].stop: continue
|
|
||||||
|
|
||||||
eTag = self.copyEntityWithOffset(entity, copyOffset)
|
|
||||||
|
|
||||||
self.addEntity(eTag);
|
self.addEntity(eTag);
|
||||||
|
|
||||||
for tileEntity in chunk.TileEntities:
|
for tileEntityTag in chunk.TileEntities:
|
||||||
if not 'x' in tileEntity: continue
|
if not 'x' in tileEntityTag: continue
|
||||||
|
|
||||||
x, y, z = tileEntity['x'].value, tileEntity['y'].value, tileEntity['z'].value
|
x, y, z = TileEntity.pos(tileEntityTag)
|
||||||
if x - wx < slices[0].start or x - wx >= slices[0].stop: continue
|
if (x, y, z) not in sourceBox: continue
|
||||||
if y < slices[2].start or y >= slices[2].stop: continue
|
|
||||||
if z - wz < slices[1].start or z - wz >= slices[1].stop: continue
|
|
||||||
|
|
||||||
eTag = self.copyTileEntityWithOffset(tileEntity, copyOffset)
|
eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
|
||||||
|
|
||||||
self.addTileEntity(eTag)
|
self.addTileEntity(eTag)
|
||||||
|
|
||||||
@ -628,7 +613,7 @@ class MCLevel(object):
|
|||||||
tileEntsCopied = 0;
|
tileEntsCopied = 0;
|
||||||
copyOffset = map(lambda x, y:x - y, destinationPoint, sourcePoint0)
|
copyOffset = map(lambda x, y:x - y, destinationPoint, sourcePoint0)
|
||||||
for entity in getEntitiesInRange(sourceBox, sourceLevel.Entities):
|
for entity in getEntitiesInRange(sourceBox, sourceLevel.Entities):
|
||||||
eTag = self.copyEntityWithOffset(entity, copyOffset)
|
eTag = Entity.copyWithOffset(entity, copyOffset)
|
||||||
|
|
||||||
self.addEntity(eTag)
|
self.addEntity(eTag)
|
||||||
entsCopied += 1;
|
entsCopied += 1;
|
||||||
@ -636,13 +621,8 @@ class MCLevel(object):
|
|||||||
|
|
||||||
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
||||||
if not 'x' in entity: continue
|
if not 'x' in entity: continue
|
||||||
|
eTag = TileEntity.copyWithOffset(entity, copyOffset)
|
||||||
|
|
||||||
x, y, z = entity['x'].value, entity['y'].value, entity['z'].value
|
|
||||||
|
|
||||||
eTag = deepcopy(entity)
|
|
||||||
eTag['x'] = TAG_Int(x + copyOffset[0])
|
|
||||||
eTag['y'] = TAG_Int(y + copyOffset[1])
|
|
||||||
eTag['z'] = TAG_Int(z + copyOffset[2])
|
|
||||||
try:
|
try:
|
||||||
self.addTileEntity(eTag)
|
self.addTileEntity(eTag)
|
||||||
tileEntsCopied += 1;
|
tileEntsCopied += 1;
|
||||||
|
@ -41,12 +41,9 @@ Height = "Height"
|
|||||||
Length = "Length"
|
Length = "Length"
|
||||||
Blocks = "Blocks"
|
Blocks = "Blocks"
|
||||||
Data = "Data"
|
Data = "Data"
|
||||||
|
Inventory = 'Inventory'
|
||||||
|
|
||||||
#entities
|
#entities
|
||||||
Inventory = 'Inventory'
|
|
||||||
Motion = "Motion"
|
|
||||||
Pos = "Pos"
|
|
||||||
Rotation = "Rotation"
|
|
||||||
|
|
||||||
def decompress_first(func):
|
def decompress_first(func):
|
||||||
def dec_first(self, *args, **kw):
|
def dec_first(self, *args, **kw):
|
||||||
|
81
tests.py
81
tests.py
@ -3,9 +3,10 @@ Created on Jul 23, 2011
|
|||||||
|
|
||||||
@author: Rio
|
@author: Rio
|
||||||
'''
|
'''
|
||||||
from mclevel import fromFile, loadWorldNumber, BoundingBox
|
#from mclevel import fromFile, loadWorldNumber, BoundingBox
|
||||||
from infiniteworld import MCInfdevOldLevel
|
#from infiniteworld import MCInfdevOldLevel
|
||||||
from schematic import MCSchematic
|
#from schematic import MCSchematic
|
||||||
|
from pymclevel import *
|
||||||
|
|
||||||
import itertools
|
import itertools
|
||||||
import traceback
|
import traceback
|
||||||
@ -54,6 +55,16 @@ class TestIndevLevel(unittest.TestCase):
|
|||||||
self.srclevel = TempLevel("hell.mclevel")
|
self.srclevel = TempLevel("hell.mclevel")
|
||||||
self.indevlevel = TempLevel("hueg.mclevel")
|
self.indevlevel = TempLevel("hueg.mclevel")
|
||||||
|
|
||||||
|
def testEntities(self):
|
||||||
|
level = self.indevlevel.level
|
||||||
|
entityTag = Entity.Create("Zombie")
|
||||||
|
tileEntityTag = TileEntity.Create("Painting")
|
||||||
|
level.addEntity(entityTag)
|
||||||
|
level.addTileEntity(tileEntityTag)
|
||||||
|
schem = level.extractSchematic(level.bounds)
|
||||||
|
level.copyBlocksFrom(schem, schem.bounds, (0, 0, 0))
|
||||||
|
|
||||||
|
#raise Failure
|
||||||
|
|
||||||
def testCopy(self):
|
def testCopy(self):
|
||||||
info("Indev level")
|
info("Indev level")
|
||||||
@ -96,19 +107,25 @@ class TestAlphaLevel(unittest.TestCase):
|
|||||||
self.alphalevel = TempLevel("PyTestWorld")
|
self.alphalevel = TempLevel("PyTestWorld")
|
||||||
|
|
||||||
|
|
||||||
def testAlphaLevels(self):
|
def testCreateChunks(self):
|
||||||
info("Alpha level")
|
|
||||||
|
|
||||||
indevlevel = self.indevlevel.level
|
indevlevel = self.indevlevel.level
|
||||||
|
|
||||||
level = self.alphalevel.level
|
level = self.alphalevel.level
|
||||||
|
|
||||||
for ch in list(level.allChunks): level.deleteChunk(*ch)
|
for ch in list(level.allChunks): level.deleteChunk(*ch)
|
||||||
level.createChunksInBox(BoundingBox((0, 0, 0), (32, 0, 32)))
|
level.createChunksInBox(BoundingBox((0, 0, 0), (32, 0, 32)))
|
||||||
|
|
||||||
|
def testCopyConvertBlocks(self):
|
||||||
|
indevlevel = self.indevlevel.level
|
||||||
|
level = self.alphalevel.level
|
||||||
level.copyBlocksFrom(indevlevel, BoundingBox((0, 0, 0), (256, 128, 256)), (-0, 0, 0))
|
level.copyBlocksFrom(indevlevel, BoundingBox((0, 0, 0), (256, 128, 256)), (-0, 0, 0))
|
||||||
|
|
||||||
convertedSourceBlocks, convertedSourceData = indevlevel.convertBlocksFromLevel(level, indevlevel.Blocks[0:16, 0:16, 0:indevlevel.Height], indevlevel.Data[0:16, 0:16, 0:indevlevel.Height])
|
convertedSourceBlocks, convertedSourceData = indevlevel.convertBlocksFromLevel(level, indevlevel.Blocks[0:16, 0:16, 0:indevlevel.Height], indevlevel.Data[0:16, 0:16, 0:indevlevel.Height])
|
||||||
assert (level.getChunk(0, 0).Blocks[0:16, 0:16, 0:indevlevel.Height] == convertedSourceBlocks).all()
|
assert (level.getChunk(0, 0).Blocks[0:16, 0:16, 0:indevlevel.Height] == convertedSourceBlocks).all()
|
||||||
|
|
||||||
|
def testImportSchematic(self):
|
||||||
|
indevlevel = self.indevlevel.level
|
||||||
|
level = self.alphalevel.level
|
||||||
|
|
||||||
schem = fromFile("schematics\\CreativeInABox.schematic");
|
schem = fromFile("schematics\\CreativeInABox.schematic");
|
||||||
level.copyBlocksFrom(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 64, 0));
|
level.copyBlocksFrom(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 64, 0));
|
||||||
schem = MCSchematic(shape=(1, 1, 3))
|
schem = MCSchematic(shape=(1, 1, 3))
|
||||||
@ -116,32 +133,37 @@ class TestAlphaLevel(unittest.TestCase):
|
|||||||
convertedSourceBlocks, convertedSourceData = schem.convertBlocksFromLevel(level, schem.Blocks, schem.Data)
|
convertedSourceBlocks, convertedSourceData = schem.convertBlocksFromLevel(level, schem.Blocks, schem.Data)
|
||||||
assert (level.getChunk(0, 0).Blocks[0:1, 0:3, 64:65] == convertedSourceBlocks).all()
|
assert (level.getChunk(0, 0).Blocks[0:1, 0:3, 64:65] == convertedSourceBlocks).all()
|
||||||
|
|
||||||
try:
|
def testRecreateChunks(self):
|
||||||
for x, z in itertools.product(xrange(-1, 3), xrange(-1, 2)):
|
level = self.alphalevel.level
|
||||||
level.deleteChunk(x, z);
|
|
||||||
level.createChunk(x, z)
|
for x, z in itertools.product(xrange(-1, 3), xrange(-1, 2)):
|
||||||
except Exception, e:
|
level.deleteChunk(x, z);
|
||||||
traceback.print_exc();
|
level.createChunk(x, z)
|
||||||
print e;
|
|
||||||
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , indevlevel.materials.WoodPlanks);
|
def testFill(self):
|
||||||
|
level = self.alphalevel.level
|
||||||
|
|
||||||
|
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , level.materials.WoodPlanks);
|
||||||
c = level.getChunk(0, 0)
|
c = level.getChunk(0, 0)
|
||||||
assert (c.Blocks == 5).all()
|
assert (c.Blocks == 5).all()
|
||||||
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , indevlevel.materials.WoodPlanks, [indevlevel.materials.Dirt, indevlevel.materials.Grass]);
|
|
||||||
#print b.shape
|
def testReplace(self):
|
||||||
#raise SystemExit
|
level = self.alphalevel.level
|
||||||
|
|
||||||
|
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , level.materials.WoodPlanks, [level.materials.Dirt, level.materials.Grass]);
|
||||||
|
|
||||||
|
def testSaveRelight(self):
|
||||||
|
indevlevel = self.indevlevel.level
|
||||||
|
level = self.alphalevel.level
|
||||||
|
|
||||||
cx, cz = -3, -1;
|
cx, cz = -3, -1;
|
||||||
|
|
||||||
try:
|
level.deleteChunk(cx, cz);
|
||||||
level.deleteChunk(cx, cz);
|
|
||||||
except KeyError:pass
|
|
||||||
level.createChunk(cx, cz);
|
level.createChunk(cx, cz);
|
||||||
level.copyBlocksFrom(indevlevel, BoundingBox((0, 0, 0), (64, 64, 64,)), (-96, 32, 0))
|
level.copyBlocksFrom(indevlevel, BoundingBox((0, 0, 0), (64, 64, 64,)), (-96, 32, 0))
|
||||||
#blocks = zeros((16,16,128), 'uint8');
|
|
||||||
#blocks[:,:,:] = level.getChunk(cx, cz).Blocks[:,:,:]
|
|
||||||
#level.getChunk(cx, cz).Blocks[:,:,:] = blocks[:,:,:]
|
|
||||||
level.generateLights();
|
|
||||||
level.saveInPlace();
|
|
||||||
|
|
||||||
|
level.generateLights();
|
||||||
level.saveInPlace();
|
level.saveInPlace();
|
||||||
|
|
||||||
|
|
||||||
@ -157,11 +179,10 @@ class TestSchematics(unittest.TestCase):
|
|||||||
schematic = MCSchematic(shape=size, filename="hell.schematic", mats='Classic');
|
schematic = MCSchematic(shape=size, filename="hell.schematic", mats='Classic');
|
||||||
level = self.indevlevel.level
|
level = self.indevlevel.level
|
||||||
schematic.rotateLeft();
|
schematic.rotateLeft();
|
||||||
try:
|
|
||||||
schematic.copyBlocksFrom(level, BoundingBox((-32, -32, -32), (64, 64, 64,)), (0, 0, 0))
|
|
||||||
except ValueError:
|
|
||||||
pass;
|
|
||||||
|
|
||||||
|
self.failUnlessRaises(ValueError, lambda:(
|
||||||
|
schematic.copyBlocksFrom(level, BoundingBox((-32, -32, -32), (64, 64, 64,)), (0, 0, 0))
|
||||||
|
))
|
||||||
|
|
||||||
schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), (64, 64, 64,)), (0, 0, 0))
|
schematic.copyBlocksFrom(level, BoundingBox((0, 0, 0), (64, 64, 64,)), (0, 0, 0))
|
||||||
assert((schematic.Blocks[0:64, 0:64, 0:64] == level.Blocks[0:64, 0:64, 0:64]).all())
|
assert((schematic.Blocks[0:64, 0:64, 0:64] == level.Blocks[0:64, 0:64, 0:64]).all())
|
||||||
|
Reference in New Issue
Block a user