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(", ")
|
||||
|
||||
EntityId = "EntityId"
|
||||
id = "id"
|
||||
|
||||
Motion = "Motion"
|
||||
Pos = "Pos"
|
||||
Rotation = "Rotation"
|
||||
|
||||
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
|
||||
def pos(cls, tag):
|
||||
return [tag[a].value for a in 'xyz']
|
||||
@ -17,12 +32,28 @@ class TileEntity(object):
|
||||
for a, p in zip('xyz', pos):
|
||||
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):
|
||||
@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
|
||||
def pos(cls, tag):
|
||||
if "Pos" not in tag:
|
||||
print tag
|
||||
return [a.value for a in tag["Pos"]]
|
||||
if Pos not in tag:
|
||||
raise InvalidEntity, tag
|
||||
return [a.value for a in tag[Pos]]
|
||||
|
||||
@classmethod
|
||||
def setpos(cls, tag, pos):
|
||||
@ -41,3 +72,6 @@ class Entity(object):
|
||||
eTag["TileZ"].value += copyOffset[2]
|
||||
|
||||
return eTag
|
||||
|
||||
class InvalidEntity(ValueError): pass
|
||||
class InvalidTileEntity(ValueError): pass
|
||||
|
@ -1896,22 +1896,21 @@ class MCInfdevOldLevel(MCLevel):
|
||||
entities = [];
|
||||
if chunk.Entities is None: return 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);
|
||||
|
||||
return entities;
|
||||
|
||||
def addEntity(self, entity):
|
||||
assert isinstance(entity, TAG_Compound)
|
||||
x = int(entity[Pos][0].value)
|
||||
z = int(entity[Pos][2].value)
|
||||
def addEntity(self, entityTag):
|
||||
assert isinstance(entityTag, TAG_Compound)
|
||||
x, y, z = map(lambda x:int(floor(x)), Entity.pos(entityTag))
|
||||
|
||||
try:
|
||||
chunk = self.getChunk(x >> 4, z >> 4)
|
||||
except (ChunkNotPresent, ChunkMalformed), e:
|
||||
return None
|
||||
# raise Error, can't find a chunk?
|
||||
chunk.Entities.append(entity);
|
||||
chunk.Entities.append(entityTag);
|
||||
chunk.dirty = True
|
||||
|
||||
def tileEntityAt(self, x, y, z):
|
||||
@ -1931,13 +1930,10 @@ class MCInfdevOldLevel(MCLevel):
|
||||
return entities[0];
|
||||
|
||||
|
||||
def addTileEntity(self, entity):
|
||||
assert isinstance(entity, TAG_Compound)
|
||||
if not 'x' in entity: return
|
||||
|
||||
x = int(entity['x'].value)
|
||||
y = int(entity['y'].value)
|
||||
z = int(entity['z'].value)
|
||||
def addTileEntity(self, tileEntityTag):
|
||||
assert isinstance(tileEntityTag, TAG_Compound)
|
||||
if not 'x' in tileEntityTag: return
|
||||
x, y, z = TileEntity.pos(tileEntityTag)
|
||||
|
||||
try:
|
||||
chunk = self.getChunk(x >> 4, z >> 4)
|
||||
@ -1945,11 +1941,11 @@ class MCInfdevOldLevel(MCLevel):
|
||||
return
|
||||
# raise Error, can't find a chunk?
|
||||
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.append(entity);
|
||||
chunk.TileEntities.append(tileEntityTag);
|
||||
chunk.dirty = True
|
||||
|
||||
def removeEntitiesInBox(self, box):
|
||||
|
44
level.py
44
level.py
@ -569,16 +569,6 @@ class MCLevel(object):
|
||||
def playerOrientation(self, player="Player"):
|
||||
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):
|
||||
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
||||
@ -586,29 +576,24 @@ class MCLevel(object):
|
||||
for (chunk, slices, point) in chunkIterator:
|
||||
#remember, slices are ordered x,z,y so you can subscript them like so: chunk.Blocks[slices]
|
||||
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)
|
||||
for entity in chunk.Entities:
|
||||
x, y, z = map(lambda x:x.value, entity[Pos])
|
||||
for entityTag in chunk.Entities:
|
||||
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
|
||||
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)
|
||||
eTag = Entity.copyWithOffset(entityTag, copyOffset)
|
||||
|
||||
self.addEntity(eTag);
|
||||
|
||||
for tileEntity in chunk.TileEntities:
|
||||
if not 'x' in tileEntity: continue
|
||||
for tileEntityTag in chunk.TileEntities:
|
||||
if not 'x' in tileEntityTag: continue
|
||||
|
||||
x, y, z = tileEntity['x'].value, tileEntity['y'].value, tileEntity['z'].value
|
||||
if x - wx < slices[0].start or x - wx >= slices[0].stop: 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
|
||||
x, y, z = TileEntity.pos(tileEntityTag)
|
||||
if (x, y, z) not in sourceBox: continue
|
||||
|
||||
eTag = self.copyTileEntityWithOffset(tileEntity, copyOffset)
|
||||
eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
|
||||
|
||||
self.addTileEntity(eTag)
|
||||
|
||||
@ -628,7 +613,7 @@ class MCLevel(object):
|
||||
tileEntsCopied = 0;
|
||||
copyOffset = map(lambda x, y:x - y, destinationPoint, sourcePoint0)
|
||||
for entity in getEntitiesInRange(sourceBox, sourceLevel.Entities):
|
||||
eTag = self.copyEntityWithOffset(entity, copyOffset)
|
||||
eTag = Entity.copyWithOffset(entity, copyOffset)
|
||||
|
||||
self.addEntity(eTag)
|
||||
entsCopied += 1;
|
||||
@ -636,13 +621,8 @@ class MCLevel(object):
|
||||
|
||||
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
||||
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:
|
||||
self.addTileEntity(eTag)
|
||||
tileEntsCopied += 1;
|
||||
|
@ -41,12 +41,9 @@ Height = "Height"
|
||||
Length = "Length"
|
||||
Blocks = "Blocks"
|
||||
Data = "Data"
|
||||
Inventory = 'Inventory'
|
||||
|
||||
#entities
|
||||
Inventory = 'Inventory'
|
||||
Motion = "Motion"
|
||||
Pos = "Pos"
|
||||
Rotation = "Rotation"
|
||||
|
||||
def decompress_first(func):
|
||||
def dec_first(self, *args, **kw):
|
||||
|
81
tests.py
81
tests.py
@ -3,9 +3,10 @@ Created on Jul 23, 2011
|
||||
|
||||
@author: Rio
|
||||
'''
|
||||
from mclevel import fromFile, loadWorldNumber, BoundingBox
|
||||
from infiniteworld import MCInfdevOldLevel
|
||||
from schematic import MCSchematic
|
||||
#from mclevel import fromFile, loadWorldNumber, BoundingBox
|
||||
#from infiniteworld import MCInfdevOldLevel
|
||||
#from schematic import MCSchematic
|
||||
from pymclevel import *
|
||||
|
||||
import itertools
|
||||
import traceback
|
||||
@ -54,6 +55,16 @@ class TestIndevLevel(unittest.TestCase):
|
||||
self.srclevel = TempLevel("hell.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):
|
||||
info("Indev level")
|
||||
@ -96,19 +107,25 @@ class TestAlphaLevel(unittest.TestCase):
|
||||
self.alphalevel = TempLevel("PyTestWorld")
|
||||
|
||||
|
||||
def testAlphaLevels(self):
|
||||
info("Alpha level")
|
||||
|
||||
def testCreateChunks(self):
|
||||
indevlevel = self.indevlevel.level
|
||||
|
||||
level = self.alphalevel.level
|
||||
|
||||
for ch in list(level.allChunks): level.deleteChunk(*ch)
|
||||
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))
|
||||
|
||||
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()
|
||||
|
||||
def testImportSchematic(self):
|
||||
indevlevel = self.indevlevel.level
|
||||
level = self.alphalevel.level
|
||||
|
||||
schem = fromFile("schematics\\CreativeInABox.schematic");
|
||||
level.copyBlocksFrom(schem, BoundingBox((0, 0, 0), (1, 1, 3)), (0, 64, 0));
|
||||
schem = MCSchematic(shape=(1, 1, 3))
|
||||
@ -116,32 +133,37 @@ class TestAlphaLevel(unittest.TestCase):
|
||||
convertedSourceBlocks, convertedSourceData = schem.convertBlocksFromLevel(level, schem.Blocks, schem.Data)
|
||||
assert (level.getChunk(0, 0).Blocks[0:1, 0:3, 64:65] == convertedSourceBlocks).all()
|
||||
|
||||
try:
|
||||
for x, z in itertools.product(xrange(-1, 3), xrange(-1, 2)):
|
||||
level.deleteChunk(x, z);
|
||||
level.createChunk(x, z)
|
||||
except Exception, e:
|
||||
traceback.print_exc();
|
||||
print e;
|
||||
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , indevlevel.materials.WoodPlanks);
|
||||
def testRecreateChunks(self):
|
||||
level = self.alphalevel.level
|
||||
|
||||
for x, z in itertools.product(xrange(-1, 3), xrange(-1, 2)):
|
||||
level.deleteChunk(x, z);
|
||||
level.createChunk(x, z)
|
||||
|
||||
def testFill(self):
|
||||
level = self.alphalevel.level
|
||||
|
||||
level.fillBlocks(BoundingBox((-11, 0, -7), (38, 128, 25)) , level.materials.WoodPlanks);
|
||||
c = level.getChunk(0, 0)
|
||||
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
|
||||
#raise SystemExit
|
||||
|
||||
def testReplace(self):
|
||||
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;
|
||||
|
||||
try:
|
||||
level.deleteChunk(cx, cz);
|
||||
except KeyError:pass
|
||||
level.deleteChunk(cx, cz);
|
||||
|
||||
level.createChunk(cx, cz);
|
||||
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();
|
||||
|
||||
|
||||
@ -157,11 +179,10 @@ class TestSchematics(unittest.TestCase):
|
||||
schematic = MCSchematic(shape=size, filename="hell.schematic", mats='Classic');
|
||||
level = self.indevlevel.level
|
||||
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))
|
||||
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