mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-23 09:47:38 +00:00
Re-add smooth filtering via a mask.
Instead of trying to maintain a list of "natural terrain blocks", just let the user specify a mask of blocks to use for the height map filter. https://gfycat.com/severaljauntycondor
This commit is contained in:
parent
9eeb0acffe
commit
243d6476ac
@ -592,10 +592,25 @@ public class EditSession implements Extent, AutoCloseable {
|
|||||||
* @return height of highest block found or 'minY'
|
* @return height of highest block found or 'minY'
|
||||||
*/
|
*/
|
||||||
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
|
public int getHighestTerrainBlock(int x, int z, int minY, int maxY) {
|
||||||
|
return getHighestTerrainBlock(x, z, minY, maxY, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highest solid 'terrain' block.
|
||||||
|
*
|
||||||
|
* @param x the X coordinate
|
||||||
|
* @param z the Z coordinate
|
||||||
|
* @param minY minimal height
|
||||||
|
* @param maxY maximal height
|
||||||
|
* @param filter a mask of blocks to consider, or null to consider any solid (movement-blocking) block
|
||||||
|
* @return height of highest block found or 'minY'
|
||||||
|
*/
|
||||||
|
public int getHighestTerrainBlock(int x, int z, int minY, int maxY, Mask filter) {
|
||||||
for (int y = maxY; y >= minY; --y) {
|
for (int y = maxY; y >= minY; --y) {
|
||||||
BlockVector3 pt = BlockVector3.at(x, y, z);
|
BlockVector3 pt = BlockVector3.at(x, y, z);
|
||||||
BlockState block = getBlock(pt);
|
if (filter == null
|
||||||
if (block.getBlockType().getMaterial().isMovementBlocker()) {
|
? getBlock(pt).getBlockType().getMaterial().isMovementBlocker()
|
||||||
|
: filter.test(pt)) {
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ import com.sk89q.worldedit.command.util.CreatureButcher;
|
|||||||
import com.sk89q.worldedit.entity.Player;
|
import com.sk89q.worldedit.entity.Player;
|
||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
import com.sk89q.worldedit.function.mask.BlockTypeMask;
|
||||||
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
@ -158,24 +159,24 @@ public class BrushCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "smooth" },
|
aliases = { "smooth" },
|
||||||
usage = "[size] [iterations]",
|
usage = "[size] [iterations] [filter]",
|
||||||
desc = "Choose the terrain softener brush",
|
desc = "Choose the terrain softener brush",
|
||||||
help =
|
help =
|
||||||
"Chooses the terrain softener brush.",
|
"Chooses the terrain softener brush. Optionally, specify a mask of blocks to be used for the heightmap.\n" +
|
||||||
|
"For example, '/brush smooth 2 4 grass_block,dirt,stone'.",
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 2
|
max = 3
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.brush.smooth")
|
@CommandPermissions("worldedit.brush.smooth")
|
||||||
public void smoothBrush(Player player, LocalSession session, EditSession editSession,
|
public void smoothBrush(Player player, LocalSession session, EditSession editSession,
|
||||||
@Optional("2") double radius, @Optional("4") int iterations) throws WorldEditException {
|
@Optional("2") double radius, @Optional("4") int iterations, @Optional Mask mask) throws WorldEditException {
|
||||||
|
|
||||||
worldEdit.checkMaxBrushRadius(radius);
|
worldEdit.checkMaxBrushRadius(radius);
|
||||||
|
|
||||||
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
BrushTool tool = session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType());
|
||||||
tool.setSize(radius);
|
tool.setSize(radius);
|
||||||
tool.setBrush(new SmoothBrush(iterations), "worldedit.brush.smooth");
|
tool.setBrush(new SmoothBrush(iterations, mask), "worldedit.brush.smooth");
|
||||||
|
|
||||||
player.print(String.format("Smooth brush equipped (%.0f x %dx, using any block).", radius, iterations));
|
player.print(String.format("Smooth brush equipped (%.0f x %dx, using %s).", radius, iterations, mask == null ? "any block" : "filter"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
|
@ -240,17 +240,19 @@ public class RegionCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "/smooth" },
|
aliases = { "/smooth" },
|
||||||
usage = "[iterations]",
|
usage = "[iterations] [filter]",
|
||||||
desc = "Smooth the elevation in the selection",
|
desc = "Smooth the elevation in the selection",
|
||||||
help =
|
help =
|
||||||
"Smooths the elevation in the selection.",
|
"Smooths the elevation in the selection.\n" +
|
||||||
|
"Optionally, restricts the height map to a set of blocks specified with mask syntax.\n" +
|
||||||
|
"For example, '//smooth 1 grass_block,dirt,stone' would only smooth natural surface terrain.",
|
||||||
min = 0,
|
min = 0,
|
||||||
max = 1
|
max = 2
|
||||||
)
|
)
|
||||||
@CommandPermissions("worldedit.region.smooth")
|
@CommandPermissions("worldedit.region.smooth")
|
||||||
@Logging(REGION)
|
@Logging(REGION)
|
||||||
public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations) throws WorldEditException {
|
public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations, @Optional Mask mask) throws WorldEditException {
|
||||||
HeightMap heightMap = new HeightMap(editSession, region);
|
HeightMap heightMap = new HeightMap(editSession, region, mask);
|
||||||
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
||||||
int affected = heightMap.applyFilter(filter, iterations);
|
int affected = heightMap.applyFilter(filter, iterations);
|
||||||
player.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
|
player.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
|
||||||
|
@ -21,6 +21,7 @@ package com.sk89q.worldedit.command.tool.brush;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.math.Vector3;
|
import com.sk89q.worldedit.math.Vector3;
|
||||||
@ -31,12 +32,20 @@ import com.sk89q.worldedit.regions.CuboidRegion;
|
|||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.util.Location;
|
import com.sk89q.worldedit.util.Location;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class SmoothBrush implements Brush {
|
public class SmoothBrush implements Brush {
|
||||||
|
|
||||||
|
private final Mask mask;
|
||||||
private int iterations;
|
private int iterations;
|
||||||
|
|
||||||
public SmoothBrush(int iterations) {
|
public SmoothBrush(int iterations) {
|
||||||
|
this(iterations, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SmoothBrush(int iterations, @Nullable Mask mask) {
|
||||||
this.iterations = iterations;
|
this.iterations = iterations;
|
||||||
|
this.mask = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -45,7 +54,7 @@ public class SmoothBrush implements Brush {
|
|||||||
Location min = new Location(editSession.getWorld(), posDouble.subtract(size, size, size));
|
Location min = new Location(editSession.getWorld(), posDouble.subtract(size, size, size));
|
||||||
BlockVector3 max = posDouble.add(size, size + 10, size).toBlockPoint();
|
BlockVector3 max = posDouble.add(size, size + 10, size).toBlockPoint();
|
||||||
Region region = new CuboidRegion(editSession.getWorld(), min.toVector().toBlockPoint(), max);
|
Region region = new CuboidRegion(editSession.getWorld(), min.toVector().toBlockPoint(), max);
|
||||||
HeightMap heightMap = new HeightMap(editSession, region);
|
HeightMap heightMap = new HeightMap(editSession, region, mask);
|
||||||
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
||||||
heightMap.applyFilter(filter, iterations);
|
heightMap.applyFilter(filter, iterations);
|
||||||
}
|
}
|
||||||
|
@ -23,11 +23,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
|
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.math.BlockVector3;
|
import com.sk89q.worldedit.math.BlockVector3;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import com.sk89q.worldedit.world.block.BlockState;
|
import com.sk89q.worldedit.world.block.BlockState;
|
||||||
import com.sk89q.worldedit.world.block.BlockTypes;
|
import com.sk89q.worldedit.world.block.BlockTypes;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows applications of Kernels onto the region's height map.
|
* Allows applications of Kernels onto the region's height map.
|
||||||
*
|
*
|
||||||
@ -48,7 +51,7 @@ public class HeightMap {
|
|||||||
* @param session an edit session
|
* @param session an edit session
|
||||||
* @param region the region
|
* @param region the region
|
||||||
*/
|
*/
|
||||||
public HeightMap(EditSession session, Region region) {
|
public HeightMap(EditSession session, Region region, @Nullable Mask mask) {
|
||||||
checkNotNull(session);
|
checkNotNull(session);
|
||||||
checkNotNull(region);
|
checkNotNull(region);
|
||||||
|
|
||||||
@ -67,7 +70,7 @@ public class HeightMap {
|
|||||||
data = new int[width * height];
|
data = new int[width * height];
|
||||||
for (int z = 0; z < height; ++z) {
|
for (int z = 0; z < height; ++z) {
|
||||||
for (int x = 0; x < width; ++x) {
|
for (int x = 0; x < width; ++x) {
|
||||||
data[z * width + x] = session.getHighestTerrainBlock(x + minX, z + minZ, minY, maxY);
|
data[z * width + x] = session.getHighestTerrainBlock(x + minX, z + minZ, minY, maxY, mask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user