mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-11-28 21:56:33 +01:00
Add flatten brush (needs testing)
This commit is contained in:
parent
85ac3dff41
commit
49fc44bb4d
@ -0,0 +1,28 @@
|
|||||||
|
package com.boydti.fawe.object.brush;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.EditSession;
|
||||||
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
|
import com.sk89q.worldedit.Vector;
|
||||||
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
|
import com.sk89q.worldedit.function.mask.Masks;
|
||||||
|
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
public class FlattenBrush extends HeightBrush {
|
||||||
|
|
||||||
|
public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
|
||||||
|
super(stream, rotation, yscale, tool, clipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
|
||||||
|
int size = (int) sizeDouble;
|
||||||
|
Mask mask = tool.getMask();
|
||||||
|
if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) {
|
||||||
|
mask = null;
|
||||||
|
}
|
||||||
|
heightMap.setSize(size);
|
||||||
|
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true);
|
||||||
|
}
|
||||||
|
}
|
@ -16,9 +16,9 @@ import java.io.InputStream;
|
|||||||
public class HeightBrush implements DoubleActionBrush {
|
public class HeightBrush implements DoubleActionBrush {
|
||||||
|
|
||||||
public final ScalableHeightMap heightMap;
|
public final ScalableHeightMap heightMap;
|
||||||
private final int rotation;
|
public final int rotation;
|
||||||
double yscale = 1;
|
public final double yscale;
|
||||||
private final DoubleActionBrushTool tool;
|
public final DoubleActionBrushTool tool;
|
||||||
|
|
||||||
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
|
public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) {
|
||||||
this.tool = tool;
|
this.tool = tool;
|
||||||
@ -45,6 +45,6 @@ public class HeightBrush implements DoubleActionBrush {
|
|||||||
mask = null;
|
mask = null;
|
||||||
}
|
}
|
||||||
heightMap.setSize(size);
|
heightMap.setSize(size);
|
||||||
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true);
|
heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush.heightmap;
|
|||||||
|
|
||||||
import com.boydti.fawe.object.IntegerPair;
|
import com.boydti.fawe.object.IntegerPair;
|
||||||
import com.boydti.fawe.object.PseudoRandom;
|
import com.boydti.fawe.object.PseudoRandom;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.sk89q.worldedit.EditSession;
|
import com.sk89q.worldedit.EditSession;
|
||||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||||
@ -12,9 +11,7 @@ import com.sk89q.worldedit.blocks.BaseBlock;
|
|||||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||||
import com.sk89q.worldedit.function.mask.Mask;
|
import com.sk89q.worldedit.function.mask.Mask;
|
||||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||||
import com.sk89q.worldedit.math.convolution.GaussianKernel;
|
|
||||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||||
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.Region;
|
import com.sk89q.worldedit.regions.Region;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
@ -103,7 +100,7 @@ public class ScalableHeightMap {
|
|||||||
return new ArrayHeightMap(array);
|
return new ArrayHeightMap(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth) throws MaxChangedBlocksException {
|
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth, boolean towards) throws MaxChangedBlocksException {
|
||||||
Vector top = session.getMaximumPoint();
|
Vector top = session.getMaximumPoint();
|
||||||
int maxY = top.getBlockY();
|
int maxY = top.getBlockY();
|
||||||
int diameter = 2 * size + 1;
|
int diameter = 2 * size + 1;
|
||||||
@ -113,31 +110,65 @@ public class ScalableHeightMap {
|
|||||||
int startY = pos.getBlockY() - size;
|
int startY = pos.getBlockY() - size;
|
||||||
int[] newData = new int[diameter * diameter];
|
int[] newData = new int[diameter * diameter];
|
||||||
Vector mutablePos = new Vector(0, 0, 0);
|
Vector mutablePos = new Vector(0, 0, 0);
|
||||||
for (int x = -size; x <= size; x++) {
|
if (towards) {
|
||||||
int xx = centerX + x;
|
int targetY = pos.getBlockY();
|
||||||
mutablePos.mutX(xx);
|
for (int x = -size; x <= size; x++) {
|
||||||
for (int z = -size; z <= size; z++) {
|
int xx = centerX + x;
|
||||||
int index = (z + size) * diameter + (x + size);
|
mutablePos.mutX(xx);
|
||||||
int zz = centerZ + z;
|
for (int z = -size; z <= size; z++) {
|
||||||
double raise;
|
int index = (z + size) * diameter + (x + size);
|
||||||
switch (rotationMode) {
|
int zz = centerZ + z;
|
||||||
default:
|
double raise;
|
||||||
raise = getHeight(x, z);
|
switch (rotationMode) {
|
||||||
break;
|
default:
|
||||||
case 1:
|
raise = getHeight(x, z);
|
||||||
raise = getHeight(z, x);
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 2:
|
raise = getHeight(z, x);
|
||||||
raise = getHeight(-x, -z);
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 3:
|
raise = getHeight(-x, -z);
|
||||||
raise = getHeight(-z, -x);
|
break;
|
||||||
break;
|
case 3:
|
||||||
|
raise = getHeight(-z, -x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
raise = (yscale * raise);
|
||||||
|
int height = session.getHighestTerrainBlock(xx, zz, 0, 255, true);
|
||||||
|
int diff = targetY - height;
|
||||||
|
double raiseScaled = 1 + diff * (raise / (double) size);
|
||||||
|
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raiseScaled - (int) raiseScaled) * (maxY + 1)) ? 1 : 0;
|
||||||
|
int raiseScaledInt = (int) raiseScaled + random;
|
||||||
|
newData[index] = height + raiseScaledInt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int x = -size; x <= size; x++) {
|
||||||
|
int xx = centerX + x;
|
||||||
|
mutablePos.mutX(xx);
|
||||||
|
for (int z = -size; z <= size; z++) {
|
||||||
|
int index = (z + size) * diameter + (x + size);
|
||||||
|
int zz = centerZ + z;
|
||||||
|
double raise;
|
||||||
|
switch (rotationMode) {
|
||||||
|
default:
|
||||||
|
raise = getHeight(x, z);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
raise = getHeight(z, x);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
raise = getHeight(-x, -z);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
raise = getHeight(-z, -x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
raise = (yscale * raise);
|
||||||
|
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
|
||||||
|
int height = session.getHighestTerrainBlock(xx, zz, 0, maxY, true) + (int) raise + random;
|
||||||
|
newData[index] = height;
|
||||||
}
|
}
|
||||||
raise = (yscale * raise);
|
|
||||||
int random = PseudoRandom.random.random(maxY + 1) < (int) ((raise - (int) raise) * (maxY + 1)) ? 1 : 0;
|
|
||||||
int height = session.getHighestTerrainBlock(xx, zz, 0, maxY, true) + (int) raise + random;
|
|
||||||
newData[index] = height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int iterations = 1;
|
int iterations = 1;
|
||||||
@ -145,14 +176,14 @@ public class ScalableHeightMap {
|
|||||||
Vector max = pos.add(size, maxY, size);
|
Vector max = pos.add(size, maxY, size);
|
||||||
Region region = new CuboidRegion(session.getWorld(), min, max);
|
Region region = new CuboidRegion(session.getWorld(), min, max);
|
||||||
HeightMap heightMap = new HeightMap(session, region, true);
|
HeightMap heightMap = new HeightMap(session, region, true);
|
||||||
if (smooth) {
|
// if (smooth) {
|
||||||
try {
|
// try {
|
||||||
HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
// HeightMapFilter filter = (HeightMapFilter) HeightMapFilter.class.getConstructors()[0].newInstance(GaussianKernel.class.getConstructors()[0].newInstance(5, 1));
|
||||||
newData = filter.filter(newData, diameter, diameter);
|
// newData = filter.filter(newData, diameter, diameter);
|
||||||
} catch (Throwable e) {
|
// } catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
// MainUtil.handleError(e);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
heightMap.apply(newData);
|
heightMap.apply(newData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import com.boydti.fawe.object.brush.CommandBrush;
|
|||||||
import com.boydti.fawe.object.brush.CopyPastaBrush;
|
import com.boydti.fawe.object.brush.CopyPastaBrush;
|
||||||
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
|
import com.boydti.fawe.object.brush.DoubleActionBrushTool;
|
||||||
import com.boydti.fawe.object.brush.ErodeBrush;
|
import com.boydti.fawe.object.brush.ErodeBrush;
|
||||||
|
import com.boydti.fawe.object.brush.FlattenBrush;
|
||||||
import com.boydti.fawe.object.brush.HeightBrush;
|
import com.boydti.fawe.object.brush.HeightBrush;
|
||||||
import com.boydti.fawe.object.brush.LineBrush;
|
import com.boydti.fawe.object.brush.LineBrush;
|
||||||
import com.boydti.fawe.object.brush.RecurseBrush;
|
import com.boydti.fawe.object.brush.RecurseBrush;
|
||||||
@ -405,6 +406,58 @@ public class BrushCommands {
|
|||||||
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
|
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
aliases = { "flatten", "flatmap", "flat" },
|
||||||
|
usage = "[radius] [file|#clipboard|null] [rotation] [yscale]",
|
||||||
|
flags = "h",
|
||||||
|
desc = "Flatten brush",
|
||||||
|
help =
|
||||||
|
"This brush raises and lowers land towards the clicked point\n",
|
||||||
|
min = 1,
|
||||||
|
max = 4
|
||||||
|
)
|
||||||
|
@CommandPermissions("worldedit.brush.height")
|
||||||
|
public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException {
|
||||||
|
worldEdit.checkMaxBrushRadius(radius);
|
||||||
|
String filenamePng = (filename.endsWith(".png") ? filename : filename + ".png");
|
||||||
|
File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + filenamePng);
|
||||||
|
InputStream stream = null;
|
||||||
|
if (!file.exists()) {
|
||||||
|
if (!filename.equals("#clipboard") && filename.length() >= 7) {
|
||||||
|
try {
|
||||||
|
URL url;
|
||||||
|
if (filename.startsWith("http")) {
|
||||||
|
url = new URL(filename);
|
||||||
|
if (!url.getHost().equals("i.imgur.com")) {
|
||||||
|
throw new FileNotFoundException(filename);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
url = new URL("https://i.imgur.com/" + filenamePng);
|
||||||
|
}
|
||||||
|
ReadableByteChannel rbc = Channels.newChannel(url.openStream());
|
||||||
|
stream = Channels.newInputStream(rbc);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!filename.equalsIgnoreCase("#clipboard")){
|
||||||
|
try {
|
||||||
|
stream = new FileInputStream(file);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
|
||||||
|
tool.setSize(radius);
|
||||||
|
try {
|
||||||
|
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height");
|
||||||
|
} catch (EmptyClipboardException ignore) {
|
||||||
|
tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height");
|
||||||
|
}
|
||||||
|
player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "copypaste", "copy", "paste", "cp", "copypasta" },
|
aliases = { "copypaste", "copy", "paste", "cp", "copypasta" },
|
||||||
usage = "[depth]",
|
usage = "[depth]",
|
||||||
|
Loading…
Reference in New Issue
Block a user