diff --git a/build.gradle b/build.gradle index da307cec..1aa3af9e 100644 --- a/build.gradle +++ b/build.gradle @@ -74,8 +74,8 @@ subprojects { apply plugin: 'eclipse' apply plugin: 'idea' - sourceCompatibility = 1.7 - targetCompatibility = 1.7 + sourceCompatibility = 1.8 + targetCompatibility = 1.8 repositories { mavenCentral() diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BrushListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BrushListener.java new file mode 100644 index 00000000..29ff0ed7 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BrushListener.java @@ -0,0 +1,135 @@ +package com.boydti.fawe.bukkit; + +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.brush.MovableBrush; +import com.boydti.fawe.object.brush.scroll.ScrollableBrush; +import com.boydti.fawe.object.brush.visualization.VisualBrush; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.InvalidToolBindException; +import com.sk89q.worldedit.command.tool.Tool; +import com.sk89q.worldedit.command.tool.brush.Brush; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerItemHeldEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.plugin.Plugin; + +public class BrushListener implements Listener { + public BrushListener(Plugin plugin) { + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerItemHoldEvent(final PlayerItemHeldEvent event) { + final Player bukkitPlayer = event.getPlayer(); + if (bukkitPlayer.isSneaking()) { + return; + } + FawePlayer fp = FawePlayer.wrap(bukkitPlayer); + com.sk89q.worldedit.entity.Player player = fp.getPlayer(); + LocalSession session = fp.getSession(); + Tool tool = session.getTool(player); + if (tool != null) { + ScrollableBrush scrollable; + if (tool instanceof ScrollableBrush) { + scrollable = (ScrollableBrush) tool; + } else if (tool instanceof BrushTool) { + Brush brush = ((BrushTool) tool).getBrush(); + scrollable = brush instanceof ScrollableBrush ? (ScrollableBrush) brush : null; + } else { + return; + } + if (scrollable != null) { + final int slot = event.getNewSlot(); + final int oldSlot = event.getPreviousSlot(); + final int ri; + if ((((slot - oldSlot) <= 4) && ((slot - oldSlot) > 0)) || (((slot - oldSlot) < -4))) { + ri = 1; + } else { + ri = -1; + } + if (scrollable.increment(ri)) { + final PlayerInventory inv = bukkitPlayer.getInventory(); + final ItemStack item = inv.getItem(slot); + final ItemStack newItem = inv.getItem(oldSlot); + inv.setItem(slot, newItem); + inv.setItem(oldSlot, item); + bukkitPlayer.updateInventory(); + if (scrollable instanceof VisualBrush) { + try { + ((VisualBrush) scrollable).queueVisualization(fp); + } catch (Throwable e) { + WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onPlayerMove(PlayerMoveEvent event) { + Location from = event.getFrom(); + Location to = event.getTo(); + if ((from.getYaw() != to.getYaw() && from.getPitch() != to.getPitch()) || from.getBlockX() != to.getBlockX() || from.getBlockZ() != to.getBlockZ() || from.getBlockY() != to.getBlockY()) { + Player bukkitPlayer = event.getPlayer(); + FawePlayer fp = FawePlayer.wrap(bukkitPlayer); + com.sk89q.worldedit.entity.Player player = fp.getPlayer(); + LocalSession session = fp.getSession(); + Tool tool = session.getTool(player); + if (tool != null) { + if (tool instanceof MovableBrush) { + ((MovableBrush) tool).move(player); + } else if (tool instanceof BrushTool) { + Brush brush = ((BrushTool) tool).getBrush(); + if (brush instanceof MovableBrush) { + if (((MovableBrush) brush).move(player)) { + if (brush instanceof VisualBrush) { + try { + ((VisualBrush) brush).queueVisualization(fp); + } catch (Throwable e) { + WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); + } + } + } + } + } + } + } + } + + @EventHandler(priority = EventPriority.LOWEST) + public void onPlayerInteract(final PlayerInteractEvent event) { + switch (event.getAction()) { + case LEFT_CLICK_AIR: + case LEFT_CLICK_BLOCK: + Player bukkitPlayer = event.getPlayer(); + if (!bukkitPlayer.isSneaking()) { + return; + } + FawePlayer fp = FawePlayer.wrap(bukkitPlayer); + com.sk89q.worldedit.entity.Player player = fp.getPlayer(); + LocalSession session = fp.getSession(); + int item = player.getItemInHand(); + Tool tool = session.getTool(item); + if (tool != null) { + try { + session.setTool(item, null, player); + BBC.TOOL_NONE.send(player); + } catch (InvalidToolBindException e) { + e.printStackTrace(); + } + } + } + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java index 5048e878..20ba3026 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java @@ -5,6 +5,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0; import com.boydti.fawe.bukkit.v0.BukkitQueue_All; import com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10; import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11; +import com.boydti.fawe.bukkit.v1_11.compression.CompressionOptimizer; import com.boydti.fawe.bukkit.v1_7.BukkitQueue17; import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3; import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1; @@ -68,6 +69,15 @@ public class BukkitMain extends JavaPlugin { break; } catch (IllegalStateException e) {} } + switch (version) { + case v1_11_R1: + try { + CompressionOptimizer optimizer = new CompressionOptimizer(); +// optimizer.optimize(); + } catch (Throwable throwable) { + throwable.printStackTrace(); + } + } } private enum Version { diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java index c843035e..e83c4c2c 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitPlayer.java @@ -92,7 +92,7 @@ public class BukkitPlayer extends FawePlayer { } @Override - public com.sk89q.worldedit.entity.Player getPlayer() { + public com.sk89q.worldedit.entity.Player toWorldEditPlayer() { return PlayerWrapper.wrap(Fawe. imp().getWorldEditPlugin().wrapPlayer(this.parent)); } 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 d23c83f3..6fce129f 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -70,6 +70,7 @@ public class FaweBukkit implements IFawe, Listener { try { Fawe.set(this); setupInjector(); + new BrushListener(plugin); if (Bukkit.getVersion().contains("git-Spigot")) { debug("====== USE PAPER ======"); debug("DOWNLOAD: https://ci.destroystokyo.com/job/PaperSpigot/"); diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java index 6c4c6094..c978a14f 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/BukkitQueue_0.java @@ -9,6 +9,7 @@ import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -142,9 +143,9 @@ public abstract class BukkitQueue_0 extends NMSMa if ((BukkitQueue_0.adapter = adapter) != null) { fieldAdapter.set(instance, adapter); } else { - BukkitQueue_0.adapter = (BukkitImplAdapter) fieldAdapter.get(instance); + BukkitQueue_0.adapter = adapter = (BukkitImplAdapter) fieldAdapter.get(instance); } - for (Method method : BukkitQueue_0.adapter.getClass().getDeclaredMethods()) { + for (Method method : adapter.getClass().getDeclaredMethods()) { switch (method.getName()) { case "toNative": methodToNative = method; @@ -237,28 +238,41 @@ public abstract class BukkitQueue_0 extends NMSMa } @Override - public void sendBlockUpdate(Map> blockMap, FawePlayer... players) { - for (FawePlayer player : players) { - Player bukkitPlayer = ((BukkitPlayer) player).parent; - World world = bukkitPlayer.getWorld(); - for (Map.Entry> entry : blockMap.entrySet()) { - long chunkHash = entry.getKey(); - int cx = MathMan.unpairIntX(chunkHash); - int cz = MathMan.unpairIntY(chunkHash); - Map blocks = entry.getValue(); - for (Map.Entry blockEntry : blocks.entrySet()) { - short blockHash = blockEntry.getKey(); - int x = (blockHash >> 12 & 0xF) + (cx << 4); - int y = (blockHash & 0xFF); - int z = (blockHash >> 8 & 0xF) + (cz << 4); - char combined = blockEntry.getValue(); - int id = FaweCache.getId(combined); - byte data = (byte) FaweCache.getData(combined); - Location loc = new Location(world, x, y, z); - bukkitPlayer.sendBlockChange(loc, id, data); - } + public void sendBlockUpdate(final FaweChunk chunk, FawePlayer... players) { + if (players.length == 0) { + return; + } + int cx = chunk.getX(); + int cz = chunk.getZ(); + int view = Bukkit.getServer().getViewDistance(); + boolean sendAny = false; + boolean[] send = new boolean[players.length]; + for (int i = 0; i < players.length; i++) { + FawePlayer player = players[i]; + Player bp = ((BukkitPlayer) player).parent; + Location loc = bp.getLocation(); + if (Math.abs((loc.getBlockX() >> 4) - cx) <= view && Math.abs((loc.getBlockZ() >> 4) - cz) <= view) { + sendAny = true; + send[i] = true; } } + if (!sendAny) { + return; + } + final World world = getWorld(); + final int bx = cx << 4; + final int bz = cz << 4; + chunk.forEachQueuedBlock(new FaweChunkVisitor() { + @Override + public void run(int localX, int y, int localZ, int combined) { + Location loc = new Location(world, bx + localX, y, bz + localZ); + for (int i = 0; i < players.length; i++) { + if (send[i]) { + ((BukkitPlayer) players[i]).parent.sendBlockChange(loc, FaweCache.getId(combined), (byte) FaweCache.getData(combined)); + } + } + } + }); } @Override diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10_Copy.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10_Copy.java new file mode 100644 index 00000000..3d19dc5b --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitChunk_1_10_Copy.java @@ -0,0 +1,80 @@ +package com.boydti.fawe.bukkit.v1_10; + +import com.boydti.fawe.object.FaweQueue; +import net.minecraft.server.v1_10_R1.ChunkSection; +import net.minecraft.server.v1_10_R1.DataPaletteBlock; +import net.minecraft.server.v1_10_R1.NibbleArray; + +public class BukkitChunk_1_10_Copy extends BukkitChunk_1_10 { + public final byte[][] idsBytes; + public final byte[][] datasBytes; + + public BukkitChunk_1_10_Copy(FaweQueue parent, int x, int z) { + super(parent, x, z); + idsBytes = new byte[16][]; + datasBytes = new byte[16][]; + } + + public void set(int i, byte[] ids, byte[] data) { + this.idsBytes[i] = ids; + this.datasBytes[i] = data; + } + + public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException { + if (section == null) { + return false; + } + DataPaletteBlock blocks = section.getBlocks(); + byte[] ids = new byte[4096]; + NibbleArray data = new NibbleArray(); + blocks.exportData(ids, data); + set(layer, ids, data.asBytes()); + short solid = (short) getParent().fieldNonEmptyBlockCount.getInt(section); + count[layer] = solid; + air[layer] = (short) (4096 - solid); + return true; + } + + @Override + public char[][] getCombinedIdArrays() { + for (int i = 0; i < ids.length; i++) { + getIdArray(i); + } + return super.getCombinedIdArrays(); + } + + @Override + public char[] getIdArray(int i) { + char[] combined = this.ids[i]; + if (combined != null) { + return combined; + } + byte[] idsBytesArray = idsBytes[i]; + if (idsBytesArray == null) { + return null; + } + byte[] datasBytesArray = datasBytes[i]; + + idsBytes[i] = null; + datasBytes[i] = null; + + this.ids[i] = combined = new char[4096]; + for (int j = 0, k = 0; j < 2048; j++, k += 2) { + combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + (datasBytesArray[j] & 15)); + } + for (int j = 0, k = 1; j < 2048; j++, k += 2) { + combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + ((datasBytesArray[j] >> 4) & 15)); + } + return combined; + } + + @Override + public void setBlock(int x, int y, int z, int id) { + throw new UnsupportedOperationException("This chunk is an immutable copy"); + } + + @Override + public void setBlock(int x, int y, int z, int id, int data) { + throw new UnsupportedOperationException("This chunk is an immutable copy"); + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java index 15724e60..e8fd2283 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_10/BukkitQueue_1_10.java @@ -25,10 +25,13 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorCompletionService; +import net.minecraft.server.v1_10_R1.BiomeBase; +import net.minecraft.server.v1_10_R1.BiomeCache; import net.minecraft.server.v1_10_R1.Block; import net.minecraft.server.v1_10_R1.BlockPosition; +import net.minecraft.server.v1_10_R1.ChunkProviderGenerate; +import net.minecraft.server.v1_10_R1.ChunkProviderServer; import net.minecraft.server.v1_10_R1.ChunkSection; -import net.minecraft.server.v1_10_R1.DataBits; import net.minecraft.server.v1_10_R1.DataPaletteBlock; import net.minecraft.server.v1_10_R1.Entity; import net.minecraft.server.v1_10_R1.EntityPlayer; @@ -47,6 +50,7 @@ import net.minecraft.server.v1_10_R1.PlayerChunk; import net.minecraft.server.v1_10_R1.PlayerChunkMap; import net.minecraft.server.v1_10_R1.ServerNBTManager; import net.minecraft.server.v1_10_R1.TileEntity; +import net.minecraft.server.v1_10_R1.WorldChunkManager; import net.minecraft.server.v1_10_R1.WorldData; import net.minecraft.server.v1_10_R1.WorldManager; import net.minecraft.server.v1_10_R1.WorldServer; @@ -68,6 +72,8 @@ public class BukkitQueue_1_10 extends BukkitQueue_0> 4).fromLegacyData(i & 0xF); } catch (Throwable ignore) {} @@ -140,6 +150,40 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { Map tiles = (Map) tilesGeneric; Collection[] entities = (Collection[]) entitiesGeneric; - BukkitChunk_1_10 previous = getFaweChunk(fs.getX(), fs.getZ()); // Copy blocks - char[][] idPrevious = previous.getCombinedIdArrays(); + BukkitChunk_1_10_Copy previous = new BukkitChunk_1_10_Copy(this, fs.getX(), fs.getZ()); for (int layer = 0; layer < sections.length; layer++) { if (fs.getCount(layer) != 0 || all) { ChunkSection section = sections[layer]; if (section != null) { - short solid = 0; - char[] previousLayer = idPrevious[layer] = new char[4096]; DataPaletteBlock blocks = section.getBlocks(); - for (int j = 0; j < 4096; j++) { - int x = FaweCache.CACHE_X[0][j]; - int y = FaweCache.CACHE_Y[0][j]; - int z = FaweCache.CACHE_Z[0][j]; - IBlockData ibd = blocks.a(x, y, z); - Block block = ibd.getBlock(); - int combined = Block.getId(block); - if (FaweCache.hasData(combined)) { - combined = (combined << 4) + block.toLegacyData(ibd); - } else { - combined = combined << 4; - } - if (combined > 1) { - solid++; - } - previousLayer[j] = (char) combined; - } + byte[] ids = new byte[4096]; + NibbleArray data = new NibbleArray(); + blocks.exportData(ids, data); + previous.set(layer, ids, data.asBytes()); + short solid = (short) fieldNonEmptyBlockCount.getInt(section); previous.count[layer] = solid; previous.air[layer] = (short) (4096 - solid); } @@ -605,7 +602,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0 constructor = $0.getClass().getDeclaredClasses()[0].getConstructors()[0]; +// constructor.setAccessible(true); +// return $0.d($1, $2) ? null : new java.io.DataOutputStream(new java.io.BufferedOutputStream(new com.boydti.fawe.object.io.PGZIPOutputStream((OutputStream) constructor.newInstance($1, $2)))); + } + } + + public static Object newInstance(Constructor constructor, RegionFile file, int a, int b) throws IllegalAccessException, InvocationTargetException, InstantiationException { + return constructor.newInstance(file, a, b); + } +} diff --git a/core/build.gradle b/core/build.gradle index 0e0cb565..2d184af7 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -14,9 +14,6 @@ dependencies { } } -sourceCompatibility = 1.7 -targetCompatibility = 1.7 - processResources { from('src/main/resources') { include 'fawe.properties' diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index 14e6aa3c..cc3c80f2 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -8,6 +8,7 @@ import com.boydti.fawe.config.BBC; import com.boydti.fawe.config.Commands; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.brush.visualization.VisualQueue; import com.boydti.fawe.regions.general.plot.PlotSquaredFeature; import com.boydti.fawe.util.FaweTimer; import com.boydti.fawe.util.MainUtil; @@ -26,6 +27,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockData; import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BrushCommands; @@ -69,6 +71,7 @@ import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.function.entity.ExtentEntityCopy; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.FuzzyBlockMask; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskUnion; import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.mask.OffsetMask; @@ -77,6 +80,7 @@ import com.sk89q.worldedit.function.operation.ChangeSetExecutor; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.ClipboardPattern; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Patterns; import com.sk89q.worldedit.function.pattern.RandomPattern; import com.sk89q.worldedit.function.visitor.BreadthFirstSearch; @@ -167,6 +171,8 @@ public class Fawe { */ private final FaweTimer timer; private FaweVersion version; + private VisualQueue visualQueue; + private Updater updater; /** * Get the implementation specific class @@ -242,7 +248,7 @@ public class Fawe { * Instance independent stuff */ this.setupMemoryListener(); - timer = new FaweTimer(); + this.timer = new FaweTimer(); Fawe.this.IMP.setupVault(); // Delayed worldedit setup @@ -250,6 +256,7 @@ public class Fawe { @Override public void run() { try { + visualQueue = new VisualQueue(); WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers()); WEManager.IMP.managers.add(new PlotSquaredFeature()); Fawe.debug("Plugin 'PlotSquared' found. Using it now."); @@ -265,7 +272,8 @@ public class Fawe { TaskManager.IMP.repeatAsync(new Runnable() { @Override public void run() { - Updater.update(IMP.getPlatform(), getVersion()); + updater = new Updater(); + updater.update(IMP.getPlatform(), getVersion()); } }, 36000); } @@ -277,6 +285,15 @@ public class Fawe { return isJava8; } + /** + * The FAWE updater class + * - Use to get basic update information (changelog/version etc) + * @return + */ + public Updater getUpdater() { + return updater; + } + /** * The FaweTimer is a useful class for monitoring TPS * @return FaweTimer @@ -285,6 +302,14 @@ public class Fawe { return timer; } + /** + * The visual queue is used to queue visualizations + * @return + */ + public VisualQueue getVisualQueue() { + return visualQueue; + } + /** * The FAWE version * - Unofficial jars may be lacking version information @@ -306,6 +331,7 @@ public class Fawe { } public void setupConfigs() { + MainUtil.copyFile(MainUtil.getJarFile(), "de/messages.yml", null); // Setting up config.yml File file = new File(this.IMP.getDirectory(), "config.yml"); Settings.IMP.PLATFORM = IMP.getPlatform().replace("\"", ""); @@ -345,7 +371,7 @@ public class Fawe { Commands.inject(); // Translations EditSession.inject(); // Custom block placer + optimizations EditSessionEvent.inject(); // Add EditSession to event (API) - LocalSession.inject(); // Add remember order / queue flushing / Optimizations for disk + LocalSession.inject(); // Add remember order / queue flushing / Optimizations for disk / brush visualization SessionManager.inject(); // Faster custom session saving + Memory improvements Request.inject(); // Custom pattern extent // Commands @@ -381,7 +407,7 @@ public class Fawe { LongRangeBuildTool.inject(); AreaPickaxe.inject(); // Fixes RecursivePickaxe.inject(); // Fixes - BrushTool.inject(); // Add transform + BrushTool.inject(); // Add transform + support for double action brushes + visualizations // Selectors CuboidRegionSelector.inject(); // Translations EllipsoidRegion.inject(); // Optimizations @@ -415,13 +441,17 @@ public class Fawe { BlockVector.inject(); // Optimizations Vector.inject(); // Optimizations Vector2D.inject(); // Optimizations + // Block + BaseBlock.inject(); // Optimizations // Pattern + Pattern.inject(); // Simplify API Patterns.inject(); // Optimizations (reduce object creation) RandomPattern.inject(); // Optimizations ClipboardPattern.inject(); // Optimizations HashTagPatternParser.inject(); // Add new patterns DefaultBlockParser.inject(); // Fix block lookups // Mask + Mask.inject(); // Extend deprecated mask BlockMask.inject(); // Optimizations SolidBlockMask.inject(); // Optimizations FuzzyBlockMask.inject(); // Optimizations diff --git a/core/src/main/java/com/boydti/fawe/FaweCache.java b/core/src/main/java/com/boydti/fawe/FaweCache.java index 0869e0df..526b25c7 100644 --- a/core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/core/src/main/java/com/boydti/fawe/FaweCache.java @@ -14,9 +14,10 @@ import com.sk89q.jnbt.LongTag; import com.sk89q.jnbt.ShortTag; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; -import com.sk89q.worldedit.CuboidClipboard; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BaseItem; +import com.sk89q.worldedit.blocks.ImmutableBlock; +import com.sk89q.worldedit.blocks.ImmutableDatalessBlock; import com.sk89q.worldedit.world.biome.BaseBiome; import com.sk89q.worldedit.world.registry.BundledBlockData; import java.awt.Color; @@ -171,34 +172,11 @@ public class FaweCache { for (int i = 0; i < Character.MAX_VALUE; i++) { int id = i >> 4; int data = i & 0xf; - CACHE_BLOCK[i] = new BaseBlock(id, data) { - @Override - public void setData(int data) { - throw new IllegalStateException("Cannot set data"); - } - - @Override - public void setId(int id) { - throw new IllegalStateException("Cannot set id"); - } - - @Override - public BaseBlock flip() { - BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData()); - return clone.flip(); - } - - @Override - public BaseBlock flip(CuboidClipboard.FlipDirection direction) { - BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData()); - return clone.flip(direction); - } - - @Override - public boolean hasWildcardData() { - return true; - } - }; + if (FaweCache.hasData(id)) { + CACHE_BLOCK[i] = new ImmutableBlock(id, data); + } else { + CACHE_BLOCK[i] = new ImmutableDatalessBlock(id); + } CACHE_ITEM[i] = new BaseItem(id, (short) data) { @Override diff --git a/core/src/main/java/com/boydti/fawe/command/Reload.java b/core/src/main/java/com/boydti/fawe/command/Reload.java index d9942ad3..f6ac7709 100644 --- a/core/src/main/java/com/boydti/fawe/command/Reload.java +++ b/core/src/main/java/com/boydti/fawe/command/Reload.java @@ -7,12 +7,14 @@ import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.util.HastebinUtility; import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.Updater; import java.io.File; import java.io.IOException; -import java.time.LocalDate; +import java.net.URL; import java.util.Date; import java.util.GregorianCalendar; import java.util.Map; +import java.util.Scanner; public class Reload extends FaweCommand { @@ -23,7 +25,7 @@ public class Reload extends FaweCommand { @Override public boolean execute(final FawePlayer player, final String... args) { if (args.length != 1) { - BBC.COMMAND_SYNTAX.send(player, "/fawe [reload|version|debugpaste|threads]"); + BBC.COMMAND_SYNTAX.send(player, "/fawe [reload|version|debugpaste|threads|changelog]"); return false; } switch (args[0].toLowerCase()) { @@ -54,6 +56,22 @@ public class Reload extends FaweCommand { } return true; } + case "changelog": { + try { + Updater updater = Fawe.get().getUpdater(); + String changes = updater != null ? updater.getChanges() : null; + if (changes == null) { + try (Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8")) { + changes = scanner.useDelimiter("\\A").next(); + } + } + player.sendMessage(BBC.getPrefix() + changes); + return true; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } case "debugpaste": case "paste": { try { 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 46eeb66f..da2ac025 100644 --- a/core/src/main/java/com/boydti/fawe/config/BBC.java +++ b/core/src/main/java/com/boydti/fawe/config/BBC.java @@ -123,6 +123,7 @@ public enum BBC { BRUSH_SPLINE_SECONDARY("Created spline", "WorldEdit.Brush"), BRUSH_BLEND_BALL("Blend ball brush equipped (%s0).", "WorldEdit.Brush"), BRUSH_ERODE("Erode brush equipped (%s0). Right click to erode, left click to pull.", "WorldEdit.Brush"), + BRUSH_CIRCLE("Circle brush equipped (%s0). Right click to create a circle.", "WorldEdit.Brush"), BRUSH_RECURSIVE("Recursive brush equipped (%s0).", "WorldEdit.Brush"), BRUSH_PASTE_NONE("Nothing to paste", "WorldEdit.Brush"), BRUSH_SIZE("Brush size set", "WorldEdit.Brush"), 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 a1830bd5..24681852 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -2,7 +2,6 @@ package com.boydti.fawe.config; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; -import com.sk89q.worldedit.LocalSession; import java.io.File; import java.util.ArrayList; import java.util.Collection; @@ -26,6 +25,9 @@ public class Settings extends Config { @Final public String PLATFORM; // These values are set from FAWE before loading + @Comment({"Options: de", + "Create a PR to contribute a translation: https://github.com/boy0001/FastAsyncWorldedit/new/master/core/src/main/resources",}) + public String LANGUAGE = ""; @Comment("Allow the plugin to update") public boolean UPDATE = true; @Comment("Send anonymous usage statistics to MCStats.org") @@ -330,9 +332,6 @@ public class Settings extends Config { public void reload(File file) { load(file); save(file); - if (HISTORY.USE_DISK) { - LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE; - } } public FaweLimit getLimit(FawePlayer player) { diff --git a/core/src/main/java/com/boydti/fawe/example/NullQueueCharFaweChunk.java b/core/src/main/java/com/boydti/fawe/example/NullQueueCharFaweChunk.java new file mode 100644 index 00000000..bee7e991 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/example/NullQueueCharFaweChunk.java @@ -0,0 +1,34 @@ +package com.boydti.fawe.example; + +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.util.MainUtil; + +public class NullQueueCharFaweChunk extends CharFaweChunk { + + public NullQueueCharFaweChunk(int cx, int cz) { + super(null, cx, cz); + } + + public NullQueueCharFaweChunk(int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) { + super(null, x, z, ids, count, air, heightMap); + } + + @Override + public Object getNewChunk() { + return null; + } + + @Override + public CharFaweChunk copy(boolean shallow) { + if (shallow) { + return new NullQueueCharFaweChunk(getX(), getZ(), ids, count, air, heightMap); + } else { + return new NullQueueCharFaweChunk(getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone()); + } + } + + @Override + public FaweChunk call() { + return null; + } +} 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 8be99df1..4c3c1a94 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 @@ -350,9 +350,9 @@ public class MCAQueue extends NMSMappedFaweQueue> blockMap, FawePlayer... players) { + public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) { if (parent != null) { - parentNMS.sendBlockUpdate(blockMap, players); + parentNMS.sendBlockUpdate(chunk, players); } } } diff --git a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java index ef346b2c..b21fe936 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweChunk.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweChunk.java @@ -1,6 +1,7 @@ package com.boydti.fawe.object; import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.blocks.BaseBlock; @@ -146,6 +147,20 @@ public abstract class FaweChunk implements Callable { public abstract byte[] getBiomeArray(); + public void forEachQueuedBlock(FaweChunkVisitor onEach) { + for (int y = 0; y < HEIGHT; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + int combined = getBlockCombinedId(x, y, z); + if (combined == 0) { + continue; + } + onEach.run(x, y, z, combined); + } + } + } + } + public char[][] getCombinedIdArrays() { char[][] ids = new char[HEIGHT >> 4][]; for (int y = 0; y < HEIGHT >> 4; y++) { diff --git a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java index a20f8dc9..e92c4359 100644 --- a/core/src/main/java/com/boydti/fawe/object/FawePlayer.java +++ b/core/src/main/java/com/boydti/fawe/object/FawePlayer.java @@ -209,7 +209,7 @@ public abstract class FawePlayer extends Metadatable { try { if (file.exists() && file.length() > 5) { DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file); - Player player = getPlayer(); + Player player = toWorldEditPlayer(); LocalSession session = getSession(); try { if (session.getClipboard() != null) { @@ -331,7 +331,16 @@ public abstract class FawePlayer extends Metadatable { * Get the WorldEdit player object * @return */ - public abstract Player getPlayer(); + public abstract Player toWorldEditPlayer(); + + private Player cachedWorldEditPlayer; + + public Player getPlayer() { + if (cachedWorldEditPlayer == null) { + cachedWorldEditPlayer = toWorldEditPlayer(); + } + return cachedWorldEditPlayer; + } /** * Get the player's current selection (or null) @@ -382,7 +391,7 @@ public abstract class FawePlayer extends Metadatable { * @param selector */ public void setSelection(final RegionSelector selector) { - this.getSession().setRegionSelector(getPlayer().getWorld(), selector); + this.getSession().setRegionSelector(toWorldEditPlayer().getWorld(), selector); } /** @@ -422,7 +431,7 @@ public abstract class FawePlayer extends Metadatable { public void unregister() { if (Settings.IMP.HISTORY.DELETE_ON_LOGOUT) { session = getSession(); - WorldEdit.getInstance().removeSession(getPlayer()); + WorldEdit.getInstance().removeSession(toWorldEditPlayer()); session.setClipboard(null); session.clearHistory(); } @@ -433,7 +442,7 @@ public abstract class FawePlayer extends Metadatable { * Get a new EditSession from this player */ public EditSession getNewEditSession() { - return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, getPlayer()); + return WorldEdit.getInstance().getEditSessionFactory().getEditSession(getWorld(), -1, toWorldEditPlayer()); } 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 72a2c4ba..2f9e2ad6 100644 --- a/core/src/main/java/com/boydti/fawe/object/FaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/object/FaweQueue.java @@ -25,7 +25,6 @@ import com.sk89q.worldedit.world.registry.BundledBlockData; import java.io.File; import java.util.Collection; import java.util.HashSet; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; @@ -308,7 +307,7 @@ public abstract class FaweQueue implements HasFaweQueue { return count; } - public abstract void sendBlockUpdate(Map> blockMap, FawePlayer... players); + public abstract void sendBlockUpdate(FaweChunk chunk, FawePlayer... players); @Deprecated public boolean next() { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/CircleBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/CircleBrush.java new file mode 100644 index 00000000..d2ff316e --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/CircleBrush.java @@ -0,0 +1,48 @@ +package com.boydti.fawe.object.brush; + +import com.boydti.fawe.object.brush.visualization.VisualBrush; +import com.boydti.fawe.object.collection.LocalBlockVectorSet; +import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.math.transform.AffineTransform; + +public class CircleBrush extends VisualBrush { + private final Player player; + + public CircleBrush(BrushTool tool, Player player) { + super(tool); + this.player = LocationMaskedPlayerWrapper.unwrap(player); + } + + @Override + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + switch (action) { + case PRIMARY: + LocalBlockVectorSet set = new LocalBlockVectorSet(); + int radius = (int) size; + Vector normal = position.subtract(player.getPosition()); + editSession.makeCircle(position, pattern, size, size, size, false, normal); + break; + case SECONDARY: + break; + } + } + + private static Vector any90Rotate(Vector normal) { + normal = normal.normalize(); + if (normal.getX() == 1 || normal.getY() == 1 || normal.getZ() == 1) { + return new Vector(normal.getZ(), normal.getX(), normal.getY()); + } + AffineTransform affine = new AffineTransform(); + affine = affine.rotateX(90); + affine = affine.rotateY(90); + affine = affine.rotateZ(90); + Vector random = affine.apply(normal); + return random.cross(normal).normalize(); + } +} 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 index cd66874e..efa81ceb 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java @@ -11,6 +11,7 @@ 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.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; @@ -23,14 +24,14 @@ import com.sk89q.worldedit.session.ClipboardHolder; public class CopyPastaBrush implements DoubleActionBrush { - private final DoubleActionBrushTool tool; + private final BrushTool tool; - public CopyPastaBrush(DoubleActionBrushTool tool) { + public CopyPastaBrush(BrushTool tool) { this.tool = tool; } @Override - public void build(DoubleActionBrushTool.BrushAction action, final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, final EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { FawePlayer fp = editSession.getPlayer(); LocalSession session = fp.getSession(); switch (action) { 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 index ae3452bc..d2fd753b 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrush.java @@ -3,8 +3,16 @@ 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.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.brush.Brush; 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; +public interface DoubleActionBrush extends Brush { + + @Override + default void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + build(BrushTool.BrushAction.PRIMARY, editSession, position, pattern, size); + } + + public void build(BrushTool.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 deleted file mode 100644 index 688c53ad..00000000 --- a/core/src/main/java/com/boydti/fawe/object/brush/DoubleActionBrushTool.java +++ /dev/null @@ -1,239 +0,0 @@ -package com.boydti.fawe.object.brush; - -import com.boydti.fawe.config.BBC; -import com.boydti.fawe.object.extent.ResettableExtent; -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 Mask sourceMask = null; - private ResettableExtent transform = 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); - } - - public ResettableExtent getTransform() { - return transform; - } - - public void setTransform(ResettableExtent transform) { - this.transform = transform; - } - - /** - * Get the filter. - * - * @return the filter - */ - public Mask getMask() { - return mask; - } - - /** - * Get the filter. - * - * @return the filter - */ - public Mask getSourceMask() { - return sourceMask; - } - - /** - * 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 block filter used for identifying blocks to replace. - * - * @param filter the filter to set - */ - public void setSourceMask(Mask filter) { - this.sourceMask = 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) { - BBC.NO_BLOCK.send(player); - 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); - } - } - if (sourceMask != null) { - Mask existingMask = editSession.getSourceMask(); - - if (existingMask == null) { - editSession.setSourceMask(sourceMask); - } else if (existingMask instanceof MaskIntersection) { - ((MaskIntersection) existingMask).add(sourceMask); - } else { - MaskIntersection newMask = new MaskIntersection(existingMask); - newMask.add(sourceMask); - editSession.setSourceMask(newMask); - } - } - if (transform != null) { - editSession.addTransform(transform); - } - try { - brush.build(action, editSession, target, material, size); - } catch (MaxChangedBlocksException e) { - player.printError("Max blocks change limit reached."); // Never happens - } 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 index 8cba997d..fb35cfc4 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/ErodeBrush.java @@ -10,6 +10,7 @@ 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.BrushTool; import com.sk89q.worldedit.function.pattern.Pattern; import java.util.Arrays; @@ -20,7 +21,7 @@ public class ErodeBrush implements DoubleActionBrush { 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 { + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { switch (action) { case PRIMARY: { int erodeFaces = 2; diff --git a/core/src/main/java/com/boydti/fawe/object/brush/FlattenBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/FlattenBrush.java index 4ac3dcbc..ed8e1a32 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/FlattenBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/FlattenBrush.java @@ -4,6 +4,7 @@ import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; @@ -12,18 +13,18 @@ import java.io.InputStream; public class FlattenBrush extends HeightBrush { - public FlattenBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) { + public FlattenBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) { super(stream, rotation, yscale, tool, clipboard, shape); } @Override - public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { int size = (int) sizeDouble; Mask mask = tool.getMask(); if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { mask = null; } heightMap.setSize(size); - heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true); + heightMap.apply(editSession, mask, position, size, rotation, action == BrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, true); } } diff --git a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java index 92c2f02c..a5288a7b 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java @@ -6,6 +6,7 @@ import com.boydti.fawe.object.exception.FaweException; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; @@ -18,14 +19,13 @@ public class HeightBrush implements DoubleActionBrush { public final ScalableHeightMap heightMap; public final int rotation; public final double yscale; - public final DoubleActionBrushTool tool; + public final BrushTool tool; - public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard) { + public HeightBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard) { this(stream, rotation, yscale, tool, clipboard, ScalableHeightMap.Shape.CONE); } - public HeightBrush(InputStream stream, int rotation, double yscale, DoubleActionBrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) { - this.tool = tool; + public HeightBrush(InputStream stream, int rotation, double yscale, BrushTool tool, Clipboard clipboard, ScalableHeightMap.Shape shape) { this.rotation = (rotation / 90) % 4; this.yscale = yscale; if (stream != null) { @@ -39,16 +39,17 @@ public class HeightBrush implements DoubleActionBrush { } else { heightMap = ScalableHeightMap.fromShape(shape); } + this.tool = tool; } @Override - public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException { int size = (int) sizeDouble; Mask mask = tool.getMask(); if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { mask = null; } heightMap.setSize(size); - heightMap.apply(editSession, mask, position, size, rotation, action == DoubleActionBrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false); + heightMap.apply(editSession, mask, position, size, rotation, action == BrushTool.BrushAction.PRIMARY ? yscale : -yscale, true, false); } } 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 index 947f8675..12c717e6 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java @@ -3,6 +3,7 @@ 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.command.tool.BrushTool; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Patterns; @@ -18,7 +19,7 @@ public class LineBrush implements DoubleActionBrush { } @Override - public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, final Pattern pattern, double size) throws MaxChangedBlocksException { switch (action) { case PRIMARY: if (pos1 == null) { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/MovableBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/MovableBrush.java new file mode 100644 index 00000000..b1bde41a --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/MovableBrush.java @@ -0,0 +1,7 @@ +package com.boydti.fawe.object.brush; + +import com.sk89q.worldedit.entity.Player; + +public interface MovableBrush { + public boolean move(Player player); +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/RaiseBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/RaiseBrush.java index 78146158..dc7c72f1 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/RaiseBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/RaiseBrush.java @@ -3,13 +3,14 @@ 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.command.tool.BrushTool; import com.sk89q.worldedit.function.pattern.Pattern; public class RaiseBrush implements DoubleActionBrush { @Override - public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { switch (action) { case PRIMARY: break; diff --git a/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java index 6b9e3cfb..71f9bbe5 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java @@ -1,6 +1,7 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.visitor.DFSRecursiveVisitor; @@ -9,6 +10,7 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.mask.Mask; @@ -16,8 +18,6 @@ import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Patterns; -import com.sk89q.worldedit.math.interpolation.Interpolation; -import com.sk89q.worldedit.math.interpolation.KochanekBartelsInterpolation; import com.sk89q.worldedit.math.interpolation.Node; import com.sk89q.worldedit.math.transform.AffineTransform; import java.util.ArrayList; @@ -30,11 +30,11 @@ public class SplineBrush implements DoubleActionBrush { private ArrayList> positionSets; private int numSplines; - private final DoubleActionBrushTool tool; + private final BrushTool tool; private final LocalSession session; private final Player player; - public SplineBrush(Player player, LocalSession session, DoubleActionBrushTool tool) { + public SplineBrush(Player player, LocalSession session, BrushTool tool) { this.tool = tool; this.session = session; this.player = player; @@ -42,15 +42,20 @@ public class SplineBrush implements DoubleActionBrush { } @Override - public void build(DoubleActionBrushTool.BrushAction action, EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + public void build(BrushTool.BrushAction action, EditSession editSession, final Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { Mask mask = tool.getMask(); if (mask == null) { mask = new IdMask(editSession); } else { mask = new MaskIntersection(mask, new IdMask(editSession)); } + boolean visualization = editSession.getExtent() instanceof VisualExtent; + if (visualization && positionSets.isEmpty()) { + return; + } + int originalSize = numSplines; switch (action) { - case PRIMARY: { // Right + case PRIMARY: { if (positionSets.size() >= MAX_POINTS) { throw new FaweException(BBC.WORLDEDIT_CANCEL_REASON_MAX_CHECKS); } @@ -62,6 +67,17 @@ public class SplineBrush implements DoubleActionBrush { return true; } }, (int) size, 1); + Collection directions = visitor.getDirections(); + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + Vector pos = new Vector(x, y, z); + if (!directions.contains(pos)) { + directions.add(pos); + } + } + } + } visitor.visit(position); Operations.completeBlindly(visitor); if (points.size() > numSplines) { @@ -69,7 +85,9 @@ public class SplineBrush implements DoubleActionBrush { } this.positionSets.add(points); player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE_PRIMARY.s()); - break; + if (!visualization) { + break; + } } case SECONDARY: { if (positionSets.size() < 2) { @@ -88,7 +106,6 @@ public class SplineBrush implements DoubleActionBrush { final List nodes = new ArrayList(centroids.size()); - final Interpolation interpol = new KochanekBartelsInterpolation(); for (final Vector nodevector : centroids) { final Node n = new Node(nodevector); n.setTension(tension); @@ -113,8 +130,13 @@ public class SplineBrush implements DoubleActionBrush { editSession.drawSpline(Patterns.wrap(pattern), currentSpline, 0, 0, 0, 10, 0, true); } player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE_SECONDARY.s()); - positionSets.clear(); - numSplines = 0; + if (visualization) { + positionSets.clear(); + numSplines = 0; + } else { + numSplines = originalSize; + positionSets.remove(positionSets.size() - 1); + } break; } } diff --git a/core/src/main/java/com/boydti/fawe/object/brush/TargetMode.java b/core/src/main/java/com/boydti/fawe/object/brush/TargetMode.java new file mode 100644 index 00000000..eb3732c4 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/TargetMode.java @@ -0,0 +1,8 @@ +package com.boydti.fawe.object.brush; + +public enum TargetMode { + TARGET_BLOCK_RANGE, + FOWARD_POINT_PITCH, + TARGET_POINT_HEIGHT, + TARGET_POINT_RANGE, +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollAction.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollAction.java new file mode 100644 index 00000000..4b61cc0a --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollAction.java @@ -0,0 +1,11 @@ +package com.boydti.fawe.object.brush.scroll; + +import com.sk89q.worldedit.command.tool.BrushTool; + +public abstract class ScrollAction implements ScrollableBrush { + public final BrushTool tool; + + public ScrollAction(BrushTool tool) { + this.tool = tool; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollClipboard.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollClipboard.java new file mode 100644 index 00000000..f7c3409d --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollClipboard.java @@ -0,0 +1,4 @@ +package com.boydti.fawe.object.brush.scroll; + +public class ScrollClipboard { +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollMask.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollMask.java new file mode 100644 index 00000000..531232a3 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollMask.java @@ -0,0 +1,25 @@ +package com.boydti.fawe.object.brush.scroll; + +import com.boydti.fawe.util.MathMan; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.function.mask.Mask; + +public class ScrollMask extends ScrollAction { + private final Mask[] masks; + private int index; + + public ScrollMask(BrushTool tool, Mask... masks) { + super(tool); + this.masks = masks; + } + + + @Override + public boolean increment(int amount) { + if (masks.length > 1) { + tool.setMask(masks[MathMan.wrap(index += amount, 0, masks.length - 1)]); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollPattern.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollPattern.java new file mode 100644 index 00000000..3cd0bfbe --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollPattern.java @@ -0,0 +1,25 @@ +package com.boydti.fawe.object.brush.scroll; + +import com.boydti.fawe.util.MathMan; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.function.pattern.Pattern; + +public class ScrollPattern extends ScrollAction { + private final Pattern[] patterns; + private int index; + + public ScrollPattern(BrushTool tool, Pattern... patterns) { + super(tool); + this.patterns = patterns; + } + + + @Override + public boolean increment(int amount) { + if (patterns.length > 1) { + tool.setFill(patterns[MathMan.wrap(index += amount, 0, patterns.length - 1)]); + return true; + } + return false; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollRange.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollRange.java new file mode 100644 index 00000000..066f0766 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollRange.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.object.brush.scroll; + +import com.boydti.fawe.util.MathMan; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.BrushTool; + +public class ScrollRange extends ScrollAction { + public ScrollRange(BrushTool tool) { + super(tool); + } + + @Override + public boolean increment(int amount) { + int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius; + int newSize = MathMan.wrap(tool.getRange() + amount, (int) (tool.getSize() + 1), max); + tool.setRange(newSize); + return true; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollSize.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollSize.java new file mode 100644 index 00000000..d10a9415 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollSize.java @@ -0,0 +1,18 @@ +package com.boydti.fawe.object.brush.scroll; + +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.BrushTool; + +public class ScrollSize extends ScrollAction { + public ScrollSize(BrushTool tool) { + super(tool); + } + + @Override + public boolean increment(int amount) { + int max = WorldEdit.getInstance().getConfiguration().maxRadius; + double newSize = Math.max(0, Math.min(max, tool.getSize() + amount)); + tool.setSize(newSize); + return true; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollableBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollableBrush.java new file mode 100644 index 00000000..d04a9af5 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/scroll/ScrollableBrush.java @@ -0,0 +1,5 @@ +package com.boydti.fawe.object.brush.scroll; + +public interface ScrollableBrush { + public boolean increment(int amount); +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/DelegateVisualBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/DelegateVisualBrush.java new file mode 100644 index 00000000..adddc602 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/DelegateVisualBrush.java @@ -0,0 +1,32 @@ +package com.boydti.fawe.object.brush.visualization; + +import com.boydti.fawe.object.brush.DoubleActionBrush; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.brush.Brush; +import com.sk89q.worldedit.function.pattern.Pattern; + +public class DelegateVisualBrush extends VisualBrush { + private final Brush brush; + + public DelegateVisualBrush(BrushTool tool, Brush brush) { + super(tool); + this.brush = brush; + } + + @Override + public void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException { + switch (action) { + case PRIMARY: + brush.build(editSession, position, pattern, size); + break; + case SECONDARY: + if (brush instanceof DoubleActionBrush) { + ((DoubleActionBrush) brush).build(BrushTool.BrushAction.SECONDARY, editSession, position, pattern, size); + } + break; + } + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualBrush.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualBrush.java new file mode 100644 index 00000000..94a63abf --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualBrush.java @@ -0,0 +1,142 @@ +package com.boydti.fawe.object.brush.visualization; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.brush.DoubleActionBrush; +import com.boydti.fawe.object.brush.MovableBrush; +import com.boydti.fawe.object.brush.TargetMode; +import com.boydti.fawe.object.brush.scroll.ScrollableBrush; +import com.boydti.fawe.util.EditSessionBuilder; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.util.Location; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +public abstract class VisualBrush implements DoubleActionBrush, MovableBrush, ScrollableBrush { + + private Lock lock = new ReentrantLock(); + private final BrushTool tool; + private VisualExtent visualExtent; + private TargetMode mode; + + public VisualBrush(BrushTool tool) { + this.tool = tool; + this.mode = TargetMode.TARGET_POINT_RANGE; + } + + public BrushTool getTool() { + return tool; + } + + public TargetMode getMode() { + return mode; + } + + public void setMode(TargetMode mode) { + this.mode = mode; + } + + @Override + public abstract void build(BrushTool.BrushAction action, EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException; + + public Vector getPosition(EditSession editSession, Player player) { + switch (mode) { + case TARGET_BLOCK_RANGE: + return player.getBlockTrace(tool.getRange(), false); + case FOWARD_POINT_PITCH: { + int d = 0; + Location loc = player.getLocation(); + float pitch = loc.getPitch(); + pitch = 23 - (pitch / 4); + d += (int) (Math.sin(Math.toRadians(pitch)) * 50); + final Vector vector = loc.getDirection().setY(0).normalize().multiply(d); + vector.add(loc.getX(), loc.getY(), loc.getZ()).toBlockVector(); + return vector; + } + case TARGET_POINT_HEIGHT: { + Location loc = player.getLocation(); + final int height = loc.getBlockY(); + final int x = loc.getBlockX(); + final int z = loc.getBlockZ(); + int y; + for (y = height; y > 0; y--) { + BaseBlock block = editSession.getBlock(x, y, z); + if (!FaweCache.isLiquidOrGas(block.getId())) { + break; + } + } + final int distance = (height - y) + 8; + return player.getBlockTrace(distance, true); + } + case TARGET_POINT_RANGE: + return player.getBlockTrace(tool.getRange(), true); + default: + return null; + } + } + + public void queueVisualization(FawePlayer player) { + Fawe.get().getVisualQueue().queue(player); + } + + /** + * Visualize the brush action + * @deprecated It is preferred to visualize only if a visualization is not in progress + * @param action + * @param player + * @throws MaxChangedBlocksException + */ + @Deprecated + public synchronized void visualize(BrushTool.BrushAction action, Player player) throws MaxChangedBlocksException { + FawePlayer fp = FawePlayer.wrap(player); + EditSession editSession = new EditSessionBuilder(player.getWorld()) + .player(fp) + .allowedRegionsEverywhere() + .autoQueue(false) + .blockBag(null) + .changeSetNull() + .combineStages(false) + .build(); + VisualExtent newVisualExtent = new VisualExtent(editSession.getExtent(), editSession.getQueue()); + editSession.setExtent(newVisualExtent); + Vector position = getPosition(editSession, player); + if (position != null) { + build(BrushTool.BrushAction.PRIMARY, editSession, position, tool.getMaterial(), tool.getSize()); + } + if (visualExtent != null) { + // clear old data + visualExtent.clear(newVisualExtent, fp); + } + visualExtent = newVisualExtent; + newVisualExtent.visualize(fp); + } + + public void clear(Player player) { + FawePlayer fp = FawePlayer.wrap(player); + Fawe.get().getVisualQueue().dequeue(fp); + if (visualExtent != null) { + visualExtent.clear(null, fp); + } + } + + @Override + public boolean move(Player player) { + return true; + } + + @Override + public boolean increment(int amount) { + int max = WorldEdit.getInstance().getConfiguration().maxBrushRadius; + double newSize = Math.max(0, Math.min(max, tool.getSize() + amount)); + tool.setSize(newSize); + return true; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualChunk.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualChunk.java new file mode 100644 index 00000000..a144abf1 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualChunk.java @@ -0,0 +1,171 @@ +package com.boydti.fawe.object.brush.visualization; + +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.collection.SparseBitSet; +import com.boydti.fawe.object.visitor.FaweChunkVisitor; +import com.boydti.fawe.util.MathMan; +import com.sk89q.jnbt.CompoundTag; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +/** + * FAWE visualizations display glass (20) as a placeholder + * - Using a non transparent block can cause FPS lag + */ +public class VisualChunk extends FaweChunk { + + public static int VISUALIZE_BLOCK = (95 << 4); + + private SparseBitSet add; + private SparseBitSet remove; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param x + * @param z + */ + public VisualChunk(int x, int z) { + super(null, x, z); + this.add = new SparseBitSet(); + this.remove = new SparseBitSet(); + } + + protected VisualChunk(int x, int z, SparseBitSet add, SparseBitSet remove) { + super(null, x, z); + this.add = add; + this.remove = remove; + } + + public int size() { + return add.cardinality() + remove.cardinality(); + } + + private final int getIndex(int x, int y, int z) { + return MathMan.tripleBlockCoordChar(x, y, z); + } + + @Override + public int getBitMask() { + return 0; + } + + @Override + public int getBlockCombinedId(int x, int y, int z) { + int index = getIndex(x, y, z); + if (add.get(index)) { + return VISUALIZE_BLOCK; + } else if (remove.get(index)) { + return 1; + } else { + return 0; + } + } + + @Override + public void forEachQueuedBlock(FaweChunkVisitor onEach) { + int index = -1; + while ((index = add.nextSetBit(index + 1)) != -1) { + int x = MathMan.untripleBlockCoordX(index); + int y = MathMan.untripleBlockCoordY(index); + int z = MathMan.untripleBlockCoordZ(index); + onEach.run(x, y, z, VISUALIZE_BLOCK); + } + index = -1; + while ((index = remove.nextSetBit(index + 1)) != -1) { + int x = MathMan.untripleBlockCoordX(index); + int y = MathMan.untripleBlockCoordY(index); + int z = MathMan.untripleBlockCoordZ(index); + onEach.run(x, y, z, 1); + } + } + + @Override + public byte[] getBiomeArray() { + return new byte[256]; + } + + @Override + public FaweChunk getChunk() { + return this; + } + + @Override + public void setTile(int x, int y, int z, CompoundTag tile) { + // Unsupported + } + + @Override + public void setEntity(CompoundTag entity) { + // Unsupported + } + + @Override + public void removeEntity(UUID uuid) { + // Unsupported + } + + @Override + public void setBlock(int x, int y, int z, int id, int data) { + int index = getIndex(x, y, z); + try { + if (id == 0) { + add.clear(index); + remove.set(index); + } else { + remove.clear(index); + add.set(index); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public void unset(int x, int y, int z) { + int index = getIndex(x, y, z); + remove.clear(index); + add.clear(index); + } + + @Override + public Set getEntities() { + return new HashSet<>(); + } + + @Override + public Set getEntityRemoves() { + return new HashSet<>(); + } + + @Override + public Map getTiles() { + return new HashMap<>(); + } + + @Override + public CompoundTag getTile(int x, int y, int z) { + return null; + } + + @Override + public void setBiome(int x, int z, byte biome) { + // Unsupported + } + + @Override + public FaweChunk copy(boolean shallow) { + if (shallow) { + return new VisualChunk(getX(), getZ(), add, remove); + } else { + return new VisualChunk(getX(), getZ(), add.clone(), remove.clone()); + } + } + + @Override + public FaweChunk call() { + return this; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java new file mode 100644 index 00000000..470887fa --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java @@ -0,0 +1,110 @@ +package com.boydti.fawe.object.brush.visualization; + +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.example.NullQueueCharFaweChunk; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.object.visitor.FaweChunkVisitor; +import com.boydti.fawe.util.MathMan; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.Vector2D; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.extent.AbstractDelegateExtent; +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.world.biome.BaseBiome; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import it.unimi.dsi.fastutil.objects.ObjectIterator; + +public class VisualExtent extends AbstractDelegateExtent { + + private final FaweQueue queue; + private Long2ObjectMap chunks = new Long2ObjectOpenHashMap<>(); + + public VisualExtent(Extent parent, FaweQueue queue) { + super(parent); + this.queue = queue; + } + + @Override + public boolean setBlock(Vector location, BaseBlock block) throws WorldEditException { + return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); + } + + public VisualChunk getChunk(int cx, int cz) { + return chunks.get(MathMan.pairInt(cx, cz)); + } + + @Override + public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException { + BaseBlock previous = super.getLazyBlock(x, y, z); + int cx = x >> 4; + int cz = z >> 4; + long chunkPair = MathMan.pairInt(cx, cz); + VisualChunk chunk = chunks.get(chunkPair); + if (previous.equals(block)) { + if (chunk != null) { + chunk.unset(x, y, z); + } + return false; + } else { + if (chunk == null) { + chunk = new VisualChunk(cx, cz); + chunks.put(chunkPair, chunk); + } + chunk.setBlock(x, y, z, block.getId(), block.getData()); + return true; + } + } + + @Override + public boolean setBiome(Vector2D position, BaseBiome biome) { + // Do nothing + return false; + } + + public void clear(VisualExtent other, FawePlayer... players) { + ObjectIterator> iter = chunks.long2ObjectEntrySet().iterator(); + while (iter.hasNext()) { + Long2ObjectMap.Entry entry = iter.next(); + long pair = entry.getLongKey(); + int cx = MathMan.unpairIntX(pair); + int cz = MathMan.unpairIntY(pair); + VisualChunk chunk = entry.getValue(); + final VisualChunk otherChunk = other != null ? other.getChunk(cx, cz) : null; + final CharFaweChunk newChunk = new NullQueueCharFaweChunk(cx, cz); + final int bx = cx << 4; + final int bz = cz << 4; + if (otherChunk == null) { + chunk.forEachQueuedBlock(new FaweChunkVisitor() { + @Override + public void run(int localX, int y, int localZ, int combined) { + combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0); + newChunk.setBlock(localX, y, localZ, FaweCache.getId(combined), FaweCache.getData(combined)); + } + }); + } else { + chunk.forEachQueuedBlock(new FaweChunkVisitor() { + @Override + public void run(int localX, int y, int localZ, int combined) { + if (combined != otherChunk.getBlockCombinedId(localX, y, localZ)) { + combined = queue.getCombinedId4Data(bx + localX, y, bz + localZ, 0); + newChunk.setBlock(localX, y, localZ, FaweCache.getId(combined), FaweCache.getData(combined)); + } + } + }); + } + if (newChunk.getTotalCount() != 0) { + queue.sendBlockUpdate(newChunk, players); + } + } + } + + public void visualize(FawePlayer players) { + for (VisualChunk chunk : chunks.values()) { + queue.sendBlockUpdate(chunk, players); + } + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java new file mode 100644 index 00000000..8979312e --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java @@ -0,0 +1,7 @@ +package com.boydti.fawe.object.brush.visualization; + +public enum VisualMode { + NONE, + POINT, + OUTLINE +} diff --git a/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java new file mode 100644 index 00000000..9affa8f8 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java @@ -0,0 +1,66 @@ +package com.boydti.fawe.object.brush.visualization; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.Tool; +import com.sk89q.worldedit.command.tool.brush.Brush; +import com.sk89q.worldedit.entity.Player; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class VisualQueue { + + private ConcurrentHashMap playerMap; + + public VisualQueue() { + playerMap = new ConcurrentHashMap<>(); + Runnable task = new Runnable() { + @Override + public void run() { + long allowedTick = Fawe.get().getTimer().getTick() - 1; + Iterator> iter = playerMap.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + Long time = entry.getValue(); + if (time < allowedTick) { + FawePlayer fp = entry.getKey(); + iter.remove(); + LocalSession session = fp.getSession(); + Player player = fp.getPlayer(); + Tool tool = session.getTool(player.getItemInHand()); + Brush brush; + if (tool instanceof BrushTool) { + brush = ((BrushTool) tool).getBrush(); + } else if (tool instanceof VisualBrush) { + brush = (Brush) tool; + } else { + continue; + } + if (brush instanceof VisualBrush) { + try { + ((VisualBrush) brush).visualize(BrushTool.BrushAction.PRIMARY, player); + } catch (Throwable e) { + WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); + } + } + } + } + TaskManager.IMP.laterAsync(this, 3); + } + }; + TaskManager.IMP.laterAsync(task, 3); + } + + public boolean dequeue(FawePlayer player) { + return playerMap.remove(player) != null; + } + + public void queue(FawePlayer player) { + playerMap.put(player, Fawe.get().getTimer().getTick()); + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java index a9827528..cbf860fb 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/DiskStorageHistory.java @@ -75,19 +75,8 @@ public class DiskStorageHistory extends FaweStreamChangeSet { private void init(UUID uuid, String worldName) { File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + worldName + File.separator + uuid); - int max = 0; - if (folder.exists()) { - for (File file : folder.listFiles()) { - String name = file.getName().split("\\.")[0]; - if (name.matches("\\d+")) { - int index = Integer.parseInt(name); - if (index > max) { - max = index; - } - } - } - } - init(uuid, ++max); + int max = MainUtil.getMaxFileId(folder); + init(uuid, max); } public DiskStorageHistory(String world, UUID uuid, int index) { diff --git a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java index 62f1e0c2..9d84c618 100644 --- a/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java +++ b/core/src/main/java/com/boydti/fawe/object/changeset/FaweChangeSet.java @@ -69,6 +69,11 @@ public abstract class FaweChangeSet implements ChangeSet { return world; } + @Deprecated + public boolean flushAsync() { + return closeAsync(); + } + public boolean closeAsync() { waitingAsync.incrementAndGet(); TaskManager.IMP.async(new Runnable() { diff --git a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java index 183dda68..815066c6 100644 --- a/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java +++ b/core/src/main/java/com/boydti/fawe/object/clipboard/WorldCopyClipboard.java @@ -53,6 +53,7 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { final Vector pos = new Vector(); if (region instanceof CuboidRegion) { if (air) { + ((CuboidRegion) region).setUseOldIterator(true); RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { @Override public boolean apply(Vector pos) throws WorldEditException { @@ -76,27 +77,33 @@ public class WorldCopyClipboard extends ReadOnlyClipboard { }, editSession); Operations.completeBlindly(visitor); } else { - RegionVisitor visitor = new RegionVisitor(region, new RegionFunction() { + CuboidRegion cuboidEquivalent = new CuboidRegion(region.getMinimumPoint(), region.getMaximumPoint()); + cuboidEquivalent.setUseOldIterator(true); + RegionVisitor visitor = new RegionVisitor(cuboidEquivalent, new RegionFunction() { @Override public boolean apply(Vector pos) throws WorldEditException { - int x = pos.getBlockX(); - int y = pos.getBlockY(); - int z = pos.getBlockZ(); - BaseBlock block = getBlockAbs(x, y, z); - if (block == EditSession.nullBlock) { - return false; + if (region.contains(pos)) { + int x = pos.getBlockX(); + int y = pos.getBlockY(); + int z = pos.getBlockZ(); + BaseBlock block = getBlockAbs(x, y, z); + pos.mutX(x - mx); + pos.mutY(y - my); + pos.mutZ(z - mz); + CompoundTag tag = block.getNbtData(); + if (tag != null) { + Map values = ReflectionUtils.getMap(tag.getValue()); + values.put("x", new IntTag(pos.getBlockX())); + values.put("y", new IntTag(pos.getBlockY())); + values.put("z", new IntTag(pos.getBlockZ())); + } + task.run(pos, block); + } else { + pos.mutX(pos.getBlockX() - mx); + pos.mutY(pos.getBlockY() - my); + pos.mutZ(pos.getBlockZ() - mz); + task.run(pos, EditSession.nullBlock); } - pos.mutX(x - mx); - pos.mutY(y - my); - pos.mutZ(z - mz); - CompoundTag tag = block.getNbtData(); - if (tag != null) { - Map values = ReflectionUtils.getMap(tag.getValue()); - values.put("x", new IntTag(pos.getBlockX())); - values.put("y", new IntTag(pos.getBlockY())); - values.put("z", new IntTag(pos.getBlockZ())); - } - task.run(pos, block); return true; } }, editSession); diff --git a/core/src/main/java/com/boydti/fawe/object/io/PGZIPBlock.java b/core/src/main/java/com/boydti/fawe/object/io/PGZIPBlock.java new file mode 100644 index 00000000..25cc6248 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/io/PGZIPBlock.java @@ -0,0 +1,43 @@ +package com.boydti.fawe.object.io; + +import java.util.concurrent.Callable; + +public class PGZIPBlock implements Callable { + public PGZIPBlock(final PGZIPOutputStream parent) { + STATE = new PGZIPThreadLocal(parent); + } + + /** This ThreadLocal avoids the recycling of a lot of memory, causing lumpy performance. */ + protected final ThreadLocal STATE; + public static final int SIZE = 64 * 1024; + // private final int index; + protected final byte[] in = new byte[SIZE]; + protected int in_length = 0; + + /* + public Block(@Nonnegative int index) { + this.index = index; + } + */ + // Only on worker thread + @Override + public byte[] call() throws Exception { + // LOG.info("Processing " + this + " on " + Thread.currentThread()); + + PGZIPState state = STATE.get(); + // ByteArrayOutputStream buf = new ByteArrayOutputStream(in.length); // Overestimate output size required. + // DeflaterOutputStream def = newDeflaterOutputStream(buf); + state.def.reset(); + state.buf.reset(); + state.str.write(in, 0, in_length); + state.str.flush(); + + // return Arrays.copyOf(in, in_length); + return state.buf.toByteArray(); + } + + @Override + public String toString() { + return "Block" /* + index */ + "(" + in_length + "/" + in.length + " bytes)"; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java b/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java index 259f88eb..fccb2a4b 100644 --- a/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java +++ b/core/src/main/java/com/boydti/fawe/object/io/PGZIPOutputStream.java @@ -37,7 +37,7 @@ public class PGZIPOutputStream extends FilterOutputStream { private int strategy = Deflater.HUFFMAN_ONLY; @Nonnull - private Deflater newDeflater() { + protected Deflater newDeflater() { Deflater def = new Deflater(level, true); def.setStrategy(strategy); return def; @@ -52,63 +52,16 @@ public class PGZIPOutputStream extends FilterOutputStream { } @Nonnull - private static DeflaterOutputStream newDeflaterOutputStream(@Nonnull OutputStream out, @Nonnull Deflater deflater) { + protected static DeflaterOutputStream newDeflaterOutputStream(@Nonnull OutputStream out, @Nonnull Deflater deflater) { return new DeflaterOutputStream(out, deflater, 512, true); } - private class Block implements Callable { - - private class State { - - private final Deflater def = newDeflater(); - private final ByteArrayOutputStream buf = new ByteArrayOutputStream(SIZE); - private final DeflaterOutputStream str = newDeflaterOutputStream(buf, def); - } - /** This ThreadLocal avoids the recycling of a lot of memory, causing lumpy performance. */ - private final ThreadLocal STATE = new ThreadLocal() { - @Override - protected State initialValue() { - return new State(); - } - }; - public static final int SIZE = 64 * 1024; - // private final int index; - private final byte[] in = new byte[SIZE]; - private int in_length = 0; - - /* - public Block(@Nonnegative int index) { - this.index = index; - } - */ - // Only on worker thread - @Override - public byte[] call() throws Exception { - // LOG.info("Processing " + this + " on " + Thread.currentThread()); - - State state = STATE.get(); - // ByteArrayOutputStream buf = new ByteArrayOutputStream(in.length); // Overestimate output size required. - // DeflaterOutputStream def = newDeflaterOutputStream(buf); - state.def.reset(); - state.buf.reset(); - state.str.write(in, 0, in_length); - state.str.flush(); - - // return Arrays.copyOf(in, in_length); - return state.buf.toByteArray(); - } - - @Override - public String toString() { - return "Block" /* + index */ + "(" + in_length + "/" + in.length + " bytes)"; - } - } // TODO: Share, daemonize. private final ExecutorService executor; private final int nthreads; private final CRC32 crc = new CRC32(); private final BlockingQueue> emitQueue; - private Block block = new Block(/* 0 */); + private PGZIPBlock block = new PGZIPBlock(this/* 0 */); /** Used as a sentinel for 'closed'. */ private int bytesWritten = 0; @@ -201,7 +154,7 @@ public class PGZIPOutputStream extends FilterOutputStream { private void submit() throws IOException { emitUntil(nthreads - 1); emitQueue.add(executor.submit(block)); - block = new Block(/* block.index + 1 */); + block = new PGZIPBlock(this/* block.index + 1 */); } // Emit If Available - submit always diff --git a/core/src/main/java/com/boydti/fawe/object/io/PGZIPState.java b/core/src/main/java/com/boydti/fawe/object/io/PGZIPState.java new file mode 100644 index 00000000..8e31eda7 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/io/PGZIPState.java @@ -0,0 +1,19 @@ +package com.boydti.fawe.object.io; + +import java.io.ByteArrayOutputStream; +import java.util.zip.Deflater; +import java.util.zip.DeflaterOutputStream; + +public class PGZIPState { + protected final DeflaterOutputStream str; + protected final ByteArrayOutputStream buf; + protected final Deflater def; + + public PGZIPState(PGZIPOutputStream parent) { + this.def = parent.newDeflater(); + this.buf = new ByteArrayOutputStream(PGZIPBlock.SIZE); + this.str = parent.newDeflaterOutputStream(buf, def); + } + + +} diff --git a/core/src/main/java/com/boydti/fawe/object/io/PGZIPThreadLocal.java b/core/src/main/java/com/boydti/fawe/object/io/PGZIPThreadLocal.java new file mode 100644 index 00000000..de3c0721 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/io/PGZIPThreadLocal.java @@ -0,0 +1,15 @@ +package com.boydti.fawe.object.io; + +public class PGZIPThreadLocal extends ThreadLocal { + + private final PGZIPOutputStream parent; + + public PGZIPThreadLocal(PGZIPOutputStream parent) { + this.parent = parent; + } + + @Override + protected PGZIPState initialValue() { + return new PGZIPState(parent); + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java b/core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java new file mode 100644 index 00000000..79daa889 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/visitor/FaweChunkVisitor.java @@ -0,0 +1,12 @@ +package com.boydti.fawe.object.visitor; + +public abstract class FaweChunkVisitor { + /** + * The will run for each set block in the chunk + * @param localX The x position in the chunk (0-15) + * @param y The y position (0 - 255) + * @param localZ The z position in the chunk (0-15) + * @param combined The combined id + */ + public abstract void run(int localX, int y, int localZ, int combined); +} 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 ca2509ab..6ffb0245 100644 --- a/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java +++ b/core/src/main/java/com/boydti/fawe/util/DelegateFaweQueue.java @@ -16,7 +16,6 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BaseBiome; import java.io.File; import java.util.Collection; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentLinkedDeque; @@ -222,8 +221,8 @@ public class DelegateFaweQueue extends FaweQueue { } @Override - public void sendBlockUpdate(Map> blockMap, FawePlayer... players) { - parent.sendBlockUpdate(blockMap, players); + public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) { + parent.sendBlockUpdate(chunk, players); } @Deprecated diff --git a/core/src/main/java/com/boydti/fawe/util/MainUtil.java b/core/src/main/java/com/boydti/fawe/util/MainUtil.java index efa4dbfd..09af0afd 100644 --- a/core/src/main/java/com/boydti/fawe/util/MainUtil.java +++ b/core/src/main/java/com/boydti/fawe/util/MainUtil.java @@ -56,6 +56,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.zip.GZIPInputStream; import java.util.zip.ZipEntry; @@ -180,6 +181,29 @@ public class MainUtil { } } + public static int getMaxFileId(File folder) { + final AtomicInteger max = new AtomicInteger(); + if (folder.exists()) { + MainUtil.traverse(folder.toPath(), new RunnableVal2() { + @Override + public void run(Path path, BasicFileAttributes attr) { + try { + String file = path.getFileName().toString(); + int index = file.indexOf('.'); + if (index == -1) { + return; + } + int id = Integer.parseInt(file.substring(0, index)); + if (id > max.get()) { + max.set(id); + } + } catch (NumberFormatException ignore){} + } + }); + } + return max.get() + 1; + } + public static File getFile(File base, String path) { if (Paths.get(path).isAbsolute()) { return new File(path); diff --git a/core/src/main/java/com/boydti/fawe/util/MathMan.java b/core/src/main/java/com/boydti/fawe/util/MathMan.java index 31649a18..4dac4b72 100644 --- a/core/src/main/java/com/boydti/fawe/util/MathMan.java +++ b/core/src/main/java/com/boydti/fawe/util/MathMan.java @@ -43,6 +43,20 @@ public class MathMan { 253, 254, 254, 255 }; + public static final int wrap(int value, int min, int max) { + if (max <= min) { + return value; + } + int diff = max - min + 1; + if (value < min) { + return max - ((min - value) % diff); + } else if (value > max) { + return min + ((value - min) % diff); + } else { + return value; + } + } + public static final long inverseRound(double val) { long round = Math.round(val); return (long) (round + Math.signum(val - round)); @@ -84,6 +98,22 @@ public class MathMan { return (short) ((x & 15) << 12 | (z & 15) << 8 | y); } + public static final char tripleBlockCoordChar(int x, int y, int z) { + return (char) ((x & 15) << 12 | (z & 15) << 8 | y); + } + + public static final int untripleBlockCoordX(int triple) { + return (triple >> 12) & 0xF; + } + + public static final int untripleBlockCoordY(int triple) { + return (triple & 0xFF); + } + + public static final int untripleBlockCoordZ(int triple) { + return (triple >> 8) & 0xF; + } + public static int tripleSearchCoords(int x, int y, int z) { byte b1 = (byte) y; byte b3 = (byte) (x); diff --git a/core/src/main/java/com/boydti/fawe/util/Updater.java b/core/src/main/java/com/boydti/fawe/util/Updater.java index 25b393bb..e97c6d1a 100644 --- a/core/src/main/java/com/boydti/fawe/util/Updater.java +++ b/core/src/main/java/com/boydti/fawe/util/Updater.java @@ -4,15 +4,21 @@ import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweVersion; import java.io.File; import java.io.FileOutputStream; +import java.io.IOException; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.util.Scanner; public class Updater { - private static FaweVersion newVersion = null; + private FaweVersion newVersion; + private String changes = "N/A"; - public static void update(String platform, FaweVersion currentVersion) { + public String getChanges() throws IOException { + return changes; + } + + public void update(String platform, FaweVersion currentVersion) { if (currentVersion == null || platform == null) { return; } @@ -42,7 +48,11 @@ public class Updater { fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); } Fawe.debug("Updated FAWE to " + versionString); - MainUtil.sendAdmin("Restart to update FAWE with these changes: " + "http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)); + Scanner scanner = new Scanner(new URL("http://boydti.com/fawe/cl?" + Integer.toHexString(Fawe.get().getVersion().hash)).openStream(), "UTF-8"); + changes = scanner.useDelimiter("\\A").next(); + scanner.close(); + MainUtil.sendAdmin("&7Restart to update FAWE with these changes: &c/fawe changelog &7or&c " + "http://boydti.com/fawe/cl?" + Integer.toHexString(currentVersion.hash)); + } } } diff --git a/core/src/main/java/com/boydti/fawe/wrappers/FakePlayer.java b/core/src/main/java/com/boydti/fawe/wrappers/FakePlayer.java index 4d8cd041..d8cd8d2d 100644 --- a/core/src/main/java/com/boydti/fawe/wrappers/FakePlayer.java +++ b/core/src/main/java/com/boydti/fawe/wrappers/FakePlayer.java @@ -122,7 +122,7 @@ public class FakePlayer extends LocalPlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return FakePlayer.this; } }; diff --git a/core/src/main/java/com/sk89q/worldedit/BlockVector.java b/core/src/main/java/com/sk89q/worldedit/BlockVector.java index 84d2e162..20965c52 100644 --- a/core/src/main/java/com/sk89q/worldedit/BlockVector.java +++ b/core/src/main/java/com/sk89q/worldedit/BlockVector.java @@ -84,6 +84,10 @@ public class BlockVector extends Vector { } + public boolean equals(BlockVector obj) { + return obj.getBlockX() == this.getBlockX() && obj.getBlockY() == this.getBlockY() && obj.getBlockZ() == this.getBlockZ(); + } + @Override public int hashCode() { return ((int) getX() ^ ((int) getZ() << 16)) ^ ((int) getY() << 30); diff --git a/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java b/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java index 509e756e..d475cf5a 100644 --- a/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java +++ b/core/src/main/java/com/sk89q/worldedit/CuboidClipboard.java @@ -454,14 +454,14 @@ public class CuboidClipboard { } if (reverse) { for (int i = 0; i < numRotations; ++i) { - if (block.hasWildcardData()) { + if (block.isImmutable()) { block = new BaseBlock(block); } block.rotate90Reverse(); } } else { for (int i = 0; i < numRotations; ++i) { - if (block.hasWildcardData()) { + if (block.isImmutable()) { block = new BaseBlock(block); } block.rotate90(); diff --git a/core/src/main/java/com/sk89q/worldedit/EditSession.java b/core/src/main/java/com/sk89q/worldedit/EditSession.java index 649d230d..97dbd95a 100644 --- a/core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -415,6 +415,22 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting return traverser == null ? null : traverser.get(); } + public Extent getBypassAll() { + return bypassAll; + } + + public Extent getBypassHistory() { + return bypassHistory; + } + + public Extent getExtent() { + return extent; + } + + public void setExtent(AbstractDelegateExtent extent) { + this.extent = extent; + } + /** * Get the FawePlayer or null * @return @@ -2151,20 +2167,26 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final double invRadiusX = 1 / radiusX; final double invRadiusZ = 1 / radiusZ; + int px = pos.getBlockX(); + int py = pos.getBlockY(); + int pz = pos.getBlockZ(); + MutableBlockVector mutable = new MutableBlockVector(); + final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusZ = (int) Math.ceil(radiusZ); - + double dx, dxz, dz; double nextXn = 0; forX: for (int x = 0; x <= ceilRadiusX; ++x) { final double xn = nextXn; nextXn = (x + 1) * invRadiusX; double nextZn = 0; + dx = xn * xn; forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { final double zn = nextZn; nextZn = (z + 1) * invRadiusZ; - - final double distanceSq = this.lengthSq(xn, zn); - if (distanceSq > 1) { + dz = zn * zn; + dxz = dx + dz; + if (dxz > 1) { if (z == 0) { break forX; } @@ -2172,16 +2194,16 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } if (!filled) { - if ((this.lengthSq(nextXn, zn) <= 1) && (this.lengthSq(xn, nextZn) <= 1)) { + if ((dz + nextXn * nextXn <= 1) && (nextZn * nextZn + dx <= 1)) { continue; } } for (int y = 0; y < height; ++y) { - this.setBlock(pos.add(x, y, z), block); - this.setBlock(pos.add(-x, y, z), block); - this.setBlock(pos.add(x, y, -z), block); - this.setBlock(pos.add(-x, y, -z), block); + this.setBlock(mutable.setComponents(px + x, py + y, pz + z), block); + this.setBlock(mutable.setComponents(px - x, py + y, pz + z), block); + this.setBlock(mutable.setComponents(px + x, py + y, pz - z), block); + this.setBlock(mutable.setComponents(px - x, py + y, pz - z), block); } } } @@ -2189,6 +2211,82 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting return this.changes; } + public int makeCircle(Vector pos, final Pattern block, double radiusX, double radiusY, double radiusZ, boolean filled, Vector normal) throws MaxChangedBlocksException { + radiusX += 0.5; + radiusY += 0.5; + radiusZ += 0.5; + + normal = normal.normalize(); + double nx = normal.getX(); + double ny = normal.getY(); + double nz = normal.getZ(); + + + final double invRadiusX = 1 / radiusX; + final double invRadiusY = 1 / radiusY; + final double invRadiusZ = 1 / radiusZ; + + int px = pos.getBlockX(); + int py = pos.getBlockY(); + int pz = pos.getBlockZ(); + MutableBlockVector mutable = new MutableBlockVector(); + + final int ceilRadiusX = (int) Math.ceil(radiusX); + final int ceilRadiusY = (int) Math.ceil(radiusY); + final int ceilRadiusZ = (int) Math.ceil(radiusZ); + + double threshold = 0.5; + + LocalBlockVectorSet set = new LocalBlockVectorSet(); + + double nextXn = 0; + double dx, dy, dz, dxy, dxyz; + forX: for (int x = 0; x <= ceilRadiusX; ++x) { + final double xn = nextXn; + dx = xn * xn; + nextXn = (x + 1) * invRadiusX; + double nextYn = 0; + forY: for (int y = 0; y <= ceilRadiusY; ++y) { + final double yn = nextYn; + dy = yn * yn; + dxy = dx + dy; + nextYn = (y + 1) * invRadiusY; + double nextZn = 0; + forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { + final double zn = nextZn; + dz = zn * zn; + dxyz = dxy + dz; + nextZn = (z + 1) * invRadiusZ; + if (dxyz > 1) { + if (z == 0) { + if (y == 0) { + break forX; + } + break forY; + } + break forZ; + } + if (!filled) { + if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1) { + continue; + } + } + + if (Math.abs((x) * nx + (y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py + y, pz + z), block); + if (Math.abs((-x) * nx + (y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py + y, pz + z), block); + if (Math.abs((x) * nx + (-y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py - y, pz + z), block); + if (Math.abs((x) * nx + (y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py + y, pz - z), block); + if (Math.abs((-x) * nx + (-y) * ny + (z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py - y, pz + z), block); + if (Math.abs((x) * nx + (-y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px + x, py - y, pz - z), block); + if (Math.abs((-x) * nx + (y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py + y, pz - z), block); + if (Math.abs((-x) * nx + (-y) * ny + (-z) * nz) < threshold) setBlock(mutable.setComponents(px - x, py - y, pz - z), block); + } + } + } + + return changes; + } + /** * Makes a sphere. * @@ -2224,25 +2322,34 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting final double invRadiusY = 1 / radiusY; final double invRadiusZ = 1 / radiusZ; + int px = pos.getBlockX(); + int py = pos.getBlockY(); + int pz = pos.getBlockZ(); + MutableBlockVector mutable = new MutableBlockVector(); + final int ceilRadiusX = (int) Math.ceil(radiusX); final int ceilRadiusY = (int) Math.ceil(radiusY); final int ceilRadiusZ = (int) Math.ceil(radiusZ); double nextXn = 0; + double dx, dy, dz, dxy, dxyz; forX: for (int x = 0; x <= ceilRadiusX; ++x) { final double xn = nextXn; + dx = xn * xn; nextXn = (x + 1) * invRadiusX; double nextYn = 0; forY: for (int y = 0; y <= ceilRadiusY; ++y) { final double yn = nextYn; + dy = yn * yn; + dxy = dx + dy; nextYn = (y + 1) * invRadiusY; double nextZn = 0; forZ: for (int z = 0; z <= ceilRadiusZ; ++z) { final double zn = nextZn; + dz = zn * zn; + dxyz = dxy + dz; nextZn = (z + 1) * invRadiusZ; - - final double distanceSq = this.lengthSq(xn, yn, zn); - if (distanceSq > 1) { + if (dxyz > 1) { if (z == 0) { if (y == 0) { break forX; @@ -2253,19 +2360,19 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } if (!filled) { - if ((this.lengthSq(nextXn, yn, zn) <= 1) && (this.lengthSq(xn, nextYn, zn) <= 1) && (this.lengthSq(xn, yn, nextZn) <= 1)) { + if (nextXn * nextXn + dy + dz <= 1 && nextYn * nextYn + dx + dz <= 1 && nextZn * nextZn + dx + dy <= 1 ) { continue; } } - this.setBlock(pos.add(x, y, z), block); - this.setBlock(pos.add(-x, y, z), block); - this.setBlock(pos.add(x, -y, z), block); - this.setBlock(pos.add(x, y, -z), block); - this.setBlock(pos.add(-x, -y, z), block); - this.setBlock(pos.add(x, -y, -z), block); - this.setBlock(pos.add(-x, y, -z), block); - this.setBlock(pos.add(-x, -y, -z), block); + this.setBlock(mutable.setComponents(px + x, py + y, pz + z), block); + this.setBlock(mutable.setComponents(px - x, py + y, pz + z), block); + this.setBlock(mutable.setComponents(px + x, py - y, pz + z), block); + this.setBlock(mutable.setComponents(px + x, py + y, pz - z), block); + this.setBlock(mutable.setComponents(px - x, py - y, pz + z), block); + this.setBlock(mutable.setComponents(px + x, py - y, pz - z), block); + this.setBlock(mutable.setComponents(px - x, py + y, pz - z), block); + this.setBlock(mutable.setComponents(px - x, py - y, pz - z), block); } } } @@ -2960,9 +3067,11 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } private Set getBallooned(final Set vset, final double radius) { + if (radius < 1) { + return vset; + } final Set returnset = new LocalBlockVectorSet(); 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++) { @@ -2979,6 +3088,9 @@ public class EditSession extends AbstractWorld implements HasFaweQueue, Lighting } private Set getStretched(final Set vset, final double radius) { + if (radius < 1) { + return vset; + } final Set returnset = new LocalBlockVectorSet(); final int ceilrad = (int) Math.ceil(radius); 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 9877d77e..742e30b3 100644 --- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -25,7 +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.brush.visualization.VisualBrush; import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; @@ -42,6 +42,7 @@ import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.Tool; +import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; @@ -440,6 +441,9 @@ public class LocalSession { } public synchronized void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) { + if (Settings.IMP.HISTORY.USE_DISK) { + LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE; + } // It should have already been flushed, but just in case! editSession.flushQueue(); if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) { @@ -953,6 +957,14 @@ public class LocalSession { return tools.get(item); } + @Nullable + public Tool getTool(Player player) { + if (tools.isEmpty()) { + return null; + } + return getTool(player.getItemInHand()); + } + /** * 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 @@ -963,36 +975,20 @@ public class LocalSession { * @throws InvalidToolBindException if the item can't be bound to that item */ public BrushTool getBrushTool(int item) throws InvalidToolBindException { + return getBrushTool(item, null); + } + + public BrushTool getBrushTool(int item, Player player) throws InvalidToolBindException { Tool tool = getTool(item); if (tool == null || !(tool instanceof BrushTool)) { tool = new BrushTool("worldedit.brush.sphere"); - setTool(item, tool); + setTool(item, tool, player); } 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. * @@ -1001,6 +997,10 @@ public class LocalSession { * @throws InvalidToolBindException if the item can't be bound to that item */ public void setTool(int item, @Nullable Tool tool) throws InvalidToolBindException { + setTool(item, tool, null); + } + + public void setTool(int item, @Nullable Tool tool, Player player) throws InvalidToolBindException { if (item > 0 && item < 255) { throw new InvalidToolBindException(item, "Blocks can't be used"); } else if (item == config.wandItem) { @@ -1008,8 +1008,17 @@ public class LocalSession { } else if (item == config.navigationWand) { throw new InvalidToolBindException(item, "Already used for the navigation wand"); } - - this.tools.put(item, tool); + Tool previous = this.tools.put(item, tool); + if (player != null) { + if (previous instanceof BrushTool) { + Brush brush = ((BrushTool) previous).getBrush(); + if (brush instanceof VisualBrush) { + ((VisualBrush) brush).clear(player); + } + } else if (previous instanceof VisualBrush) { + ((VisualBrush) tool).clear(player); + } + } } /** diff --git a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java index e46d9500..873d5dd0 100644 --- a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java +++ b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java @@ -1,6 +1,17 @@ package com.sk89q.worldedit; public class MutableBlockVector extends BlockVector { + private static ThreadLocal MUTABLE_CACHE = new ThreadLocal() { + @Override + protected MutableBlockVector initialValue() { + return new MutableBlockVector(); + } + }; + + public static Vector get(int x, int y, int z) { + return MUTABLE_CACHE.get().setComponents(x, y, z); + } + private int x,y,z; public MutableBlockVector(Vector v) { diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java new file mode 100644 index 00000000..d0da313a --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java @@ -0,0 +1,421 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.blocks; + +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.CuboidClipboard.FlipDirection; +import com.sk89q.worldedit.foundation.Block; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.world.registry.WorldData; + +import javax.annotation.Nullable; +import java.util.Collection; + +/** + * Represents a mutable "snapshot" of a block. + * + *

An instance of this block contains all the information needed to + * accurately reproduce the block, provided that the instance was + * made correctly. In some implementations, it may not be possible to get a + * snapshot of blocks correctly, so, for example, the NBT data for a block + * may be missing.

+ * + *

This class identifies blocks using an integer ID. However, IDs for + * a given block may differ between worlds so it is important that users of + * this class convert the ID from one "world space" to another "world space," + * a task that that is assisted with by working with the source and + * destination {@link WorldData} instances. Numeric IDs are utilized because + * they are more space efficient to store, and it also implies that internal + * uses of this class (i.e. history, etc.) do not need to worry about + * interning block string IDs.

+ * + *

A peculiar detail of this class is that it accepts {@code -1} as a + * valid data value. This is due to legacy reasons: WorldEdit uses -1 + * as a "wildcard" block value, even though a {@link Mask} would be + * more appropriate.

+ */ +@SuppressWarnings("deprecation") +public class BaseBlock extends Block implements TileEntityBlock { + + /** + * Indicates the highest possible block ID (inclusive) that can be used. + * This value is subject to change depending on the implementation, but + * internally this class only supports a range of 4096 IDs (for space + * reasons), which coincides with the number of possible IDs that official + * Minecraft supports as of version 1.7. + */ + public static final int MAX_ID = 4095; + + /** + * Indicates the maximum data value (inclusive) that can be used. A future + * version of Minecraft may abolish block data values. + */ + public static final int MAX_DATA = 15; + + // Instances of this class should be _as small as possible_ because there will + // be millions of instances of this object. + + private short id; + private short data; + @Nullable + private CompoundTag nbtData; + + /** + * Construct a block with the given ID and a data value of 0. + * + * @param id ID value + * @see #setId(int) + */ + public BaseBlock(int id) { + internalSetId(id); + internalSetData(0); + } + + /** + * Construct a block with the given ID and data value. + * + * @param id ID value + * @param data data value + * @see #setId(int) + * @see #setData(int) + */ + public BaseBlock(int id, int data) { + internalSetId(id); + internalSetData(data); + } + + /** + * Construct a block with the given ID, data value and NBT data structure. + * + * @param id ID value + * @param data data value + * @param nbtData NBT data, which may be null + */ + public BaseBlock(int id, int data, @Nullable CompoundTag nbtData) { + setId(id); + setData(data); + setNbtData(nbtData); + } + + /** + * Create a clone of another block. + * + * @param other the other block + */ + public BaseBlock(BaseBlock other) { + this(other.getId(), other.getData(), other.getNbtData()); + } + + /** + * Get the ID of the block. + * + * @return ID (between 0 and {@link #MAX_ID}) + */ + @Override + public int getId() { + return id; + } + + /** + * Set the block ID. + * + * @param id block id (between 0 and {@link #MAX_ID}). + */ + protected final void internalSetId(int id) { + if (id > MAX_ID) { + throw new IllegalArgumentException("Can't have a block ID above " + + MAX_ID + " (" + id + " given)"); + } + + if (id < 0) { + throw new IllegalArgumentException("Can't have a block ID below 0"); + } + + this.id = (short) id; + } + + /** + * Set the block ID. + * + * @param id block id (between 0 and {@link #MAX_ID}). + */ + @Override + public void setId(int id) { + internalSetId(id); + } + + /** + * Get the block's data value. + * + * @return data value (0-15) + */ + @Override + public int getData() { + return data; + } + + /** + * Set the block's data value. + * + * @param data block data value (between 0 and {@link #MAX_DATA}). + */ + protected final void internalSetData(int data) { + if (data > MAX_DATA) { + throw new IllegalArgumentException( + "Can't have a block data value above " + MAX_DATA + " (" + + data + " given)"); + } + + if (data < -1) { + throw new IllegalArgumentException("Can't have a block data value below -1"); + } + + this.data = (short) data; + } + + /** + * Set the block's data value. + * + * @param data block data value (between 0 and {@link #MAX_DATA}). + */ + @Override + public void setData(int data) { + internalSetData(data); + } + + /** + * Set both the block's ID and data value. + * + * @param id ID value + * @param data data value + * @see #setId(int) + * @see #setData(int) + */ + @Override + public void setIdAndData(int id, int data) { + setId(id); + setData(data); + } + + /** + * Returns whether the data value is -1, indicating that this block is to be + * used as a wildcard matching block. + * + * @return true if the data value is -1 + */ + @Override + public boolean hasWildcardData() { + return getData() == -1; + } + + @Override + public boolean hasNbtData() { + return getNbtData() != null; + } + + @Override + public String getNbtId() { + CompoundTag nbtData = getNbtData(); + if (nbtData == null) { + return ""; + } + Tag idTag = nbtData.getValue().get("id"); + if (idTag != null && idTag instanceof StringTag) { + return ((StringTag) idTag).getValue(); + } else { + return ""; + } + } + + @Nullable + @Override + public CompoundTag getNbtData() { + return nbtData; + } + + @Override + public void setNbtData(@Nullable CompoundTag nbtData) { + this.nbtData = nbtData; + } + + /** + * Get the type of block. + * + * @return the type + */ + public int getType() { + return getId(); + } + + /** + * Set the type of block. + * + * @param type the type to set + */ + public void setType(int type) { + setId(type); + } + + /** + * Returns true if it's air. + * + * @return if air + */ + public boolean isAir() { + return getType() == BlockID.AIR; + } + + /** + * Rotate this block 90 degrees. + * + * @return new data value + * @deprecated Use {@link BlockData#rotate90(int, int)} + */ + @Deprecated + public int rotate90() { + int newData = BlockData.rotate90(getType(), getData()); + setData(newData); + return newData; + } + + /** + * Rotate this block -90 degrees. + * + * @return new data value + * @deprecated Use {@link BlockData#rotate90Reverse(int, int)} + */ + @Deprecated + public int rotate90Reverse() { + int newData = BlockData.rotate90Reverse(getType(), getData()); + setData((short) newData); + return newData; + } + + /** + * Cycle the damage value of the block forward or backward + * + * @param increment 1 for forward, -1 for backward + * @return new data value + * @deprecated Use {@link BlockData#cycle(int, int, int)} + */ + @Deprecated + public int cycleData(int increment) { + int newData = BlockData.cycle(getType(), getData(), increment); + setData((short) newData); + return newData; + } + + /** + * Flip this block. + * + * @return this block + * @deprecated Use {@link BlockData#flip(int, int)} + */ + @Deprecated + public BaseBlock flip() { + setData((short) BlockData.flip(getType(), getData())); + return this; + } + + /** + * Flip this block. + * + * @param direction direction to flip in + * @return this block + * @deprecated Use {@link BlockData#flip(int, int, FlipDirection)} + */ + @Deprecated + public BaseBlock flip(FlipDirection direction) { + setData((short) BlockData.flip(getType(), getData(), direction)); + return this; + } + + /** + * Checks whether the type ID and data value are equal. + */ + @Override + public boolean equals(Object o) { + if (!(o instanceof BaseBlock)) { + return false; + } + + final BaseBlock otherBlock = (BaseBlock) o; + + return getType() == otherBlock.getType() && getData() == otherBlock.getData(); + + } + + public boolean equals(BaseBlock block) { + return block.getId() == this.getId() && block.getData() == this.getData(); + } + + /** + * Checks if the type is the same, and if data is the same if only data != -1. + * + * @param o other block + * @return true if equal + */ + public boolean equalsFuzzy(BaseBlock o) { + return (getType() == o.getType()) && (getData() == o.getData() || getData() == -1 || o.getData() == -1); + } + + /** + * @deprecated This method is silly, use {@link #containsFuzzy(java.util.Collection, BaseBlock)} instead. + */ + @Deprecated + public boolean inIterable(Iterable iter) { + for (BaseBlock block : iter) { + if (block.equalsFuzzy(this)) { + return true; + } + } + return false; + } + + /** + * @deprecated Use {@link Blocks#containsFuzzy(Collection, BaseBlock)} + */ + @Deprecated + public static boolean containsFuzzy(Collection collection, BaseBlock o) { + return Blocks.containsFuzzy(collection, o); + } + + @Override + public int hashCode() { + int ret = getId() << 3; + if (getData() != (byte) -1) ret |= getData(); + return ret; + } + + @Override + public String toString() { + return "Block{ID:" + getId() + ", Data: " + getData() + "}"; + } + + public boolean isImmutable() { + return false; + } + + public static Class inject() { + return BaseBlock.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java new file mode 100644 index 00000000..ef7fee33 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableBlock.java @@ -0,0 +1,36 @@ +package com.sk89q.worldedit.blocks; + +import com.sk89q.worldedit.CuboidClipboard; + +public class ImmutableBlock extends BaseBlock { + public ImmutableBlock(int id, int data) { + super(id, data); + } + + @Override + public void setData(int data) { + throw new IllegalStateException("Cannot set data"); + } + + @Override + public void setId(int id) { + throw new IllegalStateException("Cannot set id"); + } + + @Override + public BaseBlock flip() { + BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData()); + return clone.flip(); + } + + @Override + public BaseBlock flip(CuboidClipboard.FlipDirection direction) { + BaseBlock clone = new BaseBlock(getId(), getData(), getNbtData()); + return clone.flip(direction); + } + + @Override + public boolean isImmutable() { + return true; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java new file mode 100644 index 00000000..da580444 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/blocks/ImmutableDatalessBlock.java @@ -0,0 +1,26 @@ +package com.sk89q.worldedit.blocks; + +public class ImmutableDatalessBlock extends ImmutableBlock { + public ImmutableDatalessBlock(int id) { + super(id, 0); + } + + @Override + public int getData() { + return 0; + } + + @Override + public boolean equals(BaseBlock block) { + return block.getId() == this.getId(); + } + + @Override + public boolean equals(Object o) { + if (o instanceof BaseBlock) { + return ((BaseBlock) o).getId() == this.getId(); + } else { + return false; + } + } +} 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 3eb1f870..0d089368 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -25,9 +25,9 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.BlendBall; +import com.boydti.fawe.object.brush.CircleBrush; import com.boydti.fawe.object.brush.CommandBrush; import com.boydti.fawe.object.brush.CopyPastaBrush; -import com.boydti.fawe.object.brush.DoubleActionBrushTool; import com.boydti.fawe.object.brush.ErodeBrush; import com.boydti.fawe.object.brush.FlattenBrush; import com.boydti.fawe.object.brush.HeightBrush; @@ -106,9 +106,9 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.blendball") public void blendBallBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new BlendBall(), "worldedit.brush.blendball"); + tool.setBrush(new BlendBall(), "worldedit.brush.blendball", player); player.print(BBC.getPrefix() + BBC.BRUSH_BLEND_BALL.f(radius)); } @@ -123,12 +123,30 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.erode") public void erodeBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new ErodeBrush(), "worldedit.brush.erode"); + tool.setBrush(new ErodeBrush(), "worldedit.brush.erode", player); player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius)); } + @Command( + aliases = { "circle" }, + usage = " [radius]", + desc = "Choose the circle brush", + help = "Chooses the circle brush.", + min = 1, + max = 2 + ) + @CommandPermissions("worldedit.brush.sphere") + public void circleBrush(Player player, LocalSession session, Pattern fill, @Optional("5") double radius, @Switch('h') boolean hollow) throws WorldEditException { + worldEdit.checkMaxBrushRadius(radius); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); + tool.setSize(radius); + tool.setFill(fill); + tool.setBrush(new CircleBrush(tool, player), "worldedit.brush.circle", player); + player.print(BBC.getPrefix() + BBC.BRUSH_CIRCLE.f(radius)); + } + @Command( aliases = { "recursive", "recurse", "r" }, usage = " [radius]", @@ -141,9 +159,9 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.recursive") public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("2") double radius, @Switch('d') boolean depthFirst) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new RecurseBrush(tool, depthFirst), "worldedit.brush.recursive"); + tool.setBrush(new RecurseBrush(tool, depthFirst), "worldedit.brush.recursive", player); tool.setMask(new IdMask(editSession)); tool.setFill(fill); player.print(BBC.getPrefix() + BBC.BRUSH_RECURSIVE.f(radius)); @@ -165,10 +183,10 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.line") public void lineBrush(Player player, LocalSession session, 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()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setFill(fill); tool.setSize(radius); - tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line"); + tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line", player); player.print(BBC.getPrefix() + BBC.BRUSH_LINE.f(radius)); } @@ -183,10 +201,10 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.spline") public void splineBrush(Player player, LocalSession session, Pattern fill, @Optional("25") double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setFill(fill); tool.setSize(radius); - tool.setBrush(new SplineBrush(player, session, tool), "worldedit.brush.spline"); + tool.setBrush(new SplineBrush(player, session, tool), "worldedit.brush.spline", player); player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); } @@ -205,14 +223,14 @@ public class BrushCommands { public void sphereBrush(Player player, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setFill(fill); tool.setSize(radius); if (hollow) { - tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere"); + tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere", player); } else { - tool.setBrush(new SphereBrush(), "worldedit.brush.sphere"); + tool.setBrush(new SphereBrush(), "worldedit.brush.sphere", player); } if (fill instanceof BlockPattern) { BaseBlock block = ((BlockPattern) fill).getBlock(); @@ -245,14 +263,14 @@ public class BrushCommands { worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(height); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setFill(fill); tool.setSize(radius); if (hollow) { - tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder"); + tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder", player); } else { - tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder"); + tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder", player); } player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius, height)); } @@ -279,8 +297,8 @@ public class BrushCommands { worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockZ()); - BrushTool tool = session.getBrushTool(player.getItemInHand()); - tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard"); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); + tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard", player); player.print(BBC.getPrefix() + BBC.BRUSH_CLIPBOARD.s()); } @@ -305,9 +323,9 @@ public class BrushCommands { FawePlayer fp = FawePlayer.wrap(player); FaweLimit limit = Settings.IMP.getLimit(fp); iterations = Math.min(limit.MAX_ITERATIONS, iterations); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth"); + tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth", player); player.print(BBC.getPrefix() + BBC.BRUSH_SMOOTH.f(radius, iterations, (naturalBlocksOnly ? "natural blocks only" : "any block"))); } @@ -323,12 +341,12 @@ public class BrushCommands { public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); Pattern fill = new BlockPattern(new BaseBlock(0)); tool.setFill(fill); tool.setSize(radius); tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE))); - tool.setBrush(new SphereBrush(), "worldedit.brush.ex"); + tool.setBrush(new SphereBrush(), "worldedit.brush.ex", player); BBC.BRUSH_EXTINGUISHER.send(player, radius); player.print(BBC.getPrefix() + BBC.BRUSH_EXTINGUISHER.f(radius)); } @@ -349,9 +367,9 @@ public class BrushCommands { public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity"); + tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity", player); player.print(BBC.getPrefix() + BBC.BRUSH_GRAVITY.f(radius)); } @@ -431,19 +449,19 @@ public class BrushCommands { } } - DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); if (flat) { try { - tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape), "worldedit.brush.height"); + tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null, shape), "worldedit.brush.height", player); } catch (EmptyClipboardException ignore) { - tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null, shape), "worldedit.brush.height"); + tool.setBrush(new FlattenBrush(stream, rotation, yscale, tool, null, shape), "worldedit.brush.height", player); } } else { try { - tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height"); + tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null), "worldedit.brush.height", player); } catch (EmptyClipboardException ignore) { - tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height"); + tool.setBrush(new HeightBrush(stream, rotation, yscale, tool, null), "worldedit.brush.height", player); } } player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius)); @@ -464,9 +482,9 @@ public class BrushCommands { @CommandPermissions("worldedit.brush.copy") public void copy(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - DoubleActionBrushTool tool = session.getDoubleActionBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new CopyPastaBrush(tool), "worldedit.brush.copy"); + tool.setBrush(new CopyPastaBrush(tool), "worldedit.brush.copy", player); player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius)); } @@ -481,9 +499,9 @@ public class BrushCommands { ) @CommandPermissions("worldedit.brush.command") public void command(Player player, LocalSession session, @Optional("5") double radius, CommandContext args) throws WorldEditException { - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); String cmd = args.getJoinedStrings(1); - tool.setBrush(new CommandBrush(tool, cmd, radius), "worldedit.brush.copy"); + tool.setBrush(new CommandBrush(tool, cmd, radius), "worldedit.brush.copy", player); player.print(BBC.getPrefix() + BBC.BRUSH_COMMAND.f(cmd)); } @@ -526,9 +544,9 @@ public class BrushCommands { CreatureButcher flags = new CreatureButcher(player); flags.fromCommand(args); - BrushTool tool = session.getBrushTool(player.getItemInHand()); + BrushTool tool = session.getBrushTool(player.getItemInHand(), player); tool.setSize(radius); - tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher"); + tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher", player); player.print(BBC.getPrefix() + BBC.BRUSH_BUTCHER.f(radius)); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java index 7a791ae1..605cf1ae 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -61,7 +61,7 @@ public class ToolCommands { ) @CommandPermissions("worldedit.tool.inspect") public void inspectBrush(Player player, LocalSession session, @Optional("1") double radius) throws WorldEditException { - session.setTool(player.getItemInHand(), new InspectBrush()); + session.setTool(player.getItemInHand(), new InspectBrush(), player); BBC.TOOL_INSPECT.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -73,7 +73,7 @@ public class ToolCommands { max = 0 ) public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(player.getItemInHand(), null); + session.setTool(player.getItemInHand(), null, player); BBC.TOOL_NONE.send(player); } @@ -86,7 +86,7 @@ public class ToolCommands { ) @CommandPermissions("worldedit.tool.info") public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(player.getItemInHand(), new QueryTool()); + session.setTool(player.getItemInHand(), new QueryTool(), player); BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -110,7 +110,7 @@ public class ToolCommands { return; } - session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type))); + session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)), player); BBC.TOOL_TREE.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -124,7 +124,7 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.replacer") public void repl(Player player, LocalSession session, CommandContext args) throws WorldEditException { BaseBlock targetBlock = we.getBlock(player, args.getString(0)); - session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock)); + session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock), player); BBC.TOOL_REPL.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -138,7 +138,7 @@ public class ToolCommands { @CommandPermissions("worldedit.tool.data-cycler") public void cycler(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(player.getItemInHand(), new BlockDataCyler()); + session.setTool(player.getItemInHand(), new BlockDataCyler(), player); BBC.TOOL_CYCLER.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -160,7 +160,7 @@ public class ToolCommands { } Pattern pattern = we.getBlockPattern(player, args.getString(0)); - session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern)); + session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern), player); BBC.TOOL_FLOOD_FILL.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -173,7 +173,7 @@ public class ToolCommands { ) @CommandPermissions("worldedit.tool.deltree") public void deltree(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(player.getItemInHand(), new FloatingTreeRemover()); + session.setTool(player.getItemInHand(), new FloatingTreeRemover(), player); BBC.TOOL_DELTREE.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -186,7 +186,7 @@ public class ToolCommands { ) @CommandPermissions("worldedit.tool.farwand") public void farwand(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(player.getItemInHand(), new DistanceWand()); + session.setTool(player.getItemInHand(), new DistanceWand(), player); BBC.TOOL_FARWAND.send(player, ItemType.toHeldName(player.getItemInHand())); } @@ -202,7 +202,7 @@ public class ToolCommands { BaseBlock secondary = we.getBlock(player, args.getString(0)); BaseBlock primary = we.getBlock(player, args.getString(1)); - session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary)); + session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary), player); BBC.TOOL_LRBUILD_BOUND.send(player, ItemType.toHeldName(player.getItemInHand())); BBC.TOOL_LRBUILD_INFO.send(player, ItemType.toName(secondary.getType()), ItemType.toName(primary.getType())); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index af392378..db574166 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -1,7 +1,6 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.config.BBC; -import com.boydti.fawe.object.brush.DoubleActionBrushTool; import com.boydti.fawe.object.extent.DefaultTransformParser; import com.boydti.fawe.object.extent.ResettableExtent; import com.sk89q.minecraft.util.commands.Command; @@ -77,8 +76,6 @@ public class ToolUtilCommands { if (context == null || context.argsLength() == 0) { if (tool instanceof BrushTool) { ((BrushTool) tool).setMask(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setMask(null); } BBC.BRUSH_MASK_DISABLED.send(player); } else { @@ -90,8 +87,6 @@ public class ToolUtilCommands { Mask mask = we.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); if (tool instanceof BrushTool) { ((BrushTool) tool).setMask(mask); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setMask(mask); } BBC.BRUSH_MASK.send(player); } @@ -114,8 +109,6 @@ public class ToolUtilCommands { if (context == null || context.argsLength() == 0) { if (tool instanceof BrushTool) { ((BrushTool) tool).setSourceMask(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setMask(null); } BBC.BRUSH_SOURCE_MASK_DISABLED.send(player); } else { @@ -127,8 +120,6 @@ public class ToolUtilCommands { Mask mask = we.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); if (tool instanceof BrushTool) { ((BrushTool) tool).setSourceMask(mask); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setSourceMask(mask); } BBC.BRUSH_SOURCE_MASK.send(player); } @@ -150,8 +141,6 @@ public class ToolUtilCommands { if (context == null || context.argsLength() == 0) { if (tool instanceof BrushTool) { ((BrushTool) tool).setTransform(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setTransform(null); } BBC.BRUSH_TRANSFORM_DISABLED.send(player); } else { @@ -163,8 +152,6 @@ public class ToolUtilCommands { ResettableExtent transform = transformParser.parseFromInput(context.getJoinedStrings(0), parserContext); if (tool instanceof BrushTool) { ((BrushTool) tool).setTransform(transform); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setTransform(transform); } BBC.BRUSH_TRANSFORM.send(player); } @@ -181,9 +168,7 @@ public class ToolUtilCommands { public void material(Player player, LocalSession session, Pattern pattern) throws WorldEditException { Tool tool = session.getTool(player.getItemInHand()); if (tool instanceof BrushTool) { - ((BrushTool) tool).setMask(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setFill(pattern); + ((BrushTool) tool).setFill(pattern); } BBC.BRUSH_MATERIAL.send(player); } @@ -197,12 +182,10 @@ public class ToolUtilCommands { ) @CommandPermissions("worldedit.brush.options.range") public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException { - int range = args.getInteger(0); + int range = Math.max(0, Math.min(256, args.getInteger(0))); Tool tool = session.getTool(player.getItemInHand()); if (tool instanceof BrushTool) { - ((BrushTool) tool).setMask(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setRange(range); + ((BrushTool) tool).setRange(range); } BBC.BRUSH_RANGE.send(player); } @@ -222,9 +205,7 @@ public class ToolUtilCommands { Tool tool = session.getTool(player.getItemInHand()); if (tool instanceof BrushTool) { - ((BrushTool) tool).setMask(null); - } else if (tool instanceof DoubleActionBrushTool) { - ((DoubleActionBrushTool) tool).setSize(radius); + ((BrushTool) tool).setSize(radius); } BBC.BRUSH_SIZE.send(player); } diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index 03b26eae..b32d5650 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -1,6 +1,8 @@ package com.sk89q.worldedit.command.tool; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.brush.DoubleActionBrush; +import com.boydti.fawe.object.brush.visualization.VisualBrush; import com.boydti.fawe.object.extent.ResettableExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; @@ -8,7 +10,6 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldVector; import com.sk89q.worldedit.command.tool.brush.Brush; -import com.sk89q.worldedit.command.tool.brush.SphereBrush; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; @@ -22,17 +23,19 @@ import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; -/** - * Builds a shape at the place being looked at. - */ -public class BrushTool implements TraceTool { +public class BrushTool implements DoubleActionTraceTool { + + public enum BrushAction { + PRIMARY, + SECONDARY + } protected static int MAX_RANGE = 500; protected int range = -1; private Mask mask = null; private Mask sourceMask = null; private ResettableExtent transform = null; - private Brush brush = new SphereBrush(); + private Brush brush = null; @Nullable private Pattern material; private double size = 1; @@ -70,15 +73,6 @@ public class BrushTool implements TraceTool { 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; - } - /** * Get the filter. * @@ -88,6 +82,15 @@ public class BrushTool implements TraceTool { return sourceMask; } + /** + * 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 block filter used for identifying blocks to replace. * @@ -104,6 +107,13 @@ public class BrushTool implements TraceTool { * @param permission the permission */ public void setBrush(Brush brush, String permission) { + setBrush(brush, permission, null); + } + + public void setBrush(Brush brush, String permission, Player player) { + if (player != null && brush instanceof VisualBrush) { + ((VisualBrush) brush).clear(player); + } this.brush = brush; this.permission = permission; } @@ -171,8 +181,10 @@ public class BrushTool implements TraceTool { this.range = range; } - @Override - public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) { + public boolean act(BrushAction action, Platform server, LocalConfiguration config, Player player, LocalSession session) { + if (action == BrushAction.SECONDARY && !(brush instanceof DoubleActionBrush)) { + return false; + } WorldVector target = null; target = player.getBlockTrace(getRange(), true); @@ -199,7 +211,7 @@ public class BrushTool implements TraceTool { } } if (sourceMask != null) { - Mask existingMask = editSession.getMask(); + Mask existingMask = editSession.getSourceMask(); if (existingMask == null) { editSession.setSourceMask(sourceMask); @@ -215,7 +227,11 @@ public class BrushTool implements TraceTool { editSession.addTransform(transform); } try { - brush.build(editSession, target, material, size); + if (brush instanceof DoubleActionBrush) { + ((DoubleActionBrush) brush).build(action, editSession, target, material, size); + } else { + brush.build(editSession, target, material, size); + } } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); // Never happens } finally { @@ -224,11 +240,20 @@ public class BrushTool implements TraceTool { } 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); + } + public static Class inject() { return BrushTool.class; } -} \ No newline at end of file +} diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index dc492825..c31ea649 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -447,14 +447,18 @@ public class PlatformManager { } } } catch (Throwable e) { - FaweException faweException = FaweException.get(e); - if (faweException != null) { - BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage()); - } else { - actor.printError("Please report this error: [See console]"); - actor.printRaw(e.getClass().getName() + ": " + e.getMessage()); - MainUtil.handleError(e); - } + handleThrowable(e, actor); + } + } + + public void handleThrowable(Throwable e, Actor actor) { + FaweException faweException = FaweException.get(e); + if (faweException != null) { + BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage()); + } else { + actor.printError("Please report this error: [See console]"); + actor.printRaw(e.getClass().getName() + ": " + e.getMessage()); + MainUtil.handleError(e); } } diff --git a/core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java b/core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java index 84409fe7..6902fe70 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/transform/BlockTransformExtent.java @@ -204,7 +204,7 @@ public class BlockTransformExtent extends ResettableExtent { if (value != null && value.getDirection() != null) { StateValue newValue = getNewStateValue(state, transform, value.getDirection()); if (newValue != null) { - if (changedBlock.hasWildcardData()) { + if (changedBlock.isImmutable()) { changedBlock = new BaseBlock(changedBlock.getId(), changedBlock.getData(), changedBlock.getNbtData()); } newValue.set(changedBlock); diff --git a/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java b/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java new file mode 100644 index 00000000..28fa7dba --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -0,0 +1,59 @@ +/* + * WorldEdit, a Minecraft world manipulation toolkit + * Copyright (C) sk89q + * Copyright (C) WorldEdit team and contributors + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.sk89q.worldedit.function.mask; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.LocalPlayer; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.Vector; + +import javax.annotation.Nullable; + +/** + * Tests whether a given vector meets a criteria. + */ +public interface Mask extends com.sk89q.worldedit.masks.Mask { + + /** + * Returns true if the criteria is met. + * + * @param vector the vector to test + * @return true if the criteria is met + */ + boolean test(Vector vector); + + /** + * Get the 2D version of this mask if one exists. + * + * @return a 2D mask version or {@code null} if this mask can't be 2D + */ + @Nullable + Mask2D toMask2D(); + + default void prepare(LocalSession session, LocalPlayer player, Vector target) {} + + default boolean matches(EditSession editSession, Vector position) { + return test(position); + } + + public static Class inject() { + return Mask.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java similarity index 50% rename from core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java rename to core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java index cd6ba723..3ec30135 100644 --- a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Pattern.java @@ -17,39 +17,36 @@ * along with this program. If not, see . */ -package com.sk89q.worldedit.patterns; +package com.sk89q.worldedit.function.pattern; -import com.sk89q.worldedit.*; +import com.sk89q.worldedit.MutableBlockVector; +import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; /** - * @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern} + * Returns a {@link BaseBlock} for a given position. */ -@Deprecated -public interface Pattern { //extends com.sk89q.worldedit.function.pattern.Pattern { +public interface Pattern extends com.sk89q.worldedit.patterns.Pattern { /** - * Get a block for a position. This return value of this method does - * not have to be consistent for the same position. + * Return a {@link BaseBlock} for the given position. * - * @param position the position where a block is needed + * @param position the position * @return a block */ - public BaseBlock next(Vector position); + BaseBlock apply(Vector position); - /** - * Get a block for a position. This return value of this method does - * not have to be consistent for the same position. - * - * @param x the X coordinate - * @param y the Y coordinate - * @param z the Z coordinate - * @return a block - */ - public BaseBlock next(int x, int y, int z); + @Override + default BaseBlock next(Vector position) { + return apply(position); + } -// @Override -// default BaseBlock apply(Vector position) { -// return next(position); -// } + @Override + default BaseBlock next(int x, int y, int z) { + return apply(MutableBlockVector.get(x, y, z)); + } + + public static Class inject() { + return Pattern.class; + } } 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 index f71f3ba8..008da8f6 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/Patterns.java @@ -22,6 +22,9 @@ public final class Patterns { * @return a new-style pattern */ public static Pattern wrap(final com.sk89q.worldedit.patterns.Pattern pattern) { + if (pattern instanceof Pattern) { + return (Pattern) pattern; + } checkNotNull(pattern); return new Pattern() { @Override diff --git a/core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java index fc38b9f1..1099debb 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java +++ b/core/src/main/java/com/sk89q/worldedit/function/visitor/BreadthFirstSearch.java @@ -14,11 +14,22 @@ import com.sk89q.worldedit.function.RegionFunction; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.RunContext; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.List; public abstract class BreadthFirstSearch implements Operation { + public static Vector[] DEFAULT_DIRECTIONS = new Vector[6]; + static { + DEFAULT_DIRECTIONS[0] = (new MutableBlockVector(0, -1, 0)); + DEFAULT_DIRECTIONS[1] = (new MutableBlockVector(0, 1, 0)); + DEFAULT_DIRECTIONS[2] = (new MutableBlockVector(-1, 0, 0)); + DEFAULT_DIRECTIONS[3] = (new MutableBlockVector(1, 0, 0)); + DEFAULT_DIRECTIONS[4] = (new MutableBlockVector(0, 0, -1)); + DEFAULT_DIRECTIONS[5] = (new MutableBlockVector(0, 0, 1)); + } + private final RegionFunction function; private final List directions = new ArrayList<>(); private BlockVectorSet visited; @@ -41,12 +52,7 @@ public abstract class BreadthFirstSearch implements Operation { this.queue = new BlockVectorSet(); this.visited = new BlockVectorSet(); this.function = function; - this.directions.add(new Vector(0, -1, 0)); - this.directions.add(new Vector(0, 1, 0)); - this.directions.add(new Vector(-1, 0, 0)); - this.directions.add(new Vector(1, 0, 0)); - this.directions.add(new Vector(0, 0, -1)); - this.directions.add(new Vector(0, 0, 1)); + this.directions.addAll(Arrays.asList(DEFAULT_DIRECTIONS)); this.maxDepth = maxDepth; } diff --git a/core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java b/core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java index 80965575..1ba83fab 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java +++ b/core/src/main/java/com/sk89q/worldedit/function/visitor/RegionVisitor.java @@ -46,6 +46,7 @@ public class RegionVisitor implements Operation { public final Iterable iterable; public final RegionFunction function; private final MappedFaweQueue queue; + private boolean useCuboidIterator = false; public int affected = 0; /** diff --git a/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java b/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java index d4cc1e3b..ed83ac25 100644 --- a/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java +++ b/core/src/main/java/com/sk89q/worldedit/regions/CuboidRegion.java @@ -44,6 +44,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { private Vector pos1; private Vector pos2; + private boolean useOldIterator; private int minX,minY,minZ,maxX,maxY,maxZ; /** @@ -80,6 +81,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { recalculate(); } + public void setUseOldIterator(boolean useOldIterator) { + this.useOldIterator = useOldIterator; + } + /** * Get the first cuboid-defining corner. * @@ -400,7 +405,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { @Override public Iterator iterator() { - if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9) { + if (Settings.IMP.HISTORY.COMPRESSION_LEVEL >= 9 || useOldIterator) { return iterator_old(); } return new Iterator() { @@ -445,7 +450,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { y = by; if (x > tx) { x = bx; - if (z >= tz) { + if (z > tz) { if (!hasNext) { throw new NoSuchElementException("End of iterator") { @Override @@ -494,10 +499,11 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { private int nextX = min.getBlockX(); private int nextY = min.getBlockY(); private int nextZ = min.getBlockZ(); + private boolean hasNext = true; @Override public boolean hasNext() { - return (nextZ != Integer.MIN_VALUE); + return hasNext; } @Override @@ -507,10 +513,10 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { mutable.mutZ(nextZ); if (++nextX > max.getBlockX()) { nextX = min.getBlockX(); - if (++nextY > max.getBlockY()) { - nextY = min.getBlockY(); - if (++nextZ > max.getBlockZ()) { - if (nextZ == Integer.MIN_VALUE) { + if (++nextZ > max.getBlockZ()) { + nextZ = min.getBlockZ(); + if (++nextY > max.getBlockY()) { + if (!hasNext) { throw new NoSuchElementException("End of iterator") { @Override public synchronized Throwable fillInStackTrace() { @@ -519,8 +525,9 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion { }; } nextX = max.getBlockX(); + nextZ = max.getBlockZ(); nextY = max.getBlockY(); - nextZ = Integer.MIN_VALUE; + hasNext = false; } } } diff --git a/core/src/main/resources/de/messages.yml b/core/src/main/resources/de/messages.yml new file mode 100644 index 00000000..cd2ed55f --- /dev/null +++ b/core/src/main/resources/de/messages.yml @@ -0,0 +1,311 @@ +info: + prefix: '&4&lFAWE:&f&7' + schematic_pasting: '&7Das Schematic wird eingefügt. Dies kann nicht rückgängig gemacht + werden.' + updated_lighting_selection: '&7Updates des Lichts werden in %s0 chunks durchgeführt. + (Es kann einige Sekunden dauern bis die Pakete gesendet wurden.)' + set_region: '&7Markierung wurde auf aktuelle WorldEdit Region übertragen.' + worldedit_command_limit: '&7Bitte warte bist deine momentane Aktion fertig gestellt + wurde.' + worldedit_delayed: '&7Bitte warte während wir deine aktuelle WorldEdit Aktion durchführen...' + worldedit_run: '&7Entschuldige die Verzögerung. Nun führen wir folgende Aktion von + dir aus: %s' + worldedit_complete: '&7WorldEdit Aktion fertiggestellt..' + require_selection_in_mask: '&7%s deiner Auswahl ist nicht innerhalb deiner Maske. + Du kannst du innerhalb erlaubter Regionen Veränderungen durchführen.' + worldedit_volume: '&7Du kannst keine %current% verändern. Die maximale Anzahl an + Blöcken die du verändern kannst ist %max%.' + worldedit_iterations: '&7Du kannst keine Aktion %current% Mal wiederholen. Die maximale + Anzahl an erlaubten Wiederholungen ist %max%.' + worldedit_unsafe: '&7Der Zugang zu diesem Befehl wurde verboten.' + worldedit_dangerous_worldedit: '&cFAWE führt unsicher WorldEdit Aktionen aus! Position: + %s0 Username: %s1' + worldedit_bypass: '&7&oUm deine Beschränkungen zu ignorieren nutze &c/wea' + worldedit_bypassed: '&7Beschränkungen werden nun ignoriert.' + worldedit_unmasked: '&6Deine WorldEdit Beschränkungen sind nun aufgehoben.' + worldedit_restricted: '&6Deine WorldEdit Beschränkungen sind nun aktiv.' + worldedit_oom_admin: |- + &cPossible options: + &8 - &7//fast + &8 - &7Do smaller edits + &8 - &7Allocate more memory + &8 - &7Disable this safeguard + compressed: WorldEdit Verlauf komprimiert. Saved ~ %s0b (%s1x smaller) + action_complete: Aktion fertiggestellt in %s0 Sekunden + lighting_propogate_selection: '&7Licht wurde berechnet in %s0 Chunks. (Info: Um + Licht zu entfernen nutze //removelight)' + worldedit_toggle_tips_on: '&7WorldEdit Tipps deaktiviert.' + worldedit_toggle_tips_off: '&7WorldEdit Tipps aktiviert.' +error: + worldedit_extend: '&cDeine WorldEdit Aktion überschreitet die erlaubte Region' + command_syntax: '&cBenutzung: &7%s0' + no_perm: '&cDir fehlt die Berechtigung: %s0' + setting_disable: '&cFehlende Einstellung: %s0' + schematic_not_found: '&cSchematic nicht gefunden: &7%s0' + no_region: '&cDu hast keine aktive WorldEdit Markierung' + no_mask: '&cDu hast keine Mask gesetzt' + not_player: '&cDieser Befehl kann nur von Spielern ausgeführt werden!' + player_not_found: '&cSpieler nicht gefunden:&7 %s0' + oom: |- + &8[&cCritical&8] &cDetected low memory i.e. < 1%. FAWE will take the following actions: + &8 - &7Terminate WE block placement + &8 - &7Clear WE history + &8 - &7Unload non essential chunks + &8 - &7Kill entities + &8 - &7Garbage collect + &cIgnore this if trying to crash server. + &7Note: Low memory is likely (but not necessarily) caused by WE + worldedit_some_fails: '&c%s0 Blöcke wurden nicht platziert, da sie ausserhalb der + erlaubten Region sind.' + worldedit_some_fails_blockbag: '&cFehlende Blöcke: %s0' +web: + generating_link: Upload %s, Bitte warten... + generating_link_failed: '&cErstellung eines Download-Links fehlgeschlagen!' + download_link: '%s' +worldedit: + general: + mask_disabled: Globale Maske deaktiviert + mask: Globale Maske gesetzt + transform_disabled: Globale Transformation deaktiviert + transform: Globale Transformation gesetzt + source_mask_disabled: Globale Quell-Maske deaktiviert + source_mask: Global Quell-Maske gesetzt + fast_enabled: Fast-Modus aktiviert. Verlauf und Beschränkungen werden ignoriert. + fast_disabled: Fast-Modus deaktiviert + place_enabled: 'Platziere nun an Pos. #1.' + place_disabled: Platziere nun an dem Block in dem du stehst. + copy: + command_copy: '%s0 Blöcke kopiert' + cut: + command_cut_slow: |- + %s0 blocks were cut. + Tip: lazycut is safer + command_cut_lazy: '%s0 Blöcke werden beim einfügen entfernt' + paste: + command_paste: Zwischenablage wurde bei Position %s0 eingefügt + rotate: + command_rotate: Zwischenablage wurde gedreht + flip: + command_flipped: Zwischenablage wurde gespiegelt + regen: + command_regen_0: |- + Region regenerated. + Tip: Use a biome with /regen [biome] + command_regen_1: |- + Region regenerated. + Tip: Use a seed with /regen [biome] [seed] + command_regen_2: Region regeneriert. + tree: + command_tree: '%s0 Bäume erstellt.' + command_pumpkin: '%s0 Kürbis-Patch erstellt.' + flora: + command_flora: '%s0 Pflanzen erstellt.' + history: + command_history_clear: Verlauf gelöscht + command_redo_success: Redo erfolgreich. + command_undo_success: Undo erfolgreich. + command_redo_error: Nothing left to redo. (See also `/inspect` and `/frb`) + command_undo_error: Nothing left to undo. (See also `/inspect` and `/frb`) + command_history_other_error: WorldEdit Verlauf für %s0 konnte nicht gefunden werden. + operation: + operation: Operation wird durchgeführt (%s0) + selection: + selection_wand: 'Linksklick: Markiere Position #1; Rechtsklick: Markiere Position + #2' + selection_wand_disable: Bearbeitungs-Tool deaktiviert. + selection_wand_enable: Bearbeitungs-Tool aktiviert. + selection_chunk: Chunk ausgewählt (%s0) + selection_chunks: Chunks ausgewählt (%s0) - (%s1) + selection_contract: Markierung verkleinert um %s0 Blöcke. + selection_count: '%s0 Blöcke wurden gezählt.' + selection_distr: '# Gesamtanzahl Blöcke: %s0' + selection_expand: Markierung erweitert um %s0 Blöcke + selection_expand_vert: Markierung erweitert um %s0 Blöcke (Maximaler Baubereich) + selection_inset: Markierung verkleinert + selection_outset: Markierung vergößert + selection_shift: Region verschoben + selection_cleared: Auswahl gelöscht + brush: + brush_butcher: Butcher Pinsel ausgerüstet (%s0) + brush_clipboard: Clipboard Pinsel Format ausgerüstet + brush_cylinder: Cylinder Pinsel Format ausgerüstet (%s0 by %s1). + brush_extinguisher: Extinguisher ausgerüstet (%s0). + brush_gravity: Gravity Pinsel ausgerüstet (%s0) + brush_height: Height Pinsel ausgerüstet (%s0) + brush_copy: Copy Pinsel ausgerüstet (%s0) + brush_command: Command Pinsel ausgerüstet (%s0) + brush_height_invalid: Invalid height map file (%s0) + brush_smooth: Smooth Pinsel ausgerüstet (%s0 x %s1 using %s2). + brush_sphere: Sphere Pinsel Format ausgerüstet (%s0). + brush_line: Linien Pinsel Format ausgerüstet (%s0). + brush_spline: Linien Pinsel Format ausgerüstet (%s0). Rechstklicke ein Ende um ein Format hinzuzufügen + brush_spline_primary: Position hinzugefügt, Linksklick zum verbinden! + brush_spline_secondary_error: Nicht genügend Positionen gesetzt! + brush_spline_secondary: Kurve erstellt + brush_blend_ball: Blend ball Pinsel ausgerüstet (%s0). + brush_erode: Erode Pinsel ausgerüstet (%s0). + brush_paste_none: Zwischenablage leer! Nichts zum einfügen! + brush_size: Pinsel Größe gesetzt + brush_range: Pinsel Größe gesetzt + brush_mask_disabled: Pinsel Maske deaktiviert + brush_mask: Pinsel Maske gesetzt + brush_transform_disabled: Pinsel Transformation deaktiviert + brush_transform: Pinsel Transformation gesetzt + brush_material: Pinsel Material gesetzt + brush_recursive: Rekursiver Pinsel ausgerüstet (%s0). + brush_try_other: |- + &cFAWE adds other, more suitable brushes e.g. + &8 - &7//br height [radius=5] [#clipboard|file=null] [rotation=0] [yscale=1.00] + brush_none: You aren't holding a brush! + brush_source_mask_disabled: Pinsel Quell-Maske deaktiviert + brush_source_mask: Pinsel Quell-Maske gesetzt + rollback: + rollback_element: annullierend %s0 + tool: + tool_inspect: Inpektions-Tool gebunden an %s0. + tool_inspect_info: '&7%s0 änderte %s1 zu %s2 %s3 zuvor' + tool_inspect_info_footer: '&6Total: &7%s0 Änderungen' + tool_none: Tool vom aktuellen Item entfernt. + tool_info: Info-Tool gebunden an %s0. + tool_tree: Tree-Tool gebunden an %s0. + tool_tree_error: Baum Typ %s0 ist unbekannt. + tool_repl: Block Replacer-Tool gebunden an %s0. + tool_cycler: Block Data Cycler-Tool gebunden an %s0. + tool_flood_fill: Block Flood Fill-Tool gebunden an %s0. + tool_deltree: Floating Tree Remover-Tool gebunden an %s0. + tool_farwand: Far Wand-Tool gebunden an%s0. + tool_lrbuild_bound: Long-range Building-Tool gebunden an %s0. + tool_lrbuild_info: 'Linksklick: Setze Position %s0; Rechtsklick: Setze Position + %s1' + superpickaxe_enabled: Super Pickaxe aktiviert. + superpickaxe_disabled: Super Pickaxe deaktiviert. + tool_range_error: 'Maximale Reichweite: %s0.' + tool_radius_error: 'Maximal erlaubter Pinsel Radius: %s0.' + superpickaxe_area_enabled: Modus geändert. Linksklick mit einer Spitzhacke. // zum deaktivieren. + schematic: + schematic_delete: Schematic %s0 wurde gelöscht. + schematic_format: 'Verfügbare Zwischenspeicher Formate (Name: Suche Namen)' + schematic_loaded: Schematic %s0 geladen. Platziere es mit //paste + schematic_saved: Schematic %s0 gespeichert. + schematic_page: Seite muss %s sein + schematic_none: Keine Schematics gefunden. + schematic_list: 'Verfügbare Schematics (Filename: Format) [%s0/%s1]:' + clipboard: + clipboard_cleared: Zwischenablage geleert + clipboard_invalid_format: 'Unbekanntes Zwischenspeicher Format: %s0' + visitor: + visitor_block: '%s0 Blöcke betroffen' + visitor_entity: '%s0 Entities betroffen' + visitor_flat: '%s0 Rubriken betroffen' + selector: + selector_cuboid_pos1: Pos 1 gesetzt %s0 %s1. + selector_cuboid_pos2: Pos 2 gesetzt %s0 %s1. + selector_invalid_coordinates: Ungültige Koordinaten %s0 + selector_already_set: Position bereits gesetzt. + selector_fuzzy_pos1: Region gesetzt und expandiert von %s0 %s1. + selector_fuzzy_pos2: Erweiterung hinzugefügt um %s0 %s1. + selector_set_default: Dein Standard Auswahl-Tool ist nun %s0. + command: + command_invalid_syntax: The command was not used properly (no more help available). + snapshot: + snapshot_loaded: Snapshot '%s0' loaded; now restoring... + snapshot_set: 'Snapshot set to: %s0' + snapshot_newest: Now using newest snapshot. + snapshot_list_header: 'Snapshots for world (%s0):' + snapshot_list_footer: Use /snap use [snapshot] or /snap use latest. + biome: + biome_list_header: 'Biome (page %s0/%s1):' + biome_changed: Biome wurden geändert in %s0 Bezirken. + utility: + kill_success: '%s0 Entities in einem Radius von %s1 getötet.' + timezone: + timezone_set: 'Zeitzone für diese Sitzung gesetzt auf: %s0' + timezone_display: 'Aktuelle Zeit in dieser Zeitzone: %s0' +progress: + progress_message: '[ Zwischenspeicher: %s0 | Erledigt: %s1 ]' + progress_finished: '[ Fertiggestellt! ]' +cancel: + worldedit_cancel_count: '&c%s0 Veränderungen abgebrochen.' + worldedit_cancel_reason: '&cDeine WorldEdit Aktion wurde abgebrochen:&7 %s0&c.' + worldedit_cancel_reason_manual: Manueller Abbruch + worldedit_cancel_reason_low_memory: Zu wenig Speicher + worldedit_cancel_reason_max_changes: Zu viele Blöcke bearbeitet + worldedit_cancel_reason_max_checks: Zu viele Blöcke gecheckt + worldedit_cancel_reason_max_tiles: Zu viele Blockstatus + worldedit_cancel_reason_max_entities: Zu viele Entities + worldedit_cancel_reason_max_iterations: Maximale Wiederholungen + worldedit_cancel_reason_max_fails: Ausserhalb erlaubter Regionen (Bypass mit /wea) + worldedit_cancel_reason_no_region: Keine erlaubte Region (Bypass mit /wea) + worldedit_failed_load_chunk: '&cÜberspringe das Laden von Chunk: &7%s0;%s1&c. Versuche + chunk-wait zu erhöhen.' +history: + loading_clipboard: Lade Zwischenablage bitte warten. + indexing_history: Indiziere %s Verlauf auf der Platte, Bitte warten. + indexing_complete: 'Indizierung vollständig. Dauer: %s Sekunden!' +navigation: + ascend_fail: Kein freier Platz über dir gefunden. + ascended_plural: '%s0 Schichten aufgestiegen.' + ascended_singular: Eine Schicht aufgestiegen. + unstuck: Auf gehts! + descend_fail: Kein freier Platz unter dir gefunden. + descend_plural: '%s0 Schichten abgestiegen.' + descend_singular: Eine Schicht abgestiegen. + whoosh: Whoosh! + poof: Poof! + thru_fail: Kein freier Platz vor dir gefunden. + up_fail: Du würdest einen Block treffen! + no_block: Kein Block in Sichweite! (oder zu weit entfernt) +selection: + sel_cuboid: 'Quader: Linksklick für Position1, Rechtsklick für Position2' + sel_cuboid_extend: 'Quader: Linksklick für einen Startpunkt, Rechtsklick zum erweitern' + sel_2d_polygon: '2D Polygon Selektierer: Links/Rechtsklick um eine Markierung hinzuzufügen.' + sel_ellipsiod: 'Ellipsen Selektierer: Linksklick=Mitte, Rechtsklick zum erweitern' + sel_sphere: 'Kugel Selektierer : Linksklick=Mitte, Rechtsklick um den Radius zu + setzen' + sel_cylindrical: 'Zylinder Selektierer: Linksklick=Mitte, Rechtsklick zum erweitern' + sel_max: '%s0 Punkte maximal.' + sel_fuzzy: 'Fuzzy Selektierer: Linksklick um alle verbundenen Blöcke zu markieren, + Rechtsklick zum hinzufügen' + sel_convex_polyhedral: 'Convex polyhedral selector: Left click=First vertex, right + click to add more.' + sel_list: Für eine Liste der Selektoren nutze:&c //sel + sel_modes: 'Wähle einen der unten aufgelisteten Modi:' +tips: + tip_cancel: 'Tip: Du kannst eine Aktion abbrechen mit `//cancel`' + tip_download: 'Tip: Du kannst deinen Zwischenspeicher mit`//download` herunterladen' + tip_sel_list: 'Tip: Liste die verschiedenen Selektoren auf mit &c//sel list' + tip_select_connected: 'Tip: Wähle alle verbundenen Blöcke mit //sel fuzzy' + tip_set_pos1: 'Tip: Nutze pos1 als Muster &c//set pos1' + tip_farwand: 'Tip: Markiere entferne Blöcke mit &c//farwand' + tip_fast: '&7Tip: Platziere schnell und ohne Undo-Historie &c//fast' + tip_mask: '&7Tip: Setze eine Globale Zielmaske mit &c/gmask' + tip_mask_angle: 'Tip: Ersetze aufwärts Steigungen von 3-20 Blöcken mit&c //replace + /-20:-3 bedrock' + tip_set_linear: '&7Tip: Setze Blöcke linear mit&c //set #l3d:wood,bedrock' + tip_surface_spread: '&7Tip: Streue einen flachen Untergrund mit&c //set #surfacespread:5:0:5:#existing' + tip_set_hand: '&7Tip: Setze das Item in deiner Hand mit&c//set hand' + tip_replace_id: '&7Tip: Ersetze nur die Block-ID:&c //replace woodenstair #id:cobblestair' + tip_replace_light: 'Tip: Entferne Licht-Quellen&c //replace #brightness:1:15 0' + tip_tab_complete: 'Tip: Der Replace-Befehl unterstützt Tab-Vervollständigung' + tip_flip: 'Tip: Spiegeln mit &c//flip' + tip_deform: 'Tip: Forme um mit &c//deform' + tip_transform: 'Tip: Platziere eine Umformung mit &c//gtransform' + tip_copypaste: 'Tip: Füge durch Klick ein mit &c//br copypaste' + tip_source_mask: 'Tip: Setze eine Quell-Maske &c/gsmask &7' + tip_replace_marker: 'Tip: Ersetze einen Block mit deinem vollständigen Zwischenspeicher + mit &c//replace wool #fullcopy' + tip_paste: 'Tip: Füge deine Zwischeneinlage mit &c//paste ein' + tip_lazycopy: 'Tip: lazycopy ist schneller' + tip_rotate: 'Tip: Ausrichten mit &c//rotate' + tip_copy_pattern: 'Tip: Um ein Muster zu verwenden nutze &c#copy' + tip_brush_spline: '&7Tip Der spline &c//brush &7verbindet multiple Formen miteinander' + tip_brush_height: '&7Tip: Der Höhe &c//brush &7erhöht oder senkt Terrain sanft' + tip_brush_copy: '&7Tip: Der copypaste &c//brush &7erlaubt dir leichtes kopieren + und einfügen von Objekten.' + tip_brush_mask: '&7Tip: Setze eine brush Ziel-Maske mit &c/mask' + tip_brush_mask_source: '&7Tip: Setze eine brush Quell-Maske mit &c/smask' + tip_brush_transform: '&7Tip: Setze eine brush Transformation mit &c/transform' + tip_brush_relative: '&7Tip: Nutze ein relatives Zwischenspeicher-Muster mit //br + sphere #~:#copy' + tip_brush_command: '&7Tip: Probiere den Befehl &c//br cmd ' + tip_lazycut: '&7Tip: Es ist sicherer den Befehl &c//lazycut zu verwenden.' diff --git a/forge110/build.gradle b/forge110/build.gradle index 4376197b..157620f4 100644 --- a/forge110/build.gradle +++ b/forge110/build.gradle @@ -21,9 +21,6 @@ dependencies { compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1' } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { maven { name = 'forge' diff --git a/forge110/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge110/src/main/java/com/boydti/fawe/forge/ForgePlayer.java index 17cc95e9..e23efdfe 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/ForgePlayer.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/ForgePlayer.java @@ -71,7 +71,7 @@ public class ForgePlayer extends FawePlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent)); } } diff --git a/forge111/build.gradle b/forge111/build.gradle index db87e419..328e7c58 100644 --- a/forge111/build.gradle +++ b/forge111/build.gradle @@ -21,9 +21,6 @@ dependencies { compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1' } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { maven { name = 'forge' diff --git a/forge111/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge111/src/main/java/com/boydti/fawe/forge/ForgePlayer.java index 971974c2..ed2461a6 100644 --- a/forge111/src/main/java/com/boydti/fawe/forge/ForgePlayer.java +++ b/forge111/src/main/java/com/boydti/fawe/forge/ForgePlayer.java @@ -71,7 +71,7 @@ public class ForgePlayer extends FawePlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent)); } } diff --git a/forge1710/build.gradle b/forge1710/build.gradle index 621473d0..caf8f53a 100644 --- a/forge1710/build.gradle +++ b/forge1710/build.gradle @@ -21,9 +21,6 @@ dependencies { compile 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' } -sourceCompatibility = 1.7 -targetCompatibility = 1.7 - repositories { maven { name = 'forge' diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge1710/src/main/java/com/boydti/fawe/forge/ForgePlayer.java index a7e1b5bf..4a350d3c 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/ForgePlayer.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/ForgePlayer.java @@ -73,7 +73,7 @@ public class ForgePlayer extends FawePlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return ForgeWorldEdit.inst.wrap(this.parent); } } diff --git a/forge189/build.gradle b/forge189/build.gradle index 0d99fdcc..b9b68b25 100644 --- a/forge189/build.gradle +++ b/forge189/build.gradle @@ -21,9 +21,6 @@ dependencies { compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1' } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { maven { name = 'forge' diff --git a/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java index c61cdcf0..75215501 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/ForgePlayer.java @@ -74,7 +74,7 @@ public class ForgePlayer extends FawePlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent)); } } diff --git a/forge194/build.gradle b/forge194/build.gradle index 045233e2..4bfbc6cf 100644 --- a/forge194/build.gradle +++ b/forge194/build.gradle @@ -20,9 +20,6 @@ dependencies { compile 'com.sk89q.worldedit:worldedit-forge-mc1.8.9:6.1.1' } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - repositories { maven { name = 'forge' diff --git a/forge194/src/main/java/com/boydti/fawe/forge/ForgePlayer.java b/forge194/src/main/java/com/boydti/fawe/forge/ForgePlayer.java index 161f7d5c..88117dd3 100644 --- a/forge194/src/main/java/com/boydti/fawe/forge/ForgePlayer.java +++ b/forge194/src/main/java/com/boydti/fawe/forge/ForgePlayer.java @@ -22,10 +22,12 @@ public class ForgePlayer extends FawePlayer { @Override public void sendTitle(String head, String sub) { // Not supported + Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false"; } @Override public void resetTitle() { // Not supported + Settings.IMP.QUEUE.PROGRESS.DISPLAY = "false"; } @Override @@ -71,7 +73,7 @@ public class ForgePlayer extends FawePlayer { } @Override - public Player getPlayer() { + public Player toWorldEditPlayer() { return PlayerWrapper.wrap(ForgeWorldEdit.inst.wrap(this.parent)); } } diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java index 4619085b..d1df58a7 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkit.java @@ -14,6 +14,7 @@ import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.object.brush.visualization.VisualChunk; import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.TaskManager; import com.sk89q.worldedit.world.World; @@ -30,6 +31,7 @@ public class FaweNukkit implements IFawe, Listener { public FaweNukkit(NukkitWorldEdit mod) { this.plugin = mod; FaweChunk.HEIGHT = 256; + VisualChunk.VISUALIZE_BLOCK = 241 << 4; plugin.getServer().getPluginManager().registerEvents(this, plugin); } diff --git a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkitPlayer.java b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkitPlayer.java index f0ba35e6..c223b457 100644 --- a/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkitPlayer.java +++ b/nukkit/src/main/java/com/boydti/fawe/nukkit/optimization/FaweNukkitPlayer.java @@ -66,7 +66,7 @@ public class FaweNukkitPlayer extends FawePlayer { } @Override - public com.sk89q.worldedit.entity.Player getPlayer() { + public com.sk89q.worldedit.entity.Player toWorldEditPlayer() { return new NukkitPlayer((NukkitPlatform) Fawe. imp().getPlugin().getPlatform(), parent); } diff --git a/sponge/build.gradle b/sponge/build.gradle index dd155115..fc37ab46 100644 --- a/sponge/build.gradle +++ b/sponge/build.gradle @@ -52,9 +52,6 @@ dependencies { compile name: 'worldedit-core-6.1.7-SNAPSHOT-dist' } -sourceCompatibility = 1.8 -targetCompatibility = 1.8 - minecraft { version = "1.11" mappings = "snapshot_20161116" diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java b/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java index fc292463..3c0a4036 100644 --- a/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java +++ b/sponge/src/main/java/com/boydti/fawe/sponge/SpongePlayer.java @@ -73,7 +73,7 @@ public class SpongePlayer extends FawePlayer { } @Override - public com.sk89q.worldedit.entity.Player getPlayer() { + public com.sk89q.worldedit.entity.Player toWorldEditPlayer() { if (WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.USER_COMMANDS) != null) { for (Platform platform : WorldEdit.getInstance().getPlatformManager().getPlatforms()) { return platform.matchPlayer(new FakePlayer(getName(), getUUID(), null));