Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor: Simplify ZipSchematic code and move it to schematic.py

Upon loading, extract the zip file to a temporary folder and load that as an Anvil world
Upon saving, recreate the zip file from the temporary folder.
Register an atexit func to remove the temp folder.
  • Loading branch information...
commit 428a95088a77f0c4bed9a472c4dd340eac1847ff 1 parent 36e7972
@codewarrior0 codewarrior0 authored
Showing with 88 additions and 131 deletions.
  1. +2 −2 __init__.py
  2. +4 −81 infiniteworld.py
  3. +2 −2 mclevel.py
  4. +80 −46 schematic.py
View
4 __init__.py
@@ -2,7 +2,7 @@
from entity import Entity, TileEntity
from faces import faceDirections, FaceXDecreasing, FaceXIncreasing, FaceYDecreasing, FaceYIncreasing, FaceZDecreasing, FaceZIncreasing, MaxDirections
from indev import MCIndevLevel
-from infiniteworld import ChunkedLevelMixin, AnvilChunk, MCAlphaDimension, MCInfdevOldLevel, ZeroChunk, ZipSchematic
+from infiniteworld import ChunkedLevelMixin, AnvilChunk, MCAlphaDimension, MCInfdevOldLevel, ZeroChunk
import items
from java import MCJavaLevel
from level import ChunkBase, computeChunkHeightMap, EntityLevel, FakeChunk, LightedChunk, MCLevel
@@ -11,4 +11,4 @@
from mclevel import fromFile, loadWorld, loadWorldNumber
from nbt import load, gunzip, TAG_Byte, TAG_Byte_Array, TAG_Compound, TAG_Double, TAG_Float, TAG_Int, TAG_Int_Array, TAG_List, TAG_Long, TAG_Short, TAG_String
import pocket
-from schematic import INVEditChest, MCSchematic
+from schematic import INVEditChest, MCSchematic, ZipSchematic
View
85 infiniteworld.py
@@ -4,7 +4,6 @@
@author: Rio
'''
-from contextlib import closing
from datetime import datetime
import itertools
from logging import getLogger
@@ -15,13 +14,14 @@
import time
import traceback
import zlib
-import shutil
import sys
-import tempfile
+import blockrotation
+from box import BoundingBox
from entity import Entity, TileEntity
from faces import FaceXDecreasing, FaceXIncreasing, FaceZDecreasing, FaceZIncreasing
-from materials import alphaMaterials, namedMaterials
+from level import LightedChunk, EntityLevel, computeChunkHeightMap, MCLevel, ChunkBase
+from materials import alphaMaterials
from mclevelbase import ChunkMalformed, ChunkNotPresent, exhaust, PlayerNotFound
import nbt
from numpy import array, clip, maximum, zeros
@@ -30,9 +30,6 @@
log = getLogger(__name__)
warn, error, info, debug = log.warn, log.error, log.info, log.debug
-import blockrotation
-from box import BoundingBox
-from level import LightedChunk, EntityLevel, computeChunkHeightMap, MCLevel, ChunkBase
DIM_NETHER = -1
DIM_END = 1
@@ -1841,77 +1838,3 @@ def saveInPlace(self, saveSelf=False):
else:
self.parentWorld.saveInPlace()
-from zipfile import ZipFile, is_zipfile
-
-
-class ZipSchematic (MCInfdevOldLevel):
- def __init__(self, filename):
- tempdir = tempfile.mktemp("schematic")
- zf = ZipFile(filename)
- self.zipfile = zf
- zf.extract("level.dat", tempdir)
-
- MCInfdevOldLevel.__init__(self, tempdir)
-
- self.filename = filename
-
- try:
- with closing(self.zipfile.open("schematic.dat")) as f:
- schematicDat = nbt.load(buf=nbt.gunzip(f.read()))
-
- self.Width = schematicDat['Width'].value
- self.Height = schematicDat['Height'].value
- self.Length = schematicDat['Length'].value
-
- if "Materials" in schematicDat:
- self.materials = namedMaterials[schematicDat["Materials"].value]
-
- except Exception, e:
- print "Exception reading schematic.dat, skipping: {0!r}".format(e)
- self.Width = 0
- self.Height = 128
- self.Length = 0
-
- def close(self):
- MCInfdevOldLevel.close(self)
- self.zipfile.close()
- shutil.rmtree(self.worldFolder.filename, True)
-
- def getWorldBounds(self):
- return BoundingBox((0, 0, 0), (self.Width, self.Height, self.Length))
-
- @classmethod
- def _isLevel(cls, filename):
- return is_zipfile(filename)
-
- def saveInPlace(self):
- self.saveToFile(self.filename)
-
- def saveToFile(self, filename):
- tempfile = filename + ".new"
- from schematic import zipdir
- zipdir(self.worldFolder.filename, tempfile)
-
- if os.path.exists(filename):
- os.remove(filename)
- shutil.copy(tempfile, filename)
-
- def containsChunk(self, cx, cz):
- return (cx, cz) in self.allChunks
-
- def preloadRegions(self):
- self.zipfile.extractall(self.worldFolder.filename)
- self.regionFiles = {}
-
- MCInfdevOldLevel.preloadRegions(self)
-
- def preloadDimensions(self):
- pass
-
- def loadLevelDat(self, create=False, random_seed=None, last_played=None):
- if create:
- raise NotImplementedError("Cannot save zipfiles yet!")
-
- with closing(self.zipfile.open("level.dat")) as f:
- self.root_tag = nbt.load(buf=f)
-
View
4 mclevel.py
@@ -171,7 +171,7 @@ def fillBlocks(self, box, blockType, blockData = 0):
"""
from indev import MCIndevLevel
-from infiniteworld import MCInfdevOldLevel, ZipSchematic
+from infiniteworld import MCInfdevOldLevel
from java import MCJavaLevel
from logging import getLogger
from mclevelbase import saveFileDir
@@ -179,7 +179,7 @@ def fillBlocks(self, box, blockType, blockData = 0):
from numpy import fromstring
import os
from pocket import PocketWorld
-from schematic import INVEditChest, MCSchematic
+from schematic import INVEditChest, MCSchematic, ZipSchematic
import sys
import traceback
View
126 schematic.py
@@ -3,21 +3,21 @@
@author: Rio
'''
+import atexit
+from contextlib import closing
+import os
+import shutil
+import zipfile
+from logging import getLogger
import blockrotation
-from contextlib import closing
-from cStringIO import StringIO
from box import BoundingBox
-import gzip
+import infiniteworld
from level import MCLevel, EntityLevel
-from logging import getLogger
from materials import alphaMaterials, MCMaterials, namedMaterials
from mclevelbase import exhaust
import nbt
from numpy import array, swapaxes, uint8, zeros
-import os
-import shutil
-import sys
log = getLogger(__name__)
warn, error, info, debug = log.warn, log.error, log.info, log.debug
@@ -367,6 +367,71 @@ def TileEntities(self):
return nbt.TAG_List([chestTag], name="TileEntities")
+class ZipSchematic (infiniteworld.MCInfdevOldLevel):
+ def __init__(self, filename, create=False):
+ self.zipfilename = filename
+
+ tempdir = tempfile.mktemp("schematic")
+ if create is False:
+ zf = zipfile.ZipFile(filename)
+ zf.extractall(tempdir)
+ zf.close()
+
+ super(ZipSchematic, self).__init__(tempdir, create)
+ atexit.register(shutil.rmtree, self.worldFolder.filename, True)
+
+
+ try:
+ schematicDat = nbt.load(self.worldFolder.getFilePath("schematic.dat"))
+
+ self.Width = schematicDat['Width'].value
+ self.Height = schematicDat['Height'].value
+ self.Length = schematicDat['Length'].value
+
+ if "Materials" in schematicDat:
+ self.materials = namedMaterials[schematicDat["Materials"].value]
+
+ except Exception, e:
+ print "Exception reading schematic.dat, skipping: {0!r}".format(e)
+ self.Width = 0
+ self.Height = 128
+ self.Length = 0
+
+ def __del__(self):
+ shutil.rmtree(self.worldFolder.filename, True)
+
+ def saveInPlace(self):
+ super(ZipSchematic, self).saveInPlace()
+ schematicDat = nbt.TAG_Compound()
+ schematicDat.name = "Mega Schematic"
+
+ schematicDat["Width"] = nbt.TAG_Int(self.size[0])
+ schematicDat["Height"] = nbt.TAG_Int(self.size[1])
+ schematicDat["Length"] = nbt.TAG_Int(self.size[2])
+ schematicDat["Materials"] = nbt.TAG_String(self.materials.name)
+
+ schematicDat.save(self.worldFolder.getFilePath("schematic.dat"))
+
+ basedir = self.worldFolder.filename
+ assert os.path.isdir(basedir)
+ with closing(zipfile.ZipFile(self.zipfilename, "w", zipfile.ZIP_STORED)) as z:
+ for root, dirs, files in os.walk(basedir):
+ # NOTE: ignore empty directories
+ for fn in files:
+ absfn = os.path.join(root, fn)
+ zfn = absfn[len(basedir) + len(os.sep):] # XXX: relative path
+ z.write(absfn, zfn)
+
+ def getWorldBounds(self):
+ return BoundingBox((0, 0, 0), (self.Width, self.Height, self.Length))
+
+ @classmethod
+ def _isLevel(cls, filename):
+ return zipfile.is_zipfile(filename)
+
+
+
+
def adjustExtractionParameters(self, box):
x, y, z = box.origin
w, h, l = box.size
@@ -453,7 +518,7 @@ def extractZipSchematicFromIter(sourceLevel, box, zipfilename=None, entities=Tru
# probably should only apply to alpha levels
if zipfilename is None:
- zipfilename = tempfile.mktemp("zipschematic")
+ zipfilename = tempfile.mktemp("zipschematic.zip")
p = sourceLevel.adjustExtractionParameters(box)
if p is None:
@@ -462,32 +527,15 @@ def extractZipSchematicFromIter(sourceLevel, box, zipfilename=None, entities=Tru
destPoint = (0, 0, 0)
- tempfolder = tempfile.mktemp("schematic")
- try:
- tempSchematic = MCInfdevOldLevel(tempfolder, create=True)
- tempSchematic.materials = sourceLevel.materials
-
- 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
-
- schematicDat = nbt.TAG_Compound()
- schematicDat.name = "Mega Schematic"
-
- schematicDat["Width"] = nbt.TAG_Int(sourceBox.size[0])
- schematicDat["Height"] = nbt.TAG_Int(sourceBox.size[1])
- schematicDat["Length"] = nbt.TAG_Int(sourceBox.size[2])
- schematicDat["Materials"] = nbt.TAG_String(tempSchematic.materials.name)
- schematicDat.save(os.path.join(tempfolder, "schematic.dat"))
+ tempSchematic = ZipSchematic(zipfilename, create=True)
+ tempSchematic.materials = sourceLevel.materials
- zipdir(tempfolder, zipfilename)
+ for i in tempSchematic.copyBlocksFromIter(sourceLevel, sourceBox, destPoint, entities=entities, create=True):
+ yield i
- import mclevel
- yield mclevel.fromFile(zipfilename)
- finally:
- # We get here if the generator is GCed also
- if os.path.exists(tempfolder):
- shutil.rmtree(tempfolder, False)
+ tempSchematic.Width, tempSchematic.Height, tempSchematic.Length = sourceBox.size
+ tempSchematic.saveInPlace() # lights not needed for this format - crashes minecraft though
+ yield tempSchematic
MCLevel.extractZipSchematic = extractZipSchematicFrom
MCLevel.extractZipSchematicIter = extractZipSchematicFromIter
@@ -508,17 +556,3 @@ def extractAnySchematicIter(level, box):
MCLevel.extractAnySchematic = extractAnySchematic
MCLevel.extractAnySchematicIter = extractAnySchematicIter
-from zipfile import ZipFile, ZIP_STORED
-
-
-def zipdir(basedir, archivename):
- assert os.path.isdir(basedir)
- with closing(ZipFile(archivename, "w", ZIP_STORED)) as z:
- for root, dirs, files in os.walk(basedir):
- # NOTE: ignore empty directories
- for fn in files:
- absfn = os.path.join(root, fn)
- zfn = absfn[len(basedir) + len(os.sep):] # XXX: relative path
- z.write(absfn, zfn)
-
-from infiniteworld import MCInfdevOldLevel
Please sign in to comment.
Something went wrong with that request. Please try again.