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
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
import numpy
|
import numpy
|
||||||
from box import BoundingBox
|
from box import BoundingBox
|
||||||
from mclevelbase import exhaust
|
from mclevelbase import exhaust
|
||||||
import materials
|
import materials
|
||||||
|
from entity import Entity, TileEntity
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
def convertBlocks(destLevel, sourceLevel, blocks, blockData):
|
def convertBlocks(destLevel, sourceLevel, blocks, blockData):
|
||||||
return materials.convertBlocks(destLevel.materials, sourceLevel.materials, 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)
|
destBox = BoundingBox(destinationPoint, sourceBox.size)
|
||||||
chunkCount = destBox.chunkCount
|
chunkCount = destBox.chunkCount
|
||||||
i = 0
|
i = 0
|
||||||
|
e = 0
|
||||||
|
t = 0
|
||||||
|
|
||||||
sourceMask = sourceMaskFunc(blocksToCopy)
|
sourceMask = sourceMaskFunc(blocksToCopy)
|
||||||
|
|
||||||
copyOffset = [d - s for s, d in zip(sourceBox.origin, destinationPoint)]
|
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:
|
if convertedSourceData is not None:
|
||||||
destChunk.Data[destSlices][mask] = convertedSourceData[mask]
|
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()
|
destChunk.chunkChanged()
|
||||||
|
|
||||||
for i in destLevel.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
|
|
||||||
yield i
|
|
||||||
|
|
||||||
log.info("Duration: {0}".format(datetime.now() - startTime))
|
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):
|
def copyBlocksFrom(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True, create=False):
|
||||||
return exhaust(copyBlocksFromIter(destLevel, sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities, create))
|
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):
|
def getTileEntitiesInBox(self, box):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def copyEntitiesFromIter(self, *args, **kw):
|
|
||||||
yield
|
|
||||||
|
|
||||||
def removeEntitiesInBox(self, box):
|
def removeEntitiesInBox(self, box):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -475,78 +472,6 @@ class MCLevel(object):
|
|||||||
class EntityLevel(MCLevel):
|
class EntityLevel(MCLevel):
|
||||||
"""Abstract subclass of MCLevel that adds default entity behavior"""
|
"""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):
|
def getEntitiesInBox(self, box):
|
||||||
"""Returns a list of references to entities in this chunk, whose positions are within 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]
|
return [ent for ent in self.Entities if Entity.pos(ent) in box]
|
||||||
|
Reference in New Issue
Block a user