def __init__(self, filename, resume=None):
        """

        :param resume: Whether to resume editing if an undo folder already exists. Pass True to resume editing,
        False to delete the old world folder, or None to raise an exception if the folder exists.
        :type resume: bool | None
        :param filename: Path to the world folder to open
        :type filename: str | unicode
        :rtype: RevisionHistory
        """

        # Create undo folder in the folder containing the root folder.
        self.tempFolder = os.path.join(
            os.path.dirname(filename),
            "##%s.UNDO##" % os.path.basename(filename))
        if os.path.exists(self.tempFolder):
            if resume is True:
                raise NotImplementedError(
                    "Cannot resume from existing undo folder (yet)")
            elif resume is False:
                shutil.move(self.tempFolder, self.tempFolder + "__")
                shutil.rmtree(self.tempFolder + "__", ignore_errors=True)
            else:
                raise UndoFolderExists("Undo folder already exists for %s" %
                                       filename)
        os.makedirs(self.tempFolder)

        self.rootFolder = AnvilWorldFolder(filename)
        self.rootNode = RevisionHistoryNode(self, self.rootFolder, None)
        self.rootNode.differences = RevisionChanges()
        self.rootNodeIndex = 0
        self.orphanChainIndex = None
        self.IDcounter = 0
        self.nodes = [self.rootNode]
Beispiel #2
0
    def __init__(self, filename=None, create=False, readonly=False, resume=None):
        """
        Load a Minecraft for PC level (Anvil format) from the given filename. It can point to either
        a level.dat or a folder containing one. If create is True, it will
        also create the world using a randomly selected seed.

        If you try to create an existing world, IOError will be raised.

        Uses a RevisionHistory to manage undo history. Upon creation, the world is read-only until createRevision() is
        called. Call createRevision() to create a new revision, or selectRevision() to revert to an earlier
        revision. Older revisions are read-only, so createRevision() must be called again to make further changes.

        Call writeAllChanges() to write all changes into the original world.

        :type filename: str or unicode
        :type create: bool
        :type readonly: bool
        :rtype: AnvilWorldAdapter
        """
        self.lockTime = 0

        self.EntityRef = PCEntityRef
        self.TileEntityRef = PCTileEntityRef

        assert not (create and readonly)

        if os.path.basename(filename) in ("level.dat", "level.dat_old"):
            filename = os.path.dirname(filename)

        if not os.path.exists(filename):
            if not create:
                raise IOError('File not found')

            os.mkdir(filename)
        else:
            if create:
                if not os.path.isdir(filename) or os.path.exists(os.path.join(filename, "level.dat")):
                    raise IOError('File exists!')

        if not os.path.isdir(filename):
            raise IOError('File is not a Minecraft Anvil world')

        if readonly:
            self.revisionHistory = AnvilWorldFolder(filename)
            self.selectedRevision = self.revisionHistory
        else:
            self.revisionHistory = RevisionHistory(filename, resume)
            self.selectedRevision = self.revisionHistory.getHead()

        self.filename = filename
        self.readonly = readonly
        if not readonly:
            self.acquireSessionLock()

        if create:
            self._createMetadataTag()
            self.selectedRevision.writeFile("level.dat", self.metadata.metadataTag.save())

        else:
            self.loadMetadata()
Beispiel #3
0
    def _createRevisionFolder(self):
        ID = "%08d" % self.IDcounter
        self.IDcounter += 1

        filename = os.path.join(self.tempFolder, ID)
        return AnvilWorldFolder(filename, create=True)
Beispiel #4
0
    def __init__(self, filename=None, create=False, readonly=False, resume=None):
        """
        Load a Minecraft for PC level (Anvil format) from the given filename. It can point to either
        a level.dat or a folder containing one. If create is True, it will
        also create the world using a randomly selected seed.

        If you try to create an existing world, IOError will be raised.

        Uses a RevisionHistory to manage undo history. Upon creation, the world is read-only until createRevision() is
        called. Call createRevision() to create a new revision, or selectRevision() to revert to an earlier
        revision. Older revisions are read-only, so createRevision() must be called again to make further changes.

        Call writeAllChanges() to write all changes into the original world.

        :type filename: str or unicode
        :type create: bool
        :type readonly: bool
        :rtype: AnvilWorldAdapter
        """
        self.lockTime = 0

        assert not (create and readonly)

        if os.path.basename(filename) in ("level.dat", "level.dat_old"):
            filename = os.path.dirname(filename)

        if not os.path.exists(filename):
            if not create:
                raise IOError('File not found')

            os.mkdir(filename)
        else:
            if create:
                if not os.path.isdir(filename) or os.path.exists(os.path.join(filename, "level.dat")):
                    raise IOError('File exists!')

        if not os.path.isdir(filename):
            raise IOError('File is not a Minecraft Anvil world')

        if readonly:
            self.revisionHistory = AnvilWorldFolder(filename)
            self.selectedRevision = self.revisionHistory
        else:
            self.revisionHistory = RevisionHistory(filename, resume)
            self.selectedRevision = self.revisionHistory.getHead()

        self.filename = filename
        self.readonly = readonly
        if not readonly:
            self.acquireSessionLock()

        if create:
            self._createMetadataTag()
            self.selectedRevision.writeFile("level.dat", self.metadata.metadataTag.save())

        else:
            try:
                metadataTag = nbt.load(buf=self.selectedRevision.readFile("level.dat"))
                self.metadata = AnvilWorldMetadata(metadataTag)
                self.loadFMLMapping()
            except (EnvironmentError, zlib.error) as e:
                log.info("Error loading level.dat, trying level.dat_old ({0})".format(e))
                try:
                    metadataTag = nbt.load(buf=self.selectedRevision.readFile("level.dat_old"))
                    self.metadata = AnvilWorldMetadata(metadataTag)
                    log.info("level.dat restored from backup.")
                    self.saveChanges()
                except Exception as e:
                    traceback.print_exc()
                    log.info("%r while loading level.dat_old. Initializing with defaults.", e)
                    self._createMetadataTag()

        assert self.metadata.version == VERSION_ANVIL, "Pre-Anvil world formats are not supported (for now)"