refactor base entity code into an EntityLevel subclass and derive Indev/Infdev levels and MCSchematic from it. remove the hasEntities flag.
This commit is contained in:
parent
9127ee0ff5
commit
2a4e0435a0
3
indev.py
3
indev.py
@ -85,11 +85,10 @@ Spawn = "Spawn"
|
|||||||
__all__ = ["MCIndevLevel"]
|
__all__ = ["MCIndevLevel"]
|
||||||
|
|
||||||
|
|
||||||
class MCIndevLevel(MCLevel):
|
class MCIndevLevel(EntityLevel):
|
||||||
|
|
||||||
""" 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
|
|
||||||
|
|
||||||
def setPlayerSpawnPosition(self, pos, player=None):
|
def setPlayerSpawnPosition(self, pos, player=None):
|
||||||
assert len(pos) == 3
|
assert len(pos) == 3
|
||||||
|
@ -46,7 +46,7 @@ class ZeroChunk(object):
|
|||||||
self.SkyLight = whiteLight
|
self.SkyLight = whiteLight
|
||||||
self.Data = zeroChunk
|
self.Data = zeroChunk
|
||||||
|
|
||||||
class InfdevChunk(MCLevel):
|
class InfdevChunk(EntityLevel):
|
||||||
""" This is a 16x16xH chunk in an (infinite) world.
|
""" This is a 16x16xH chunk in an (infinite) world.
|
||||||
The properties Blocks, Data, SkyLight, BlockLight, and Heightmap
|
The properties Blocks, Data, SkyLight, BlockLight, and Heightmap
|
||||||
are ndarrays containing the respective blocks in the chunk file.
|
are ndarrays containing the respective blocks in the chunk file.
|
||||||
@ -54,8 +54,6 @@ class InfdevChunk(MCLevel):
|
|||||||
arrays are automatically unpacked from nibble arrays into byte arrays
|
arrays are automatically unpacked from nibble arrays into byte arrays
|
||||||
for better handling.
|
for better handling.
|
||||||
"""
|
"""
|
||||||
hasEntities = True
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def filename(self):
|
def filename(self):
|
||||||
if self.world.version:
|
if self.world.version:
|
||||||
@ -396,18 +394,18 @@ class InfdevChunk(MCLevel):
|
|||||||
chunkTag[Level][SkyLight].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
chunkTag[Level][SkyLight].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
||||||
chunkTag[Level][BlockLight].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
chunkTag[Level][BlockLight].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
||||||
chunkTag[Level]["Data"].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
chunkTag[Level]["Data"].value.shape = (chunkSize, chunkSize, self.world.ChunkHeight / 2)
|
||||||
if not TileEntities in chunkTag[Level]:
|
if TileEntities not in chunkTag[Level]:
|
||||||
chunkTag[Level][TileEntities] = TAG_List();
|
chunkTag[Level][TileEntities] = TAG_List();
|
||||||
if not Entities in chunkTag[Level]:
|
if Entities not in chunkTag[Level]:
|
||||||
chunkTag[Level][Entities] = TAG_List();
|
chunkTag[Level][Entities] = TAG_List();
|
||||||
|
|
||||||
def removeEntitiesInBox(self, box):
|
def removeEntitiesInBox(self, box):
|
||||||
self.dirty = True;
|
self.dirty = True;
|
||||||
return MCLevel.removeEntitiesInBox(self, box)
|
return super(InfdevChunk, self).removeEntitiesInBox(box)
|
||||||
|
|
||||||
def removeTileEntitiesInBox(self, box):
|
def removeTileEntitiesInBox(self, box):
|
||||||
self.dirty = True;
|
self.dirty = True;
|
||||||
return MCLevel.removeTileEntitiesInBox(self, box)
|
return super(InfdevChunk, self).removeTileEntitiesInBox(box)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -847,10 +845,9 @@ def deflate(data):
|
|||||||
def inflate(data):
|
def inflate(data):
|
||||||
return zlib.decompress(data)
|
return zlib.decompress(data)
|
||||||
|
|
||||||
class MCInfdevOldLevel(MCLevel):
|
class MCInfdevOldLevel(EntityLevel):
|
||||||
materials = alphaMaterials;
|
materials = alphaMaterials;
|
||||||
isInfinite = True
|
isInfinite = True
|
||||||
hasEntities = True;
|
|
||||||
parentWorld = None;
|
parentWorld = None;
|
||||||
dimNo = 0;
|
dimNo = 0;
|
||||||
ChunkHeight = 128
|
ChunkHeight = 128
|
||||||
@ -1904,24 +1901,12 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
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(entityTag);
|
chunk.addEntity(entityTag);
|
||||||
chunk.dirty = True
|
chunk.dirty = True
|
||||||
|
|
||||||
def tileEntityAt(self, x, y, z):
|
def tileEntityAt(self, x, y, z):
|
||||||
chunk = self.getChunk(x >> 4, z >> 4)
|
chunk = self.getChunk(x >> 4, z >> 4)
|
||||||
entities = [];
|
return chunk.tileEntityAt(x, y, z)
|
||||||
if chunk.TileEntities is None: return None;
|
|
||||||
for entity in chunk.TileEntities:
|
|
||||||
pos = [entity[a].value for a in 'xyz']
|
|
||||||
if pos == [x, y, z]:
|
|
||||||
entities.append(entity);
|
|
||||||
|
|
||||||
if len(entities) > 1:
|
|
||||||
info("Multiple tile entities found: {0}".format(entities))
|
|
||||||
if len(entities) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return entities[0];
|
|
||||||
|
|
||||||
|
|
||||||
def addTileEntity(self, tileEntityTag):
|
def addTileEntity(self, tileEntityTag):
|
||||||
@ -1942,6 +1927,13 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
chunk.TileEntities.append(tileEntityTag);
|
chunk.TileEntities.append(tileEntityTag);
|
||||||
chunk.dirty = True
|
chunk.dirty = True
|
||||||
|
|
||||||
|
def getEntitiesInBox(self, box):
|
||||||
|
entities = []
|
||||||
|
for chunk, slices, point in self.getChunkSlices(box):
|
||||||
|
entities += chunk.getEntitiesInBox(box)
|
||||||
|
|
||||||
|
return entities
|
||||||
|
|
||||||
def removeEntitiesInBox(self, box):
|
def removeEntitiesInBox(self, box):
|
||||||
count = 0;
|
count = 0;
|
||||||
for chunk, slices, point in self.getChunkSlices(box):
|
for chunk, slices, point in self.getChunkSlices(box):
|
||||||
@ -2061,11 +2053,11 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
|
|
||||||
destBox = BoundingBox(destinationPoint, sourceBox.size)
|
destBox = BoundingBox(destinationPoint, sourceBox.size)
|
||||||
destChunks = self.getChunkSlices(destBox)
|
|
||||||
i = 0;
|
i = 0;
|
||||||
chunkCount = float(destBox.chunkCount)
|
chunkCount = float(destBox.chunkCount)
|
||||||
|
|
||||||
for (chunk, slices, point) in destChunks:
|
for (chunk, slices, point) in self.getChunkSlices(destBox):
|
||||||
i += 1;
|
i += 1;
|
||||||
yield (i, chunkCount)
|
yield (i, chunkCount)
|
||||||
|
|
||||||
|
310
level.py
310
level.py
@ -7,8 +7,7 @@ Created on Jul 22, 2011
|
|||||||
|
|
||||||
from mclevelbase import *
|
from mclevelbase import *
|
||||||
import tempfile
|
import tempfile
|
||||||
|
from collections import defaultdict
|
||||||
#decorator for the primitive methods of MCLevel.
|
|
||||||
|
|
||||||
class MCLevel(object):
|
class MCLevel(object):
|
||||||
""" MCLevel is an abstract class providing many routines to the different level types,
|
""" MCLevel is an abstract class providing many routines to the different level types,
|
||||||
@ -30,7 +29,6 @@ class MCLevel(object):
|
|||||||
materials = classicMaterials;
|
materials = classicMaterials;
|
||||||
isInfinite = False
|
isInfinite = False
|
||||||
|
|
||||||
hasEntities = False;
|
|
||||||
compressedTag = None
|
compressedTag = None
|
||||||
root_tag = None
|
root_tag = None
|
||||||
|
|
||||||
@ -96,20 +94,20 @@ class MCLevel(object):
|
|||||||
Blocks, Data, Light, SkyLight, HeightMap attributes if present """
|
Blocks, Data, Light, SkyLight, HeightMap attributes if present """
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def close(self):
|
def close(self): pass
|
||||||
pass
|
|
||||||
|
|
||||||
def compress(self):
|
|
||||||
pass
|
|
||||||
def decompress(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
def compress(self): pass
|
||||||
|
def decompress(self):pass
|
||||||
|
|
||||||
def compressChunk(self, cx, cz): pass
|
def compressChunk(self, cx, cz): pass
|
||||||
def tileEntityAt(self, x, y, z):
|
def addEntity(self, entityTag): pass
|
||||||
return None
|
def tileEntityAt(self, x, y, z): return None
|
||||||
def addEntity(self, *args): pass
|
def addTileEntity(self, entityTag): pass
|
||||||
def addTileEntity(self, *args): pass
|
def getEntitiesInBox(self, box): return []
|
||||||
|
def getTileEntitiesInBox(self, box): return []
|
||||||
|
|
||||||
|
def copyEntitiesFromIter(self, *args, **kw): yield;
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def loadedChunks(self):
|
def loadedChunks(self):
|
||||||
@ -130,6 +128,12 @@ class MCLevel(object):
|
|||||||
being a chunked level format."""
|
being a chunked level format."""
|
||||||
return self.loadedChunks
|
return self.loadedChunks
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _getFakeChunkEntities(self, cx, cz):
|
||||||
|
"""Returns Entities, TileEntities"""
|
||||||
|
return ([], [])
|
||||||
|
|
||||||
def getChunk(self, cx, cz):
|
def getChunk(self, cx, cz):
|
||||||
"""Synthesize a FakeChunk object representing the chunk at the given
|
"""Synthesize a FakeChunk object representing the chunk at the given
|
||||||
position. Subclasses override fakeBlocksForChunk and fakeDataForChunk
|
position. Subclasses override fakeBlocksForChunk and fakeDataForChunk
|
||||||
@ -157,8 +161,9 @@ class MCLevel(object):
|
|||||||
|
|
||||||
f.BlockLight = whiteLight
|
f.BlockLight = whiteLight
|
||||||
f.SkyLight = whiteLight
|
f.SkyLight = whiteLight
|
||||||
f.Entities = []
|
|
||||||
f.TileEntities = []
|
f.Entities, f.TileEntities = self._getFakeChunkEntities(cx, cz)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
f.root_tag = TAG_Compound();
|
f.root_tag = TAG_Compound();
|
||||||
@ -444,14 +449,11 @@ class MCLevel(object):
|
|||||||
|
|
||||||
def copyBlocksFromInfinite(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
def copyBlocksFromInfinite(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
||||||
|
|
||||||
chunkIterator = sourceLevel.getChunkSlices(sourceBox)
|
|
||||||
|
|
||||||
|
|
||||||
if blocksToCopy is not None:
|
if blocksToCopy is not None:
|
||||||
typemask = zeros((256) , dtype='bool')
|
typemask = zeros((256) , dtype='bool')
|
||||||
typemask[blocksToCopy] = True;
|
typemask[blocksToCopy] = True;
|
||||||
|
|
||||||
for (chunk, slices, point) in chunkIterator:
|
for (chunk, slices, point) in sourceLevel.getChunkSlices(sourceBox):
|
||||||
point = map(lambda a, b:a + b, point, destinationPoint)
|
point = map(lambda a, b:a + b, point, destinationPoint)
|
||||||
point = point[0], point[2], point[1]
|
point = point[0], point[2], point[1]
|
||||||
mask = slice(None, None)
|
mask = slice(None, None)
|
||||||
@ -475,8 +477,6 @@ class MCLevel(object):
|
|||||||
#self.Data[ destSlices ][mask] = chunk.Data[slices][mask]
|
#self.Data[ destSlices ][mask] = chunk.Data[slices][mask]
|
||||||
|
|
||||||
|
|
||||||
chunk.compress();
|
|
||||||
|
|
||||||
|
|
||||||
def adjustCopyParameters(self, sourceLevel, sourceBox, destinationPoint):
|
def adjustCopyParameters(self, sourceLevel, sourceBox, destinationPoint):
|
||||||
|
|
||||||
@ -578,113 +578,6 @@ class MCLevel(object):
|
|||||||
return (-45., 0.)
|
return (-45., 0.)
|
||||||
|
|
||||||
|
|
||||||
def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint):
|
|
||||||
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
|
||||||
chunkCount = sourceBox.chunkCount
|
|
||||||
i = 0
|
|
||||||
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
|
|
||||||
|
|
||||||
copyOffset = map(lambda x, y:x - y, destinationPoint, sourceBox.origin)
|
|
||||||
for entityTag in chunk.Entities:
|
|
||||||
x, y, z = Entity.pos(entityTag)
|
|
||||||
if (x, y, z) not in sourceBox: continue
|
|
||||||
|
|
||||||
eTag = Entity.copyWithOffset(entityTag, copyOffset)
|
|
||||||
|
|
||||||
self.addEntity(eTag);
|
|
||||||
|
|
||||||
for tileEntityTag in chunk.TileEntities:
|
|
||||||
if not 'x' in tileEntityTag: continue
|
|
||||||
|
|
||||||
x, y, z = TileEntity.pos(tileEntityTag)
|
|
||||||
if (x, y, z) not in sourceBox: continue
|
|
||||||
|
|
||||||
eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
|
|
||||||
|
|
||||||
self.addTileEntity(eTag)
|
|
||||||
|
|
||||||
chunk.compress();
|
|
||||||
yield (i, chunkCount)
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
def copyEntitiesFrom(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
|
||||||
for i in self.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def copyEntitiesFromIter(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
|
||||||
#assume coords have already been adjusted by copyBlocks
|
|
||||||
if not self.hasEntities or not sourceLevel.hasEntities: return;
|
|
||||||
sourcePoint0 = sourceBox.origin;
|
|
||||||
sourcePoint1 = sourceBox.maximum;
|
|
||||||
|
|
||||||
if sourceLevel.isInfinite:
|
|
||||||
for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox, destinationPoint):
|
|
||||||
yield i
|
|
||||||
else:
|
|
||||||
entsCopied = 0;
|
|
||||||
tileEntsCopied = 0;
|
|
||||||
copyOffset = map(lambda x, y:x - y, destinationPoint, sourcePoint0)
|
|
||||||
if entities:
|
|
||||||
for entity in getEntitiesInRange(sourceBox, sourceLevel.Entities):
|
|
||||||
eTag = Entity.copyWithOffset(entity, copyOffset)
|
|
||||||
|
|
||||||
self.addEntity(eTag)
|
|
||||||
entsCopied += 1;
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
|
||||||
i += 1
|
|
||||||
if i % 100 == 0:
|
|
||||||
yield
|
|
||||||
|
|
||||||
if not 'x' in entity: continue
|
|
||||||
eTag = TileEntity.copyWithOffset(entity, copyOffset)
|
|
||||||
|
|
||||||
try:
|
|
||||||
self.addTileEntity(eTag)
|
|
||||||
tileEntsCopied += 1;
|
|
||||||
except ChunkNotPresent:
|
|
||||||
pass
|
|
||||||
|
|
||||||
yield
|
|
||||||
debug(u"Copied {0} entities, {1} tile entities".format(entsCopied, tileEntsCopied))
|
|
||||||
|
|
||||||
|
|
||||||
def removeEntitiesInBox(self, box):
|
|
||||||
|
|
||||||
if not self.hasEntities: return 0;
|
|
||||||
newEnts = [];
|
|
||||||
for ent in self.Entities:
|
|
||||||
if map(lambda x:x.value, ent["Pos"]) in box:
|
|
||||||
continue;
|
|
||||||
newEnts.append(ent);
|
|
||||||
|
|
||||||
entsRemoved = len(self.Entities) - len(newEnts);
|
|
||||||
debug("Removed {0} entities".format(entsRemoved))
|
|
||||||
|
|
||||||
self.Entities.value[:] = newEnts
|
|
||||||
|
|
||||||
return entsRemoved
|
|
||||||
|
|
||||||
def removeTileEntitiesInBox(self, box):
|
|
||||||
|
|
||||||
if not hasattr(self, "TileEntities"): return;
|
|
||||||
newEnts = [];
|
|
||||||
for ent in self.TileEntities:
|
|
||||||
if not "x" in ent: continue
|
|
||||||
if map(lambda x:x.value, (ent[a] for a in "xyz")) in box:
|
|
||||||
continue;
|
|
||||||
newEnts.append(ent);
|
|
||||||
|
|
||||||
entsRemoved = len(self.TileEntities) - len(newEnts);
|
|
||||||
debug("Removed {0} tile entities".format(entsRemoved))
|
|
||||||
|
|
||||||
self.TileEntities.value[:] = newEnts
|
|
||||||
|
|
||||||
return entsRemoved
|
|
||||||
|
|
||||||
def generateLights(self, dirtyChunks=None):
|
def generateLights(self, dirtyChunks=None):
|
||||||
pass;
|
pass;
|
||||||
@ -738,23 +631,150 @@ class MCLevel(object):
|
|||||||
return box, (destX, destY, destZ)
|
return box, (destX, destY, destZ)
|
||||||
|
|
||||||
|
|
||||||
def getEntitiesInRange(sourceBox, entities):
|
|
||||||
entsInRange = [];
|
|
||||||
for entity in entities:
|
|
||||||
dir()
|
|
||||||
x, y, z = Entity.pos(entity)
|
|
||||||
if not (x, y, z) in sourceBox: continue
|
|
||||||
entsInRange.append(entity)
|
|
||||||
|
|
||||||
return entsInRange
|
class EntityLevel(MCLevel):
|
||||||
|
"""Abstract subclass of MCLevel that adds default entity behavior"""
|
||||||
|
def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint):
|
||||||
|
chunkCount = sourceBox.chunkCount
|
||||||
|
i = 0
|
||||||
|
copyOffset = map(lambda x, y:x - y, destinationPoint, sourceBox.origin)
|
||||||
|
for (chunk, slices, point) in sourceLevel.getChunkSlices(sourceBox):
|
||||||
|
self.copyEntitiesFromInfiniteChunk(chunk, slices, point, sourceBox, copyOffset)
|
||||||
|
yield (i, chunkCount)
|
||||||
|
i += 1
|
||||||
|
|
||||||
def getTileEntitiesInRange(sourceBox, tileEntities):
|
def copyEntitiesFromInfiniteChunk(self, chunk, slices, point, sourceBox, copyOffset):
|
||||||
entsInRange = [];
|
|
||||||
for tileEntity in tileEntities:
|
|
||||||
if not 'x' in tileEntity: continue
|
|
||||||
|
|
||||||
x, y, z = TileEntity.pos(tileEntity)
|
for entityTag in chunk.Entities:
|
||||||
if not (x, y, z) in sourceBox: continue
|
x, y, z = Entity.pos(entityTag)
|
||||||
entsInRange.append(tileEntity)
|
if (x, y, z) not in sourceBox: continue
|
||||||
|
|
||||||
|
eTag = Entity.copyWithOffset(entityTag, copyOffset)
|
||||||
|
|
||||||
|
self.addEntity(eTag);
|
||||||
|
|
||||||
|
for tileEntityTag in chunk.TileEntities:
|
||||||
|
x, y, z = TileEntity.pos(tileEntityTag)
|
||||||
|
if (x, y, z) not in sourceBox: continue
|
||||||
|
|
||||||
|
eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
|
||||||
|
|
||||||
|
self.addTileEntity(eTag)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def copyEntitiesFromIter(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
||||||
|
#assume coords have already been adjusted by copyBlocks
|
||||||
|
#if not self.hasEntities or not sourceLevel.hasEntities: return;
|
||||||
|
sourcePoint0 = sourceBox.origin;
|
||||||
|
sourcePoint1 = sourceBox.maximum;
|
||||||
|
|
||||||
|
if sourceLevel.isInfinite:
|
||||||
|
for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox, destinationPoint):
|
||||||
|
yield i
|
||||||
|
else:
|
||||||
|
entsCopied = 0;
|
||||||
|
tileEntsCopied = 0;
|
||||||
|
copyOffset = map(lambda x, y:x - y, destinationPoint, sourcePoint0)
|
||||||
|
if entities:
|
||||||
|
for entity in sourceLevel.getEntitiesInBox(sourceBox):
|
||||||
|
eTag = Entity.copyWithOffset(entity, copyOffset)
|
||||||
|
|
||||||
|
self.addEntity(eTag)
|
||||||
|
entsCopied += 1;
|
||||||
|
|
||||||
|
i = 0
|
||||||
|
for entity in sourceLevel.getTileEntitiesInBox(sourceBox):
|
||||||
|
i += 1
|
||||||
|
if i % 100 == 0:
|
||||||
|
yield
|
||||||
|
|
||||||
|
if not 'x' in entity: continue
|
||||||
|
eTag = TileEntity.copyWithOffset(entity, copyOffset)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.addTileEntity(eTag)
|
||||||
|
tileEntsCopied += 1;
|
||||||
|
except ChunkNotPresent:
|
||||||
|
pass
|
||||||
|
|
||||||
|
yield
|
||||||
|
debug(u"Copied {0} entities, {1} tile entities".format(entsCopied, tileEntsCopied))
|
||||||
|
|
||||||
|
def getEntitiesInBox(self, box):
|
||||||
|
"""Returns a list of references to entities in this chunk, whose positions are within box"""
|
||||||
|
return [ent for ent in self.Entities if Entity.pos(ent) in box]
|
||||||
|
|
||||||
|
def getTileEntitiesInBox(self, box):
|
||||||
|
"""Returns a list of references to tile entities in this chunk, whose positions are within box"""
|
||||||
|
return [ent for ent in self.TileEntities if TileEntity.pos(ent) in box]
|
||||||
|
|
||||||
|
def removeEntitiesInBox(self, box):
|
||||||
|
|
||||||
|
newEnts = [];
|
||||||
|
for ent in self.Entities:
|
||||||
|
if Entity.pos(ent) in box:
|
||||||
|
continue;
|
||||||
|
newEnts.append(ent);
|
||||||
|
|
||||||
|
entsRemoved = len(self.Entities) - len(newEnts);
|
||||||
|
debug("Removed {0} entities".format(entsRemoved))
|
||||||
|
|
||||||
|
self.Entities.value[:] = newEnts
|
||||||
|
|
||||||
|
return entsRemoved
|
||||||
|
|
||||||
|
def removeTileEntitiesInBox(self, box):
|
||||||
|
|
||||||
|
if not hasattr(self, "TileEntities"): return;
|
||||||
|
newEnts = [];
|
||||||
|
for ent in self.TileEntities:
|
||||||
|
if TileEntity.pos(ent) in box:
|
||||||
|
continue;
|
||||||
|
newEnts.append(ent);
|
||||||
|
|
||||||
|
entsRemoved = len(self.TileEntities) - len(newEnts);
|
||||||
|
debug("Removed {0} tile entities".format(entsRemoved))
|
||||||
|
|
||||||
|
self.TileEntities.value[:] = newEnts
|
||||||
|
|
||||||
|
return entsRemoved
|
||||||
|
|
||||||
|
def addEntity(self, entityTag):
|
||||||
|
assert isinstance(entityTag, TAG_Compound)
|
||||||
|
self.Entities.append(entityTag);
|
||||||
|
|
||||||
|
def tileEntityAt(self, x, y, z):
|
||||||
|
entities = [];
|
||||||
|
for entityTag in self.TileEntities:
|
||||||
|
if TileEntity.pos(entityTag) == [x, y, z]:
|
||||||
|
entities.append(entityTag);
|
||||||
|
|
||||||
|
if len(entities) > 1:
|
||||||
|
info("Multiple tile entities found: {0}".format(entities))
|
||||||
|
if len(entities) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return entities[0];
|
||||||
|
|
||||||
|
def addTileEntity(self, entityTag):
|
||||||
|
assert isinstance(entityTag, TAG_Compound)
|
||||||
|
self.TileEntities.append(entityTag);
|
||||||
|
|
||||||
|
|
||||||
|
_fakeEntities = None
|
||||||
|
def _getFakeChunkEntities(self, cx, cz):
|
||||||
|
"""distribute entities into sublists based on fake chunk position
|
||||||
|
_fakeEntities keys are (cx,cz) and values are (Entities, TileEntities)"""
|
||||||
|
if self._fakeEntities is None:
|
||||||
|
self._fakeEntities = defaultdict(lambda: ([], []))
|
||||||
|
for i, e in enumerate((self.Entities, self.TileEntities)):
|
||||||
|
for ent in e:
|
||||||
|
x, y, z = Entity.pos(ent)
|
||||||
|
ecx, ecz = map(lambda x:(int(floor(x)) >> 4), (x, z))
|
||||||
|
|
||||||
|
self._fakeEntities[ecx, ecz][i].append(ent)
|
||||||
|
|
||||||
|
return self._fakeEntities[cx, cz]
|
||||||
|
|
||||||
return entsInRange
|
|
||||||
|
@ -63,4 +63,4 @@ class ChunkNotPresent(Exception): pass
|
|||||||
class RegionMalformed(Exception): pass
|
class RegionMalformed(Exception): pass
|
||||||
class ChunkMalformed(ChunkNotPresent): pass
|
class ChunkMalformed(ChunkNotPresent): pass
|
||||||
|
|
||||||
from level import MCLevel
|
from level import MCLevel, EntityLevel
|
||||||
|
26
schematic.py
26
schematic.py
@ -8,10 +8,8 @@ from mclevelbase import *
|
|||||||
Materials = 'Materials'
|
Materials = 'Materials'
|
||||||
|
|
||||||
__all__ = ['MCSchematic', 'INVEditChest']
|
__all__ = ['MCSchematic', 'INVEditChest']
|
||||||
class MCSchematic (MCLevel):
|
class MCSchematic (EntityLevel):
|
||||||
materials = alphaMaterials
|
materials = alphaMaterials
|
||||||
hasEntities = True;
|
|
||||||
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return u"MCSchematic(shape={0}, filename=\"{1}\")".format(self.size, self.filename or u"")
|
return u"MCSchematic(shape={0}, filename=\"{1}\")".format(self.size, self.filename or u"")
|
||||||
@ -359,28 +357,6 @@ class MCSchematic (MCLevel):
|
|||||||
return self.Data[x, z, y];
|
return self.Data[x, z, y];
|
||||||
|
|
||||||
|
|
||||||
def addEntity(self, entityTag):
|
|
||||||
assert isinstance(entityTag, TAG_Compound)
|
|
||||||
self.Entities.append(entityTag);
|
|
||||||
|
|
||||||
def tileEntityAt(self, x, y, z):
|
|
||||||
entities = [];
|
|
||||||
for entityTag in self.TileEntities:
|
|
||||||
pos = [entityTag[a].value for a in 'xyz']
|
|
||||||
if pos == [x, y, z]:
|
|
||||||
entities.append(entityTag);
|
|
||||||
|
|
||||||
if len(entities) > 1:
|
|
||||||
info("Multiple tile entities found: {0}".format(entities))
|
|
||||||
if len(entities) == 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
return entities[0];
|
|
||||||
|
|
||||||
def addTileEntity(self, entityTag):
|
|
||||||
assert isinstance(entityTag, TAG_Compound)
|
|
||||||
self.TileEntities.append(entityTag);
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def chestWithItemID(self, itemID, count=64, damage=0):
|
def chestWithItemID(self, itemID, count=64, damage=0):
|
||||||
""" Creates a chest with a stack of 'itemID' in each slot.
|
""" Creates a chest with a stack of 'itemID' in each slot.
|
||||||
|
3
tests.py
3
tests.py
@ -113,6 +113,9 @@ class TestAlphaLevel(unittest.TestCase):
|
|||||||
level.LastPlayed
|
level.LastPlayed
|
||||||
level.LastPlayed = time.time() * 1000 - 1000000
|
level.LastPlayed = time.time() * 1000 - 1000000
|
||||||
|
|
||||||
|
def testGetEntities(self):
|
||||||
|
level = self.alphalevel.level
|
||||||
|
print len(level.getEntitiesInBox(level.bounds))
|
||||||
|
|
||||||
def testCreateChunks(self):
|
def testCreateChunks(self):
|
||||||
indevlevel = self.indevlevel.level
|
indevlevel = self.indevlevel.level
|
||||||
|
Reference in New Issue
Block a user