Skip to content

Instantly share code, notes, and snippets.

@egamble
Last active December 27, 2015 08:49
Show Gist options
  • Save egamble/7299765 to your computer and use it in GitHub Desktop.
Save egamble/7299765 to your computer and use it in GitHub Desktop.
Modified version of the MCEdit smoothing filter https://github.com/mcedit/mcedit/blob/master/filters/smooth.py. This version smooths under water correctly, uses the surrounding terrain blocks for fill, and both raises and lowers terrain correctly.
from numpy import zeros, array
import itertools
from pymclevel.level import extractHeights
terrainBlocktypes = [1, 2, 3, 7, 12, 13, 14, 15, 16, 24, 56, 73, 74, 82, 87, 88, 89]
terrainBlockmask = zeros((256,), dtype='bool')
terrainBlockmask[terrainBlocktypes] = True
inputs = (
("Repeat count", (1, 50)),
)
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)
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
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]
column = array(schema.Blocks[x, z])
# fill with terrain blocks from whichever adjacent column is at least as high
if nh > oh:
if terrainBlocks[x-1, z, nh] != 0:
column[oh:nh] = schema.Blocks[x-1, z][oh:nh]
elif terrainBlocks[x+1, z, nh] != 0:
column[oh:nh] = schema.Blocks[x+1, z][oh:nh]
elif terrainBlocks[x, z-1, nh] != 0:
column[oh:nh] = schema.Blocks[x, z-1][oh:nh]
elif terrainBlocks[x, z+1, nh] != 0:
column[oh:nh] = schema.Blocks[x, z+1][oh:nh]
column[nh:oh] = 0 # clear removed terrain blocks
column[nh:63] = 8 # fill with water from new height up to sea level
schema.Blocks[x, z] = column
level.copyBlocksFrom(schema, schema.bounds, box.origin)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment