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:
parent
b0ef494546
commit
a7fd3ed3ca
@ -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))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
75
level.py
75
level.py
@ -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]
|
||||
|
Reference in New Issue
Block a user