diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 3361dc3a..5daf09a6 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -569,6 +569,15 @@ public class FaweBukkit implements IFawe, Listener { } } + if (Settings.IMP.EXPERIMENTAL.FREEBUILD) { + try { + managers.add(new FreeBuildRegion()); + Fawe.debug("Plugin '' found. Using it now."); + } catch (final Throwable e) { + MainUtil.handleError(e); + } + } + return managers; } // diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FreeBuildRegion.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FreeBuildRegion.java new file mode 100644 index 00000000..265ca040 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/regions/FreeBuildRegion.java @@ -0,0 +1,110 @@ +package com.boydti.fawe.bukkit.regions; + +import com.boydti.fawe.bukkit.wrapper.AsyncBlock; +import com.boydti.fawe.bukkit.wrapper.AsyncWorld; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.queue.NullFaweQueue; +import com.boydti.fawe.regions.FaweMask; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.bukkit.BukkitUtil; +import com.sk89q.worldedit.regions.CuboidRegion; +import com.sk89q.worldedit.regions.Region; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.EventException; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.plugin.RegisteredListener; + +import java.util.ArrayList; + +public class FreeBuildRegion extends BukkitMaskManager { + private final ArrayList listeners; + + public FreeBuildRegion() { + super("freebuild"); + this.listeners = new ArrayList<>(); + RegisteredListener[] listeners = BlockBreakEvent.getHandlerList().getRegisteredListeners(); + for (RegisteredListener listener : listeners) { + if (listener.getPriority() == EventPriority.MONITOR) continue; + if (!listener.isIgnoringCancelled()) continue; + this.listeners.add(listener); + } + } + + @Override + public boolean isExclusive() { + return true; + } + + @Override + public FaweMask getMask(FawePlayer player, MaskType type) { + if (type != MaskType.MEMBER) return null; + ArrayList currRegList = new ArrayList<>(); + for (RegisteredListener listener : this.listeners) { + String name = listener.getPlugin().getName(); + if (!player.hasPermission("fawe.freebuild." + name.toLowerCase())) continue; + currRegList.add(listener); + } + if (currRegList.isEmpty()) return null; + RegisteredListener[] listeners = currRegList.toArray(new RegisteredListener[currRegList.size()]); + + World bukkitWorld = player.parent.getWorld(); + AsyncWorld asyncWorld = AsyncWorld.wrap(bukkitWorld); + + Vector vec1 = new Vector(0, 0, 0); + Vector vec2 = vec1; + Location pos1 = BukkitUtil.toLocation(bukkitWorld, vec1); + Location pos2 = BukkitUtil.toLocation(bukkitWorld, vec2); + + AsyncBlock block = new AsyncBlock(asyncWorld, new NullFaweQueue(asyncWorld.getWorldName()), 0, 0, 0); + BlockBreakEvent event = new BlockBreakEvent(block, player.parent); + + return new BukkitMask(pos1, pos2) { + @Override + public String getName() { + return "freebuild-global"; + } + + @Override + public boolean isValid(FawePlayer player, MaskType type) { + return bukkitWorld == ((FawePlayer)player).parent.getWorld() && type == MaskType.MEMBER; + } + + @Override + public Region getRegion() { + return new CuboidRegion(vec1, vec2) { + + @Override + public boolean contains(int x, int z) { + return contains(x, 127, z); + } + + private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE; + private boolean lastResult; + + @Override + public boolean contains(int x, int y, int z) { + if (x == lastX && z == lastZ) return lastResult; + lastX = x; + lastZ = z; + event.setCancelled(false); + block.setPosition(x, y, z); + try { + synchronized (Bukkit.getPluginManager()) { + for (RegisteredListener listener : listeners) { + listener.callEvent(event); + } + } + } catch (EventException e) { + throw new RuntimeException(e); + } + return lastResult = !event.isCancelled(); + } + }; + } + }; + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java index 2689fb26..867fdff3 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/wrapper/AsyncBlock.java @@ -21,9 +21,9 @@ import org.bukkit.plugin.Plugin; public class AsyncBlock implements Block { - public final int z; - public final int y; - public final int x; + public int z; + public int y; + public int x; public final FaweQueue queue; public final AsyncWorld world; @@ -284,4 +284,10 @@ public class AsyncBlock implements Block { public void removeMetadata(String metadataKey, Plugin owningPlugin) { } + + public void setPosition(int x, int y, int z) { + this.x = x; + this.y = y; + this.z = z; + } } 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 0827e75d..8f660a77 100644 --- a/core/src/main/java/com/boydti/fawe/config/BBC.java +++ b/core/src/main/java/com/boydti/fawe/config/BBC.java @@ -91,9 +91,9 @@ public enum BBC { COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"), COMMAND_REDO_ERROR("Nothing left to redo. (See also `/inspect` and `/frb`)", "WorldEdit.History"), COMMAND_HISTORY_OTHER_ERROR("Unable to find session for %s0.", "WorldEdit.History"), - COMMAND_REDO_SUCCESS("Redo successful.", "WorldEdit.History"), + COMMAND_REDO_SUCCESS("Redo successful%s0.", "WorldEdit.History"), COMMAND_UNDO_ERROR("Nothing left to undo. (See also `/inspect` and `/frb`)", "WorldEdit.History"), - COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"), + COMMAND_UNDO_SUCCESS("Undo successful%s0.", "WorldEdit.History"), OPERATION("Operation queued (%s0)", "WorldEdit.Operation"), diff --git a/core/src/main/java/com/boydti/fawe/config/Settings.java b/core/src/main/java/com/boydti/fawe/config/Settings.java index 4b217ab1..3d96eb00 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -357,6 +357,13 @@ public class Settings extends Config { " - " }) public boolean MODERN_CRAFTSCRIPTS = false; + + @Comment({ + "[SAFE] Experimental freebuild region restrictions", + " - PERM: fawe.freebuild", + " - PERM: fawe.freebuild." + }) + public boolean FREEBUILD = false; } public static class WEB { diff --git a/core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java b/core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java index 48a42d74..4ba7bee9 100644 --- a/core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java +++ b/core/src/main/java/com/boydti/fawe/regions/FaweMaskManager.java @@ -56,4 +56,8 @@ public abstract class FaweMaskManager { private boolean hasMemberPermission(FawePlayer fp) { return fp.hasPermission("fawe." + getKey() + ".member"); } + + public boolean isExclusive() { + return false; + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/util/WEManager.java b/core/src/main/java/com/boydti/fawe/util/WEManager.java index 9d34e076..bbe9a1db 100644 --- a/core/src/main/java/com/boydti/fawe/util/WEManager.java +++ b/core/src/main/java/com/boydti/fawe/util/WEManager.java @@ -125,16 +125,19 @@ public class WEManager { } } if (!removed) return regions.toArray(new Region[regions.size()]); + masks.clear(); } } Set tmpMasks = new HashSet<>(); for (final FaweMaskManager manager : managers) { if (player.hasPermission("fawe." + manager.getKey())) { try { + if (manager.isExclusive() && !masks.isEmpty()) continue; final FaweMask mask = manager.getMask(player, FaweMaskManager.MaskType.getDefaultMaskType()); if (mask != null) { regions.add(mask.getRegion()); masks.add(mask); + if (manager.isExclusive()) break; } } catch (Throwable e) { e.printStackTrace(); diff --git a/core/src/main/java/com/boydti/fawe/util/terrain/Erosion.java b/core/src/main/java/com/boydti/fawe/util/terrain/Erosion.java new file mode 100644 index 00000000..698cb3df --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/util/terrain/Erosion.java @@ -0,0 +1,35 @@ +package com.boydti.fawe.util.terrain; + +import java.util.Arrays; + + +import static com.boydti.fawe.util.MathMan.pairInt; + +public final class Erosion { + private final int area; + private float[][] terrainHeight; + private float[][] waterHeight; + + private long[] queue_2; + private long[] queue; + private int queueIndex; + + public Erosion(int width, int length) { + this.area = width * length; + queue = new long[area]; + Arrays.fill(queue, -1); + + } + + public void addWater(int x, int z, float amt) { + waterHeight[x][z] += amt; + queue[queueIndex++] = pairInt(x, z); + } + + public void propogateWater() { + + } + + + +} diff --git a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java index 7e10d797..1e569c99 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/HistoryCommands.java @@ -233,8 +233,9 @@ public class HistoryCommands extends MethodCommands { public void undo(Player player, LocalSession session, CommandContext context) throws WorldEditException { int times = Math.max(1, context.getInteger(0, 1)); FawePlayer.wrap(player).checkConfirmation(() -> { - for (int i = 0; i < times; ++i) { - EditSession undone; + EditSession undone = null; + int i = 0; + for (; i < times; ++i) { if (context.argsLength() < 2) { undone = session.undo(session.getBlockBag(player), player); } else { @@ -245,14 +246,16 @@ public class HistoryCommands extends MethodCommands { break; } undone = sess.undo(session.getBlockBag(player), player); + if (undone == null) break; } - if (undone != null) { - BBC.COMMAND_UNDO_SUCCESS.send(player); - worldEdit.flushBlockBag(player, undone); - } else { - BBC.COMMAND_UNDO_ERROR.send(player); - break; - } + } + if (undone == null) i--; + if (i > 0) { + BBC.COMMAND_UNDO_SUCCESS.send(player, i == 1 ? "" : " x" + i); + worldEdit.flushBlockBag(player, undone); + } + if (undone == null) { + BBC.COMMAND_UNDO_ERROR.send(player); } }, getArguments(context), times, 50, context); } @@ -269,8 +272,9 @@ public class HistoryCommands extends MethodCommands { int times = Math.max(1, args.getInteger(0, 1)); - for (int i = 0; i < times; ++i) { - EditSession redone; + EditSession redone = null; + int i = 0; + for (; i < times; ++i) { if (args.argsLength() < 2) { redone = session.redo(session.getBlockBag(player), player); } else { @@ -281,13 +285,16 @@ public class HistoryCommands extends MethodCommands { break; } redone = sess.redo(session.getBlockBag(player), player); + if (redone == null) break; } - if (redone != null) { - BBC.COMMAND_REDO_SUCCESS.send(player); - worldEdit.flushBlockBag(player, redone); - } else { - BBC.COMMAND_REDO_ERROR.send(player); - } + } + if (redone == null) i--; + if (i > 0) { + BBC.COMMAND_REDO_SUCCESS.send(player, i == 1 ? "" : " x" + i); + worldEdit.flushBlockBag(player, redone); + } + if (redone == null) { + BBC.COMMAND_REDO_ERROR.send(player); } }