Refactor: Move copyEntitiesFrom logic into copyBlocksFrom and remove "copyEntitiesFromFinite" implementation.

copyBlocksFrom now copies everything in a single pass instead of doing the entities in a second pass through every chunk.
This commit is contained in:
David Vierra 2012-10-30 18:48:48 -10:00
parent b0ef494546
commit a7fd3ed3ca
2 changed files with 33 additions and 79 deletions

View File

@ -1,11 +1,13 @@
from datetime import datetime
import logging
log = logging.getLogger(__name__)
import numpy
from box import BoundingBox
from mclevelbase import exhaust
import materials
from entity import Entity, TileEntity
log = logging.getLogger(__name__)
def convertBlocks(destLevel, sourceLevel, blocks, blockData):
return materials.convertBlocks(destLevel.materials, sourceLevel.materials, blocks, blockData)
@ -86,6 +88,9 @@ def copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, bloc
destBox = BoundingBox(destinationPoint, sourceBox.size)
chunkCount = destBox.chunkCount
i = 0
e = 0
t = 0
sourceMask = sourceMaskFunc(blocksToCopy)
copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]
@ -139,12 +144,36 @@ def copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, bloc
if convertedSourceData is not None:
destChunk.Data[destSlices][mask] = convertedSourceData[mask]
if entities:
e += len(sourceChunk.Entities)
for entityTag in sourceChunk.Entities:
x, y, z = Entity.pos(entityTag)
if (x, y, z) not in sourceBox:
continue
eTag = Entity.copyWithOffset(entityTag, copyOffset)
destLevel.addEntity(eTag)
t += len(sourceChunk.TileEntities)
for tileEntityTag in sourceChunk.TileEntities:
x, y, z = TileEntity.pos(tileEntityTag)
if (x, y, z) not in sourceBox:
continue
eTag = TileEntity.copyWithOffset(tileEntityTag, copyOffset)
destLevel.addTileEntity(eTag)
destChunk.chunkChanged()
for i in destLevel.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
yield i
log.info("Duration: {0}".format(datetime.now() - startTime))
log.info("Copied {0} entities and {1} tile entities".format(e, t))
def copyBlocksFrom(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True, create=False):
return exhaust(copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities, create))

View File

@ -207,9 +207,6 @@ class MCLevel(object):
def getTileEntitiesInBox(self, box):
return []
def copyEntitiesFromIter(self, *args, **kw):
yield
def removeEntitiesInBox(self, box):
pass
@ -475,78 +472,6 @@ class MCLevel(object):
class EntityLevel(MCLevel):
"""Abstract subclass of MCLevel that adds default entity behavior"""
def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, entities):
chunkCount = sourceBox.chunkCount
i = 0
copyOffset = map(lambda x, y: x - y, destinationPoint, sourceBox.origin)
e = t = 0
for (chunk, slices, point) in sourceLevel.getChunkSlices(sourceBox):
yield (i, chunkCount)
i += 1
if entities:
e += len(chunk.Entities)
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)
t += len(chunk.TileEntities)
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)
info("Copied {0} entities, {1} tile entities".format(e, t))
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
if sourceLevel.isInfinite:
for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox, destinationPoint, entities):
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
info(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]