added a 'create' option to copyBlocksFrom and getChunkSlices.

This commit is contained in:
David Vierra 2011-09-13 16:03:58 -10:00
parent 2e4b8e43ad
commit a94c032c94
4 changed files with 46 additions and 39 deletions

View File

@ -2495,7 +2495,7 @@ class MCInfdevOldLevel(EntityLevel):
return slice(None, None)
return sourceMask
def copyBlocksFromFiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
def copyBlocksFromFiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy, create = False):
#assumes destination point and bounds have already been checked.
(sx, sy, sz) = sourceBox.origin
@ -2561,7 +2561,7 @@ class MCInfdevOldLevel(EntityLevel):
#chunk.compress(); #xxx find out why this trashes changes to tile entities
def copyBlocksFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
def copyBlocksFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy, create = False):
""" copy blocks between two infinite levels via repeated export/import. hilariously slow. """
#assumes destination point and bounds have already been checked.
@ -2570,7 +2570,19 @@ class MCInfdevOldLevel(EntityLevel):
i = 0
sourceMask = self.sourceMaskFunc(blocksToCopy)
for chunk, slices, point in self.getChunkSlices(destBox):
def subbox(slices, point):
size = [s.stop - s.start for s in slices]
size[1], size[2] = size[2], size[1]
return BoundingBox([p + a for p, a in zip(point, sourceBox.origin)], size)
def shouldCreateFunc(slices, point):
box = subbox(slices, point)
b = any(list(sourceLevel.containsChunk(*c) for c in box.chunkPositions)) #any() won't take a generator-expression :(
if b == False:
print 'Skipped ', list(box.chunkPositions)
return b
for chunk, slices, point in self.getChunkSlices(destBox, create=(create and shouldCreateFunc)):
i += 1
yield (i, chunkCount)
if i % 100 == 0:
@ -2578,9 +2590,7 @@ class MCInfdevOldLevel(EntityLevel):
dstblocks = chunk.Blocks[slices]
dstdata = chunk.Data[slices]
size = [s.stop - s.start for s in slices]
size[1], size[2] = size[2], size[1]
sourceSubBox = BoundingBox([p + a for p, a in zip(point, sourceBox.origin)], size)
sourceSubBox = subbox(slices, point)
for srcchunk, srcslices, srcpoint in sourceLevel.getChunkSlices(sourceSubBox):
srcpoint = srcpoint[0], srcpoint[2], srcpoint[1]
sourceBlocks = srcchunk.Blocks[srcslices]
@ -2597,10 +2607,10 @@ class MCInfdevOldLevel(EntityLevel):
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
return exhaust(self.copyBlocksFromIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities))
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True, create=False):
return exhaust(self.copyBlocksFromIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities, create))
def copyBlocksFromIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
def copyBlocksFromIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True, create=False):
(x, y, z) = destinationPoint;
(lx, ly, lz) = sourceBox.size
#sourcePoint, sourcePoint1 = sourceBox
@ -2611,12 +2621,12 @@ class MCInfdevOldLevel(EntityLevel):
startTime = datetime.now()
if(not isinstance(sourceLevel, MCInfdevOldLevel)):
for i in self.copyBlocksFromFiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy):
for i in self.copyBlocksFromFiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, create):
yield i
else:
for i in self.copyBlocksFromInfiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy):
for i in self.copyBlocksFromInfiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, create):
yield i
for i in self.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):

View File

@ -180,8 +180,10 @@ class MCLevel(object):
yield (chunk, slices, (xPos * 16 - x, 0, zPos * 16 - z))
def getChunkSlicesCreating(self, box):
return self.getChunkSlices(box, create=True)
def getChunkSlices(self, box):
def getChunkSlices(self, box, create=False):
""" call this method to iterate through a large slice of the world by
visiting each chunk and indexing its data with a subslice.
@ -194,6 +196,9 @@ class MCLevel(object):
and the 'offset' triplet. x,z,y ordering is used only
to index arrays, since it reflects the order of the blocks in memory.
In all other places, including an entity's 'Pos', the order is x,y,z.
'create' controls whether to create absent chunks or skip over them.
create can be False, True, or a function of (slices, point)
"""
level = self
@ -229,14 +234,21 @@ class MCLevel(object):
localMaxZ = maxzoff
newMinZ = localMinZ + (cz << 4) - box.minz
newMaxZ = localMaxZ + (cz << 4) - box.minz
try:
ch = level.getChunk(cx, cz)
except ChunkNotPresent, e:
continue;
yield (ch,
slices, point = (
(slice(localMinX, localMaxX), slice(localMinZ, localMaxZ), slice(miny, maxy)),
(newMinX, newMinY, newMinZ))
(newMinX, newMinY, newMinZ)
)
if not level.containsChunk(cx,cz):
if create and hasattr(level, 'createChunk'):
if not hasattr(create, "__call__") or create(slices, point):
level.createChunk(cx,cz)
else:
continue
else:
continue;
chunk = level.getChunk(cx,cz)
yield chunk, slices, point
def containsPoint(self, x, y, z):

3
mce.py
View File

@ -522,9 +522,8 @@ class mce(object):
importLevel = mclevel.fromFile(filename)
destBox = BoundingBox(destPoint, importLevel.size)
self.level.createChunksInBox(destBox);
self.level.copyBlocksFrom(importLevel, importLevel.bounds, destPoint, blocksToCopy);
self.level.copyBlocksFrom(importLevel, importLevel.bounds, destPoint, blocksToCopy, create=True);
self.needsSave = True;

View File

@ -516,21 +516,7 @@ def extractZipSchematicFromIter(sourceLevel, box, zipfilename=None, entities=Tru
destBox = BoundingBox(destPoint, sourceBox.size);
if (sourceBox.isChunkAligned):
#create chunks in the destination area corresponding only to chunks
#present in the source
chunks = sourceBox.chunkPositions
destChunks = destBox.chunkPositions
chunkIter = itertools.izip(chunks, destChunks)
for i, (src, chunk) in enumerate(chunkIter):
if sourceLevel.containsChunk(*src):
tempSchematic.createChunk(*chunk)
yield i, sourceBox.chunkCount
else:
tempSchematic.createChunksInBox(destBox)
for i in tempSchematic.copyBlocksFromIter(sourceLevel, sourceBox, destPoint, entities=entities):
for i in tempSchematic.copyBlocksFromIter(sourceLevel, sourceBox, destPoint, entities=entities, create=True):
yield i
tempSchematic.saveInPlace(); #lights not needed for this format - crashes minecraft though