From a94c032c9484ca96cb43872cd3b6c3df8ff28a67 Mon Sep 17 00:00:00 2001 From: David Vierra Date: Tue, 13 Sep 2011 16:03:58 -1000 Subject: [PATCH] added a 'create' option to copyBlocksFrom and getChunkSlices. --- infiniteworld.py | 34 ++++++++++++++++++++++------------ level.py | 32 ++++++++++++++++++++++---------- mce.py | 3 +-- schematic.py | 16 +--------------- 4 files changed, 46 insertions(+), 39 deletions(-) diff --git a/infiniteworld.py b/infiniteworld.py index 2a8a26f..763dc0d 100644 --- a/infiniteworld.py +++ b/infiniteworld.py @@ -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. @@ -2569,8 +2569,20 @@ class MCInfdevOldLevel(EntityLevel): chunkCount = destBox.chunkCount 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): diff --git a/level.py b/level.py index 3ed2bcf..1ed40dd 100644 --- a/level.py +++ b/level.py @@ -180,8 +180,10 @@ class MCLevel(object): yield (chunk, slices, (xPos * 16 - x, 0, zPos * 16 - z)) - - def getChunkSlices(self, box): + def getChunkSlicesCreating(self, box): + return self.getChunkSlices(box, create=True) + + 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, - (slice(localMinX, localMaxX), slice(localMinZ, localMaxZ), slice(miny, maxy)), - (newMinX, newMinY, newMinZ)) + slices, point = ( + (slice(localMinX, localMaxX), slice(localMinZ, localMaxZ), slice(miny, maxy)), + (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): diff --git a/mce.py b/mce.py index 1ff8183..d87e34f 100644 --- a/mce.py +++ b/mce.py @@ -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; diff --git a/schematic.py b/schematic.py index 575716c..a182e72 100644 --- a/schematic.py +++ b/schematic.py @@ -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