def do_relight(): cx, cy, cz = poses.next() indices = numpy.indices((16, 16, 16), numpy.int32) indices.shape = 3, 16*16*16 indices += ([cx << 4], [cy << 4], [cz << 4]) x, y, z = indices relight.updateLightsByCoord(dim, x, y, z)
def postCopy(): # profiling start = time.time() count = 0 print("Relighting outside of copyBlocks. Updating %d cells" % (len(positions) * 16 * 16 * 16)) for cx, cy, cz in positions: indices = numpy.indices((16, 16, 16), numpy.int32) indices.shape = 3, 16*16*16 indices += ([cx << 4], [cy << 4], [cz << 4]) x, y, z = indices relight.updateLightsByCoord(dim, x, y, z) count += 1 t = time.time() - start print "Relight manmade building (outside copyBlocks): " \ "%d (out of %d) chunk-sections in %.02f seconds (%f sections per second; %dms per section)" \ % (count, len(positions), t, count / t, 1000 * t / count)
def postCopy(): # profiling start = time.time() count = 0 print ("Relighting outside of copyBlocks. Updating %d cells" % (len(positions) * 16 * 16 * 16)) for cx, cy, cz in positions: indices = numpy.indices((16, 16, 16), numpy.int32) indices.shape = 3, 16 * 16 * 16 indices += ([cx << 4], [cy << 4], [cz << 4]) x, y, z = indices relight.updateLightsByCoord(dim, x, y, z) count += 1 t = time.time() - start print "Relight manmade building (outside copyBlocks): " "%d (out of %d) chunk-sections in %.02f seconds (%f sections per second; %dms per section)" % ( count, len(positions), t, count / t, 1000 * t / count, )
def copyBlocksIter(destDim, sourceDim, sourceSelection, destinationPoint, blocksToCopy=None, entities=True, create=False, biomes=False, updateLights=False): """ Copy blocks and entities from the `sourceBox` area of `sourceDim` to `destDim` starting at `destinationPoint`. :param sourceDim: WorldEditorDimension :param destDim: WorldEditorDimension Optional parameters: - `blocksToCopy`: list of blockIDs to copy. - `entities`: True to copy Entities and TileEntities, False otherwise. - `create`: True to create new chunks in destLevel, False otherwise. - `biomes`: True to copy biome data, False otherwise. """ (lx, ly, lz) = sourceSelection.size # needs work xxx log.info(u"Copying {0} blocks from {1} to {2}" .format(ly * lz * lx, sourceSelection, destinationPoint)) startTime = time.time() destBox = BoundingBox(destinationPoint, sourceSelection.size) chunkCount = destBox.chunkCount i = 0 entitiesCopied = 0 tileEntitiesCopied = 0 entitiesSeen = 0 tileEntitiesSeen = 0 if updateLights: allChangedX = [] allChangedY = [] allChangedZ = [] makeSourceMask = sourceMaskFunc(blocksToCopy) copyOffset = destBox.origin - sourceSelection.origin # Visit each chunk in the source area # Visit each section in this chunk # Find the chunks and sections of the destination area corresponding to this section # Compute slices for Blocks array and mask # Use slices and mask to copy Blocks and Data # Copy entities and tile entities from this chunk. sourceBiomeMask = None convertBlocks = blocktypes.blocktypeConverter(destDim.blocktypes, sourceDim.blocktypes) for sourceCpos in sourceSelection.chunkPositions(): # Visit each chunk if not sourceDim.containsChunk(*sourceCpos): continue sourceChunk = sourceDim.getChunk(*sourceCpos) i += 1 yield (i, chunkCount) if i % 20 == 0: log.info("Copying: Chunk {0}/{1}...".format(i, chunkCount)) # Use sourceBiomeMask to accumulate a list of columns over all sections whose biomes should be copied. sourceBiomes = None if biomes and hasattr(sourceChunk, 'Biomes'): sourceBiomes = sourceChunk.Biomes sourceBiomeMask = numpy.zeros_like(sourceBiomes) for sourceCy in sourceChunk.sectionPositions(): # Visit each section sourceSection = sourceChunk.getSection(sourceCy) if sourceSection is None: continue selectionMask = sourceSelection.section_mask(sourceCpos[0], sourceCy, sourceCpos[1]) if selectionMask is None: continue typeMask = makeSourceMask(sourceSection.Blocks) sourceMask = selectionMask & typeMask # Update sourceBiomeMask if sourceBiomes is not None: sourceBiomeMask |= sourceMask.any(axis=0) # Find corresponding destination area(s) sectionBox = SectionBox(sourceCpos[0], sourceCy, sourceCpos[1]) destBox = BoundingBox(sectionBox.origin + copyOffset, sectionBox.size) for destCpos in destBox.chunkPositions(): if not create and not destDim.containsChunk(*destCpos): continue destChunk = destDim.getChunk(*destCpos, create=True) for destCy in destBox.sectionPositions(*destCpos): # Compute slices for source and dest arrays destSectionBox = SectionBox(destCpos[0], destCy, destCpos[1]) intersect = destSectionBox.intersect(destBox) if intersect.volume == 0: continue destSection = destChunk.getSection(destCy, create=True) if destSection is None: continue destSlices = ( slice(intersect.miny - (destCy << 4), intersect.maxy - (destCy << 4)), slice(intersect.minz - (destCpos[1] << 4), intersect.maxz - (destCpos[1] << 4)), slice(intersect.minx - (destCpos[0] << 4), intersect.maxx - (destCpos[0] << 4)), ) sourceIntersect = BoundingBox(intersect.origin - copyOffset, intersect.size) sourceSlices = ( slice(sourceIntersect.miny - (sourceCy << 4), sourceIntersect.maxy - (sourceCy << 4)), slice(sourceIntersect.minz - (sourceCpos[1] << 4), sourceIntersect.maxz - (sourceCpos[1] << 4)), slice(sourceIntersect.minx - (sourceCpos[0] << 4), sourceIntersect.maxx - (sourceCpos[0] << 4)), ) # Read blocks sourceBlocks = sourceSection.Blocks[sourceSlices] sourceData = sourceSection.Data[sourceSlices] sourceMaskPart = sourceMask[sourceSlices] # Convert blocks convertedSourceBlocks, convertedSourceData = convertBlocks(sourceBlocks, sourceData) convertedSourceBlocksMasked = convertedSourceBlocks[sourceMaskPart] # Find blocks that need direct lighting update - block opacity or brightness changed oldBrightness = destDim.blocktypes.brightness[destSection.Blocks[destSlices][sourceMaskPart]] newBrightness = destDim.blocktypes.brightness[convertedSourceBlocksMasked] oldOpacity = destDim.blocktypes.opacity[destSection.Blocks[destSlices][sourceMaskPart]] newOpacity = destDim.blocktypes.opacity[convertedSourceBlocksMasked] changedLight = (oldBrightness != newBrightness) | (oldOpacity != newOpacity) # Write blocks destSection.Blocks[destSlices][sourceMaskPart] = convertedSourceBlocks[sourceMaskPart] destSection.Data[destSlices][sourceMaskPart] = convertedSourceData[sourceMaskPart] if updateLights: # Find coordinates of lighting updates (changedFlat,) = changedLight.nonzero() # Since convertedSourceBlocksMasked is a 1d array, changedFlat is an index # into this array. Thus, changedFlat is also an index into the nonzero values # of sourceMaskPart. if len(changedFlat): x, y, z = sourceMaskPart.nonzero() changedX = x[changedFlat].astype('i4') changedY = y[changedFlat].astype('i4') changedZ = z[changedFlat].astype('i4') changedX += intersect.minx changedY += intersect.miny changedZ += intersect.minz if updateLights == "all": allChangedX.append(changedX) allChangedY.append(changedY) allChangedZ.append(changedZ) else: # log.info("Updating section lights in %s blocks... (ob %s)", # changedFlat.shape, # oldBrightness.shape) relight.updateLightsByCoord(destDim, changedX, changedY, changedZ) destChunk.dirty = True # Copy biomes if sourceBiomes is not None: bx, bz = sourceBiomeMask.nonzero() wbx = bx + (sourceCpos[0] << 4) wbz = bz + (sourceCpos[1] << 4) destDim.setBlocks(wbx, 1, wbz, Biomes=sourceBiomes[bx, bz]) # Copy entities and tile entities if entities: entitiesSeen += len(sourceChunk.Entities) for entity in sourceChunk.Entities: if entity.Position in sourceSelection: entitiesCopied += 1 newEntity = entity.copyWithOffset(copyOffset) destDim.addEntity(newEntity) tileEntitiesSeen += len(sourceChunk.TileEntities) for tileEntity in sourceChunk.TileEntities: if tileEntity.Position in sourceSelection: tileEntitiesCopied += 1 newEntity = tileEntity.copyWithOffset(copyOffset) destDim.addTileEntity(newEntity) duration = time.time() - startTime log.info("Duration: %0.3fs, %d/%d chunks, %0.2fms per chunk (%0.2f chunks per second)", duration, i, sourceSelection.chunkCount, 1000 * duration/i, i/duration) log.info("Copied %d/%d entities and %d/%d tile entities", entitiesCopied, entitiesSeen, tileEntitiesCopied, tileEntitiesSeen) if updateLights == "all": log.info("Updating all at once for %d sections (%d cells)", len(allChangedX), sum(len(a) for a in allChangedX)) startTime = time.time() for i in range(len(allChangedX)): x = allChangedX[i] y = allChangedY[i] z = allChangedZ[i] relight.updateLightsByCoord(destDim, x, y, z) i = i or 1 duration = time.time() - startTime duration = duration or 1 log.info("Lighting complete.") log.info("Duration: %0.3fs, %d sections, %0.2fms per section (%0.2f sections per second)", duration, i, 1000 * duration/i, i/duration)
def setBlocks( dimension, x, y, z, Blocks=None, Data=None, # Deprecate soon BlockLight=None, SkyLight=None, Biomes=None, updateLights=True): """ Change the blocks at the given positions. All parameters must be arrays of the same shape, or single values. :type dimension: mceditlib.worldeditor.WorldEditorDimension """ x = atleast_3d(x) y = atleast_3d(y) z = atleast_3d(z) if Blocks is not None: if isinstance(Blocks, (BlockType, basestring)): Blocks = [Blocks] _Blocks = [] _Data = [] if isinstance(Blocks, int): Blocks = [Blocks] for block in Blocks: if isinstance(block, basestring): block = dimension.blocktypes[block] if isinstance(block, BlockType): _Blocks.append(block.ID) _Data.append(block.meta) else: _Blocks.append(block) if len(_Blocks): Blocks = _Blocks if len(_Data): Data = _Data if Blocks is None and Data is None: updateLights = False Blocks = atleast_3d(Blocks) if Blocks is not None else None Data = atleast_3d(Data) if Data is not None else None BlockLight = atleast_3d(BlockLight) if BlockLight is not None else None SkyLight = atleast_3d(SkyLight) if SkyLight is not None else None Biomes = atleast_3d(Biomes) if Biomes is not None else None arrays_to_broadcast = [x, y, z] if Blocks is not None: arrays_to_broadcast.append(Blocks) if Data is not None: arrays_to_broadcast.append(Data) if BlockLight is not None: arrays_to_broadcast.append(BlockLight) if SkyLight is not None: arrays_to_broadcast.append(SkyLight) if Biomes is not None: arrays_to_broadcast.append(Biomes) if any(a.size == 0 for a in (x, y, z)): return broadcasted_arrays = numpy.broadcast_arrays(*arrays_to_broadcast) x, y, z = broadcasted_arrays[:3] broadcasted_arrays = broadcasted_arrays[3:] if Blocks is not None: Blocks, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[ 1:] if Data is not None: Data, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[ 1:] if BlockLight is not None: BlockLight, broadcasted_arrays = broadcasted_arrays[ 0], broadcasted_arrays[1:] if SkyLight is not None: SkyLight, broadcasted_arrays = broadcasted_arrays[ 0], broadcasted_arrays[1:] if Biomes is not None: Biomes, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[ 1:] for cx, cz, sx, sy, sz, mask in coords_by_chunk(x, y, z): chunk = dimension.getChunk(cx, cz, create=True) if chunk is None: continue setChunkBlocks(chunk, sx, sy, sz, maskArray(Blocks, mask), maskArray(Data, mask), maskArray(BlockLight, mask), maskArray(SkyLight, mask), maskArray(Biomes, mask)) chunk.dirty = True if updateLights: relight.updateLightsByCoord(dimension, x, y, z)
def setBlocks(dimension, x, y, z, Blocks=None, Data=None, # Deprecate soon BlockLight=None, SkyLight=None, Biomes=None, updateLights=True): """ Change the blocks at the given positions. All parameters must be arrays of the same shape, or single values. :type dimension: mceditlib.worldeditor.WorldEditorDimension """ x = atleast_3d(x) y = atleast_3d(y) z = atleast_3d(z) if Blocks is not None: if isinstance(Blocks, (BlockType, basestring)): Blocks = [Blocks] _Blocks = [] _Data = [] if isinstance(Blocks, int): Blocks = [Blocks] for block in Blocks: if isinstance(block, basestring): block = dimension.blocktypes[block] if isinstance(block, BlockType): _Blocks.append(block.ID) _Data.append(block.meta) else: _Blocks.append(block) if len(_Blocks): Blocks = _Blocks if len(_Data): Data = _Data if Blocks is None and Data is None: updateLights = False Blocks = atleast_3d(Blocks) if Blocks is not None else None Data = atleast_3d(Data) if Data is not None else None BlockLight = atleast_3d(BlockLight) if BlockLight is not None else None SkyLight = atleast_3d(SkyLight) if SkyLight is not None else None Biomes = atleast_3d(Biomes) if Biomes is not None else None arrays_to_broadcast = [x, y, z] if Blocks is not None: arrays_to_broadcast.append(Blocks) if Data is not None: arrays_to_broadcast.append(Data) if BlockLight is not None: arrays_to_broadcast.append(BlockLight) if SkyLight is not None: arrays_to_broadcast.append(SkyLight) if Biomes is not None: arrays_to_broadcast.append(Biomes) if any(a.size == 0 for a in (x, y, z)): return broadcasted_arrays = numpy.broadcast_arrays(*arrays_to_broadcast) x, y, z = broadcasted_arrays[:3] broadcasted_arrays = broadcasted_arrays[3:] if Blocks is not None: Blocks, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[1:] if Data is not None: Data, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[1:] if BlockLight is not None: BlockLight, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[1:] if SkyLight is not None: SkyLight, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[1:] if Biomes is not None: Biomes, broadcasted_arrays = broadcasted_arrays[0], broadcasted_arrays[1:] for cx, cz, sx, sy, sz, mask in coords_by_chunk(x, y, z): chunk = dimension.getChunk(cx, cz, create=True) if chunk is None: continue setChunkBlocks(chunk, sx, sy, sz, maskArray(Blocks, mask), maskArray(Data, mask), maskArray(BlockLight, mask), maskArray(SkyLight, mask), maskArray(Biomes, mask)) chunk.dirty = True if updateLights: relight.updateLightsByCoord(dimension, x, y, z)