diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java
index 48777ca8..8db62b31 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/ABukkitMain.java
@@ -2,6 +2,7 @@ package com.boydti.fawe.bukkit;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FaweQueue;
+import com.sk89q.worldedit.world.World;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
@@ -53,5 +54,5 @@ public abstract class ABukkitMain extends JavaPlugin {
FaweBukkit imp = new FaweBukkit(this);
}
- public abstract FaweQueue getQueue(String world);
+ public abstract FaweQueue getQueue(World world);
}
\ No newline at end of file
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java
index 6890c8c8..4ccb41ee 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java
@@ -158,7 +158,7 @@ public class FaweBukkit implements IFawe, Listener {
* - When a block change is requested, the SetQueue will first check if the chunk exists in the queue, or it will create and add it
*/
@Override
- public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
+ public FaweQueue getNewQueue(World world, boolean dontCareIfFast) {
if (playerChunk != (playerChunk = true)) {
try {
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java
index 66f291ba..6a5e97fc 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java
@@ -33,7 +33,7 @@ public abstract class BukkitQueue_0 extends NMSMa
public static Method methodToNative;
public static Method methodFromNative;
- public BukkitQueue_0(final String world) {
+ public BukkitQueue_0(final com.sk89q.worldedit.world.World world) {
super(world);
setupAdapter(null);
if (!registered) {
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java
index e9e2a1ef..8edbbebe 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_All.java
@@ -21,7 +21,7 @@ public class BukkitQueue_All extends BukkitQueue_0 {
public static double TPS_TARGET = 18.5;
private static int LIGHT_MASK = 0x739C0;
- public BukkitQueue_All(String world) {
+ public BukkitQueue_All(com.sk89q.worldedit.world.World world) {
super(world);
if (Settings.QUEUE.EXTRA_TIME_MS != Integer.MIN_VALUE) {
ALLOCATE = Settings.QUEUE.EXTRA_TIME_MS;
diff --git a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
index 3a233281..3a6e0a55 100644
--- a/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
+++ b/bukkit0/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncWorld.java
@@ -129,7 +129,7 @@ public class AsyncWorld implements World {
* @return
*/
public synchronized static AsyncWorld create(final WorldCreator creator) {
- BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(creator.name(), true, false);
+ BukkitQueue_0 queue = (BukkitQueue_0) SetQueue.IMP.getNewQueue(FaweAPI.getWorld(creator.name()), true, false);
World world = queue.createWorld(creator);
return wrap(world);
}
@@ -182,7 +182,7 @@ public class AsyncWorld implements World {
@Override
public int getHighestBlockYAt(int x, int z) {
- for (int y = 255; y >= 0; y--) {
+ for (int y = getMaxHeight() - 1; y >= 0; y--) {
if (queue.getCombinedId4Data(x, y, z, 0) != 0) {
return y;
}
diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
index 92ac5e86..5dd09b73 100644
--- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
+++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitMain_110.java
@@ -7,6 +7,7 @@ import com.boydti.fawe.object.io.BufferedRandomAccessFile;
import com.boydti.fawe.object.io.FastByteArrayInputStream;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.util.ReflectionUtils;
+import com.sk89q.worldedit.world.World;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
@@ -26,7 +27,7 @@ import net.minecraft.server.v1_10_R1.RegionFileCache;
public class BukkitMain_110 extends ABukkitMain {
@Override
- public BukkitQueue_0 getQueue(String world) {
+ public BukkitQueue_0 getQueue(World world) {
return new BukkitQueue_1_10(world);
}
diff --git a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java
index 08c0317e..23d364bf 100644
--- a/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java
+++ b/bukkit110/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java
@@ -80,7 +80,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0
* - The FaweQueue skips a bit of overhead so it's faster
@@ -108,8 +113,8 @@ public class FaweAPI {
* @param autoqueue If it should start dispatching before you enqueue it.
* @return
*/
- public static FaweQueue createQueue(String worldName, boolean autoqueue) {
- return SetQueue.IMP.getNewQueue(worldName, true, autoqueue);
+ public static FaweQueue createQueue(World world, boolean autoqueue) {
+ return SetQueue.IMP.getNewQueue(world, true, autoqueue);
}
public static World getWorld(String worldName) {
@@ -355,32 +360,21 @@ public class FaweAPI {
return (version[0] > major) || ((version[0] == major) && (version[1] > minor)) || ((version[0] == major) && (version[1] == minor) && (version[2] >= minor2));
}
-// /**
-// * Fix the lighting in a chunk
-// * @param world
-// * @param x
-// * @param z
-// * @param mode
-// */
-// public static void fixLighting(String world, int x, int z, FaweQueue.RelightMode mode) {
-// FaweQueue queue = SetQueue.IMP.getNewQueue(world, true, false);
-// queue.fixLighting(queue.getFaweChunk(x, z), mode);
-// }
-//
-// /**
-// * Fix the lighting in a chunk
-// * @param chunk
-// * @param mode
-// */
-// public static void fixLighting(final Chunk chunk, FaweQueue.RelightMode mode) {
-// FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), true, false);
-// queue.fixLighting(queue.getFaweChunk(chunk.getX(), chunk.getZ()), mode);
-// }
-
+ @Deprecated
public static int fixLighting(String world, Region selection) {
return fixLighting(world, selection, FaweQueue.RelightMode.ALL);
}
+ @Deprecated
+ public static int fixLighting(String world, Region selection, final FaweQueue.RelightMode mode) {
+ return fixLighting(world, selection, null, mode);
+ }
+
+ @Deprecated
+ public static int fixLighting(String world, Region selection, @Nullable FaweQueue queue, final FaweQueue.RelightMode mode) {
+ return fixLighting(getWorld(world), selection, queue, mode);
+ }
+
/**
* Fix the lighting in a selection
* - First removes all lighting, then relights
@@ -390,11 +384,7 @@ public class FaweAPI {
* @param selection (assumes cuboid)
* @return
*/
- public static int fixLighting(String world, Region selection, final FaweQueue.RelightMode mode) {
- return fixLighting(world, selection, null, mode);
- }
-
- public static int fixLighting(String world, Region selection, @Nullable FaweQueue queue, final FaweQueue.RelightMode mode) {
+ public static int fixLighting(World world, Region selection, @Nullable FaweQueue queue, final FaweQueue.RelightMode mode) {
final Vector bot = selection.getMinimumPoint();
final Vector top = selection.getMaximumPoint();
@@ -499,7 +489,7 @@ public class FaweAPI {
final int y_offset = loc.y + IntTag.class.cast(tagMap.get("WEOffsetY")).getValue();
final int z_offset = loc.z + IntTag.class.cast(tagMap.get("WEOffsetZ")).getValue();
- FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true, true);
+ FaweQueue queue = SetQueue.IMP.getNewQueue(getWorld(loc.world), true, true);
for (int y = 0; y < height; y++) {
final int yy = y_offset + y;
diff --git a/core/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java
index e1b308f7..c68fa161 100644
--- a/core/src/main/java/com/boydti/fawe/FaweCache.java
+++ b/core/src/main/java/com/boydti/fawe/FaweCache.java
@@ -246,6 +246,19 @@ public class FaweCache {
CACHE_COLOR[getCombined(35, 15)] = new Color(0, 0, 0); // Black
}
+ public static boolean isLiquidOrGas(int id) {
+ switch (id) {
+ case 0:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ return true;
+ default:
+ return false;
+ }
+ }
+
public static LightType getLight(int id) {
switch (id) { // Lighting
case 0:
diff --git a/core/src/main/java/com/boydti/fawe/IFawe.java b/core/src/main/java/com/boydti/fawe/IFawe.java
index 6774da5f..2f4d9ccd 100644
--- a/core/src/main/java/com/boydti/fawe/IFawe.java
+++ b/core/src/main/java/com/boydti/fawe/IFawe.java
@@ -23,7 +23,7 @@ public interface IFawe {
public TaskManager getTaskManager();
- public FaweQueue getNewQueue(String world, boolean fast);
+ public FaweQueue getNewQueue(World world, boolean fast);
public String getWorldName(World world);
diff --git a/core/src/main/java/com/boydti/fawe/config/BBC.java b/core/src/main/java/com/boydti/fawe/config/BBC.java
index c499625e..2460cb5f 100644
--- a/core/src/main/java/com/boydti/fawe/config/BBC.java
+++ b/core/src/main/java/com/boydti/fawe/config/BBC.java
@@ -79,6 +79,7 @@ public enum BBC {
SELECTION_OUTSET("Region outset", "WorldEdit.Selection"),
SELECTION_SHIFT("Region shifted", "WorldEdit.Selection"),
SELECTION_CLEARED("Selection cleared", "WorldEdit.Selection"),
+ SELECTION_NONE("Make a region selection first", "WorldEdit.Selection"),
BRUSH_BUTCHER("Butcher brush equiped (%s0)", "WorldEdit.Brush"),
BRUSH_CLIPBOARD("Clipboard brush shape equipped", "WorldEdit.Brush"),
@@ -91,6 +92,10 @@ public enum BBC {
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"),
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
+ BRUSH_BLEND_BALL("Blend ball brush equipped (%s0).", "WorldEdit.Brush"),
+ BRUSH_ERODE("Erode brush equipped (%s0).", "WorldEdit.Brush"),
+ BRUSH_PASTE_NONE("Nothing to paste", "WorldEdit.Brush"),
+
ROLLBACK_ELEMENT("Undoing %s0", "WorldEdit.Rollback"),
diff --git a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
index cae500e8..52ea52fc 100644
--- a/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
+++ b/core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
@@ -14,6 +14,7 @@ import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.blocks.BlockMaterial;
+import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.util.ArrayDeque;
@@ -31,11 +32,11 @@ public abstract class MappedFaweQueue extends FaweQueue {
private IFaweQueueMap map;
public ArrayDeque tasks = new ArrayDeque<>();
- public MappedFaweQueue(final String world) {
+ public MappedFaweQueue(final World world) {
this(world, null);
}
- public MappedFaweQueue(final String world, IFaweQueueMap map) {
+ public MappedFaweQueue(final World world, IFaweQueueMap map) {
super(world);
if (map == null) {
map = new DefaultFaweQueueMap(this);
diff --git a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java
index 427d2c78..dd76da3d 100644
--- a/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java
+++ b/core/src/main/java/com/boydti/fawe/example/NMSMappedFaweQueue.java
@@ -6,6 +6,7 @@ import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.exception.FaweException;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.world.World;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
@@ -13,13 +14,17 @@ import java.util.UUID;
public abstract class NMSMappedFaweQueue extends MappedFaweQueue {
- public NMSMappedFaweQueue(String world) {
+ private final int maxY;
+
+ public NMSMappedFaweQueue(World world) {
super(world);
+ this.maxY = world.getMaxY();
addRelightTask();
}
- public NMSMappedFaweQueue(String world, IFaweQueueMap map) {
+ public NMSMappedFaweQueue(World world, IFaweQueueMap map) {
super(world, map);
+ this.maxY = world.getMaxY();
addRelightTask();
}
@@ -57,7 +62,7 @@ public abstract class NMSMappedFaweQueue ex
}
CharFaweChunk chunk = (CharFaweChunk) fc;
boolean relight = false;
- boolean[] fix = new boolean[16];
+ boolean[] fix = new boolean[(maxY + 1) >> 4];
boolean sky = hasSky();
for (int i = 0; i < chunk.ids.length; i++) {
if ((sky && ((chunk.getAir(i) & 4095) != 0 || (chunk.getCount(i) & 4095) != 0)) || chunk.getRelight(i) != 0) {
@@ -99,7 +104,7 @@ public abstract class NMSMappedFaweQueue ex
if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) {
return 1;
}
- if ((y < 0) || (y > 255)) {
+ if ((y < 0) || (y > maxY)) {
return 1;
}
final int i = FaweCache.CACHE_I[y][z][x];
@@ -181,7 +186,7 @@ public abstract class NMSMappedFaweQueue ex
@Override
public CompoundTag getTileEntity(int x, int y, int z) throws FaweException.FaweChunkLoadException {
- if (y < 0 || y > 255) {
+ if (y < 0 || y > maxY) {
return null;
}
int cx = x >> 4;
diff --git a/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java
index 28f00758..7d940c77 100644
--- a/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java
+++ b/core/src/main/java/com/boydti/fawe/example/NMSRelighter.java
@@ -16,6 +16,7 @@ public class NMSRelighter {
private final NMSMappedFaweQueue queue;
private final HashMap skyToRelight;
private final HashMap blocksToRelight;
+ private final int maxY;
private volatile boolean relighting = false;
private static final int DISPATCH_SIZE = 64;
@@ -24,6 +25,7 @@ public class NMSRelighter {
this.queue = queue;
skyToRelight = new HashMap<>();
blocksToRelight = new HashMap<>();
+ this.maxY = queue.getWEWorld().getMaxY();
}
public boolean addChunk(int cx, int cz, boolean[] fix) {
@@ -112,7 +114,7 @@ public class NMSRelighter {
if (y > 0) {
smoothBlockLight(emit, xx, y, zz, xx, y - 1, zz);
}
- if (y < 255) {
+ if (y < maxY) {
smoothBlockLight(emit, xx, y, zz, xx, y + 1, zz);
}
}
@@ -147,7 +149,7 @@ public class NMSRelighter {
if (isTransparent(x, y, z - 1)) { queue.setBlockLight(x, y, z - 1, brightness); addBlock(x, y, z - 1); }
if (isTransparent(x, y, z + 1)) { queue.setBlockLight(x, y, z + 1, brightness); addBlock(x, y, z + 1); }
if (y > 0 && isTransparent(x, y - 1, z)) { queue.setBlockLight(x, y - 1, z, brightness); addBlock(x, y - 1, z); }
- if (y < 255 && isTransparent(x, y + 1, z)) { queue.setBlockLight(x, y + 1, z, brightness); addBlock(x, y + 1, z); }
+ if (y < maxY && isTransparent(x, y + 1, z)) { queue.setBlockLight(x, y + 1, z, brightness); addBlock(x, y + 1, z); }
}
public void fixSkyLighting() {
@@ -185,7 +187,7 @@ public class NMSRelighter {
Object section = queue.getCachedSection(sections, layer);
if (section == null)continue;
chunk.smooth = false;
- for (int j = 0; j < 256; j++) {
+ for (int j = 0; j <= maxY; j++) {
int x = cacheX[j];
int z = cacheZ[j];
byte value = mask[j];
@@ -271,7 +273,7 @@ public class NMSRelighter {
Object section = queue.getCachedSection(sections, y >> 4);
if (section == null) return;
if (direction) {
- for (int j = 0; j < 256; j++) {
+ for (int j = 0; j <= maxY; j++) {
int x = j & 15;
int z = j >> 4;
if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 1)) {
@@ -283,7 +285,7 @@ public class NMSRelighter {
if (value > mask[j]) queue.setSkyLight(section, x, y, z, mask[j] = value);
}
} else {
- for (int j = 255; j >= 0; j--) {
+ for (int j = maxY; j >= 0; j--) {
int x = j & 15;
int z = j >> 4;
if (mask[j] >= 14 || (mask[j] == 0 && queue.getOpacity(section, x, y, z) > 1)) {
@@ -340,11 +342,11 @@ public class NMSRelighter {
public RelightSkyEntry(int x, int z, boolean[] fix) {
this.x = x;
this.z = z;
- byte[] array = new byte[256];
+ byte[] array = new byte[maxY + 1];
Arrays.fill(array, (byte) 15);
this.mask = array;
if (fix == null) {
- this.fix = new boolean[16];
+ this.fix = new boolean[(maxY + 1) >> 4];
Arrays.fill(this.fix, true);
} else {
this.fix = fix;
diff --git a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java
index 08ed15cb..217a7c06 100644
--- a/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java
+++ b/core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAQueue.java
@@ -24,7 +24,7 @@ public class MCAQueue extends NMSMappedFaweQueue {
}
public FaweQueue getMaskedFaweQueue(boolean autoQueue) {
- FaweQueue queue = SetQueue.IMP.getNewQueue(getLocation().world, true, autoQueue);
+ FaweQueue queue = SetQueue.IMP.getNewQueue(getWorld(), true, autoQueue);
RegionWrapper[] allowedRegions = getCurrentRegions();
if (allowedRegions.length == 1 && allowedRegions[0].isGlobal()) {
return queue;
@@ -275,7 +276,9 @@ public abstract class FawePlayer {
*/
public void setSelection(final RegionWrapper region) {
final Player player = this.getPlayer();
- final RegionSelector selector = new CuboidRegionSelector(player.getWorld(), region.getBottomVector(), region.getTopVector());
+ Vector top = region.getTopVector();
+ top.setY(getWorld().getMaxY());
+ final RegionSelector selector = new CuboidRegionSelector(player.getWorld(), region.getBottomVector(), top);
this.getSession().setRegionSelector(player.getWorld(), selector);
}
diff --git a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java
index e06af5ed..9d610d43 100644
--- a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java
+++ b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java
@@ -14,6 +14,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockMaterial;
+import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.biome.BaseBiome;
import com.sk89q.worldedit.world.registry.BundledBlockData;
import java.io.File;
@@ -26,14 +27,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
public abstract class FaweQueue {
+ private World weWorld;
private final String world;
private ConcurrentLinkedDeque sessions;
private long modified = System.currentTimeMillis();
private RunnableVal2 changeTask;
private RunnableVal2 progressTask;
- public FaweQueue(String world) {
- this.world = world;
+ public FaweQueue(World world) {
+ this.weWorld = world;
+ this.world = Fawe.imp().getWorldName(world);
}
public enum ProgressType {
@@ -58,6 +61,10 @@ public abstract class FaweQueue {
getSessions().add(session);
}
+ public World getWEWorld() {
+ return weWorld;
+ }
+
public String getWorldName() {
return world;
}
@@ -140,6 +147,10 @@ public abstract class FaweQueue {
public abstract File getSaveFolder();
+ public int getMaxY() {
+ return weWorld == null ? 255 : weWorld.getMaxY();
+ }
+
public void forEachBlockInChunk(int cx, int cz, RunnableVal2 onEach) {
int bx = cx << 4;
int bz = cz << 4;
@@ -150,7 +161,7 @@ public abstract class FaweQueue {
for (int z = 0; z < 16; z++) {
int zz = z + bz;
mutable.z = zz;
- for (int y = 0; y < 256; y++) {
+ for (int y = 0; y <= getMaxY(); y++) {
int combined = getCombinedId4Data(xx, y, zz);
if (combined == 0) {
continue;
@@ -177,7 +188,7 @@ public abstract class FaweQueue {
int xx = x + bx;
for (int z = 0; z < 16; z++) {
int zz = z + bz;
- for (int y = 0; y < 256; y++) {
+ for (int y = 0; y < getMaxY(); y++) {
int combined = getCombinedId4Data(xx, y, zz);
if (combined == 0) {
continue;
diff --git a/core/src/main/java/com/boydti/fawe/object/PseudoRandom.java b/core/src/main/java/com/boydti/fawe/object/PseudoRandom.java
index b0545eba..dfd32f66 100644
--- a/core/src/main/java/com/boydti/fawe/object/PseudoRandom.java
+++ b/core/src/main/java/com/boydti/fawe/object/PseudoRandom.java
@@ -1,5 +1,7 @@
package com.boydti.fawe.object;
+import java.util.Random;
+
public class PseudoRandom {
public static PseudoRandom random = new PseudoRandom();
@@ -8,6 +10,7 @@ public class PseudoRandom {
public PseudoRandom() {
this.state = System.nanoTime();
+ new Random().nextDouble();
}
public PseudoRandom(final long state) {
@@ -27,6 +30,10 @@ public class PseudoRandom {
return a;
}
+ public double nextDouble() {
+ return Math.max(0, Math.min(1, Math.abs(nextLong() / Long.MAX_VALUE)));
+ }
+
public int random(final int n) {
if (n == 1) {
return 0;
@@ -34,4 +41,8 @@ public class PseudoRandom {
final long r = ((this.nextLong() >>> 32) * n) >> 32;
return (int) r;
}
+
+ public int nextInt(int i) {
+ return random(i);
+ }
}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/BlendBall.java b/core/src/main/java/com/boydti/fawe/object/brush/BlendBall.java
new file mode 100644
index 00000000..922df347
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/BlendBall.java
@@ -0,0 +1,74 @@
+package com.boydti.fawe.object.brush;
+
+import com.google.common.collect.Maps;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.command.tool.brush.Brush;
+import com.sk89q.worldedit.function.pattern.Pattern;
+import java.util.Map;
+
+public class BlendBall implements Brush {
+
+ @Override
+ public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
+ final int outsetSize = (int) (size + 1);
+ double brushSizeSquared = size * size;
+
+ int tx = position.getBlockX();
+ int ty = position.getBlockY();
+ int tz = position.getBlockZ();
+
+ Map frequency = Maps.newHashMap();
+
+ int maxY = editSession.getMaximumPoint().getBlockY();
+
+ for (int x = -outsetSize; x <= outsetSize; x++) {
+ int x0 = x + tx;
+ for (int y = -outsetSize; y <= outsetSize; y++) {
+ int y0 = y + ty;
+ for (int z = -outsetSize; z <= outsetSize; z++) {
+ if (x * x + y * y + z * z >= brushSizeSquared) {
+ continue;
+ }
+ int z0 = z + tz;
+ int highest = 1;
+ BaseBlock currentState = editSession.getBlock(x0, y0, z0);
+ BaseBlock highestState = currentState;
+ frequency.clear();
+ boolean tie = false;
+ for (int ox = -1; ox <= 1; ox++) {
+ for (int oz = -1; oz <= 1; oz++) {
+ for (int oy = -1; oy <= 1; oy++) {
+ if (oy + y0 < 0 || oy + y0 > maxY) {
+ continue;
+ }
+ BaseBlock state = editSession.getBlock(x0 + ox, y0 + oy, z0 + oz);
+ Integer count = frequency.get(state);
+ if (count == null) {
+ count = 1;
+ } else {
+ count++;
+ }
+ if (count > highest) {
+ highest = count;
+ highestState = state;
+ tie = false;
+ } else if (count == highest) {
+ tie = true;
+ }
+ frequency.put(state, count);
+ }
+ }
+ }
+ if (!tie && currentState != highestState) {
+ editSession.setBlock(x0, y0, z0, highestState);
+ }
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/CopyBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/CopyBrush.java
deleted file mode 100644
index e47552b9..00000000
--- a/core/src/main/java/com/boydti/fawe/object/brush/CopyBrush.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.boydti.fawe.object.brush;
-
-import com.boydti.fawe.config.BBC;
-import com.boydti.fawe.object.clipboard.ResizableClipboardBuilder;
-import com.boydti.fawe.object.exception.FaweException;
-import com.boydti.fawe.object.function.NullRegionFunction;
-import com.boydti.fawe.object.function.mask.AbstractDelegateMask;
-import com.sk89q.worldedit.EditSession;
-import com.sk89q.worldedit.LocalSession;
-import com.sk89q.worldedit.MaxChangedBlocksException;
-import com.sk89q.worldedit.Vector;
-import com.sk89q.worldedit.blocks.BaseBlock;
-import com.sk89q.worldedit.command.tool.BrushTool;
-import com.sk89q.worldedit.command.tool.brush.Brush;
-import com.sk89q.worldedit.entity.Player;
-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.operation.Operations;
-import com.sk89q.worldedit.function.pattern.Pattern;
-import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
-import com.sk89q.worldedit.session.ClipboardHolder;
-
-public class CopyBrush implements Brush {
-
- private final BrushTool tool;
- private final LocalSession session;
- private final Player player;
-
- public CopyBrush(Player player, LocalSession session, BrushTool tool) {
- this.tool = tool;
- this.session = session;
- this.player = player;
- }
-
- @Override
- public void build(final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
- Mask mask = tool.getMask();
- if (mask == null) {
- mask = Masks.alwaysTrue();
- }
- final ResizableClipboardBuilder builder = new ResizableClipboardBuilder(editSession.getWorld());
- final int size2 = (int) (size * size);
- final int minY = position.getBlockY();
- mask = new AbstractDelegateMask(mask) {
- private int visited = 0;
- @Override
- public boolean test(Vector vector) {
- if (super.test(vector) && vector.getBlockY() >= minY) {
- BaseBlock block = editSession.getLazyBlock(vector);
- if (block != EditSession.nullBlock) {
- if (visited++ > size2) {
- throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
- }
- builder.add(vector, EditSession.nullBlock, block);
- return true;
- }
- }
- return false;
- }
- };
- // Add origin
- mask.test(position);
-
- RecursiveVisitor visitor = new RecursiveVisitor(mask, new NullRegionFunction());
- visitor.visit(position);
- Operations.completeBlindly(visitor);
- // Build the clipboard
- Clipboard clipboard = builder.build();
- clipboard.setOrigin(position);
- ClipboardHolder holder = new ClipboardHolder(clipboard, editSession.getWorld().getWorldData());
- session.setClipboard(holder);
- int blocks = builder.size();
- BBC.COMMAND_COPY.send(player, blocks);
- }
-}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java
new file mode 100644
index 00000000..9317ea73
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java
@@ -0,0 +1,98 @@
+package com.boydti.fawe.object.brush;
+
+import com.boydti.fawe.config.BBC;
+import com.boydti.fawe.object.clipboard.ResizableClipboardBuilder;
+import com.boydti.fawe.object.exception.FaweException;
+import com.boydti.fawe.object.function.NullRegionFunction;
+import com.boydti.fawe.object.function.mask.AbstractDelegateMask;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.EmptyClipboardException;
+import com.sk89q.worldedit.LocalSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.entity.Player;
+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.operation.Operation;
+import com.sk89q.worldedit.function.operation.Operations;
+import com.sk89q.worldedit.function.pattern.Pattern;
+import com.sk89q.worldedit.function.visitor.RecursiveVisitor;
+import com.sk89q.worldedit.regions.Region;
+import com.sk89q.worldedit.session.ClipboardHolder;
+
+public class CopyPastaBrush implements DoubleActionBrush {
+
+ private final DoubleActionBrushTool tool;
+ private final LocalSession session;
+ private final Player player;
+
+ public CopyPastaBrush(Player player, LocalSession session, DoubleActionBrushTool tool) {
+ this.tool = tool;
+ this.session = session;
+ this.player = player;
+ }
+
+ @Override
+ public void build(DoubleActionBrushTool.BrushAction action, final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
+ switch (action) {
+ case SECONDARY: {
+ Mask mask = tool.getMask();
+ if (mask == null) {
+ mask = Masks.alwaysTrue();
+ }
+ final ResizableClipboardBuilder builder = new ResizableClipboardBuilder(editSession.getWorld());
+ final int size2 = (int) (size * size);
+ final int minY = position.getBlockY();
+ mask = new AbstractDelegateMask(mask) {
+ private int visited = 0;
+
+ @Override
+ public boolean test(Vector vector) {
+ if (super.test(vector) && vector.getBlockY() >= minY) {
+ BaseBlock block = editSession.getLazyBlock(vector);
+ if (block != EditSession.nullBlock) {
+ if (visited++ > size2) {
+ throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS);
+ }
+ builder.add(vector, EditSession.nullBlock, block);
+ return true;
+ }
+ }
+ return false;
+ }
+ };
+ // Add origin
+ mask.test(position);
+ RecursiveVisitor visitor = new RecursiveVisitor(mask, new NullRegionFunction());
+ visitor.visit(position);
+ Operations.completeBlindly(visitor);
+ // Build the clipboard
+ Clipboard clipboard = builder.build();
+ clipboard.setOrigin(position);
+ ClipboardHolder holder = new ClipboardHolder(clipboard, editSession.getWorld().getWorldData());
+ session.setClipboard(holder);
+ int blocks = builder.size();
+ BBC.COMMAND_COPY.send(player, blocks);
+ return;
+ }
+ case PRIMARY: {
+ try {
+ ClipboardHolder holder = session.getClipboard();
+ Clipboard clipboard = holder.getClipboard();
+ Region region = clipboard.getRegion();
+ Vector centerOffset = region.getCenter().subtract(clipboard.getOrigin());
+ Operation operation = holder
+ .createPaste(editSession, editSession.getWorld().getWorldData())
+ .to(position.add(0, 1, 0))
+ .ignoreAirBlocks(true)
+ .build();
+ Operations.completeLegacy(operation);
+ } catch (EmptyClipboardException e) {
+ BBC.BRUSH_PASTE_NONE.send(player);
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java
new file mode 100644
index 00000000..ae3452bc
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java
@@ -0,0 +1,10 @@
+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.function.pattern.Pattern;
+
+public interface DoubleActionBrush {
+ public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException;
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java
new file mode 100644
index 00000000..c2aa8b02
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java
@@ -0,0 +1,194 @@
+package com.boydti.fawe.object.brush;
+
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.LocalConfiguration;
+import com.sk89q.worldedit.LocalSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.WorldVector;
+import com.sk89q.worldedit.command.tool.DoubleActionTraceTool;
+import com.sk89q.worldedit.entity.Player;
+import com.sk89q.worldedit.extension.platform.Actor;
+import com.sk89q.worldedit.extension.platform.Platform;
+import com.sk89q.worldedit.extent.inventory.BlockBag;
+import com.sk89q.worldedit.function.mask.Mask;
+import com.sk89q.worldedit.function.mask.MaskIntersection;
+import com.sk89q.worldedit.function.pattern.Pattern;
+import com.sk89q.worldedit.session.request.Request;
+import javax.annotation.Nullable;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public class DoubleActionBrushTool implements DoubleActionTraceTool {
+
+ public enum BrushAction {
+ PRIMARY,
+ SECONDARY
+ }
+
+ protected static int MAX_RANGE = 500;
+ protected int range = -1;
+ private Mask mask = null;
+ private DoubleActionBrush brush = null;
+ @Nullable
+ private Pattern material;
+ private double size = 1;
+ private String permission;
+
+ /**
+ * Construct the tool.
+ *
+ * @param permission the permission to check before use is allowed
+ */
+ public DoubleActionBrushTool(String permission) {
+ checkNotNull(permission);
+ this.permission = permission;
+ }
+
+ @Override
+ public boolean canUse(Actor player) {
+ return player.hasPermission(permission);
+ }
+
+ /**
+ * Get the filter.
+ *
+ * @return the filter
+ */
+ public Mask getMask() {
+ return mask;
+ }
+
+ /**
+ * Set the block filter used for identifying blocks to replace.
+ *
+ * @param filter the filter to set
+ */
+ public void setMask(Mask filter) {
+ this.mask = filter;
+ }
+
+ /**
+ * Set the brush.
+ *
+ * @param brush tbe brush
+ * @param permission the permission
+ */
+ public void setBrush(DoubleActionBrush brush, String permission) {
+ this.brush = brush;
+ this.permission = permission;
+ }
+
+ /**
+ * Get the current brush.
+ *
+ * @return the current brush
+ */
+ public DoubleActionBrush getBrush() {
+ return brush;
+ }
+
+ /**
+ * Set the material.
+ *
+ * @param material the material
+ */
+ public void setFill(@Nullable Pattern material) {
+ this.material = material;
+ }
+
+ /**
+ * Get the material.
+ *
+ * @return the material
+ */
+ @Nullable public Pattern getMaterial() {
+ return material;
+ }
+
+ /**
+ * Get the set brush size.
+ *
+ * @return a radius
+ */
+ public double getSize() {
+ return size;
+ }
+
+ /**
+ * Set the set brush size.
+ *
+ * @param radius a radius
+ */
+ public void setSize(double radius) {
+ this.size = radius;
+ }
+
+ /**
+ * Get the set brush range.
+ *
+ * @return the range of the brush in blocks
+ */
+ public int getRange() {
+ return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE);
+ }
+
+ /**
+ * Set the set brush range.
+ *
+ * @param range the range of the brush in blocks
+ */
+ public void setRange(int range) {
+ this.range = range;
+ }
+
+ public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) {
+ WorldVector target = null;
+ target = player.getBlockTrace(getRange(), true);
+
+ if (target == null) {
+ player.printError("No block in sight!");
+ return true;
+ }
+
+ BlockBag bag = session.getBlockBag(player);
+
+ EditSession editSession = session.createEditSession(player);
+ Request.request().setEditSession(editSession);
+ if (mask != null) {
+ Mask existingMask = editSession.getMask();
+
+ if (existingMask == null) {
+ editSession.setMask(mask);
+ } else if (existingMask instanceof MaskIntersection) {
+ ((MaskIntersection) existingMask).add(mask);
+ } else {
+ MaskIntersection newMask = new MaskIntersection(existingMask);
+ newMask.add(mask);
+ editSession.setMask(newMask);
+ }
+ }
+
+ try {
+ brush.build(action, editSession, target, material, size);
+ } catch (MaxChangedBlocksException e) {
+ player.printError("Max blocks change limit reached.");
+ } finally {
+ if (bag != null) {
+ bag.flushChanges();
+ }
+ session.remember(editSession);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
+ return act(BrushAction.PRIMARY, server, config, player, session);
+ }
+
+ @Override
+ public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
+ return act(BrushAction.SECONDARY, server, config, player, session);
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java
new file mode 100644
index 00000000..cd450ca4
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java
@@ -0,0 +1,178 @@
+package com.boydti.fawe.object.brush;
+
+import com.boydti.fawe.FaweCache;
+import com.boydti.fawe.object.PseudoRandom;
+import com.boydti.fawe.object.RunnableVal2;
+import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
+import com.boydti.fawe.object.clipboard.FaweClipboard;
+import com.boydti.fawe.object.clipboard.OffsetFaweClipboard;
+import com.google.common.collect.Maps;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.function.pattern.Pattern;
+import java.util.Map;
+
+public class ErodeBrush implements DoubleActionBrush {
+
+ private PseudoRandom rand = new PseudoRandom();
+
+ private static final Vector[] FACES_TO_CHECK = {new Vector(0, 0, 1), new Vector(0, 0, -1), new Vector(0, 1, 0), new Vector(0, -1, 0), new Vector(1, 0, 0), new Vector(-1, 0, 0)};
+
+ @Override
+ public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
+ switch (action) {
+ case PRIMARY: {
+ int erodeFaces = this.rand.nextInt(5) + 1;
+ int erodeRec = this.rand.nextInt(4) + 1;
+ int fillFaces = (int)(this.rand.nextDouble() * this.rand.nextDouble() * 5) + 1;
+ int fillRec = this.rand.nextInt(3) + 1;
+ this.erosion(editSession, erodeFaces, erodeRec, fillFaces, fillRec, position, size);
+ break;
+ }
+ case SECONDARY: {
+ int erodeFaces = (int)(this.rand.nextDouble() * this.rand.nextDouble() * 5) + 1;
+ int erodeRec = this.rand.nextInt(3) + 1;
+ int fillFaces = this.rand.nextInt(5) + 1;
+ int fillRec = this.rand.nextInt(4) + 1;
+ this.erosion(editSession, erodeFaces, erodeRec, fillFaces, fillRec, position, size);
+ break;
+ }
+ }
+ }
+
+ protected void erosion(final EditSession es, int erodeFaces, int erodeRec, int fillFaces, int fillRec, Vector target, double size) {
+ int brushSize = (int) size + 1;
+ int brushSizeSquared = (int) size * (int) size;
+ int dimension = brushSize * 2 + 1;
+ FaweClipboard buffer1 = new OffsetFaweClipboard(new CPUOptimizedClipboard(dimension + 2, dimension + 2, dimension + 2), brushSize + 1);
+ FaweClipboard buffer2 = new OffsetFaweClipboard(new CPUOptimizedClipboard(dimension + 2, dimension + 2, dimension + 2), brushSize + 1);
+
+ final int bx = target.getBlockX();
+ final int by = target.getBlockY();
+ final int bz = target.getBlockZ();
+
+ for (int x = -brushSize - 1; x <= brushSize + 1; x++) {
+ int x0 = x + bx;
+ for (int y = -brushSize - 1; y <= brushSize + 1; y++) {
+ int y0 = y + by;
+ for (int z = -brushSize - 1; z <= brushSize + 1; z++) {
+ int z0 = z + bz;
+ BaseBlock state = es.getBlock(x0, y0, z0);
+ buffer1.setBlock(x, y, z, state);
+ buffer2.setBlock(x, y, z, state);
+ }
+ }
+ }
+
+ int swap = 0;
+ for (int i = 0; i < erodeRec; ++i) {
+ erosionIteration(brushSize, brushSizeSquared, erodeFaces, swap % 2 == 0 ? buffer1 : buffer2, swap % 2 == 1 ? buffer1 : buffer2);
+ swap++;
+ }
+
+ for (int i = 0; i < fillRec; ++i) {
+ fillIteration(brushSize, brushSizeSquared, fillFaces, swap % 2 == 0 ? buffer1 : buffer2, swap % 2 == 1 ? buffer1 : buffer2);
+ swap++;
+ }
+ FaweClipboard finalBuffer = swap % 2 == 0 ? buffer1 : buffer2;
+
+ finalBuffer.forEach(new RunnableVal2() {
+ @Override
+ public void run(Vector pos, BaseBlock block) {
+ es.setBlock(pos.getBlockX() + bx, pos.getBlockY() + by, pos.getBlockZ() + bz, block);
+ }
+ }, true);
+ }
+
+ private void fillIteration(int brushSize, int brushSizeSquared, int fillFaces, FaweClipboard current, FaweClipboard target) {
+ Map frequency = Maps.newHashMap();
+ for (int x = -brushSize; x <= brushSize; x++) {
+ for (int y = -brushSize; y <= brushSize; y++) {
+ for (int z = -brushSize; z <= brushSize; z++) {
+ target.setBlock(x, y, z, current.getBlock(x, y, z));
+ if (x * x + y * y + z * z >= brushSizeSquared) {
+ continue;
+ }
+ BaseBlock state = current.getBlock(x, y, z);
+ if (!FaweCache.isLiquidOrGas(state.getId())) {
+ continue;
+ }
+ int total = 0;
+ int highest = 1;
+ BaseBlock highestState = state;
+ frequency.clear();
+ for (Vector offs : FACES_TO_CHECK) {
+ BaseBlock next = current.getBlock(x + offs.getBlockX(), y + offs.getBlockY(), z + offs.getBlockZ());
+ if (FaweCache.isLiquidOrGas(next.getId())) {
+ continue;
+ }
+ total++;
+ Integer count = frequency.get(next);
+ if (count == null) {
+ count = 1;
+ } else {
+ count++;
+ }
+ if (count > highest) {
+ highest = count;
+ highestState = next;
+ }
+ frequency.put(next, count);
+ }
+ if (total > fillFaces) {
+ target.setBlock(x, y, z, highestState);
+ }
+ }
+ }
+ }
+ }
+
+ private void erosionIteration(int brushSize, int brushSizeSquared, int erodeFaces, FaweClipboard current, FaweClipboard target) {
+ Map frequency = Maps.newHashMap();
+
+ for (int x = -brushSize; x <= brushSize; x++) {
+ for (int y = -brushSize; y <= brushSize; y++) {
+ for (int z = -brushSize; z <= brushSize; z++) {
+ target.setBlock(x, y, z, current.getBlock(x, y, z));
+ if (x * x + y * y + z * z >= brushSizeSquared) {
+ continue;
+ }
+ BaseBlock state = current.getBlock(x, y, z);
+ if (FaweCache.isLiquidOrGas(state.getId())) {
+ continue;
+ }
+ int total = 0;
+ int highest = 1;
+ int highestState = FaweCache.getCombined(state);
+ frequency.clear();
+ for (Vector offs : FACES_TO_CHECK) {
+ BaseBlock next = current.getBlock(x + offs.getBlockX(), y + offs.getBlockY(), z + offs.getBlockZ());
+ if (!FaweCache.isLiquidOrGas(next.getId())) {
+ continue;
+ }
+ total++;
+ Integer count = frequency.get(next.getType());
+ if (count == null) {
+ count = 1;
+ } else {
+ count++;
+ }
+ if (count > highest) {
+ highest = count;
+ int combined = FaweCache.getCombined(next);
+ highestState = combined;
+ frequency.put(combined, count);
+ } else {
+ frequency.put(FaweCache.getCombined(next), count);
+ }
+ }
+ if (total > erodeFaces) {
+ target.setBlock(x, y, z, FaweCache.CACHE_BLOCK[highestState]);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java
new file mode 100644
index 00000000..177b9aa0
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java
@@ -0,0 +1,38 @@
+package com.boydti.fawe.object.brush;
+
+import com.boydti.fawe.config.BBC;
+import com.sk89q.worldedit.EditSession;
+import com.sk89q.worldedit.MaxChangedBlocksException;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.function.pattern.Pattern;
+import com.sk89q.worldedit.function.pattern.Patterns;
+
+public class LineBrush implements DoubleActionBrush {
+
+ private final boolean shell, select, flat;
+ private Vector pos1;
+
+ public LineBrush(boolean shell, boolean select, boolean flat) {
+ this.shell = shell;
+ this.select = select;
+ this.flat = flat;
+ }
+
+ @Override
+ public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException {
+ switch (action) {
+ case PRIMARY:
+ if (pos1 == null) {
+ editSession.debug(BBC.SELECTION_NONE);
+ return;
+ }
+ editSession.drawLine(Patterns.wrap(pattern), pos1, position, size, !shell, flat);
+ if (!select) {
+ return;
+ }
+ case SECONDARY:
+ pos1 = position;
+ return;
+ }
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/brush/heightmap/ScalableHeightMap.java b/core/src/main/java/com/boydti/fawe/object/brush/heightmap/ScalableHeightMap.java
index d834a043..d6cff00b 100644
--- a/core/src/main/java/com/boydti/fawe/object/brush/heightmap/ScalableHeightMap.java
+++ b/core/src/main/java/com/boydti/fawe/object/brush/heightmap/ScalableHeightMap.java
@@ -103,6 +103,8 @@ public class ScalableHeightMap {
}
public void apply(EditSession session, Mask mask, Vector pos, int size, int rotationMode, double yscale, boolean smooth) throws MaxChangedBlocksException {
+ Vector top = session.getMaximumPoint();
+ int maxY = top.getBlockY();
int diameter = 2 * size + 1;
int centerX = pos.getBlockX();
int centerZ = pos.getBlockZ();
@@ -132,20 +134,19 @@ public class ScalableHeightMap {
break;
}
raise = (yscale * raise);
- int random = PseudoRandom.random.random(256) < (int) ((raise - (int) raise) * 256) ? 1 : 0;
- int height = session.getHighestTerrainBlock(xx, zz, 0, 255, true) + (int) raise + random;
+ 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;
- WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, 255, size));
- Vector max = pos.add(size, 255, size);
+ WorldVector min = new WorldVector(LocalWorldAdapter.adapt(session.getWorld()), pos.subtract(size, maxY, size));
+ Vector max = pos.add(size, maxY, size);
Region region = new CuboidRegion(session.getWorld(), min, max);
HeightMap heightMap = new HeightMap(session, region, true);
if (smooth) {
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1));
newData = filter.filter(newData, diameter, diameter);
-// MainUtil.smoothArray(newData, diameter, 1, 4);
}
heightMap.apply(newData);
}
diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java
new file mode 100644
index 00000000..44d27953
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java
@@ -0,0 +1,83 @@
+package com.boydti.fawe.object.clipboard;
+
+import com.boydti.fawe.object.RunnableVal2;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+import com.sk89q.worldedit.entity.BaseEntity;
+import com.sk89q.worldedit.entity.Entity;
+import com.sk89q.worldedit.extent.Extent;
+import java.util.List;
+
+public class AbstractDelegateFaweClipboard extends FaweClipboard {
+ private final FaweClipboard parent;
+
+ public AbstractDelegateFaweClipboard(FaweClipboard parent) {
+ this.parent = parent;
+ }
+
+ @Override
+ public BaseBlock getBlock(int x, int y, int z) {
+ return parent.getBlock(x, y, z);
+ }
+
+ @Override
+ public boolean setBlock(int x, int y, int z, BaseBlock block) {
+ return parent.setBlock(x, y, z, block);
+ }
+
+ @Override
+ public void setId(int index, int id) {
+ parent.setId(index, id);
+ }
+
+ @Override
+ public void setData(int index, int data) {
+ parent.setData(index, data);
+ }
+
+ @Override
+ public void setAdd(int index, int id) {
+ parent.setAdd(index, id);
+ }
+
+ @Override
+ public boolean setTile(int x, int y, int z, CompoundTag tag) {
+ return parent.setTile(x, y, z, tag);
+ }
+
+ @Override
+ public Entity createEntity(Extent world, double x, double y, double z, float yaw, float pitch, BaseEntity entity) {
+ return parent.createEntity(world, x, y, z, yaw, pitch, entity);
+ }
+
+ @Override
+ public List extends Entity> getEntities() {
+ return parent.getEntities();
+ }
+
+ @Override
+ public boolean remove(ClipboardEntity clipboardEntity) {
+ return parent.remove(clipboardEntity);
+ }
+
+ @Override
+ public void setOrigin(Vector offset) {
+ parent.setOrigin(offset);
+ }
+
+ @Override
+ public void setDimensions(Vector dimensions) {
+ parent.setDimensions(dimensions);
+ }
+
+ @Override
+ public Vector getDimensions() {
+ return parent.getDimensions();
+ }
+
+ @Override
+ public void forEach(RunnableVal2 task, boolean air) {
+ parent.forEach(task, air);
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java
new file mode 100644
index 00000000..06d0de3f
--- /dev/null
+++ b/core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java
@@ -0,0 +1,49 @@
+package com.boydti.fawe.object.clipboard;
+
+import com.boydti.fawe.object.RunnableVal2;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+
+public class OffsetFaweClipboard extends AbstractDelegateFaweClipboard {
+ private final int ox, oy, oz;
+
+ public OffsetFaweClipboard(FaweClipboard parent, int ox, int oy, int oz) {
+ super(parent);
+ this.ox = ox;
+ this.oy = oy;
+ this.oz = oz;
+ }
+
+ public OffsetFaweClipboard(FaweClipboard parent, int offset) {
+ this(parent, offset, offset, offset);
+ }
+
+ @Override
+ public BaseBlock getBlock(int x, int y, int z) {
+ return super.getBlock(x + ox, y + oy, z + oz);
+ }
+
+ @Override
+ public boolean setBlock(int x, int y, int z, BaseBlock block) {
+ return super.setBlock(ox + x, oy + y, oz + z, block);
+ }
+
+ @Override
+ public boolean setTile(int x, int y, int z, CompoundTag tag) {
+ return super.setTile(ox + x, oy + y, oz + z, tag);
+ }
+
+ @Override
+ public void forEach(final RunnableVal2 task, boolean air) {
+ super.forEach(new RunnableVal2() {
+ @Override
+ public void run(Vector value, BaseBlock block) {
+ value.x -= ox;
+ value.y -= oy;
+ value.z -= oz;
+ task.run(value, block);
+ }
+ }, air);
+ }
+}
diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java
index abfaa449..fb65fbea 100644
--- a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java
+++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweLocalBlockQueue.java
@@ -1,5 +1,6 @@
package com.boydti.fawe.regions.general.plot;
+import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.FaweQueue;
@@ -16,11 +17,15 @@ import java.util.List;
public class FaweLocalBlockQueue extends LocalBlockQueue {
- private FaweQueue IMP;
-
+ public final FaweQueue IMP;
public FaweLocalBlockQueue(String world) {
super(world);
+ IMP = SetQueue.IMP.getNewQueue(FaweAPI.getWorld(world), true, false);
+ }
+
+ public FaweLocalBlockQueue(World world) {
+ super(Fawe.imp().getWorldName(world));
IMP = SetQueue.IMP.getNewQueue(world, true, false);
}
@@ -78,7 +83,7 @@ public class FaweLocalBlockQueue extends LocalBlockQueue {
public boolean setBiome(int x, int z, String biome) {
if (!StringMan.isEqual(biome, lastBiome)) {
if (reg == null) {
- World weWorld = FaweAPI.getWorld(IMP.getWorldName());
+ World weWorld = IMP.getWEWorld();
reg = weWorld.getWorldData().getBiomeRegistry();
}
List biomes = reg.getBiomes();
diff --git a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
index d2925dd2..c3f4646b 100644
--- a/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
+++ b/core/src/main/java/com/boydti/fawe/regions/general/plot/FaweSchematicHandler.java
@@ -44,7 +44,7 @@ public class FaweSchematicHandler extends SchematicHandler {
queue.setTile(x, y, z, compoundTag);
return true;
}
- FaweQueue faweQueue = SetQueue.IMP.getNewQueue(queue.getWorld(), true, false);
+ FaweQueue faweQueue = SetQueue.IMP.getNewQueue(((FaweLocalBlockQueue) queue).IMP.getWEWorld(), true, false);
faweQueue.setTile(x, y, z, (com.sk89q.jnbt.CompoundTag) FaweCache.asTag(compoundTag));
faweQueue.flush();
return false;
diff --git a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java
index 89f6a5b3..1b1aa7b4 100644
--- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java
+++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java
@@ -17,7 +17,7 @@ public class DelegateFaweQueue extends FaweQueue {
private FaweQueue parent;
public DelegateFaweQueue(FaweQueue parent) {
- super(parent.getWorldName());
+ super(parent.getWEWorld());
this.parent = parent;
}
diff --git a/core/src/main/java/com/boydti/fawe/util/SetQueue.java b/core/src/main/java/com/boydti/fawe/util/SetQueue.java
index 44630d20..be02f7b7 100644
--- a/core/src/main/java/com/boydti/fawe/util/SetQueue.java
+++ b/core/src/main/java/com/boydti/fawe/util/SetQueue.java
@@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweQueue;
import com.boydti.fawe.object.RunnableVal2;
+import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
@@ -172,7 +173,7 @@ public class SetQueue {
return inactiveQueues;
}
- public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) {
+ public FaweQueue getNewQueue(World world, boolean fast, boolean autoqueue) {
FaweQueue queue = Fawe.imp().getNewQueue(world, fast);
if (autoqueue) {
inactiveQueues.add(queue);
diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java
index db13833b..3aa088c9 100644
--- a/core/src/main/java/com/sk89q/worldedit/EditSession.java
+++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java
@@ -169,6 +169,8 @@ public class EditSession implements Extent {
private Vector mutable = new Vector();
+ private final int maxY;
+
public static final UUID CONSOLE = UUID.fromString("1-1-3-3-7");
public static final BaseBiome nullBiome = new BaseBiome(0);
public static final BaseBlock nullBlock = FaweCache.CACHE_BLOCK[0];
@@ -253,7 +255,7 @@ public class EditSession implements Extent {
if (world instanceof MCAWorld) {
queue = ((MCAWorld) world).getQueue();
} else {
- queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), fastmode, autoQueue);
+ queue = SetQueue.IMP.getNewQueue(world, fastmode, autoQueue);
}
} else if (Settings.EXPERIMENTAL.ANVIL_QUEUE_MODE && !(queue instanceof MCAQueue)) {
queue = new MCAQueue(queue);
@@ -281,6 +283,7 @@ public class EditSession implements Extent {
}
}
this.extent = wrapExtent(this.extent, bus, event, Stage.BEFORE_HISTORY);
+ this.maxY = this.world == null ? 255 : world.getMaxY();
}
/**
@@ -709,9 +712,13 @@ public class EditSession implements Extent {
return extent.getLazyBlock(x, y, z);
}
+ public BaseBlock getBlock(int x, int y, int z) {
+ return extent.getLazyBlock(x, y, z);
+ }
+
@Override
public BaseBlock getBlock(final Vector position) {
- if (position.y > 255 || position.y < 0) {
+ if (position.y > maxY || position.y < 0) {
return nullBlock;
}
return getLazyBlock((int) position.x, (int) position.y, (int) position.z);
@@ -1887,8 +1894,8 @@ public class EditSession implements Extent {
if (pos.getBlockY() < 0) {
pos = pos.setY(0);
- } else if (((pos.getBlockY() + height) - 1) > 255) {
- height = (255 - pos.getBlockY()) + 1;
+ } else if (((pos.getBlockY() + height) - 1) > maxY) {
+ height = (maxY - pos.getBlockY()) + 1;
}
final double invRadiusX = 1 / radiusX;
@@ -2074,7 +2081,7 @@ public class EditSession implements Extent {
if (dx2 + dz2 > radiusSq) {
continue;
}
- for (int y = 255; y >= 1; --y) {
+ for (int y = maxY; y >= 1; --y) {
final int id = FaweCache.getId(queue.getCombinedId4Data(x, y, z));
switch (id) {
case BlockID.ICE:
@@ -2126,7 +2133,7 @@ public class EditSession implements Extent {
if (dx2 + dz2 > radiusSq) {
continue;
}
- for (int y = 255; y >= 1; --y) {
+ for (int y = maxY; y >= 1; --y) {
final int id = FaweCache.getId(queue.getCombinedId4Data(x, y, z));
if (id == BlockID.AIR) {
continue;
@@ -2143,7 +2150,7 @@ public class EditSession implements Extent {
}
// Too high?
- if (y == 255) {
+ if (y == maxY) {
break;
}
@@ -2200,7 +2207,7 @@ public class EditSession implements Extent {
if (dx2 + dz2 > radiusSq) {
continue;
}
- loop: for (int y = 255; y >= 1; --y) {
+ loop: for (int y = maxY; y >= 1; --y) {
BaseBlock block = getLazyBlock(x, y, z);
final int id = block.getId();
final int data = block.getData();
@@ -2544,6 +2551,10 @@ public class EditSession implements Extent {
return changes;
}
+ public int drawLine(final Pattern pattern, final Vector pos1, final Vector pos2, final double radius, final boolean filled) throws MaxChangedBlocksException {
+ return drawLine(pattern, pos1, pos2, radius, filled, false);
+ }
+
/**
* Draws a line (out of blocks) between two vectors.
*
@@ -2556,7 +2567,7 @@ public class EditSession implements Extent {
* @return number of blocks affected
* @throws MaxChangedBlocksException thrown if too many blocks are changed
*/
- public int drawLine(final Pattern pattern, final Vector pos1, final Vector pos2, final double radius, final boolean filled) throws MaxChangedBlocksException {
+ public int drawLine(final Pattern pattern, final Vector pos1, final Vector pos2, final double radius, final boolean filled, boolean flat) throws MaxChangedBlocksException {
Set vset = new HashSet();
boolean notdrawn = true;
@@ -2576,7 +2587,6 @@ public class EditSession implements Extent {
tipx = x1 + (domstep * ((x2 - x1) > 0 ? 1 : -1));
tipy = (int) Math.round(y1 + (((domstep * ((double) dy)) / (dx)) * ((y2 - y1) > 0 ? 1 : -1)));
tipz = (int) Math.round(z1 + (((domstep * ((double) dz)) / (dx)) * ((z2 - z1) > 0 ? 1 : -1)));
-
vset.add(new Vector(tipx, tipy, tipz));
}
notdrawn = false;
@@ -2598,14 +2608,19 @@ public class EditSession implements Extent {
tipz = z1 + (domstep * ((z2 - z1) > 0 ? 1 : -1));
tipy = (int) Math.round(y1 + (((domstep * ((double) dy)) / (dz)) * ((y2 - y1) > 0 ? 1 : -1)));
tipx = (int) Math.round(x1 + (((domstep * ((double) dx)) / (dz)) * ((x2 - x1) > 0 ? 1 : -1)));
-
vset.add(new Vector(tipx, tipy, tipz));
}
}
-
- vset = this.getBallooned(vset, radius);
- if (!filled) {
- vset = this.getHollowed(vset);
+ if (flat) {
+ vset = this.getStretched(vset, radius);
+ if (!filled) {
+ vset = this.getOutline(vset);
+ }
+ } else {
+ vset = this.getBallooned(vset, radius);
+ if (!filled) {
+ vset = this.getHollowed(vset);
+ }
}
return this.setBlocks(vset, pattern);
}
@@ -2673,7 +2688,6 @@ public class EditSession implements Extent {
for (final Vector v : vset) {
final int tipx = v.getBlockX(), tipy = v.getBlockY(), tipz = v.getBlockZ();
-
for (int loopx = tipx - ceilrad; loopx <= (tipx + ceilrad); loopx++) {
for (int loopy = tipy - ceilrad; loopy <= (tipy + ceilrad); loopy++) {
for (int loopz = tipz - ceilrad; loopz <= (tipz + ceilrad); loopz++) {
@@ -2687,6 +2701,35 @@ public class EditSession implements Extent {
return returnset;
}
+ private Set getStretched(final Set vset, final double radius) {
+ final Set returnset = new HashSet();
+ final int ceilrad = (int) Math.ceil(radius);
+ for (final Vector v : vset) {
+ final int tipx = v.getBlockX(), tipy = v.getBlockY(), tipz = v.getBlockZ();
+ for (int loopx = tipx - ceilrad; loopx <= (tipx + ceilrad); loopx++) {
+ for (int loopz = tipz - ceilrad; loopz <= (tipz + ceilrad); loopz++) {
+ if (this.hypot(loopx - tipx, 0, loopz - tipz) <= radius) {
+ returnset.add(new Vector(loopx, v.getY(), loopz));
+ }
+ }
+ }
+ }
+ return returnset;
+ }
+
+ private Set getOutline(final Set vset) {
+ final Set returnset = new HashSet();
+ for (final Vector v : vset) {
+ final double x = v.getX(), y = v.getY(), z = v.getZ();
+ if (!(vset.contains(new Vector(x + 1, y, z))
+ && vset.contains(new Vector(x - 1, y, z))
+ && vset.contains(new Vector(x, y, z + 1)) && vset.contains(new Vector(x, y, z - 1)))) {
+ returnset.add(v);
+ }
+ }
+ return returnset;
+ }
+
private Set getHollowed(final Set vset) {
final Set returnset = new HashSet();
for (final Vector v : vset) {
diff --git a/core/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java
index 6e67d41f..ec30a755 100644
--- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java
+++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java
@@ -25,6 +25,7 @@ import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal2;
+import com.boydti.fawe.object.brush.DoubleActionBrushTool;
import com.boydti.fawe.object.changeset.DiskStorageHistory;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
@@ -935,6 +936,26 @@ public class LocalSession {
return (BrushTool) tool;
}
+ /**
+ * Get the brush tool assigned to the item. If there is no tool assigned
+ * or the tool is not assigned, the slot will be replaced with the
+ * brush tool.
+ *
+ * @param item the item type ID
+ * @return the tool, or {@code null}
+ * @throws InvalidToolBindException if the item can't be bound to that item
+ */
+ public DoubleActionBrushTool getDoubleActionBrushTool(int item) throws InvalidToolBindException {
+ Tool tool = getTool(item);
+
+ if (tool == null || !(tool instanceof DoubleActionBrushTool)) {
+ tool = new DoubleActionBrushTool("worldedit.brush.sphere");
+ setTool(item, tool);
+ }
+
+ return (DoubleActionBrushTool) tool;
+ }
+
/**
* Set the tool.
*
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
index ac7d75ea..1020fd74 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
@@ -25,8 +25,12 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.CommandBrush;
-import com.boydti.fawe.object.brush.CopyBrush;
+import com.boydti.fawe.object.brush.CopyPastaBrush;
import com.boydti.fawe.object.brush.HeightBrush;
+import com.boydti.fawe.object.brush.BlendBall;
+import com.boydti.fawe.object.brush.DoubleActionBrushTool;
+import com.boydti.fawe.object.brush.ErodeBrush;
+import com.boydti.fawe.object.brush.LineBrush;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@@ -79,6 +83,63 @@ public class BrushCommands {
this.worldEdit = worldEdit;
}
+ @Command(
+ aliases = { "blendball", "bb" },
+ usage = "[radius]",
+ desc = "Choose the blend ball brush",
+ help = "Chooses the blend ball brush",
+ min = 0,
+ max = 1
+ )
+ @CommandPermissions("worldedit.brush.blendball")
+ public void blendBallBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
+ worldEdit.checkMaxBrushRadius(radius);
+ BrushTool tool = session.getBrushTool(player.getItemInHand());
+ tool.setSize(radius);
+ tool.setBrush(new BlendBall(), "worldedit.brush.blendball");
+ BBC.BRUSH_SPHERE.send(player, radius);
+ }
+
+ @Command(
+ aliases = { "erode", "e" },
+ usage = "[radius]",
+ desc = "Choose the erode brush",
+ help = "Chooses the erode brush",
+ min = 0,
+ max = 1
+ )
+ @CommandPermissions("worldedit.brush.erode")
+ public void erodeBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
+ worldEdit.checkMaxBrushRadius(radius);
+ DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
+ tool.setSize(radius);
+ tool.setBrush(new ErodeBrush(), "worldedit.brush.erode");
+ BBC.BRUSH_SPHERE.send(player, radius);
+ }
+
+ @Command(
+ aliases = { "line", "l" },
+ usage = " [radius]",
+ flags = "hsf",
+ desc = "Choose the line brush",
+ help =
+ "Chooses the line brush.\n" +
+ "The -h flag creates only a shell\n" +
+ "The -s flag selects the clicked point after drawing\n" +
+ "The -f flag creates a flat line",
+ min = 1,
+ max = 2
+ )
+ @CommandPermissions("worldedit.brush.line")
+ public void lineBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat) throws WorldEditException {
+ worldEdit.checkMaxBrushRadius(radius);
+ DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
+ tool.setFill(fill);
+ tool.setSize(radius);
+ tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line");
+ BBC.BRUSH_SPHERE.send(player, radius);
+ }
+
@Command(
aliases = { "sphere", "s" },
usage = " [radius]",
@@ -258,20 +319,21 @@ public class BrushCommands {
}
@Command(
- aliases = { "copy" },
+ aliases = { "copypaste", "copy", "paste", "cp", "copypasta" },
usage = "[depth]",
- desc = "Copy brush",
+ desc = "Copy Paste brush",
help =
- "Right click the base of an object to copy.\n",
+ "Left click the base of an object to copy.\n" +
+ "Right click to paste",
min = 0,
max = 1
)
@CommandPermissions("worldedit.brush.copy")
public void copy(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player.getItemInHand());
+ DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand());
tool.setSize(radius);
- tool.setBrush(new CopyBrush(player, session, tool), "worldedit.brush.copy");
+ tool.setBrush(new CopyPastaBrush(player, session, tool), "worldedit.brush.copy");
BBC.BRUSH_COPY.send(player, radius);
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 7b75cc4c..16bb3afa 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -145,7 +145,7 @@ public class RegionCommands {
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
- final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getLocation().world, true, false);
+ final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getWorld(), true, false);
for (Vector pt : region) {
queue.setBlockLight((byte) pt.x, (byte) pt.y, (byte) pt.z, value);
}
@@ -169,7 +169,7 @@ public class RegionCommands {
final FaweLocation loc = fp.getLocation();
final int cx = loc.x >> 4;
final int cz = loc.z >> 4;
- final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getLocation().world, true, false);
+ final NMSMappedFaweQueue queue = (NMSMappedFaweQueue) SetQueue.IMP.getNewQueue(fp.getWorld(), true, false);
for (Vector pt : region) {
queue.setSkyLight((byte) pt.x, (byte) pt.y, (byte) pt.z, value);
}
diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java
new file mode 100644
index 00000000..36ea51db
--- /dev/null
+++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java
@@ -0,0 +1,61 @@
+package com.sk89q.worldedit.function.pattern;
+
+import com.sk89q.worldedit.Vector;
+import com.sk89q.worldedit.blocks.BaseBlock;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Utility methods related to {@link Pattern}s.
+ */
+public final class Patterns {
+
+ private Patterns() {
+ }
+
+ /**
+ * Wrap an old-style pattern and return a new pattern.
+ *
+ * @param pattern the pattern
+ * @return a new-style pattern
+ */
+ public static Pattern wrap(final com.sk89q.worldedit.patterns.Pattern pattern) {
+ checkNotNull(pattern);
+ return new Pattern() {
+ @Override
+ public BaseBlock apply(Vector position) {
+ return pattern.next(position);
+ }
+ };
+ }
+
+ /**
+ * Wrap a new-style pattern and return an old-style pattern.
+ *
+ * @param pattern the pattern
+ * @return an old-style pattern
+ */
+ public static com.sk89q.worldedit.patterns.Pattern wrap(final Pattern pattern) {
+ checkNotNull(pattern);
+ return new com.sk89q.worldedit.patterns.Pattern() {
+ private Vector mutable = new Vector(0, 0, 0);
+ @Override
+ public BaseBlock next(Vector position) {
+ return pattern.apply(position);
+ }
+
+ @Override
+ public BaseBlock next(int x, int y, int z) {
+ mutable.x = x;
+ mutable.y = y;
+ mutable.z = z;
+ return next(mutable);
+ }
+ };
+ }
+
+ public static Class> inject() {
+ return Patterns.class;
+ }
+
+}
diff --git a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java
index 1f0d7452..aa3a6675 100644
--- a/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java
+++ b/forge110/src/main/java/com/boydti/fawe/forge/v0/ForgeQueue_All.java
@@ -60,7 +60,7 @@ public class ForgeQueue_All extends NMSMappedFaweQueue