示例#1
0
    def pruneChunks(self):
        if "No" == ask(
                "Save these chunks and remove the rest? This cannot be undone.",
            ("Yes", "No")):
            return
        self.editor.saveFile()

        def _pruneChunks():
            maxChunks = self.editor.level.chunkCount
            selectedChunks = self.selectedChunks()
            for i, cPos in enumerate(list(self.editor.level.allChunks)):
                if cPos not in selectedChunks:
                    try:
                        self.editor.level.deleteChunk(*cPos)

                    except Exception as e:
                        print "Error during chunk delete: ", e

                yield i, maxChunks

        with setWindowCaption("PRUNING - "):
            showProgress("Pruning chunks...", _pruneChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.discardAllChunks()
示例#2
0
    def createChunks(self):
        panel = GeneratorPanel()
        col = [panel]
        label = Label(
            "Create chunks using the settings above? This cannot be undone.")
        col.append(Row([Label("")]))
        col.append(label)
        col = Column(col)
        if Dialog(client=col, responses=["OK",
                                         "Cancel"]).present() == "Cancel":
            return
        chunks = self.selectedChunks()

        createChunks = panel.generate(self.editor.level, chunks)

        try:
            with setWindowCaption("CREATING - "):
                showProgress("Creating {0} chunks...".format(len(chunks)),
                             createChunks,
                             cancel=True)
        except Exception as e:
            traceback.print_exc()
            alert(_("Failed to start the chunk generator. {0!r}").format(e))
        finally:
            self.editor.renderer.invalidateChunkMarkers()
            self.editor.renderer.loadNearbyChunks()
    def undo(self):
        """ Undo the operation. Ought to leave the Operation in a state where it can be performed again.
            Default implementation copies all chunks in undoLevel back into level. Non-chunk-based operations
            should override this."""

        if self.undoLevel:
            self.redoLevel = self.extractUndo(self.level, self.dirtyBox())

            def _undo():
                yield 0, 0, "Undoing..."
                if hasattr(self.level, 'copyChunkFrom'):
                    for i, (cx, cz) in enumerate(self.undoLevel.allChunks):
                        self.level.copyChunkFrom(self.undoLevel, cx, cz)
                        yield i, self.undoLevel.chunkCount, "Copying chunk %s..." % ((cx, cz),)
                else:
                    for i in self.level.copyBlocksFromIter(self.undoLevel, self.undoLevel.bounds,
                                                           self.undoLevel.sourcePoint, biomes=True):
                        yield i, self.undoLevel.chunkCount, "Copying..."

            if self.undoLevel.chunkCount > 25:
                showProgress("Undoing...", _undo())
            else:
                exhaust(_undo())

            self.editor.invalidateChunks(self.undoLevel.allChunks)
示例#4
0
    def destroyChunks(self, chunks=None):
        if "No" == ask("Really delete these chunks? This cannot be undone.",
                       ("Yes", "No")):
            return
        if chunks is None:
            chunks = self.selectedChunks()
        chunks = list(chunks)

        def _destroyChunks():
            i = 0
            chunkCount = len(chunks)

            for cx, cz in chunks:
                i += 1
                yield (i, chunkCount)
                if self.editor.level.containsChunk(cx, cz):
                    try:
                        self.editor.level.deleteChunk(cx, cz)
                    except Exception as e:
                        print "Error during chunk delete: ", e

        with setWindowCaption("DELETING - "):
            showProgress("Deleting chunks...", _destroyChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.renderer.discardAllChunks()
示例#5
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert(_("Cannot perform action while saving is taking place"))
            return

        if recordUndo:
            self.canUndo = True
            self.undoLevel = self.extractUndo(self.level, BoundingBox(self.destPoint, self.sourceBox.size))

        blocksToCopy = None
        if not (self.copyAir and self.copyWater):
            blocksToCopy = range(pymclevel.materials.id_limit)
            if not self.copyAir:
                blocksToCopy.remove(0)
            if not self.copyWater:
                blocksToCopy.remove(8)
            if not self.copyWater:
                blocksToCopy.remove(9)

        with setWindowCaption("Copying - "):
            i = self.level.copyBlocksFromIter(
                self.sourceLevel,
                self.sourceBox,
                self.destPoint,
                blocksToCopy,
                create=True,
                biomes=self.copyBiomes,
                staticCommands=self.staticCommands,
                moveSpawnerPos=self.moveSpawnerPos,
                regenerateUUID=self.regenerateUUID,
                first=False,
            )
            showProgress(_("Copying {0:n} blocks...").format(self.sourceBox.volume), i)
示例#6
0
    def undo(self):
        """ Undo the operation. Ought to leave the Operation in a state where it can be performed again.
            Default implementation copies all chunks in undoLevel back into level. Non-chunk-based operations
            should override this."""

        if self.undoLevel:
            self.redoLevel = self.extractUndo(self.level, self.dirtyBox())

            def _undo():
                yield 0, 0, "Undoing..."
                if hasattr(self.level, 'copyChunkFrom'):
                    for i, (cx, cz) in enumerate(self.undoLevel.allChunks):
                        self.level.copyChunkFrom(self.undoLevel, cx, cz)
                        yield i, self.undoLevel.chunkCount, "Copying chunk %s..." % (
                            (cx, cz), )
                else:
                    for i in self.level.copyBlocksFromIter(
                            self.undoLevel,
                            self.undoLevel.bounds,
                            self.undoLevel.sourcePoint,
                            biomes=True):
                        yield i, self.undoLevel.chunkCount, "Copying..."

            if self.undoLevel.chunkCount > 25:
                showProgress("Undoing...", _undo())
            else:
                exhaust(_undo())

            self.editor.invalidateChunks(self.undoLevel.allChunks)
示例#7
0
    def destroyChunks(self, chunks=None):
        if "No" == ask("Really delete these chunks? This cannot be undone.", ("Yes", "No")):
            return
        if chunks is None:
            chunks = self.selectedChunks()
        chunks = list(chunks)

        def _destroyChunks():
            i = 0
            chunkCount = len(chunks)

            for cx, cz in chunks:
                i += 1
                yield (i, chunkCount)
                if self.editor.level.containsChunk(cx, cz):
                    try:
                        self.editor.level.deleteChunk(cx, cz)
                    except Exception as e:
                        print "Error during chunk delete: ", e

        with setWindowCaption("DELETING - "):
            showProgress("Deleting chunks...", _destroyChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.renderer.discardAllChunks()
示例#8
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert(_("Cannot perform action while saving is taking place"))
            return

        if recordUndo:
            self.canUndo = True
            self.undoLevel = self.extractUndo(
                self.level, BoundingBox(self.destPoint, self.sourceBox.size))

        blocksToCopy = None
        if not (self.copyAir and self.copyWater):
            blocksToCopy = range(pymclevel.materials.id_limit)
            if not self.copyAir:
                blocksToCopy.remove(0)
            if not self.copyWater:
                blocksToCopy.remove(8)
            if not self.copyWater:
                blocksToCopy.remove(9)

        with setWindowCaption("Copying - "):
            i = self.level.copyBlocksFromIter(
                self.sourceLevel,
                self.sourceBox,
                self.destPoint,
                blocksToCopy,
                create=True,
                biomes=self.copyBiomes,
                staticCommands=self.staticCommands,
                moveSpawnerPos=self.moveSpawnerPos,
                regenerateUUID=self.regenerateUUID,
                first=False)
            showProgress(
                _("Copying {0:n} blocks...").format(self.sourceBox.volume), i)
示例#9
0
        def checkForUpdates():
            def _check():
                yield
                jarStorage.downloadCurrentServer(panel.snapshot)
                yield

            showProgress("Checking for server updates...", _check())
            versionChoice.choices = sorted(jarStorage.versions, reverse=True)
            versionChoice.choiceIndex = 0
示例#10
0
        def checkForUpdates():
            def _check():
                yield
                jarStorage.downloadCurrentServer(panel.snapshot)
                yield

            showProgress("Checking for server updates...", _check())
            versionChoice.choices = sorted(jarStorage.versions, reverse=True)
            versionChoice.choiceIndex = 0
示例#11
0
    def relightChunks(self):

        def _relightChunks():
            for i in self.editor.level.generateLightsIter(self.selectedChunks()):
                yield i

        with setWindowCaption("RELIGHTING - "):
            showProgress(_("Lighting {0} chunks...").format(len(self.selectedChunks())),
                         _relightChunks(), cancel=True)

            self.editor.invalidateChunks(self.selectedChunks())
            self.editor.addUnsavedEdit()
示例#12
0
    def relightChunks(self):

        def _relightChunks():
            for i in self.editor.level.generateLightsIter(self.selectedChunks()):
                yield i

        with setWindowCaption("RELIGHTING - "):
            showProgress(_("Lighting {0} chunks...").format(len(self.selectedChunks())),
                         _relightChunks(), cancel=True)

            self.editor.invalidateChunks(self.selectedChunks())
            self.editor.addUnsavedEdit()
示例#13
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert("Cannot perform action while saving is taking place")
            return
        if recordUndo:
            self.undoLevel = self.extractUndo(self.level, self.destBox)

        destBox = self.destBox
        if self.level.bounds == self.destBox:
            destBox = None

        fill = self.level.fillBlocksIter(destBox, self.blockInfo, blocksToReplace=self.blocksToReplace, noData=self.noData)
        showProgress("Replacing blocks...", fill, cancel=True)
        self.canUndo = True
示例#14
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert("Cannot perform action while saving is taking place")
            return
        if recordUndo:
            self.undoLevel = self.extractUndo(self.level, self.destBox)

        destBox = self.destBox
        if self.level.bounds == self.destBox:
            destBox = None

        fill = self.level.fillBlocksIter(destBox, self.blockInfo, blocksToReplace=self.blocksToReplace, noData=self.noData)
        showProgress("Replacing blocks...", fill, cancel=True)
        self.canUndo = True
示例#15
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert(_("Cannot perform action while saving is taking place"))
            return
        if recordUndo:
            self.canUndo = True
            self.undoLevel = self.extractUndo(self.level, self._dirtyBox)

        def _perform():
            yield 0, len(self.points), _("Applying {0} brush...").format(
                _(self.brushMode.displayName))
            if hasattr(self.brushMode, 'apply'):
                for i, point in enumerate(self.points):
                    f = self.brushMode.apply(self.brushMode, self, point)
                    if hasattr(f, "__iter__"):
                        for progress in f:
                            yield progress
                    else:
                        yield i, len(
                            self.points), _("Applying {0} brush...").format(
                                _(self.brushMode.displayName))
            if hasattr(self.brushMode, 'applyToChunkSlices'):
                for j, cPos in enumerate(self._dirtyBox.chunkPositions):
                    if not self.level.containsChunk(*cPos):
                        continue
                    chunk = self.level.getChunk(*cPos)
                    for i, point in enumerate(self.points):
                        brushBox = self.tool.getDirtyBox(point, self.tool)
                        brushBoxThisChunk, slices = chunk.getChunkSlicesForBox(
                            brushBox)
                        f = self.brushMode.applyToChunkSlices(
                            self.brushMode, self, chunk, slices, brushBox,
                            brushBoxThisChunk)
                        if brushBoxThisChunk.volume == 0:
                            f = None
                        if hasattr(f, "__iter__"):
                            for progress in f:
                                yield progress
                        else:
                            yield j * len(self.points) + i, len(
                                self.points) * self._dirtyBox.chunkCount, _(
                                    "Applying {0} brush...").format(
                                        _(self.brushMode.displayName))
                    chunk.chunkChanged()

        if len(self.points) > 10:
            showProgress("Performing brush...", _perform(), cancel=True)
        else:
            exhaust(_perform())
示例#16
0
    def extractUndoChunks(self, level, chunks, chunkCount=None):
        if not isinstance(level, pymclevel.MCInfdevOldLevel):
            chunks = numpy.array(list(chunks))
            mincx, mincz = numpy.min(chunks, 0)
            maxcx, maxcz = numpy.max(chunks, 0)
            box = BoundingBox((mincx << 4, 0, mincz << 4), (maxcx << 4, level.Height, maxcz << 4))

            return self.extractUndoSchematic(level, box)

        undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
        if not chunkCount:
            try:
                chunkCount = len(chunks)
            except TypeError:
                chunkCount = -1

        def _extractUndo():
            yield 0, 0, "Recording undo..."
            for i, (cx, cz) in enumerate(chunks):
                undoLevel.copyChunkFrom(level, cx, cz)
                yield i, chunkCount, _("Copying chunk %s...") % ((cx, cz),)
            undoLevel.saveInPlace()

        if chunkCount > 25 or chunkCount < 1:
            if "Canceled" == showProgress("Recording undo...", _extractUndo(), cancel=True):
                if albow.ask("Continue with undo disabled?", ["Continue", "Cancel"]) == "Cancel":
                    raise Cancel
                else:
                    return None
        else:
            exhaust(_extractUndo())

        return undoLevel
示例#17
0
    def redo(self):
        if self.redoLevel:
            def _redo():
                yield 0, 0, "Redoing..."
                if hasattr(self.level, 'copyChunkFrom'):
                    for i, (cx, cz) in enumerate(self.redoLevel.allChunks):
                        self.level.copyChunkFrom(self.redoLevel, cx, cz)
                        yield i, self.redoLevel.chunkCount, "Copying chunk %s..." % ((cx, cz),)
                else:
                    for i in self.level.copyBlocksFromIter(self.redoLevel, self.redoLevel.bounds,
                                                           self.redoLevel.sourcePoint, biomes=True):
                        yield i, self.undoLevel.chunkCount, "Copying..."

            if self.redoLevel.chunkCount > 25:
                showProgress("Redoing...", _redo())
            else:
                exhaust(_redo())
示例#18
0
    def createChunks(self):
        panel = GeneratorPanel()
        col = [panel]
        label = Label("Create chunks using the settings above? This cannot be undone.")
        col.append(Row([Label("")]))
        col.append(label)
        col = Column(col)
        if Dialog(client=col, responses=["OK", "Cancel"]).present() == "Cancel":
            return
        chunks = self.selectedChunks()

        createChunks = panel.generate(self.editor.level, chunks)

        try:
            with setWindowCaption("CREATING - "):
                showProgress("Creating {0} chunks...".format(len(chunks)), createChunks, cancel=True)
        except Exception, e:
            traceback.print_exc()
            alert(_("Failed to start the chunk generator. {0!r}").format(e))
示例#19
0
    def extractUndoSchematic(level, box):
        if box.volume > 131072:
            sch = showProgress("Recording undo...", level.extractZipSchematicIter(box), cancel=True)
        else:
            sch = level.extractZipSchematic(box)
        if sch == "Cancel":
            raise Cancel
        if sch:
            sch.sourcePoint = box.origin

        return sch
示例#20
0
    def redo(self):
        if self.redoLevel:

            def _redo():
                yield 0, 0, "Redoing..."
                if hasattr(self.level, 'copyChunkFrom'):
                    for i, (cx, cz) in enumerate(self.redoLevel.allChunks):
                        self.level.copyChunkFrom(self.redoLevel, cx, cz)
                        yield i, self.redoLevel.chunkCount, "Copying chunk %s..." % (
                            (cx, cz), )
                else:
                    for i in self.level.copyBlocksFromIter(
                            self.redoLevel,
                            self.redoLevel.bounds,
                            self.redoLevel.sourcePoint,
                            biomes=True):
                        yield i, self.undoLevel.chunkCount, "Copying..."

            if self.redoLevel.chunkCount > 25:
                showProgress("Redoing...", _redo())
            else:
                exhaust(_redo())
示例#21
0
    def perform(self, recordUndo=True):
        if self.level.saving:
            alert(_("Cannot perform action while saving is taking place"))
            return
        if recordUndo:
            self.canUndo = True
            self.undoLevel = self.extractUndo(self.level, self._dirtyBox)

        def _perform():
            yield 0, len(self.points), _("Applying {0} brush...").format(_(self.brushMode.displayName))
            if hasattr(self.brushMode, 'apply'):
                for i, point in enumerate(self.points):
                    f = self.brushMode.apply(self.brushMode, self, point)
                    if hasattr(f, "__iter__"):
                        for progress in f:
                            yield progress
                    else:
                        yield i, len(self.points), _("Applying {0} brush...").format(_(self.brushMode.displayName))
            if hasattr(self.brushMode, 'applyToChunkSlices'):
                for j, cPos in enumerate(self._dirtyBox.chunkPositions):
                    if not self.level.containsChunk(*cPos):
                        continue
                    chunk = self.level.getChunk(*cPos)
                    for i, point in enumerate(self.points):
                        brushBox = self.tool.getDirtyBox(point, self.tool)
                        brushBoxThisChunk, slices = chunk.getChunkSlicesForBox(brushBox)
                        f = self.brushMode.applyToChunkSlices(self.brushMode, self, chunk, slices, brushBox, brushBoxThisChunk)
                        if brushBoxThisChunk.volume == 0:
                            f = None
                        if hasattr(f, "__iter__"):
                            for progress in f:
                                yield progress
                        else:
                            yield j * len(self.points) + i, len(self.points) * self._dirtyBox.chunkCount, _("Applying {0} brush...").format(_(self.brushMode.displayName))
                    chunk.chunkChanged()
        if len(self.points) > 10:
            showProgress("Performing brush...", _perform(), cancel=True)
        else:
            exhaust(_perform())
示例#22
0
    def extractUndoSchematic(level, box):
        if box.volume > 131072:
            sch = showProgress("Recording undo...",
                               level.extractZipSchematicIter(box),
                               cancel=True)
        else:
            sch = level.extractZipSchematic(box)
        if sch == "Cancel" or sch == "Canceled":
            raise Cancel
        if sch:
            sch.sourcePoint = box.origin

        return sch
示例#23
0
    def pruneChunks(self):
        if "No" == ask("Save these chunks and remove the rest? This cannot be undone.", ("Yes", "No")):
            return
        self.editor.saveFile()

        def _pruneChunks():
            maxChunks = self.editor.level.chunkCount
            selectedChunks = self.selectedChunks()
            for i, cPos in enumerate(list(self.editor.level.allChunks)):
                if cPos not in selectedChunks:
                    try:
                        self.editor.level.deleteChunk(*cPos)

                    except Exception as e:
                        print "Error during chunk delete: ", e

                yield i, maxChunks

        with setWindowCaption("PRUNING - "):
            showProgress("Pruning chunks...", _pruneChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.discardAllChunks()
示例#24
0
    def extractUndoChunks(self, level, chunks, chunkCount=None):
        if not isinstance(level, pymclevel.MCInfdevOldLevel):
            chunks = numpy.array(list(chunks))
            mincx, mincz = numpy.min(chunks, 0)
            maxcx, maxcz = numpy.max(chunks, 0)
            box = BoundingBox((mincx << 4, 0, mincz << 4),
                              ((maxcx << 4) - (mincx << 4), level.Height,
                               (maxcz << 4) - (mincz << 4)))

            return self.extractUndoSchematic(level, box)

        undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
        if not chunkCount:
            try:
                chunkCount = len(chunks)
            except TypeError:
                chunkCount = -1

        def _extractUndo():
            yield 0, 0, "Recording undo..."
            for i, (cx, cz) in enumerate(chunks):
                undoLevel.copyChunkFrom(level, cx, cz)
                yield i, chunkCount, _("Copying chunk %s...") % ((cx, cz), )
            undoLevel.saveInPlace()

        if chunkCount > 25 or chunkCount < 1:
            if "Canceled" == showProgress("Recording undo...",
                                          _extractUndo(),
                                          cancel=True):
                if albow.ask("Continue with undo disabled?",
                             ["Continue", "Cancel"]) == "Cancel":
                    raise Cancel
                else:
                    return None
        else:
            exhaust(_extractUndo())

        return undoLevel
示例#25
0
def apply(self, op, point):

    undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
    dirtyChunks = set()

    def saveUndoChunk(cx, cz):
        if (cx, cz) in dirtyChunks:
            return
        dirtyChunks.add((cx, cz))
        undoLevel.copyChunkFrom(op.level, cx, cz)

    doomedBlock = op.level.blockAt(*point)
    doomedBlockData = op.level.blockDataAt(*point)
    checkData = (doomedBlock not in (8, 9, 10, 11))
    indiscriminate = op.options['Indiscriminate']

    if indiscriminate:
        checkData = False
        if doomedBlock == 2:  # grass
            doomedBlock = 3  # dirt
    if doomedBlock == op.options['Block'].ID and (
            doomedBlockData == op.options['Block'].blockData or not checkData):
        return

    x, y, z = point
    saveUndoChunk(x // 16, z // 16)
    op.level.setBlockAt(x, y, z, op.options['Block'].ID)
    op.level.setBlockDataAt(x, y, z, op.options['Block'].blockData)

    def processCoords(coords):
        newcoords = collections.deque()

        for (x, y, z) in coords:
            for _dir, offsets in pymclevel.faceDirections:
                dx, dy, dz = offsets
                p = (x + dx, y + dy, z + dz)

                nx, ny, nz = p
                b = op.level.blockAt(nx, ny, nz)
                if indiscriminate:
                    if b == 2:
                        b = 3
                if b == doomedBlock:
                    if checkData:
                        if op.level.blockDataAt(nx, ny, nz) != doomedBlockData:
                            continue

                    saveUndoChunk(nx // 16, nz // 16)
                    op.level.setBlockAt(nx, ny, nz, op.options['Block'].ID)
                    op.level.setBlockDataAt(nx, ny, nz,
                                            op.options['Block'].blockData)
                    newcoords.append(p)

        return newcoords

    def spread(coords):
        while len(coords):
            start = datetime.datetime.now()

            num = len(coords)
            coords = processCoords(coords)
            d = datetime.datetime.now() - start
            progress = "Did {0} coords in {1}".format(num, d)
            log.info(progress)
            yield progress

    showProgress("Flood fill...", spread([point]), cancel=True)
    op.editor.invalidateChunks(dirtyChunks)
    op.undoLevel = undoLevel
示例#26
0
def apply(self, op, point):

    undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
    dirtyChunks = set()

    def saveUndoChunk(cx, cz):
        if (cx, cz) in dirtyChunks:
            return
        dirtyChunks.add((cx, cz))
        undoLevel.copyChunkFrom(op.level, cx, cz)

    doomedBlock = op.level.blockAt(*point)
    doomedBlockData = op.level.blockDataAt(*point)
    checkData = (doomedBlock not in (8, 9, 10, 11))
    indiscriminate = op.options['Indiscriminate']

    if indiscriminate:
        checkData = False
        if doomedBlock == 2:  # grass
            doomedBlock = 3  # dirt
    if doomedBlock == op.options['Block'].ID and (doomedBlockData == op.options['Block'].blockData or not checkData):
        return

    x, y, z = point
    saveUndoChunk(x // 16, z // 16)
    op.level.setBlockAt(x, y, z, op.options['Block'].ID)
    op.level.setBlockDataAt(x, y, z, op.options['Block'].blockData)

    def processCoords(coords):
        newcoords = collections.deque()

        for (x, y, z) in coords:
            for _dir, offsets in pymclevel.faceDirections:
                dx, dy, dz = offsets
                p = (x + dx, y + dy, z + dz)

                nx, ny, nz = p
                b = op.level.blockAt(nx, ny, nz)
                if indiscriminate:
                    if b == 2:
                        b = 3
                if b == doomedBlock:
                    if checkData:
                        if op.level.blockDataAt(nx, ny, nz) != doomedBlockData:
                            continue

                    saveUndoChunk(nx // 16, nz // 16)
                    op.level.setBlockAt(nx, ny, nz, op.options['Block'].ID)
                    op.level.setBlockDataAt(nx, ny, nz, op.options['Block'].blockData)
                    newcoords.append(p)

        return newcoords

    def spread(coords):
        while len(coords):
            start = datetime.datetime.now()

            num = len(coords)
            coords = processCoords(coords)
            d = datetime.datetime.now() - start
            progress = "Did {0} coords in {1}".format(num, d)
            log.info(progress)
            yield progress

    showProgress("Flood fill...", spread([point]), cancel=True)
    op.editor.invalidateChunks(dirtyChunks)
    op.undoLevel = undoLevel
示例#27
0
def apply(self, op, point):
    # undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
    # Use the same world as the one loaded.
    create = True
    if op.level.gamePlatform == 'PE':
        create = op.level.world_version
    undoLevel = type(op.level)(mkundotemp(), create=create)
    if op.level.gamePlatform == 'PE':
        undoLevel.Height = op.level.Height
    dirtyChunks = set()

    def saveUndoChunk(cx, cz):
        if (cx, cz) in dirtyChunks:
            return
        dirtyChunks.add((cx, cz))
        undoLevel.copyChunkFrom(op.level, cx, cz)

    doomedBlock = op.level.blockAt(*point)
    doomedBlockData = op.level.blockDataAt(*point)
    checkData = (doomedBlock not in (8, 9, 10, 11))
    indiscriminate = op.options['Indiscriminate']

    if indiscriminate:
        checkData = False
        if doomedBlock == 2:  # grass
            doomedBlock = 3  # dirt
    if doomedBlock == op.options['Block'].ID and (doomedBlockData == op.options['Block'].blockData or not checkData):
        return

    tileEntity = None
    if op.options['Block'].stringID in TileEntity.stringNames.keys():
        tileEntity = TileEntity.stringNames[op.options['Block'].stringID]

    x, y, z = point
    saveUndoChunk(x // 16, z // 16)
    op.level.setBlockAt(x, y, z, op.options['Block'].ID)
    op.level.setBlockDataAt(x, y, z, op.options['Block'].blockData)
    if tileEntity:
        if op.level.tileEntityAt(x, y, z):
            op.level.removeTileEntitiesInBox(BoundingBox((x, y, z), (1, 1, 1)))
        tileEntityObject = TileEntity.Create(tileEntity, (x, y, z), defsIds=op.level.defsIds)
        createTileEntities(tileEntityObject, op.level)

    def processCoords(coords):
        newcoords = collections.deque()

        for (x, y, z) in coords:
            for _dir, offsets in pymclevel.faceDirections:
                dx, dy, dz = offsets
                p = (x + dx, y + dy, z + dz)

                nx, ny, nz = p
                b = op.level.blockAt(nx, ny, nz)
                if indiscriminate:
                    if b == 2:
                        b = 3
                if b == doomedBlock:
                    if checkData:
                        if op.level.blockDataAt(nx, ny, nz) != doomedBlockData:
                            continue

                    saveUndoChunk(nx // 16, nz // 16)
                    op.level.setBlockAt(nx, ny, nz, op.options['Block'].ID)
                    op.level.setBlockDataAt(nx, ny, nz, op.options['Block'].blockData)
                    if tileEntity:
                        if op.level.tileEntityAt(nx, ny, nz):
                            op.level.removeTileEntitiesInBox(BoundingBox((nx, ny, nz), (1, 1, 1)))
                        tileEntityObject = TileEntity.Create(tileEntity, (nx, ny, nz))
                        createTileEntities(tileEntityObject, op.level)
                    newcoords.append(p)

        return newcoords

    def spread(coords):
        while len(coords):
            start = datetime.datetime.now()

            num = len(coords)
            coords = processCoords(coords)
            d = datetime.datetime.now() - start
            progress = "Did {0} coords in {1}".format(num, d)
            log.info(progress)
            yield progress

    showProgress("Flood fill...", spread([point]), cancel=True)
    op.editor.invalidateChunks(dirtyChunks)
    op.undoLevel = undoLevel
示例#28
0
def apply(self, op, point):

    # undoLevel = pymclevel.MCInfdevOldLevel(mkundotemp(), create=True)
    # Use the same world as the one loaded.
    create = True
    if op.level.gameVersion == 'PE':
        create = op.level.world_version
    undoLevel = type(op.level)(mkundotemp(), create=create)
    dirtyChunks = set()

    def saveUndoChunk(cx, cz):
        if (cx, cz) in dirtyChunks:
            return
        dirtyChunks.add((cx, cz))
        undoLevel.copyChunkFrom(op.level, cx, cz)

    doomedBlock = op.level.blockAt(*point)
    doomedBlockData = op.level.blockDataAt(*point)
    checkData = (doomedBlock not in (8, 9, 10, 11))
    indiscriminate = op.options['Indiscriminate']

    if indiscriminate:
        checkData = False
        if doomedBlock == 2:  # grass
            doomedBlock = 3  # dirt
    if doomedBlock == op.options['Block'].ID and (doomedBlockData == op.options['Block'].blockData or not checkData):
        return

    tileEntity = None
    if op.options['Block'].stringID in TileEntity.stringNames.keys():
        tileEntity = TileEntity.stringNames[op.options['Block'].stringID]

    x, y, z = point
    saveUndoChunk(x // 16, z // 16)
    op.level.setBlockAt(x, y, z, op.options['Block'].ID)
    op.level.setBlockDataAt(x, y, z, op.options['Block'].blockData)
    if tileEntity:
        if op.level.tileEntityAt(x, y, z):
            op.level.removeTileEntitiesInBox(BoundingBox((x, y, z), (1, 1, 1)))
        tileEntityObject = TileEntity.Create(tileEntity, (x, y, z), defsIds=op.level.defsIds)
        createTileEntities(tileEntityObject, op.level)

    def processCoords(coords):
        newcoords = collections.deque()

        for (x, y, z) in coords:
            for _dir, offsets in pymclevel.faceDirections:
                dx, dy, dz = offsets
                p = (x + dx, y + dy, z + dz)

                nx, ny, nz = p
                b = op.level.blockAt(nx, ny, nz)
                if indiscriminate:
                    if b == 2:
                        b = 3
                if b == doomedBlock:
                    if checkData:
                        if op.level.blockDataAt(nx, ny, nz) != doomedBlockData:
                            continue

                    saveUndoChunk(nx // 16, nz // 16)
                    op.level.setBlockAt(nx, ny, nz, op.options['Block'].ID)
                    op.level.setBlockDataAt(nx, ny, nz, op.options['Block'].blockData)
                    if tileEntity:
                        if op.level.tileEntityAt(nx, ny, nz):
                            op.level.removeTileEntitiesInBox(BoundingBox((nx, ny, nz), (1, 1, 1)))
                        tileEntityObject = TileEntity.Create(tileEntity, (nx, ny, nz))
                        createTileEntities(tileEntityObject, op.level)
                    newcoords.append(p)

        return newcoords

    def spread(coords):
        while len(coords):
            start = datetime.datetime.now()

            num = len(coords)
            coords = processCoords(coords)
            d = datetime.datetime.now() - start
            progress = "Did {0} coords in {1}".format(num, d)
            log.info(progress)
            yield progress

    showProgress("Flood fill...", spread([point]), cancel=True)
    op.editor.invalidateChunks(dirtyChunks)
    op.undoLevel = undoLevel
示例#29
0
class ChunkTool(EditorTool):
    toolIconName = "chunk"
    tooltipText = "Chunk Control"

    @property
    def statusText(self):
        return _(
            "Click and drag to select chunks. Hold {0} to deselect chunks. Hold {1} to select chunks."
        ).format(_(config.keys.deselectChunks.get()),
                 _(config.keys.selectChunks.get()))

    def toolEnabled(self):
        return isinstance(self.editor.level, pymclevel.ChunkedLevelMixin)

    _selectedChunks = None
    _displayList = None

    def drawToolMarkers(self):
        if self._displayList is None:
            self._displayList = DisplayList(self._drawToolMarkers)

        # print len(self._selectedChunks) if self._selectedChunks else None, "!=", len(self.editor.selectedChunks)

        if self._selectedChunks != self.editor.selectedChunks or True:  # xxx
            self._selectedChunks = set(self.editor.selectedChunks)
            self._displayList.invalidate()

        self._displayList.call()

    def _drawToolMarkers(self):

        lines = (
            ((-1, 0), (0, 0, 0, 1), []),
            ((1, 0), (1, 0, 1, 1), []),
            ((0, -1), (0, 0, 1, 0), []),
            ((0, 1), (0, 1, 1, 1), []),
        )
        for ch in self._selectedChunks:
            cx, cz = ch
            for (dx, dz), points, positions in lines:
                n = (cx + dx, cz + dz)
                if n not in self._selectedChunks:
                    positions.append([ch])

        color = self.editor.selectionTool.selectionColor + (0.3, )
        GL.glColor(*color)
        with gl.glEnable(GL.GL_BLEND):

            import renderer

            sizedChunks = renderer.chunkMarkers(self._selectedChunks)
            for size, chunks in sizedChunks.iteritems():
                if not len(chunks):
                    continue
                chunks = numpy.array(chunks, dtype='float32')

                chunkPosition = numpy.zeros(shape=(chunks.shape[0], 4, 3),
                                            dtype='float32')
                chunkPosition[..., (0, 2)] = numpy.array(
                    ((0, 0), (0, 1), (1, 1), (1, 0)), dtype='float32')
                chunkPosition[..., (0, 2)] *= size
                chunkPosition[..., (0, 2)] += chunks[:, newaxis, :]
                chunkPosition *= 16
                chunkPosition[..., 1] = self.editor.level.Height
                GL.glVertexPointer(3, GL.GL_FLOAT, 0, chunkPosition.ravel())
                # chunkPosition *= 8
                GL.glDrawArrays(GL.GL_QUADS, 0, len(chunkPosition) * 4)

        for d, points, positions in lines:
            if 0 == len(positions):
                continue
            vertexArray = numpy.zeros((len(positions), 4, 3), dtype='float32')
            vertexArray[..., [0, 2]] = positions
            vertexArray.shape = len(positions), 2, 2, 3

            vertexArray[..., 0, 0, 0] += points[0]
            vertexArray[..., 0, 0, 2] += points[1]
            vertexArray[..., 0, 1, 0] += points[2]
            vertexArray[..., 0, 1, 2] += points[3]
            vertexArray[..., 1, 0, 0] += points[2]
            vertexArray[..., 1, 0, 2] += points[3]
            vertexArray[..., 1, 1, 0] += points[0]
            vertexArray[..., 1, 1, 2] += points[1]

            vertexArray *= 16

            vertexArray[..., 1, :, 1] = self.editor.level.Height

            GL.glVertexPointer(3, GL.GL_FLOAT, 0, vertexArray)
            GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE)
            GL.glDrawArrays(GL.GL_QUADS, 0, len(positions) * 4)
            GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)
            with gl.glEnable(GL.GL_BLEND, GL.GL_DEPTH_TEST):
                GL.glDepthMask(False)
                GL.glDrawArrays(GL.GL_QUADS, 0, len(positions) * 4)
                GL.glDepthMask(True)

    @property
    def worldTooltipText(self):
        box = self.editor.selectionTool.selectionBoxInProgress()
        if box:
            box = box.chunkBox(self.editor.level)
            l, w = box.length // 16, box.width // 16
            return _("%s x %s chunks") % (l, w)

    def toolSelected(self):

        self.editor.selectionToChunks()

        self.panel = ChunkToolPanel(self)

        self.panel.centery = self.editor.centery
        self.panel.left = 10

        self.editor.add(self.panel)

    def toolDeselected(self):
        self.editor.chunksToSelection()

    def cancel(self):
        self.editor.remove(self.panel)

    def selectedChunks(self):
        return self.editor.selectedChunks

    @alertException
    def destroyChunks(self, chunks=None):
        if "No" == ask("Really delete these chunks? This cannot be undone.",
                       ("Yes", "No")):
            return
        if chunks is None:
            chunks = self.selectedChunks()
        chunks = list(chunks)

        def _destroyChunks():
            i = 0
            chunkCount = len(chunks)

            for cx, cz in chunks:
                i += 1
                yield (i, chunkCount)
                if self.editor.level.containsChunk(cx, cz):
                    try:
                        self.editor.level.deleteChunk(cx, cz)
                    except Exception, e:
                        print "Error during chunk delete: ", e

        with setWindowCaption("DELETING - "):
            showProgress("Deleting chunks...", _destroyChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.renderer.discardAllChunks()
示例#30
0
        def _pruneChunks():
            maxChunks = self.editor.level.chunkCount
            selectedChunks = self.selectedChunks()
            for i, cPos in enumerate(list(self.editor.level.allChunks)):
                if cPos not in selectedChunks:
                    try:
                        self.editor.level.deleteChunk(*cPos)

                    except Exception, e:
                        print "Error during chunk delete: ", e

                yield i, maxChunks

        with setWindowCaption("PRUNING - "):
            showProgress("Pruning chunks...", _pruneChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.discardAllChunks()

        # self.editor.addUnsavedEdit()

    @alertException
    def relightChunks(self):
        def _relightChunks():
            for i in self.editor.level.generateLightsIter(
                    self.selectedChunks()):
                yield i

        with setWindowCaption("RELIGHTING - "):
            showProgress(_("Lighting {0} chunks...").format(
示例#31
0
        def _pruneChunks():
            maxChunks = self.editor.level.chunkCount
            selectedChunks = self.selectedChunks()
            for i, cPos in enumerate(list(self.editor.level.allChunks)):
                if cPos not in selectedChunks:
                    try:
                        self.editor.level.deleteChunk(*cPos)

                    except Exception, e:
                        print "Error during chunk delete: ", e

                yield i, maxChunks

        with setWindowCaption("PRUNING - "):
            showProgress("Pruning chunks...", _pruneChunks())

        self.editor.renderer.invalidateChunkMarkers()
        self.editor.discardAllChunks()

        # self.editor.addUnsavedEdit()

    @alertException
    def relightChunks(self):

        def _relightChunks():
            for i in self.editor.level.generateLightsIter(self.selectedChunks()):
                yield i

        with setWindowCaption("RELIGHTING - "):
            showProgress(_("Lighting {0} chunks...").format(len(self.selectedChunks())),