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()
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)
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()
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)
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)
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)
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
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()
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
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())
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
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())
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))
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
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())
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())
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
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()
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
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
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
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
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
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()
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(
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())),