From 71071998c64c0d7edfb2775791a205fffb3a44d8 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Fri, 9 Sep 2016 03:41:03 +1000 Subject: [PATCH] Various nukkit fixes add new brushes some other minor stuff --- .../com/boydti/fawe/bukkit/ABukkitMain.java | 3 +- .../com/boydti/fawe/bukkit/FaweBukkit.java | 2 +- .../boydti/fawe/bukkit/v0/BukkitQueue_0.java | 2 +- .../fawe/bukkit/v0/BukkitQueue_All.java | 2 +- .../fawe/bukkit/wrapper/AsyncWorld.java | 4 +- .../fawe/bukkit/v1_10/BukkitMain_110.java | 3 +- .../fawe/bukkit/v1_10/BukkitQueue_1_10.java | 2 +- .../fawe/bukkit/v1_7/BukkitMain_17.java | 3 +- .../fawe/bukkit/v1_7/BukkitQueue17.java | 2 +- .../fawe/bukkit/v1_8/BukkitMain_18.java | 3 +- .../fawe/bukkit/v1_8/BukkitQueue18R3.java | 2 +- .../fawe/bukkit/v1_9/BukkitMain_19.java | 3 +- .../fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java | 2 +- core/src/main/java/com/boydti/fawe/Fawe.java | 3 + .../main/java/com/boydti/fawe/FaweAPI.java | 50 ++--- .../main/java/com/boydti/fawe/FaweCache.java | 13 ++ core/src/main/java/com/boydti/fawe/IFawe.java | 2 +- .../main/java/com/boydti/fawe/config/BBC.java | 5 + .../boydti/fawe/example/MappedFaweQueue.java | 5 +- .../fawe/example/NMSMappedFaweQueue.java | 15 +- .../com/boydti/fawe/example/NMSRelighter.java | 16 +- .../com/boydti/fawe/jnbt/anvil/MCAQueue.java | 4 +- .../com/boydti/fawe/object/FawePlayer.java | 7 +- .../com/boydti/fawe/object/FaweQueue.java | 19 +- .../com/boydti/fawe/object/PseudoRandom.java | 11 + .../boydti/fawe/object/brush/BlendBall.java | 74 +++++++ .../boydti/fawe/object/brush/CopyBrush.java | 76 ------- .../fawe/object/brush/CopyPastaBrush.java | 98 +++++++++ .../fawe/object/brush/DoubleActionBrush.java | 10 + .../object/brush/DoubleActionBrushTool.java | 194 ++++++++++++++++++ .../boydti/fawe/object/brush/ErodeBrush.java | 178 ++++++++++++++++ .../boydti/fawe/object/brush/LineBrush.java | 38 ++++ .../brush/heightmap/ScalableHeightMap.java | 11 +- .../AbstractDelegateFaweClipboard.java | 83 ++++++++ .../object/clipboard/OffsetFaweClipboard.java | 49 +++++ .../general/plot/FaweLocalBlockQueue.java | 11 +- .../general/plot/FaweSchematicHandler.java | 2 +- .../boydti/fawe/util/DelegateFaweQueue.java | 2 +- .../java/com/boydti/fawe/util/SetQueue.java | 3 +- .../java/com/sk89q/worldedit/EditSession.java | 75 +++++-- .../com/sk89q/worldedit/LocalSession.java | 21 ++ .../worldedit/command/BrushCommands.java | 74 ++++++- .../worldedit/command/RegionCommands.java | 4 +- .../worldedit/function/pattern/Patterns.java | 61 ++++++ .../boydti/fawe/forge/v0/ForgeQueue_All.java | 2 +- .../boydti/fawe/forge/v0/ForgeQueue_All.java | 2 +- .../boydti/fawe/forge/v0/ForgeQueue_All.java | 2 +- .../boydti/fawe/forge/v0/ForgeQueue_All.java | 2 +- .../nukkit/core/NukkitRegistryDumper.java | 1 - .../fawe/nukkit/optimization/FaweNukkit.java | 2 +- .../optimization/queue/NukkitQueue.java | 5 +- 51 files changed, 1077 insertions(+), 186 deletions(-) create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/BlendBall.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/brush/CopyBrush.java create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java create mode 100644 core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java create mode 100644 core/src/main/java/com/boydti/fawe/object/clipboard/AbstractDelegateFaweClipboard.java create mode 100644 core/src/main/java/com/boydti/fawe/object/clipboard/OffsetFaweClipboard.java create mode 100644 core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java 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 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