add iterator-type counterparts to extractSchematic, extractZipSchematic and copyBlocksFrom to facilitate progress bars. iterators repeatedly yield a tuple of (progress, total). extract methods finally yield the extracted schematic object.
This commit is contained in:
parent
55dc972e22
commit
e8870e76e4
@ -1576,6 +1576,10 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
info(u"Saved {0} chunks".format(dirtyChunkCount))
|
info(u"Saved {0} chunks".format(dirtyChunkCount))
|
||||||
|
|
||||||
def generateLights(self, dirtyChunks=None):
|
def generateLights(self, dirtyChunks=None):
|
||||||
|
for i in generateLightsIter(self, dirtyChunks):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def generateLightsIter(self, dirtyChunks=None):
|
||||||
""" dirtyChunks may be an iterable yielding (xPos,zPos) tuples
|
""" dirtyChunks may be an iterable yielding (xPos,zPos) tuples
|
||||||
if none, generate lights for all chunks that need lighting
|
if none, generate lights for all chunks that need lighting
|
||||||
"""
|
"""
|
||||||
@ -1629,13 +1633,16 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
info(u"Using {0} batches to conserve memory.".format(len(chunkLists)))
|
info(u"Using {0} batches to conserve memory.".format(len(chunkLists)))
|
||||||
|
|
||||||
i = 0
|
i = 0
|
||||||
|
|
||||||
for dc in chunkLists:
|
for dc in chunkLists:
|
||||||
i += 1;
|
i += 1;
|
||||||
info(u"Batch {0}/{1}".format(i, len(chunkLists)))
|
info(u"Batch {0}/{1}".format(i, len(chunkLists)))
|
||||||
|
|
||||||
dc = sorted(dc, key=lambda x:x.chunkPosition)
|
dc = sorted(dc, key=lambda x:x.chunkPosition)
|
||||||
|
|
||||||
self._generateLights(dc)
|
for j in self._generateLightsIter(dc):
|
||||||
|
yield j
|
||||||
|
|
||||||
for ch in dc:
|
for ch in dc:
|
||||||
ch.compress();
|
ch.compress();
|
||||||
timeDelta = datetime.now() - startTime;
|
timeDelta = datetime.now() - startTime;
|
||||||
@ -1645,7 +1652,7 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
def _generateLights(self, dirtyChunks):
|
def _generateLightsIter(self, dirtyChunks):
|
||||||
conserveMemory = False
|
conserveMemory = False
|
||||||
la = array(self.materials.lightAbsorption)
|
la = array(self.materials.lightAbsorption)
|
||||||
|
|
||||||
@ -1692,6 +1699,8 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
else:
|
else:
|
||||||
lights = ("BlockLight", "SkyLight")
|
lights = ("BlockLight", "SkyLight")
|
||||||
info(u"Dispersing light...")
|
info(u"Dispersing light...")
|
||||||
|
j = 0
|
||||||
|
|
||||||
for light in lights:
|
for light in lights:
|
||||||
zerochunkLight = getattr(zeroChunk, light);
|
zerochunkLight = getattr(zeroChunk, light);
|
||||||
|
|
||||||
@ -1721,6 +1730,8 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
for chunk in dirtyChunks:
|
for chunk in dirtyChunks:
|
||||||
#xxx code duplication
|
#xxx code duplication
|
||||||
|
yield (j, len(dirtyChunks))
|
||||||
|
j += 1
|
||||||
(cx, cz) = chunk.chunkPosition
|
(cx, cz) = chunk.chunkPosition
|
||||||
neighboringChunks = {};
|
neighboringChunks = {};
|
||||||
try:
|
try:
|
||||||
@ -2030,7 +2041,7 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def copyBlocksFromFinite(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
def copyBlocksFromFiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
||||||
#assumes destination point and bounds have already been checked.
|
#assumes destination point and bounds have already been checked.
|
||||||
(sx, sy, sz) = sourceBox.origin
|
(sx, sy, sz) = sourceBox.origin
|
||||||
|
|
||||||
@ -2043,11 +2054,15 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
typemask[blocksToCopy] = 1;
|
typemask[blocksToCopy] = 1;
|
||||||
|
|
||||||
|
|
||||||
destChunks = self.getChunkSlices(BoundingBox(destinationPoint, sourceBox.size))
|
destBox = BoundingBox(destinationPoint, sourceBox.size)
|
||||||
|
destChunks = self.getChunkSlices(destBox)
|
||||||
i = 0;
|
i = 0;
|
||||||
|
chunkCount = float(destBox.chunkCount)
|
||||||
|
|
||||||
for (chunk, slices, point) in destChunks:
|
for (chunk, slices, point) in destChunks:
|
||||||
i += 1;
|
i += 1;
|
||||||
|
yield (i, chunkCount)
|
||||||
|
|
||||||
if i % 100 == 0:
|
if i % 100 == 0:
|
||||||
info("Chunk {0}...".format(i))
|
info("Chunk {0}...".format(i))
|
||||||
|
|
||||||
@ -2098,19 +2113,21 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
#chunk.compress(); #xxx find out why this trashes changes to tile entities
|
#chunk.compress(); #xxx find out why this trashes changes to tile entities
|
||||||
|
|
||||||
def copyBlocksFromInfinite(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
def copyBlocksFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
||||||
""" copy blocks between two infinite levels via repeated export/import. hilariously slow. """
|
""" copy blocks between two infinite levels via repeated export/import. hilariously slow. """
|
||||||
|
|
||||||
#assumes destination point and bounds have already been checked.
|
#assumes destination point and bounds have already been checked.
|
||||||
|
|
||||||
tempSize = 128
|
tempSize = 128
|
||||||
|
dx, dy, dz = destinationPoint
|
||||||
|
ox, oy, oz = sourceBox.origin
|
||||||
|
sx, sy, sz = sourceBox.size
|
||||||
|
mx, my, mz = sourceBox.maximum
|
||||||
|
def subsectionCount():
|
||||||
|
return (ox, ox + sx, tempSize) * (oz, oz + sz, tempSize)
|
||||||
|
|
||||||
def iterateSubsections():
|
def iterateSubsections():
|
||||||
#tempShape = (tempSize, sourceBox.height, tempSize)
|
#tempShape = (tempSize, sourceBox.height, tempSize)
|
||||||
dx, dy, dz = destinationPoint
|
|
||||||
ox, oy, oz = sourceBox.origin
|
|
||||||
sx, sy, sz = sourceBox.size
|
|
||||||
mx, my, mz = sourceBox.maximum
|
|
||||||
for x, z in itertools.product(arange(ox, ox + sx, tempSize), arange(oz, oz + sz, tempSize)):
|
for x, z in itertools.product(arange(ox, ox + sx, tempSize), arange(oz, oz + sz, tempSize)):
|
||||||
box = BoundingBox((x, oy, z), (min(tempSize, mx - x), sy, min(tempSize, mz - z)))
|
box = BoundingBox((x, oy, z), (min(tempSize, mx - x), sy, min(tempSize, mz - z)))
|
||||||
destPoint = (dx + x - ox, dy, dz + z - oz)
|
destPoint = (dx + x - ox, dy, dz + z - oz)
|
||||||
@ -2121,9 +2138,13 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
|
|
||||||
def isChunkBox(box):
|
def isChunkBox(box):
|
||||||
return box.isChunkAligned and box.miny == 0 and box.height == sourceLevel.Height
|
return box.isChunkAligned and box.miny == 0 and box.height == sourceLevel.Height
|
||||||
|
i = 0
|
||||||
|
print sourceBox.chunkCount
|
||||||
|
chunkCount = float(sourceBox.chunkCount)
|
||||||
|
|
||||||
if isChunkBox(sourceBox) and isChunkBox(destBox):
|
if isChunkBox(sourceBox) and isChunkBox(destBox):
|
||||||
print "Copying with chunk alignment!"
|
print "Copying with chunk alignment!"
|
||||||
|
|
||||||
cxoffset = destBox.mincx - sourceBox.mincx
|
cxoffset = destBox.mincx - sourceBox.mincx
|
||||||
czoffset = destBox.mincz - sourceBox.mincz
|
czoffset = destBox.mincz - sourceBox.mincz
|
||||||
|
|
||||||
@ -2132,9 +2153,9 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
typemask[blocksToCopy] = True
|
typemask[blocksToCopy] = True
|
||||||
|
|
||||||
changedChunks = deque();
|
changedChunks = deque();
|
||||||
i = 0;
|
|
||||||
for cx, cz in sourceBox.chunkPositions:
|
for cx, cz in sourceBox.chunkPositions:
|
||||||
i += 1;
|
i += 1
|
||||||
|
yield (i, chunkCount)
|
||||||
if i % 100 == 0:
|
if i % 100 == 0:
|
||||||
info("Chunk {0}...".format(i))
|
info("Chunk {0}...".format(i))
|
||||||
|
|
||||||
@ -2186,15 +2207,21 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
ch.needsLighting = True
|
ch.needsLighting = True
|
||||||
|
|
||||||
else:
|
else:
|
||||||
i = 0;
|
chunkCount = subsectionCount()
|
||||||
for box, destPoint in iterateSubsections():
|
for box, destPoint in iterateSubsections():
|
||||||
info("Subsection {0} at {1}".format(i, destPoint))
|
info("Subsection {0} at {1}".format(i, destPoint))
|
||||||
temp = sourceLevel.extractSchematic(box);
|
temp = sourceLevel.extractSchematic(box);
|
||||||
self.copyBlocksFrom(temp, BoundingBox((0, 0, 0), box.size), destPoint, blocksToCopy);
|
self.copyBlocksFrom(temp, BoundingBox((0, 0, 0), box.size), destPoint, blocksToCopy);
|
||||||
i += 1;
|
i += 1
|
||||||
|
yield (i, chunkCount)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
||||||
|
for i in self.copyBlocksFromIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def copyBlocksFromIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
||||||
(x, y, z) = destinationPoint;
|
(x, y, z) = destinationPoint;
|
||||||
(lx, ly, lz) = sourceBox.size
|
(lx, ly, lz) = sourceBox.size
|
||||||
#sourcePoint, sourcePoint1 = sourceBox
|
#sourcePoint, sourcePoint1 = sourceBox
|
||||||
@ -2205,13 +2232,16 @@ class MCInfdevOldLevel(MCLevel):
|
|||||||
startTime = datetime.now()
|
startTime = datetime.now()
|
||||||
|
|
||||||
if(not isinstance(sourceLevel, MCInfdevOldLevel)):
|
if(not isinstance(sourceLevel, MCInfdevOldLevel)):
|
||||||
self.copyBlocksFromFinite(sourceLevel, sourceBox, destinationPoint, blocksToCopy)
|
for i in self.copyBlocksFromFiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
||||||
|
yield i
|
||||||
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.copyBlocksFromInfinite(sourceLevel, sourceBox, destinationPoint, blocksToCopy)
|
for i in self.copyBlocksFromInfiniteIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy):
|
||||||
|
yield i
|
||||||
|
|
||||||
self.copyEntitiesFrom(sourceLevel, sourceBox, destinationPoint, entities)
|
for i in self.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
|
||||||
|
yield i
|
||||||
info("Duration: {0}".format(datetime.now() - startTime))
|
info("Duration: {0}".format(datetime.now() - startTime))
|
||||||
#self.saveInPlace()
|
#self.saveInPlace()
|
||||||
|
|
||||||
|
35
level.py
35
level.py
@ -526,7 +526,12 @@ class MCLevel(object):
|
|||||||
|
|
||||||
return sourceBox, destinationPoint
|
return sourceBox, destinationPoint
|
||||||
|
|
||||||
|
|
||||||
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
def copyBlocksFrom(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
||||||
|
for i in self.copyBlocksFromIter(sourceLevel, sourceBox, destinationPoint, blocksToCopy, entities):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def copyBlocksFromIter(self, sourceLevel, sourceBox, destinationPoint, blocksToCopy=None, entities=True):
|
||||||
if (not sourceLevel.isInfinite) and not(
|
if (not sourceLevel.isInfinite) and not(
|
||||||
sourceLevel.containsPoint(*sourceBox.origin) and
|
sourceLevel.containsPoint(*sourceBox.origin) and
|
||||||
sourceLevel.containsPoint(*map(lambda x:x - 1, sourceBox.maximum))):
|
sourceLevel.containsPoint(*map(lambda x:x - 1, sourceBox.maximum))):
|
||||||
@ -546,11 +551,12 @@ class MCLevel(object):
|
|||||||
else:
|
else:
|
||||||
self.copyBlocksFromInfinite(sourceLevel, sourceBox, destinationPoint, blocksToCopy)
|
self.copyBlocksFromInfinite(sourceLevel, sourceBox, destinationPoint, blocksToCopy)
|
||||||
|
|
||||||
self.copyEntitiesFrom(sourceLevel, sourceBox, destinationPoint, entities)
|
for i in self.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
|
||||||
|
yield i
|
||||||
|
|
||||||
def saveInPlace(self):
|
def saveInPlace(self):
|
||||||
self.saveToFile(self.filename);
|
self.saveToFile(self.filename);
|
||||||
@classmethod
|
|
||||||
|
|
||||||
def setPlayerPosition(self, pos, player="Player"):
|
def setPlayerPosition(self, pos, player="Player"):
|
||||||
pass;
|
pass;
|
||||||
@ -574,9 +580,10 @@ class MCLevel(object):
|
|||||||
return (-45., 0.)
|
return (-45., 0.)
|
||||||
|
|
||||||
|
|
||||||
def copyEntitiesFromInfinite(self, sourceLevel, sourceBox, destinationPoint):
|
def copyEntitiesFromInfiniteIter(self, sourceLevel, sourceBox, destinationPoint):
|
||||||
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
chunkIterator = sourceLevel.getChunkSlices(sourceBox);
|
||||||
|
chunkCount = sourceBox.chunkCount
|
||||||
|
i = 0
|
||||||
for (chunk, slices, point) in chunkIterator:
|
for (chunk, slices, point) in chunkIterator:
|
||||||
#remember, slices are ordered x,z,y so you can subscript them like so: chunk.Blocks[slices]
|
#remember, slices are ordered x,z,y so you can subscript them like so: chunk.Blocks[slices]
|
||||||
cx, cz = chunk.chunkPosition
|
cx, cz = chunk.chunkPosition
|
||||||
@ -602,16 +609,22 @@ class MCLevel(object):
|
|||||||
self.addTileEntity(eTag)
|
self.addTileEntity(eTag)
|
||||||
|
|
||||||
chunk.compress();
|
chunk.compress();
|
||||||
|
yield float(i) / float(chunkCount)
|
||||||
|
i += 1
|
||||||
|
|
||||||
def copyEntitiesFrom(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
def copyEntitiesFrom(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
||||||
|
for i in self.copyEntitiesFromIter(sourceLevel, sourceBox, destinationPoint, entities):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def copyEntitiesFromIter(self, sourceLevel, sourceBox, destinationPoint, entities=True):
|
||||||
#assume coords have already been adjusted by copyBlocks
|
#assume coords have already been adjusted by copyBlocks
|
||||||
if not self.hasEntities or not sourceLevel.hasEntities: return;
|
if not self.hasEntities or not sourceLevel.hasEntities: return;
|
||||||
sourcePoint0 = sourceBox.origin;
|
sourcePoint0 = sourceBox.origin;
|
||||||
sourcePoint1 = sourceBox.maximum;
|
sourcePoint1 = sourceBox.maximum;
|
||||||
|
|
||||||
if sourceLevel.isInfinite:
|
if sourceLevel.isInfinite:
|
||||||
self.copyEntitiesFromInfinite(sourceLevel, sourceBox, destinationPoint)
|
for i in self.copyEntitiesFromInfiniteIter(sourceLevel, sourceBox, destinationPoint):
|
||||||
|
yield i
|
||||||
else:
|
else:
|
||||||
entsCopied = 0;
|
entsCopied = 0;
|
||||||
tileEntsCopied = 0;
|
tileEntsCopied = 0;
|
||||||
@ -623,8 +636,12 @@ class MCLevel(object):
|
|||||||
self.addEntity(eTag)
|
self.addEntity(eTag)
|
||||||
entsCopied += 1;
|
entsCopied += 1;
|
||||||
|
|
||||||
|
i = 0
|
||||||
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
for entity in getTileEntitiesInRange(sourceBox, sourceLevel.TileEntities):
|
||||||
|
i += 1
|
||||||
|
if i % 100 == 0:
|
||||||
|
yield
|
||||||
|
|
||||||
if not 'x' in entity: continue
|
if not 'x' in entity: continue
|
||||||
eTag = TileEntity.copyWithOffset(entity, copyOffset)
|
eTag = TileEntity.copyWithOffset(entity, copyOffset)
|
||||||
|
|
||||||
@ -633,6 +650,8 @@ class MCLevel(object):
|
|||||||
tileEntsCopied += 1;
|
tileEntsCopied += 1;
|
||||||
except ChunkNotPresent:
|
except ChunkNotPresent:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
yield
|
||||||
debug(u"Copied {0} entities, {1} tile entities".format(entsCopied, tileEntsCopied))
|
debug(u"Copied {0} entities, {1} tile entities".format(entsCopied, tileEntsCopied))
|
||||||
|
|
||||||
|
|
||||||
@ -671,6 +690,8 @@ class MCLevel(object):
|
|||||||
|
|
||||||
def generateLights(self, dirtyChunks=None):
|
def generateLights(self, dirtyChunks=None):
|
||||||
pass;
|
pass;
|
||||||
|
def generateLightsIter(self, dirtyChunks=None):
|
||||||
|
yield 0
|
||||||
|
|
||||||
def adjustExtractionParameters(self, box):
|
def adjustExtractionParameters(self, box):
|
||||||
x, y, z = box.origin
|
x, y, z = box.origin
|
||||||
|
29
schematic.py
29
schematic.py
@ -459,20 +459,32 @@ class INVEditChest(MCSchematic):
|
|||||||
|
|
||||||
|
|
||||||
def extractSchematicFrom(sourceLevel, box, entities=True):
|
def extractSchematicFrom(sourceLevel, box, entities=True):
|
||||||
|
for i in extractSchematicFromIter(sourceLevel, box, entities):
|
||||||
|
pass
|
||||||
|
return i
|
||||||
|
|
||||||
|
def extractSchematicFromIter(sourceLevel, box, entities=True):
|
||||||
p = sourceLevel.adjustExtractionParameters(box);
|
p = sourceLevel.adjustExtractionParameters(box);
|
||||||
if p is None: return
|
if p is None: return
|
||||||
newbox, destPoint = p
|
newbox, destPoint = p
|
||||||
|
|
||||||
tempSchematic = MCSchematic(shape=box.size)
|
tempSchematic = MCSchematic(shape=box.size)
|
||||||
tempSchematic.materials = sourceLevel.materials
|
tempSchematic.materials = sourceLevel.materials
|
||||||
tempSchematic.copyBlocksFrom(sourceLevel, newbox, destPoint, entities=entities)
|
for i in tempSchematic.copyBlocksFromIter(sourceLevel, newbox, destPoint, entities=entities):
|
||||||
|
yield i
|
||||||
|
|
||||||
return tempSchematic
|
yield tempSchematic
|
||||||
|
|
||||||
MCLevel.extractSchematic = extractSchematicFrom
|
MCLevel.extractSchematic = extractSchematicFrom
|
||||||
|
MCLevel.extractSchematicIter = extractSchematicFromIter
|
||||||
|
|
||||||
import tempfile
|
import tempfile
|
||||||
def extractZipSchematicFrom(sourceLevel, box, zipfilename=None, entities=True):
|
def extractZipSchematicFrom(sourceLevel, box, zipfilename=None, entities=True):
|
||||||
|
for i in extractZipSchematicFromIter(sourceLevel, box, zipfilename, entities):
|
||||||
|
pass
|
||||||
|
return i
|
||||||
|
|
||||||
|
def extractZipSchematicFromIter(sourceLevel, box, zipfilename=None, entities=True):
|
||||||
#converts classic blocks to alpha
|
#converts classic blocks to alpha
|
||||||
#probably should only apply to alpha levels
|
#probably should only apply to alpha levels
|
||||||
|
|
||||||
@ -498,13 +510,15 @@ def extractZipSchematicFrom(sourceLevel, box, zipfilename=None, entities=True):
|
|||||||
destChunks = destBox.chunkPositions
|
destChunks = destBox.chunkPositions
|
||||||
chunkIter = itertools.izip(chunks, destChunks)
|
chunkIter = itertools.izip(chunks, destChunks)
|
||||||
|
|
||||||
chunks = (x[1] for x in chunkIter if sourceLevel.containsChunk(*x[0]))
|
for i, (src, chunk) in enumerate(chunkIter):
|
||||||
tempSchematic.createChunks(chunks)
|
if sourceLevel.containsChunk(*src):
|
||||||
|
tempSchematic.createChunk(*chunk)
|
||||||
|
yield i, sourceBox.chunkCount
|
||||||
else:
|
else:
|
||||||
tempSchematic.createChunksInBox(destBox)
|
tempSchematic.createChunksInBox(destBox)
|
||||||
|
|
||||||
tempSchematic.copyBlocksFrom(sourceLevel, sourceBox, destPoint, entities=entities)
|
for i in tempSchematic.copyBlocksFromIter(sourceLevel, sourceBox, destPoint, entities=entities):
|
||||||
|
yield i
|
||||||
tempSchematic.saveInPlace(); #lights not needed for this format - crashes minecraft though
|
tempSchematic.saveInPlace(); #lights not needed for this format - crashes minecraft though
|
||||||
|
|
||||||
schematicDat = TAG_Compound()
|
schematicDat = TAG_Compound()
|
||||||
@ -520,9 +534,10 @@ def extractZipSchematicFrom(sourceLevel, box, zipfilename=None, entities=True):
|
|||||||
import shutil
|
import shutil
|
||||||
shutil.rmtree(filename)
|
shutil.rmtree(filename)
|
||||||
import mclevel
|
import mclevel
|
||||||
return mclevel.fromFile(zipfilename)
|
yield mclevel.fromFile(zipfilename)
|
||||||
|
|
||||||
MCLevel.extractZipSchematic = extractZipSchematicFrom
|
MCLevel.extractZipSchematic = extractZipSchematicFrom
|
||||||
|
MCLevel.extractZipSchematicIter = extractZipSchematicFromIter
|
||||||
|
|
||||||
from zipfile import ZipFile, ZIP_STORED
|
from zipfile import ZipFile, ZIP_STORED
|
||||||
def zipdir(basedir, archivename):
|
def zipdir(basedir, archivename):
|
||||||
|
Reference in New Issue
Block a user