def perform(level, box, options): depth = options["Depth"] blocktype = options["Pick a block:"] replace = options["Replace Only:"] replaceType = options[""] # compute a truth table that we can index to find out whether a block # is naturally occuring and should be considered in a heightmap blockmask = naturalBlockmask() # always consider the chosen blocktype to be "naturally occuring" to stop # it from adding extra layers blockmask[blocktype.ID] = True # iterate through the slices of each chunk in the selection box for chunk, slices, point in level.getChunkSlices(box): # slicing the block array is straightforward. blocks will contain only # the area of interest in this chunk. blocks = chunk.Blocks[slices] data = chunk.Data[slices] # use indexing to look up whether or not each block in blocks is # naturally-occuring. these blocks will "count" for column height. maskedBlocks = blockmask[blocks] heightmap = extractHeights(maskedBlocks) for x, z in itertools.product(*list(map(xrange, heightmap.shape))): h = heightmap[x, z] if depth > 0: if replace: for y in range(max(0, h - depth), h): b, d = blocks[x, z, y], data[x, z, y] if (b == replaceType.ID and d == replaceType.blockData): blocks[x, z, y] = blocktype.ID data[x, z, y] = blocktype.blockData continue blocks[x, z, max(0, h - depth):h] = blocktype.ID data[x, z, max(0, h - depth):h] = blocktype.blockData else: # negative depth values mean to put a layer above the surface if replace: for y in range(h, min(blocks.shape[2], h - depth)): b, d = blocks[x, z, y], data[x, z, y] if (b == replaceType.ID and d == replaceType.blockData): blocks[x, z, y] = blocktype.ID data[x, z, y] = blocktype.blockData blocks[x, z, h:min(blocks.shape[2], h - depth)] = blocktype.ID data[x, z, h:min(blocks.shape[2], h - depth)] = blocktype.blockData # remember to do this to make sure the chunk is saved chunk.chunkChanged()
def perform(level, box, options): if box.volume > 16000000: raise ValueError("Volume too big for this filter method!") repeatCount = options["Repeat count"] schema = level.extractSchematic(box) schema.removeEntitiesInBox(schema.bounds) schema.removeTileEntitiesInBox(schema.bounds) for i in xrange(repeatCount): terrainBlocks = terrainBlockmask[schema.Blocks] heightmap = extractHeights(terrainBlocks) # terrainBlocks |= schema.Blocks == 0 nonTerrainBlocks = ~terrainBlocks nonTerrainBlocks &= schema.Blocks != 0 newHeightmap = ( heightmap[1:-1, 1:-1] + (heightmap[0:-2, 1:-1] + heightmap[2:, 1:-1] + heightmap[1:-1, 0:-2] + heightmap[1:-1, 2:]) * 0.7 ) / 3.8 # heightmap -= 0.5; newHeightmap += 0.5 newHeightmap[newHeightmap < 0] = 0 newHeightmap[newHeightmap > schema.Height] = schema.Height newHeightmap = array(newHeightmap, dtype="uint16") for x, z in itertools.product(xrange(1, schema.Width - 1), xrange(1, schema.Length - 1)): oh = heightmap[x, z] nh = newHeightmap[x - 1, z - 1] d = nh - oh column = array(schema.Blocks[x, z]) column[nonTerrainBlocks[x, z]] = 0 # schema.Blocks[x,z][nonTerrainBlocks[x,z]] = 0 if nh > oh: column[d:] = schema.Blocks[x, z, :-d] if d > oh: column[:d] = schema.Blocks[x, z, 0] if nh < oh: column[:d] = schema.Blocks[x, z, -d:] column[d : oh + 1] = schema.Blocks[x, z, min(oh + 1, schema.Height - 1)] # preserve non-terrain blocks column[~terrainBlockmask[column]] = 0 column[nonTerrainBlocks[x, z]] = schema.Blocks[x, z][nonTerrainBlocks[x, z]] schema.Blocks[x, z] = column level.copyBlocksFrom(schema, schema.bounds, box.origin)
def perform(level, box, options): depth = options["Depth"] blocktype = options["Pick a block:"] replace = options["Replace Only:"] replaceType = options[""] #compute a truth table that we can index to find out whether a block # is naturally occuring and should be considered in a heightmap blockmask = naturalBlockmask() # always consider the chosen blocktype to be "naturally occuring" to stop # it from adding extra layers blockmask[blocktype.ID] = True #iterate through the slices of each chunk in the selection box for chunk, slices, point in level.getChunkSlices(box): # slicing the block array is straightforward. blocks will contain only # the area of interest in this chunk. blocks = chunk.Blocks[slices] data = chunk.Data[slices] # use indexing to look up whether or not each block in blocks is # naturally-occuring. these blocks will "count" for column height. maskedBlocks = blockmask[blocks] heightmap = extractHeights(maskedBlocks) for x, z in itertools.product(*map(xrange, heightmap.shape)): h = heightmap[x, z] if depth > 0: if replace: for y in range(max(0, h-depth), h): b, d = blocks[x, z, y], data[x, z, y] if (b == replaceType.ID and d == replaceType.blockData): blocks[x, z, y] = blocktype.ID data[x, z, y] = blocktype.blockData continue blocks[x, z, max(0, h - depth):h] = blocktype.ID data[x, z, max(0, h - depth):h] = blocktype.blockData else: #negative depth values mean to put a layer above the surface if replace: for y in range(h, min(blocks.shape[2], h-depth)): b, d = blocks[x, z, y], data[x, z, y] if (b == replaceType.ID and d == replaceType.blockData): blocks[x, z, y] = blocktype.ID data[x, z, y] = blocktype.blockData blocks[x, z, h:min(blocks.shape[2], h - depth)] = blocktype.ID data[x, z, h:min(blocks.shape[2], h - depth)] = blocktype.blockData #remember to do this to make sure the chunk is saved chunk.chunkChanged()
def perform(level, box, options): if box.volume > 16000000: raise ValueError("Volume too big for this filter method!") repeatCount = options["Repeat count"] schema = level.extractSchematic(box) schema.removeEntitiesInBox(schema.bounds) schema.removeTileEntitiesInBox(schema.bounds) for i in xrange(repeatCount): terrainBlocks = terrainBlockmask[schema.Blocks] heightmap = extractHeights(terrainBlocks) # terrainBlocks |= schema.Blocks == 0 nonTerrainBlocks = ~terrainBlocks nonTerrainBlocks &= schema.Blocks != 0 newHeightmap = (heightmap[1:-1, 1:-1] + ( heightmap[0:-2, 1:-1] + heightmap[2:, 1:-1] + heightmap[1:-1, 0:-2] + heightmap[1:-1, 2:]) * 0.7) / 3.8 #heightmap -= 0.5; newHeightmap += 0.5 newHeightmap[newHeightmap < 0] = 0 newHeightmap[newHeightmap > schema.Height] = schema.Height newHeightmap = array(newHeightmap, dtype='uint16') for x, z in itertools.product(xrange(1, schema.Width - 1), xrange(1, schema.Length - 1)): oh = heightmap[x, z] nh = newHeightmap[x - 1, z - 1] d = nh - oh column = array(schema.Blocks[x, z]) column[nonTerrainBlocks[x, z]] = 0 #schema.Blocks[x,z][nonTerrainBlocks[x,z]] = 0 if nh > oh: column[d:] = schema.Blocks[x, z, :-d] if d > oh: column[:d] = schema.Blocks[x, z, 0] if nh < oh: column[:d] = schema.Blocks[x, z, -d:] column[d:oh + 1] = schema.Blocks[x, z, min(oh + 1, schema.Height - 1)] #preserve non-terrain blocks column[~terrainBlockmask[column]] = 0 column[nonTerrainBlocks[x, z]] = schema.Blocks[x, z][nonTerrainBlocks[x, z]] schema.Blocks[x, z] = column level.copyBlocksFrom(schema, schema.bounds, box.origin)
def applyToChunkSlices(self, op, chunk, slices, brushBox, brushBoxThisChunk): depth = op.options['Depth'] blocktype = op.options['Block'] blocks = chunk.Blocks[slices] data = chunk.Data[slices] brushMask = createBrushMask(op.tool.getBrushSize(), op.options['Style'], brushBox.origin, brushBoxThisChunk, op.options['Noise'], op.options['Hollow']) if op.options['Only Change Natural Earth']: try: # try to get the block mask from the topsoil filter import topsoil # @UnresolvedImport blockmask = topsoil.naturalBlockmask() blockmask[blocktype.ID] = True blocktypeMask = blockmask[blocks] except Exception as e: print(repr(e), " while using blockmask from filters.topsoil") blocktypeMask = blocks != 0 else: # topsoil any block blocktypeMask = blocks != 0 if depth < 0: blocktypeMask &= (blocks != blocktype.ID) if len(blocktypeMask) == 0: return heightmap = extractHeights(blocktypeMask) for x, z in itertools.product(*list(map(xrange, heightmap.shape))): h = heightmap[x, z] if h >= brushBoxThisChunk.height: continue if depth > 0: idx = x, z, slice(max(0, h - depth), h) else: # negative depth values mean to put a layer above the surface idx = x, z, slice(h, min(blocks.shape[2], h - depth)) mask = brushMask[idx] blocks[idx][mask] = blocktype.ID data[idx][mask] = blocktype.blockData createTileEntities(blocktype, brushBoxThisChunk, chunk)
def perform(level, box, options): #iterate through the slices of each chunk in the selection box for chunk, slices, point in level.getChunkSlices(box): # slicing the block array is straightforward. blocks will contain only # the area of interest in this chunk. blocks = chunk.Blocks data = chunk.Data # use indexing to look up whether or not each block in blocks is # naturally-occuring. these blocks will "count" for column height. maskedBlocks = blockmask[blocks] heightmap = extractHeights(maskedBlocks) for x in range(heightmap.shape[0]): for z in range(x + 1, heightmap.shape[1]): h = heightmap[x, z] h2 = heightmap[z, x] b2 = blocks[z, x, h2] if blocks[x, z, h] == 1: h += 2 # rock surface - top 4 layers become 2 air and 2 rock if blocks[z, x, h2] == 1: h2 += 2 # rock surface - top 4 layers become 2 air and 2 rock # topsoil is 4 layers deep def swap(s1, s2): a2 = array(s2) s2[:] = s1[:] s1[:] = a2[:] swap(blocks[x, z, h - 3:h + 1], blocks[z, x, h2 - 3:h2 + 1]) swap(data[x, z, h - 3:h + 1], data[z, x, h2 - 3:h2 + 1]) # remember to do this to make sure the chunk is saved chunk.chunkChanged()
blockmask[blocktype.ID] = True blocktypeMask = blockmask[blocks] except Exception, e: print repr(e), " while using blockmask from filters.topsoil" blocktypeMask = blocks != 0 else: # topsoil any block blocktypeMask = blocks != 0 if depth < 0: blocktypeMask &= (blocks != blocktype.ID) if len(blocktypeMask) == 0: return heightmap = extractHeights(blocktypeMask) for x, z in itertools.product(*map(xrange, heightmap.shape)): h = heightmap[x, z] if h >= brushBoxThisChunk.height: continue if depth > 0: idx = x, z, slice(max(0, h - depth), h) else: # negative depth values mean to put a layer above the surface idx = x, z, slice(h, min(blocks.shape[2], h - depth)) mask = brushMask[idx] blocks[idx][mask] = blocktype.ID data[idx][mask] = blocktype.blockData
import topsoil # @UnresolvedImport blockmask = topsoil.naturalBlockmask() blockmask[blocktype.ID] = True blocktypeMask = blockmask[blocks] except Exception, e: print repr(e), " while using blockmask from filters.topsoil" blocktypeMask = blocks != 0 else: # topsoil any block blocktypeMask = blocks != 0 if depth < 0: blocktypeMask &= (blocks != blocktype.ID) heightmap = extractHeights(blocktypeMask) for x, z in itertools.product(*map(xrange, heightmap.shape)): h = heightmap[x, z] if h >= brushBoxThisChunk.height: continue if depth > 0: idx = x, z, slice(max(0, h - depth), h) else: # negative depth values mean to put a layer above the surface idx = x, z, slice(h, min(blocks.shape[2], h - depth)) mask = brushMask[idx] blocks[idx][mask] = blocktype.ID data[idx][mask] = blocktype.blockData