From b9c056c879d8b9277801d10d30f6a57209c9d6a2 Mon Sep 17 00:00:00 2001 From: Jesse Boyd Date: Mon, 15 May 2017 21:33:03 +1000 Subject: [PATCH] Various Optimize for 1.12 Refactor commands / style / cleanup Brush saving/loading Tweak / improve ChunkListener --- bukkit/build.gradle | 1 + .../com/boydti/fawe/bukkit/BukkitMain.java | 6 + .../boydti/fawe/bukkit/v0/ChunkListener.java | 79 +- .../fawe/bukkit/v1_11/BukkitQueue_1_11.java | 2 +- .../fawe/bukkit/v1_11/FaweChunkLoader.java | 243 ------ .../fawe/bukkit/v1_12/BukkitChunk_1_12.java | 499 +++++++++++ .../bukkit/v1_12/BukkitChunk_1_12_Copy.java | 80 ++ .../fawe/bukkit/v1_12/BukkitQueue_1_12.java | 803 ++++++++++++++++++ .../fawe/bukkit/v1_12/FaweAdapter_1_12.java | 333 ++++++++ .../fawe/bukkit/v1_12/MutableGenLayer.java | 26 + .../fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java | 2 +- core/src/main/java/com/boydti/fawe/Fawe.java | 30 +- .../boydti/fawe/command/AnvilCommands.java | 2 +- .../main/java/com/boydti/fawe/config/BBC.java | 46 +- .../java/com/boydti/fawe/config/Settings.java | 8 +- .../fawe/object/brush/BrushSettings.java | 236 ++++- .../object/brush/scroll/ScrollAction.java | 71 ++ .../object/extent/BlockTranslateExtent.java | 6 +- .../fawe/object/extent/Linear3DTransform.java | 4 - .../fawe/object/extent/LinearTransform.java | 4 - .../fawe/object/extent/MultiTransform.java | 6 +- .../fawe/object/extent/OffsetExtent.java | 8 +- .../extent/PositionTransformExtent.java | 5 +- .../object/extent/RandomOffsetTransform.java | 7 +- .../fawe/object/extent/RandomTransform.java | 11 +- .../fawe/object/extent/ResettableExtent.java | 28 +- .../fawe/object/extent/ScaleTransform.java | 12 +- .../function/block/LegacyBlockReplace.java | 29 - .../function/mask/AbstractDelegateMask.java | 3 +- .../fawe/object/mask/AdjacentAnyMask.java | 10 +- .../boydti/fawe/object/mask/AdjacentMask.java | 3 +- .../boydti/fawe/object/mask/AngleMask.java | 24 +- .../boydti/fawe/object/mask/BiomeMask.java | 9 +- .../fawe/object/mask/BlockLightMask.java | 8 +- .../fawe/object/mask/BrightnessMask.java | 8 +- .../com/boydti/fawe/object/mask/DataMask.java | 11 +- .../boydti/fawe/object/mask/IdDataMask.java | 12 +- .../com/boydti/fawe/object/mask/IdMask.java | 11 +- .../boydti/fawe/object/mask/LightMask.java | 11 +- .../boydti/fawe/object/mask/OpacityMask.java | 11 +- .../boydti/fawe/object/mask/PlaneMask.java | 9 +- .../boydti/fawe/object/mask/RadiusMask.java | 7 +- .../boydti/fawe/object/mask/RandomMask.java | 9 +- .../boydti/fawe/object/mask/SkyLightMask.java | 11 +- .../fawe/object/mask/SolidPlaneMask.java | 5 +- .../boydti/fawe/object/mask/SurfaceMask.java | 2 +- .../com/boydti/fawe/object/mask/WallMask.java | 3 +- .../boydti/fawe/object/mask/XAxisMask.java | 6 +- .../boydti/fawe/object/mask/YAxisMask.java | 6 +- .../boydti/fawe/object/mask/ZAxisMask.java | 6 +- .../boydti/fawe/object/number/LongAdder.java | 179 ---- .../boydti/fawe/object/number/Striped64.java | 341 -------- .../object/pattern/AbstractExtentPattern.java | 20 + .../object/pattern/AngleColorPattern.java | 24 +- .../object/pattern/AverageColorPattern.java | 25 +- .../fawe/object/pattern/BiomePattern.java | 17 +- .../fawe/object/pattern/BufferedPattern.java | 35 +- .../object/pattern/BufferedPattern2D.java | 45 +- .../fawe/object/pattern/DataPattern.java | 9 +- .../object/pattern/DesaturatePattern.java | 17 +- .../fawe/object/pattern/ExistingPattern.java | 9 +- .../object/pattern/ExpressionPattern.java | 20 +- .../object/pattern/FullClipboardPattern.java | 12 +- .../object/pattern/IdDataMaskPattern.java | 16 +- .../boydti/fawe/object/pattern/IdPattern.java | 9 +- .../object/pattern/Linear3DBlockPattern.java | 4 - .../object/pattern/LinearBlockPattern.java | 6 +- .../fawe/object/pattern/MaskedPattern.java | 4 - .../fawe/object/pattern/NoXPattern.java | 9 +- .../fawe/object/pattern/NoYPattern.java | 8 +- .../fawe/object/pattern/NoZPattern.java | 8 +- .../fawe/object/pattern/OffsetPattern.java | 8 +- .../fawe/object/pattern/PatternExtent.java | 10 +- .../pattern/RandomFullClipboardPattern.java | 6 + .../object/pattern/RandomOffsetPattern.java | 21 +- .../fawe/object/pattern/RelativePattern.java | 11 +- .../fawe/object/pattern/SaturatePattern.java | 18 +- .../fawe/object/pattern/ShadePattern.java | 18 +- .../pattern/SolidRandomOffsetPattern.java | 25 +- .../pattern/SurfaceRandomOffsetPattern.java | 61 +- .../serializer/BaseBlockSerializer.java | 30 - .../serializer/BlockVectorSerializer.java | 36 - .../serializer/EditSessionSerializer.java | 30 - .../object/serializer/InheritedExclusion.java | 50 -- .../object/serializer/JsonSerializable.java | 10 - .../serializer/LocalSessionSerializer.java | 28 - .../object/serializer/PlayerSerializer.java | 25 - .../boydti/fawe/util/CachedTextureUtil.java | 6 +- .../boydti/fawe/util/CleanTextureUtil.java | 2 +- .../fawe/util/DocumentationPrinter.java | 14 +- .../java/com/boydti/fawe/util/StringMan.java | 5 + .../com/sk89q/worldedit/BlockWorldVector.java | 5 - .../com/sk89q/worldedit/LocalSession.java | 6 +- .../sk89q/worldedit/MutableBlockVector.java | 21 +- .../sk89q/worldedit/MutableBlockVector2D.java | 17 +- .../main/java/com/sk89q/worldedit/Vector.java | 23 +- .../java/com/sk89q/worldedit/Vector2D.java | 19 +- .../com/sk89q/worldedit/blocks/BaseBlock.java | 36 +- .../worldedit/command/BiomeCommands.java | 2 +- .../worldedit/command/BrushCommands.java | 308 ++++--- ...ommands.java => BrushOptionsCommands.java} | 368 ++++---- .../worldedit/command/BrushProcessor.java | 32 + .../worldedit/command/GenerationCommands.java | 2 +- .../worldedit/command/MethodCommands.java | 31 +- ...eralCommands.java => OptionsCommands.java} | 10 +- .../worldedit/command/PatternCommands.java | 16 +- .../worldedit/command/RegionCommands.java | 2 +- .../worldedit/command/SchematicCommands.java | 157 +--- .../worldedit/command/SelectionCommands.java | 2 +- .../sk89q/worldedit/command/ToolCommands.java | 40 +- .../worldedit/command/UtilityCommands.java | 505 +++++++---- .../worldedit/command/tool/BrushTool.java | 166 +++- .../command/tool/brush/GravityBrush.java | 3 +- .../extension/platform/CommandManager.java | 27 +- .../extension/platform/PlayerProxy.java | 5 - .../extent/AbstractDelegateExtent.java | 2 +- .../function/mask/AbstractExtentMask.java | 25 + .../worldedit/function/mask/AbstractMask.java | 31 + .../sk89q/worldedit/function/mask/Mask.java | 4 +- .../function/mask/MaskIntersection.java | 15 +- .../function/pattern/AbstractPattern.java | 12 + .../math/transform/AffineTransform.java | 11 +- .../com/sk89q/worldedit/patterns/Pattern.java | 3 +- .../util/command/CallableProcessor.java | 10 + .../util/command/DelegateCallable.java | 37 + .../util/command/ProcessedCallable.java | 27 + .../util/command/fluent/DispatcherNode.java | 155 ++++ .../command/parametric/ParametricBuilder.java | 24 +- .../voxelsniper/RangeBlockHelper.java | 5 - .../fawe/forge/v110/ForgeQueue_All.java | 2 +- .../fawe/forge/v111/ForgeQueue_All.java | 2 +- .../fawe/forge/v1710/ForgeQueue_All.java | 2 +- .../fawe/forge/v189/ForgeQueue_All.java | 2 +- .../fawe/forge/v194/ForgeQueue_All.java | 2 +- .../fawe/sponge/v1_11/SpongeQueue_1_11.java | 2 +- 135 files changed, 3965 insertions(+), 2214 deletions(-) delete mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java create mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java create mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java create mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java create mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/FaweAdapter_1_12.java create mode 100644 bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/MutableGenLayer.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/function/block/LegacyBlockReplace.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/number/LongAdder.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/number/Striped64.java create mode 100644 core/src/main/java/com/boydti/fawe/object/pattern/AbstractExtentPattern.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/BaseBlockSerializer.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/BlockVectorSerializer.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/EditSessionSerializer.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/InheritedExclusion.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/JsonSerializable.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/LocalSessionSerializer.java delete mode 100644 core/src/main/java/com/boydti/fawe/object/serializer/PlayerSerializer.java rename core/src/main/java/com/sk89q/worldedit/command/{ToolUtilCommands.java => BrushOptionsCommands.java} (57%) create mode 100644 core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java rename core/src/main/java/com/sk89q/worldedit/command/{GeneralCommands.java => OptionsCommands.java} (97%) create mode 100644 core/src/main/java/com/sk89q/worldedit/function/mask/AbstractExtentMask.java create mode 100644 core/src/main/java/com/sk89q/worldedit/function/mask/AbstractMask.java create mode 100644 core/src/main/java/com/sk89q/worldedit/function/pattern/AbstractPattern.java create mode 100644 core/src/main/java/com/sk89q/worldedit/util/command/CallableProcessor.java create mode 100644 core/src/main/java/com/sk89q/worldedit/util/command/DelegateCallable.java create mode 100644 core/src/main/java/com/sk89q/worldedit/util/command/ProcessedCallable.java create mode 100644 core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java diff --git a/bukkit/build.gradle b/bukkit/build.gradle index 1f5463eb..a05b954a 100644 --- a/bukkit/build.gradle +++ b/bukkit/build.gradle @@ -5,6 +5,7 @@ dependencies { compile project(':core') compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10' compile 'org.bukkit.craftbukkitv1_11:Craftbukkit:1.11' + compile 'org.bukkit.craftbukkitv1_12_P2:Craftbukkit:1.12' compile 'net.milkbowl.vault:VaultAPI:1.5' compile 'com.massivecraft:factions:2.8.0' compile 'com.drtshock:factions:1.6.9.5' 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..b5b9283f 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_12.BukkitQueue_1_12; 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; @@ -76,6 +77,7 @@ public class BukkitMain extends JavaPlugin { v1_9_R2, v1_10_R1, v1_11_R1, + v1_12_R1, NONE, } @@ -91,6 +93,8 @@ public class BukkitMain extends JavaPlugin { return new BukkitQueue_1_10(world); case v1_11_R1: return new BukkitQueue_1_11(world); + case v1_12_R1: + return new BukkitQueue_1_12(world); default: case NONE: return new BukkitQueue_All(world); @@ -109,6 +113,8 @@ public class BukkitMain extends JavaPlugin { return new BukkitQueue_1_10(world); case v1_11_R1: return new BukkitQueue_1_11(world); + case v1_12_R1: + return new BukkitQueue_1_12(world); default: case NONE: return new BukkitQueue_All(world); diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java index 9cbdb084..18bc7088 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java @@ -5,12 +5,11 @@ import com.boydti.fawe.bukkit.FaweBukkit; import com.boydti.fawe.config.Settings; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.TaskManager; +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.util.HashSet; import org.bukkit.Bukkit; import org.bukkit.Chunk; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; @@ -23,7 +22,8 @@ import org.bukkit.event.entity.ItemSpawnEvent; public class ChunkListener implements Listener { - int rateLimit = 0; + private int rateLimit = 0; + private int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS, Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS}; public ChunkListener() { if (Settings.IMP.TICK_LIMITER.ENABLED) { @@ -34,10 +34,14 @@ public class ChunkListener implements Listener { rateLimit--; physicsFreeze = false; itemFreeze = false; - counter.clear(); lastZ = Integer.MIN_VALUE; - for (Long badChunk : badChunks) { - counter.put(badChunk, new int[]{Settings.IMP.TICK_LIMITER.PHYSICS, Settings.IMP.TICK_LIMITER.ITEMS, Settings.IMP.TICK_LIMITER.FALLING}); + + counter.clear(); + for (Long2ObjectMap.Entry entry : badChunks.long2ObjectEntrySet()) { + long key = entry.getLongKey(); + int x = MathMan.unpairIntX(key); + int z = MathMan.unpairIntY(key); + counter.put(key, badLimit); } badChunks.clear(); } @@ -48,7 +52,7 @@ public class ChunkListener implements Listener { public static boolean physicsFreeze = false; public static boolean itemFreeze = false; - private HashSet badChunks = new HashSet<>(); + private Long2ObjectOpenHashMap badChunks = new Long2ObjectOpenHashMap<>(); private Long2ObjectOpenHashMap counter = new Long2ObjectOpenHashMap<>(); private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE; private int[] lastCount; @@ -100,11 +104,12 @@ public class ChunkListener implements Listener { if (y != lastPhysY) { lastPhysY = y; if (++count[0] == Settings.IMP.TICK_LIMITER.PHYSICS) { - badChunks.add(MathMan.pairInt(cx, cz)); + cancelNearby(cx, cz); if (rateLimit <= 0) { - rateLimit = 120; + rateLimit = 20; Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled physics lag source at " + block.getLocation()); } + event.setCancelled(true); } return; } @@ -112,24 +117,41 @@ public class ChunkListener implements Listener { } } + private void cancelNearby(int cx, int cz) { + cancel(cx, cz); + cancel(cx + 1, cz); + cancel(cx - 1, cz); + cancel(cx, cz + 1); + cancel(cx, cz - 1); + } + + private void cancel(int cx, int cz) { + long key = MathMan.pairInt(cx, cz); + badChunks.put(key, (Boolean) true); + counter.put(key, badLimit); + } + @EventHandler(priority = EventPriority.LOWEST) public void onBlockChange(EntityChangeBlockEvent event) { if (physicsFreeze) { event.setCancelled(true); return; } - Material to = event.getTo(); - if (to == Material.AIR) { - Block block = event.getBlock(); - int x = block.getX(); - int z = block.getZ(); - int cx = x >> 4; - int cz = z >> 4; - int[] count = getCount(cx, cz); + Block block = event.getBlock(); + int x = block.getX(); + int z = block.getZ(); + int cx = x >> 4; + int cz = z >> 4; + int[] count = getCount(cx, cz); + if (count[1] >= Settings.IMP.TICK_LIMITER.FALLING) { + event.setCancelled(true); + return; + } + if (event.getEntityType() == EntityType.FALLING_BLOCK) { if (++count[1] >= Settings.IMP.TICK_LIMITER.FALLING) { - if (count[1] == Settings.IMP.TICK_LIMITER.FALLING) { - count[0] = Settings.IMP.TICK_LIMITER.PHYSICS; - badChunks.add(MathMan.pairInt(cx, cz)); + cancelNearby(cx, cz); + if (rateLimit <= 0) { + rateLimit = 20; Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled falling block lag source at " + block.getLocation()); } event.setCancelled(true); @@ -148,15 +170,16 @@ public class ChunkListener implements Listener { int cx = loc.getBlockX() >> 4; int cz = loc.getBlockZ() >> 4; int[] count = getCount(cx, cz); + if (count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) { + event.setCancelled(true); + return; + } if (++count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) { - if (count[2] == Settings.IMP.TICK_LIMITER.ITEMS) { - count[0] = Settings.IMP.TICK_LIMITER.PHYSICS; - cleanup(loc.getChunk()); - badChunks.add(MathMan.pairInt(cx, cz)); - if (rateLimit <= 0) { - rateLimit = 120; - Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled item lag source at " + loc); - } + cleanup(loc.getChunk()); + cancelNearby(cx, cz); + if (rateLimit <= 0) { + rateLimit = 20; + Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled item lag source at " + loc); } event.setCancelled(true); return; diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java index 0ea15699..ecb5b98d 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java @@ -10,7 +10,6 @@ import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; @@ -35,6 +34,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.atomic.LongAdder; import net.minecraft.server.v1_11_R1.BiomeBase; import net.minecraft.server.v1_11_R1.BiomeCache; import net.minecraft.server.v1_11_R1.Block; diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java deleted file mode 100644 index b370d83d..00000000 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java +++ /dev/null @@ -1,243 +0,0 @@ -package com.boydti.fawe.bukkit.v1_11; - -import com.boydti.fawe.object.FaweInputStream; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Iterator; -import java.util.List; -import javax.annotation.Nullable; -import net.minecraft.server.v1_11_R1.Block; -import net.minecraft.server.v1_11_R1.Chunk; -import net.minecraft.server.v1_11_R1.ChunkSection; -import net.minecraft.server.v1_11_R1.Entity; -import net.minecraft.server.v1_11_R1.ExceptionWorldConflict; -import net.minecraft.server.v1_11_R1.IAsyncChunkSaver; -import net.minecraft.server.v1_11_R1.IChunkLoader; -import net.minecraft.server.v1_11_R1.MinecraftKey; -import net.minecraft.server.v1_11_R1.NBTCompressedStreamTools; -import net.minecraft.server.v1_11_R1.NBTReadLimiter; -import net.minecraft.server.v1_11_R1.NBTTagCompound; -import net.minecraft.server.v1_11_R1.NBTTagList; -import net.minecraft.server.v1_11_R1.NextTickListEntry; -import net.minecraft.server.v1_11_R1.NibbleArray; -import net.minecraft.server.v1_11_R1.TileEntity; -import net.minecraft.server.v1_11_R1.World; - -public class FaweChunkLoader implements IChunkLoader, IAsyncChunkSaver { - - private final File folder; - private Long2ObjectMap hashes = new Long2ObjectOpenHashMap<>(); - - public FaweChunkLoader(File folder) { - this.folder = folder; - System.out.println(folder); - } - - // writeNextIO (save) - @Override - public boolean c() { - return false; - } - - // loadChunk - @Nullable - @Override - public Chunk a(World world, int x, int z) throws IOException { - long pair = MathMan.pairInt(x, z); - Long hash = hashes.get(pair); - if (hash == null) { - return null; - } - File file = new File(folder, hash.toString()); - int length = (int) file.length(); - try (FaweInputStream in = MainUtil.getCompressedIS(new FileInputStream(file), Math.min(length, 8192))) { - NBTTagCompound nbttagcompound = NBTCompressedStreamTools.a(in, NBTReadLimiter.a); - return readChunkFromNBT(world, nbttagcompound); - } - } - - private Chunk readChunkFromNBT(World world, NBTTagCompound nbttagcompound) { - int i = nbttagcompound.getInt("xPos"); - int j = nbttagcompound.getInt("zPos"); - Chunk chunk = new Chunk(world, i, j); - chunk.a(nbttagcompound.getIntArray("HeightMap")); - chunk.d(nbttagcompound.getBoolean("TerrainPopulated")); - chunk.e(nbttagcompound.getBoolean("LightPopulated")); - chunk.c(nbttagcompound.getLong("InhabitedTime")); - NBTTagList nbttaglist = nbttagcompound.getList("Sections", 10); - ChunkSection[] achunksection = new ChunkSection[16]; - boolean flag1 = world.worldProvider.m(); - - for(int k = 0; k < nbttaglist.size(); ++k) { - NBTTagCompound nbttagcompound1 = nbttaglist.get(k); - byte b0 = nbttagcompound1.getByte("Y"); - ChunkSection chunksection = new ChunkSection(b0 << 4, flag1); - byte[] abyte = nbttagcompound1.getByteArray("Blocks"); - NibbleArray nibblearray = new NibbleArray(nbttagcompound1.getByteArray("Data")); - NibbleArray nibblearray1 = nbttagcompound1.hasKeyOfType("Add", 7) ? new NibbleArray(nbttagcompound1.getByteArray("Add")):null; - chunksection.getBlocks().a(abyte, nibblearray, nibblearray1); - chunksection.a(new NibbleArray(nbttagcompound1.getByteArray("BlockLight"))); - if(flag1) { - chunksection.b(new NibbleArray(nbttagcompound1.getByteArray("SkyLight"))); - } - - chunksection.recalcBlockCounts(); - achunksection[b0] = chunksection; - } - - chunk.a(achunksection); - if(nbttagcompound.hasKeyOfType("Biomes", 7)) { - chunk.a(nbttagcompound.getByteArray("Biomes")); - } - - return chunk; - } - - - // saveChunk - @Override - public void a(World world, Chunk chunk) throws IOException, ExceptionWorldConflict { - try { - NBTTagCompound exception = new NBTTagCompound(); - NBTTagCompound nbttagcompound1 = new NBTTagCompound(); - exception.set("Level", nbttagcompound1); - exception.setInt("DataVersion", 819); - this.writeChunkToNBT(chunk, world, nbttagcompound1); -// this.a(chunk.k(), exception); - } catch (Exception var5) { - } - } - - private void writeChunkToNBT(Chunk chunk, World world, NBTTagCompound nbttagcompound) { - nbttagcompound.setInt("xPos", chunk.locX); - nbttagcompound.setInt("zPos", chunk.locZ); - nbttagcompound.setLong("LastUpdate", world.getTime()); - nbttagcompound.setIntArray("HeightMap", chunk.r()); - nbttagcompound.setBoolean("TerrainPopulated", chunk.isDone()); - nbttagcompound.setBoolean("LightPopulated", chunk.v()); - nbttagcompound.setLong("InhabitedTime", chunk.x()); - ChunkSection[] achunksection = chunk.getSections(); - NBTTagList nbttaglist = new NBTTagList(); - boolean flag = world.worldProvider.m(); - ChunkSection[] achunksection1 = achunksection; - int i = achunksection.length; - - NBTTagCompound nbttagcompound1; - for(int nbttaglist1 = 0; nbttaglist1 < i; ++nbttaglist1) { - ChunkSection iterator = achunksection1[nbttaglist1]; - if(iterator != Chunk.a) { - nbttagcompound1 = new NBTTagCompound(); - nbttagcompound1.setByte("Y", (byte)(iterator.getYPosition() >> 4 & 255)); - byte[] nbttaglist2 = new byte[4096]; - NibbleArray list = new NibbleArray(); - NibbleArray nibblearray1 = iterator.getBlocks().exportData(nbttaglist2, list); - nbttagcompound1.setByteArray("Blocks", nbttaglist2); - nbttagcompound1.setByteArray("Data", list.asBytes()); - if(nibblearray1 != null) { - nbttagcompound1.setByteArray("Add", nibblearray1.asBytes()); - } - - nbttagcompound1.setByteArray("BlockLight", iterator.getEmittedLightArray().asBytes()); - if(flag) { - nbttagcompound1.setByteArray("SkyLight", iterator.getSkyLightArray().asBytes()); - } else { - nbttagcompound1.setByteArray("SkyLight", new byte[iterator.getEmittedLightArray().asBytes().length]); - } - - nbttaglist.add(nbttagcompound1); - } - } - - nbttagcompound.set("Sections", nbttaglist); - nbttagcompound.setByteArray("Biomes", chunk.getBiomeIndex()); - chunk.g(false); - NBTTagList var22 = new NBTTagList(); - - Iterator var23; - for(i = 0; i < chunk.getEntitySlices().length; ++i) { - var23 = chunk.getEntitySlices()[i].iterator(); - - while(var23.hasNext()) { - Entity var24 = (Entity)var23.next(); - nbttagcompound1 = new NBTTagCompound(); - if(var24.d(nbttagcompound1)) { - chunk.g(true); - var22.add(nbttagcompound1); - } - } - } - - nbttagcompound.set("Entities", var22); - NBTTagList var25 = new NBTTagList(); - var23 = chunk.getTileEntities().values().iterator(); - - while(var23.hasNext()) { - TileEntity var26 = (TileEntity)var23.next(); - nbttagcompound1 = var26.save(new NBTTagCompound()); - var25.add(nbttagcompound1); - } - - nbttagcompound.set("TileEntities", var25); - List var27 = world.a(chunk, false); - if(var27 != null) { - long k = world.getTime(); - NBTTagList nbttaglist3 = new NBTTagList(); - Iterator iterator1 = var27.iterator(); - - while(iterator1.hasNext()) { - NextTickListEntry nextticklistentry = (NextTickListEntry)iterator1.next(); - NBTTagCompound nbttagcompound2 = new NBTTagCompound(); - MinecraftKey minecraftkey = (MinecraftKey) Block.REGISTRY.b(nextticklistentry.a()); - nbttagcompound2.setString("i", minecraftkey == null?"":minecraftkey.toString()); - nbttagcompound2.setInt("x", nextticklistentry.a.getX()); - nbttagcompound2.setInt("y", nextticklistentry.a.getY()); - nbttagcompound2.setInt("z", nextticklistentry.a.getZ()); - nbttagcompound2.setInt("t", (int)(nextticklistentry.b - k)); - nbttagcompound2.setInt("p", nextticklistentry.c); - nbttaglist3.add(nbttagcompound2); - } - - nbttagcompound.set("TileTicks", nbttaglist3); - } - - } - - // saveExtraChunkData - @Override - public void b(World world, Chunk chunk) throws IOException { - - } - - // chunkTick - @Override - public void a() { - - } - - // saveExtraData - @Override - public void b() { -// try { -// this.savingExtraData = true; -// -// while(true) { -// if(this.writeNextIO()) { -// continue; -// } -// } -// } finally { -// this.savingExtraData = false; -// } - } - - // isChunkGeneratedAt - @Override - public boolean a(int x, int z) { - return hashes.containsKey(MathMan.pairInt(x, z)); - } -} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java new file mode 100644 index 00000000..36433cb5 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java @@ -0,0 +1,499 @@ +package com.boydti.fawe.bukkit.v1_12; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FaweQueue; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.ReflectionUtils; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.LongTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.internal.Constants; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import net.minecraft.server.v1_12_R1.Block; +import net.minecraft.server.v1_12_R1.BlockPosition; +import net.minecraft.server.v1_12_R1.ChunkSection; +import net.minecraft.server.v1_12_R1.DataBits; +import net.minecraft.server.v1_12_R1.DataPalette; +import net.minecraft.server.v1_12_R1.DataPaletteBlock; +import net.minecraft.server.v1_12_R1.DataPaletteGlobal; +import net.minecraft.server.v1_12_R1.Entity; +import net.minecraft.server.v1_12_R1.EntityPlayer; +import net.minecraft.server.v1_12_R1.EntityTypes; +import net.minecraft.server.v1_12_R1.IBlockData; +import net.minecraft.server.v1_12_R1.MinecraftKey; +import net.minecraft.server.v1_12_R1.NBTTagCompound; +import net.minecraft.server.v1_12_R1.TileEntity; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_12_R1.CraftChunk; +import org.bukkit.event.entity.CreatureSpawnEvent; + +public class BukkitChunk_1_12 extends CharFaweChunk { + + public DataPaletteBlock[] sectionPalettes; + + public static Map> entityKeys; + + /** + * A FaweSections object represents a chunk and the blocks that you wish to change in it. + * + * @param parent + * @param x + * @param z + */ + public BukkitChunk_1_12(FaweQueue parent, int x, int z) { + super(parent, x, z); + } + + public BukkitChunk_1_12(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) { + super(parent, x, z, ids, count, air, heightMap); + } + + public void storeBiomes(byte[] biomes) { + this.biomes = Arrays.copyOf(biomes, biomes.length); + } + + public boolean storeTile(TileEntity tile, BlockPosition pos) { + NBTTagCompound tag = new NBTTagCompound(); + CompoundTag nativeTag = getParent().getTag(tile); + setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); + return true; + } + + public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException { + if (ent instanceof EntityPlayer) { + return false; + } + int x = ((int) Math.round(ent.locX) & 15); + int z = ((int) Math.round(ent.locZ) & 15); + int y = ((int) Math.round(ent.locY) & 0xFF); + int i = FaweCache.CACHE_I[y][z][x]; + int j = FaweCache.CACHE_J[y][z][x]; + String id = EntityTypes.b(ent); + if (id != null) { + NBTTagCompound tag = new NBTTagCompound(); + ent.save(tag); // readEntityIntoTag + CompoundTag nativeTag = (CompoundTag) getParent().methodToNative.invoke(getParent().adapter, tag); + Map map = ReflectionUtils.getMap(nativeTag.getValue()); + map.put("Id", new StringTag(id)); + setEntity(nativeTag); + return true; + } else { + return false; + } + } + + @Override + public CharFaweChunk copy(boolean shallow) { + BukkitChunk_1_12 copy; + if (shallow) { + copy = new BukkitChunk_1_12(getParent(), getX(), getZ(), ids, count, air, heightMap); + copy.biomes = biomes; + copy.chunk = chunk; + } else { + copy = new BukkitChunk_1_12(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone()); + copy.biomes = biomes; + copy.chunk = chunk; + copy.biomes = biomes.clone(); + copy.chunk = chunk; + } + if (sectionPalettes != null) { + copy.sectionPalettes = new DataPaletteBlock[16]; + try { + for (int i = 0; i < sectionPalettes.length; i++) { + DataPaletteBlock current = sectionPalettes[i]; + if (current == null) { + continue; + } + // Clone palette + DataPalette currentPalette = (DataPalette) BukkitQueue_1_12.fieldPalette.get(current); + if (!(currentPalette instanceof DataPaletteGlobal)) { + current.a(128, null); + } + DataPaletteBlock paletteBlock = newDataPaletteBlock(); + currentPalette = (DataPalette) BukkitQueue_1_12.fieldPalette.get(current); + if (!(currentPalette instanceof DataPaletteGlobal)) { + throw new RuntimeException("Palette must be global!"); + } + BukkitQueue_1_12.fieldPalette.set(paletteBlock, currentPalette); + // Clone size + BukkitQueue_1_12.fieldSize.set(paletteBlock, BukkitQueue_1_12.fieldSize.get(current)); + // Clone palette + DataBits currentBits = (DataBits) BukkitQueue_1_12.fieldBits.get(current); + DataBits newBits = new DataBits(1, 0); + for (Field field : DataBits.class.getDeclaredFields()) { + field.setAccessible(true); + Object currentValue = field.get(currentBits); + if (currentValue instanceof long[]) { + currentValue = ((long[]) currentValue).clone(); + } + field.set(newBits, currentValue); + } + BukkitQueue_1_12.fieldBits.set(paletteBlock, newBits); + copy.sectionPalettes[i] = paletteBlock; + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + } + return copy; + } + + @Override + public Chunk getNewChunk() { + return ((BukkitQueue_1_12) getParent()).getWorld().getChunkAt(getX(), getZ()); + } + + public DataPaletteBlock newDataPaletteBlock() { + try { + return new DataPaletteBlock(); + } catch (Throwable e) { + try { + Constructor constructor = DataPaletteBlock.class.getDeclaredConstructor(IBlockData[].class); + return constructor.newInstance((Object) null); + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } + } + + public void optimize() { + if (sectionPalettes != null) { + return; + } + char[][] arrays = getCombinedIdArrays(); + IBlockData lastBlock = null; + char lastChar = Character.MAX_VALUE; + for (int layer = 0; layer < 16; layer++) { + if (getCount(layer) > 0) { + if (sectionPalettes == null) { + sectionPalettes = new DataPaletteBlock[16]; + } + DataPaletteBlock palette = newDataPaletteBlock(); + char[] blocks = getIdArray(layer); + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + char combinedId = blocks[FaweCache.CACHE_J[y][z][x]]; + if (combinedId > 1) { + palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF)); + } + } + } + } + } + } + } + + @Override + public void start() { + getChunk().load(true); + } + + private void removeEntity(Entity entity) { + entity.b(false); + entity.die(); + entity.valid = false; + } + + @Override + public FaweChunk call() { + try { + BukkitChunk_1_12_Copy copy = getParent().getChangeTask() != null ? new BukkitChunk_1_12_Copy(getParent(), getX(), getZ()) : null; + final Chunk chunk = this.getChunk(); + final World world = chunk.getWorld(); + int bx = this.getX() << 4; + int bz = this.getZ() << 4; + final boolean flag = world.getEnvironment() == World.Environment.NORMAL; + net.minecraft.server.v1_12_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle(); + nmsChunk.f(true); // Set Modified + nmsChunk.mustSave = true; + net.minecraft.server.v1_12_R1.World nmsWorld = nmsChunk.world; + ChunkSection[] sections = nmsChunk.getSections(); + final Collection[] entities = (Collection[]) getParent().getEntitySlices.invoke(nmsChunk); + Map tiles = nmsChunk.getTileEntities(); + // Set heightmap + getParent().setHeightMap(this, heightMap); + // Remove entities + HashSet entsToRemove = this.getEntityRemoves(); + if (!entsToRemove.isEmpty()) { + for (int i = 0; i < entities.length; i++) { + Collection ents = entities[i]; + if (!ents.isEmpty()) { + Iterator iter = ents.iterator(); + while (iter.hasNext()) { + Entity entity = iter.next(); + if (entsToRemove.contains(entity.getUniqueID())) { + if (copy != null) { + copy.storeEntity(entity); + } + removeEntity(entity); + iter.remove(); + } + } + } + } + } + for (int i = 0; i < entities.length; i++) { + int count = this.getCount(i); + if (count == 0) { + continue; + } else if (count >= 4096) { + Collection ents = entities[i]; + if (!ents.isEmpty()) { + if (copy != null) { + for (Entity entity : ents) { + copy.storeEntity(entity); + } + } + synchronized (BukkitQueue_0.class) { + ents.clear(); + } + } + } else { + Collection ents = entities[i]; + if (!ents.isEmpty()) { + char[] array = this.getIdArray(i); + if (array == null) continue; + Iterator iter = ents.iterator(); + while (iter.hasNext()) { + Entity entity = iter.next(); + if (entity instanceof EntityPlayer) { + continue; + } + int x = ((int) Math.round(entity.locX) & 15); + int z = ((int) Math.round(entity.locZ) & 15); + int y = (int) Math.round(entity.locY); + if (y < 0 || y > 255) continue; + if (array[FaweCache.CACHE_J[y][z][x]] != 0) { + if (copy != null) { + copy.storeEntity(entity); + } + iter.remove(); + removeEntity(entity); + } + } + } + } + } + // Set entities + Set entitiesToSpawn = this.getEntities(); + Set createdEntities = new HashSet<>(); + if (!entitiesToSpawn.isEmpty()) { + synchronized (BukkitQueue_0.class) { + for (CompoundTag nativeTag : entitiesToSpawn) { + Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue()); + StringTag idTag = (StringTag) entityTagMap.get("Id"); + ListTag posTag = (ListTag) entityTagMap.get("Pos"); + ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); + if (idTag == null || posTag == null || rotTag == null) { + Fawe.debug("Unknown entity tag: " + nativeTag); + continue; + } + double x = posTag.getDouble(0); + double y = posTag.getDouble(1); + double z = posTag.getDouble(2); + float yaw = rotTag.getFloat(0); + float pitch = rotTag.getFloat(1); + String id = idTag.getValue(); + if (entityKeys == null) { + entityKeys = new HashMap<>(); + for (MinecraftKey key : EntityTypes.a()) { + String currentId = EntityTypes.a(key); + Class clazz = EntityTypes.b.get(key); + entityKeys.put(currentId, clazz); + entityKeys.put(key.getKey(), clazz); + } + } + Class clazz = entityKeys.get(id); + if (clazz != null) { + Entity entity = EntityTypes.a(clazz, nmsWorld); + if (entity != null) { + UUID uuid = entity.getUniqueID(); + entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); + entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); + if (nativeTag != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + entity.f(tag); + } + entity.setLocation(x, y, z, yaw, pitch); + nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM); + createdEntities.add(entity.getUniqueID()); + } + } + } + } + } + // Trim tiles + Iterator> iterator = tiles.entrySet().iterator(); + HashMap toRemove = null; + while (iterator.hasNext()) { + Map.Entry tile = iterator.next(); + BlockPosition pos = tile.getKey(); + int lx = pos.getX() & 15; + int ly = pos.getY(); + int lz = pos.getZ() & 15; + int j = FaweCache.CACHE_I[ly][lz][lx]; + char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + int k = FaweCache.CACHE_J[ly][lz][lx]; + if (array[k] != 0) { + if (toRemove == null) { + toRemove = new HashMap<>(); + } + if (copy != null) { + copy.storeTile(tile.getValue(), tile.getKey()); + } + toRemove.put(tile.getKey(), tile.getValue()); + } + } + if (toRemove != null) { + for (Map.Entry entry : toRemove.entrySet()) { + BlockPosition bp = entry.getKey(); + TileEntity tile = entry.getValue(); + tiles.remove(bp); + tile.z(); + nmsWorld.s(bp); + tile.invalidateBlockCache(); + } + + } + // Set blocks + for (int j = 0; j < sections.length; j++) { + int count = this.getCount(j); + if (count == 0) { + continue; + } + int countAir = this.getAir(j); + final char[] array = this.getIdArray(j); + if (array == null) { + continue; + } + ChunkSection section = sections[j]; + if (copy != null) { + copy.storeSection(section, j); + } + if (section == null) { + if (count == countAir) { + continue; + } + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + section = sections[j] = getParent().newChunkSection(j << 4, flag, null); + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + continue; + } + } else if (count >= 4096) { + if (countAir >= 4096) { + sections[j] = null; + continue; + } + if (this.sectionPalettes != null && this.sectionPalettes[j] != null) { + getParent().setPalette(section, this.sectionPalettes[j]); + getParent().setCount(0, count - this.getAir(j), section); + continue; + } else { + sections[j] = getParent().newChunkSection(j << 4, flag, array); + continue; + } + } + int by = j << 4; + DataPaletteBlock nibble = section.getBlocks(); + int nonEmptyBlockCount = 0; + IBlockData existing; + for (int y = 0; y < 16; y++) { + short[][] i1 = FaweCache.CACHE_J[y]; + for (int z = 0; z < 16; z++) { + short[] i2 = i1[z]; + for (int x= 0; x < 16; x++) { + char combinedId = array[i2[x]]; + switch (combinedId) { + case 0: + continue; + case 1: + existing = nibble.a(x, y, z); + if (existing != BukkitQueue_1_12.air) { + if (existing.d() > 0) { + getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); + } + nonEmptyBlockCount--; + } + nibble.setBlock(x, y, z, BukkitQueue_1_12.air); + continue; + default: + existing = nibble.a(x, y, z); + if (existing != BukkitQueue_1_12.air) { + if (existing.d() > 0) { + getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z); + } + } else { + nonEmptyBlockCount++; + } + nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]); + } + } + } + } + getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section); + } + // Set biomes + if (this.biomes != null) { + if (copy != null) { + copy.storeBiomes(nmsChunk.getBiomeIndex()); + } + byte[] currentBiomes = nmsChunk.getBiomeIndex(); + for (int i = 0 ; i < this.biomes.length; i++) { + if (this.biomes[i] != 0) { + currentBiomes[i] = this.biomes[i]; + } + } + } + // Set tiles + Map tilesToSpawn = this.getTiles(); + for (Map.Entry entry : tilesToSpawn.entrySet()) { + CompoundTag nativeTag = entry.getValue(); + short blockHash = entry.getKey(); + int x = (blockHash >> 12 & 0xF) + bx; + int y = (blockHash & 0xFF); + int z = (blockHash >> 8 & 0xF) + bz; + BlockPosition pos = new BlockPosition(x, y, z); // Set pos + TileEntity tileEntity = nmsWorld.getTileEntity(pos); + if (tileEntity != null) { + NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag); + tileEntity.a(tag); // ReadTagIntoTile + } + } + // Change task + if (copy != null) { + getParent().getChangeTask().run(copy, this); + } + } catch (Throwable e) { + MainUtil.handleError(e); + } + return this; + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java new file mode 100644 index 00000000..10e39f1d --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java @@ -0,0 +1,80 @@ +package com.boydti.fawe.bukkit.v1_12; + +import com.boydti.fawe.object.FaweQueue; +import net.minecraft.server.v1_12_R1.ChunkSection; +import net.minecraft.server.v1_12_R1.DataPaletteBlock; +import net.minecraft.server.v1_12_R1.NibbleArray; + +public class BukkitChunk_1_12_Copy extends BukkitChunk_1_12 { + public final byte[][] idsBytes; + public final byte[][] datasBytes; + + public BukkitChunk_1_12_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_12/BukkitQueue_1_12.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java new file mode 100644 index 00000000..1dfa2ca3 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java @@ -0,0 +1,803 @@ +package com.boydti.fawe.bukkit.v1_12; + +import com.boydti.fawe.Fawe; +import com.boydti.fawe.FaweCache; +import com.boydti.fawe.bukkit.BukkitPlayer; +import com.boydti.fawe.bukkit.v0.BukkitQueue_0; +import com.boydti.fawe.example.CharFaweChunk; +import com.boydti.fawe.object.FaweChunk; +import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.object.RegionWrapper; +import com.boydti.fawe.object.RunnableVal; +import com.boydti.fawe.object.brush.visualization.VisualChunk; +import com.boydti.fawe.object.visitor.FaweChunkVisitor; +import com.boydti.fawe.util.MainUtil; +import com.boydti.fawe.util.MathMan; +import com.boydti.fawe.util.ReflectionUtils; +import com.boydti.fawe.util.TaskManager; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.world.biome.BaseBiome; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufAllocator; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.atomic.LongAdder; +import net.minecraft.server.v1_12_R1.BiomeBase; +import net.minecraft.server.v1_12_R1.BiomeCache; +import net.minecraft.server.v1_12_R1.Block; +import net.minecraft.server.v1_12_R1.BlockPosition; +import net.minecraft.server.v1_12_R1.ChunkProviderGenerate; +import net.minecraft.server.v1_12_R1.ChunkProviderServer; +import net.minecraft.server.v1_12_R1.ChunkSection; +import net.minecraft.server.v1_12_R1.DataPaletteBlock; +import net.minecraft.server.v1_12_R1.Entity; +import net.minecraft.server.v1_12_R1.EntityPlayer; +import net.minecraft.server.v1_12_R1.EntityTracker; +import net.minecraft.server.v1_12_R1.EntityTypes; +import net.minecraft.server.v1_12_R1.EnumDifficulty; +import net.minecraft.server.v1_12_R1.EnumGamemode; +import net.minecraft.server.v1_12_R1.EnumSkyBlock; +import net.minecraft.server.v1_12_R1.IBlockData; +import net.minecraft.server.v1_12_R1.IDataManager; +import net.minecraft.server.v1_12_R1.MinecraftServer; +import net.minecraft.server.v1_12_R1.NBTTagCompound; +import net.minecraft.server.v1_12_R1.NibbleArray; +import net.minecraft.server.v1_12_R1.PacketDataSerializer; +import net.minecraft.server.v1_12_R1.PacketPlayOutMapChunk; +import net.minecraft.server.v1_12_R1.PacketPlayOutMultiBlockChange; +import net.minecraft.server.v1_12_R1.PlayerChunk; +import net.minecraft.server.v1_12_R1.PlayerChunkMap; +import net.minecraft.server.v1_12_R1.RegionFile; +import net.minecraft.server.v1_12_R1.RegionFileCache; +import net.minecraft.server.v1_12_R1.ServerNBTManager; +import net.minecraft.server.v1_12_R1.TileEntity; +import net.minecraft.server.v1_12_R1.WorldChunkManager; +import net.minecraft.server.v1_12_R1.WorldData; +import net.minecraft.server.v1_12_R1.WorldManager; +import net.minecraft.server.v1_12_R1.WorldServer; +import net.minecraft.server.v1_12_R1.WorldSettings; +import net.minecraft.server.v1_12_R1.WorldType; +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.block.Biome; +import org.bukkit.craftbukkit.v1_12_R1.CraftChunk; +import org.bukkit.craftbukkit.v1_12_R1.CraftServer; +import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; +import org.bukkit.event.world.WorldInitEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.bukkit.generator.ChunkGenerator; + +public class BukkitQueue_1_12 extends BukkitQueue_0 { + + protected static IBlockData air; + protected static Field fieldBits; + protected static Field fieldPalette; + protected static Field fieldSize; + protected static Method getEntitySlices; + protected static Field fieldTickingBlockCount; + protected static Field fieldNonEmptyBlockCount; + protected static Field fieldSection; + protected static Field fieldBiomes; + protected static Field fieldChunkGenerator; + protected static Field fieldSeed; + protected static Field fieldBiomeCache; + protected static Field fieldBiomes2; + protected static Field fieldGenLayer1; + protected static Field fieldGenLayer2; + protected static MutableGenLayer genLayer; + protected static ChunkSection emptySection; + + public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE + 1]; + + static { + try { + emptySection = new ChunkSection(0, true); + fieldSection = ChunkSection.class.getDeclaredField("blockIds"); + fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount"); + fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); + fieldSection.setAccessible(true); + fieldTickingBlockCount.setAccessible(true); + fieldNonEmptyBlockCount.setAccessible(true); + + fieldBiomes = ChunkProviderGenerate.class.getDeclaredField("D"); + fieldBiomes.setAccessible(true); + fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("chunkGenerator"); + fieldChunkGenerator.setAccessible(true); + fieldSeed = WorldData.class.getDeclaredField("e"); + fieldSeed.setAccessible(true); + fieldBiomeCache = WorldChunkManager.class.getDeclaredField("d"); + fieldBiomeCache.setAccessible(true); + fieldBiomes2 = WorldChunkManager.class.getDeclaredField("e"); + fieldBiomes2.setAccessible(true); + fieldGenLayer1 = WorldChunkManager.class.getDeclaredField("b") ; + fieldGenLayer2 = WorldChunkManager.class.getDeclaredField("c") ; + fieldGenLayer1.setAccessible(true); + fieldGenLayer2.setAccessible(true); + + fieldPalette = DataPaletteBlock.class.getDeclaredField("c"); + fieldPalette.setAccessible(true); + fieldSize = DataPaletteBlock.class.getDeclaredField("e"); + fieldSize.setAccessible(true); + + Field fieldAir = DataPaletteBlock.class.getDeclaredField("a"); + fieldAir.setAccessible(true); + air = (IBlockData) fieldAir.get(null); + fieldBits = DataPaletteBlock.class.getDeclaredField("b"); + fieldBits.setAccessible(true); + getEntitySlices = net.minecraft.server.v1_12_R1.Chunk.class.getDeclaredMethod("getEntitySlices"); + getEntitySlices.setAccessible(true); + setupAdapter(new FaweAdapter_1_12()); + Fawe.debug("Using adapter: " + adapter); + Fawe.debug("========================================="); + for (int i = 0; i < IBD_CACHE.length; i++) { + try { + IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF); + } catch (Throwable ignore) {} + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + public BukkitQueue_1_12(final com.sk89q.worldedit.world.World world) { + super(world); + getImpWorld(); + } + + public BukkitQueue_1_12(final String world) { + super(world); + getImpWorld(); + } + + @Override + public ChunkSection[] getSections(net.minecraft.server.v1_12_R1.Chunk chunk) { + return chunk.getSections(); + } + + @Override + public net.minecraft.server.v1_12_R1.Chunk loadChunk(World world, int x, int z, boolean generate) { + ChunkProviderServer provider = ((CraftWorld) world).getHandle().getChunkProviderServer(); + if (generate) { + return provider.getOrLoadChunkAt(x, z); + } else { + return provider.loadChunk(x, z); + } + } + + @Override + public ChunkSection[] getCachedSections(World world, int cx, int cz) { + net.minecraft.server.v1_12_R1.Chunk chunk = ((CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz); + if (chunk != null) { + return chunk.getSections(); + } + return null; + } + + @Override + public net.minecraft.server.v1_12_R1.Chunk getCachedChunk(World world, int cx, int cz) { + return ((CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz); + } + + @Override + public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) { + return chunkSections[cy]; + } + + @Override + public void saveChunk(net.minecraft.server.v1_12_R1.Chunk chunk) { + chunk.f(true); // Set Modified + chunk.mustSave = true; + } + + @Override + public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) { + if (biome != null) { + try { + if (seed == null) { + seed = world.getSeed(); + } + nmsWorld.worldData.getSeed(); + boolean result; + ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, ""); + Biome bukkitBiome = adapter.getBiome(biome.getId()); + BiomeBase base = BiomeBase.getBiome(biome.getId()); + fieldBiomes.set(generator, new BiomeBase[]{base}); + boolean cold = base.getTemperature() <= 1; + net.minecraft.server.v1_12_R1.ChunkGenerator existingGenerator = nmsWorld.getChunkProviderServer().chunkGenerator; + long existingSeed = world.getSeed(); + { + if (genLayer == null) genLayer = new MutableGenLayer(seed); + genLayer.set(biome.getId()); + Object existingGenLayer1 = fieldGenLayer1.get(nmsWorld.getWorldChunkManager()); + Object existingGenLayer2 = fieldGenLayer2.get(nmsWorld.getWorldChunkManager()); + fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), genLayer); + fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), genLayer); + + fieldSeed.set(nmsWorld.worldData, seed); + + ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.getWorldChunkManager(), new BiomeCache(this.nmsWorld.getWorldChunkManager())); + + ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProviderServer(), generator); + + result = getWorld().regenerateChunk(x, z); + + ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProviderServer(), existingGenerator); + + fieldSeed.set(nmsWorld.worldData, existingSeed); + + fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), existingGenLayer1); + fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), existingGenLayer2); + } + return result; + } catch (Throwable e) { + e.printStackTrace(); + } + } + return super.regenerateChunk(world, x, z, biome, seed); + } + + @Override + public boolean setMCA(Runnable whileLocked, final RegionWrapper allowed, boolean unload) { + try { + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + try { + synchronized (RegionFileCache.class) { + ArrayDeque chunks = new ArrayDeque<>(); + World world = getWorld(); + world.setKeepSpawnInMemory(false); + ChunkProviderServer provider = nmsWorld.getChunkProviderServer(); + if (unload) { // Unload chunks + int bcx = (allowed.minX >> 9) << 5; + int bcz = (allowed.minZ >> 9) << 5; + int tcx = 31 + (allowed.maxX >> 9) << 5; + int tcz = 31 + (allowed.maxZ >> 9) << 5; + Iterator iter = provider.a().iterator(); + while (iter.hasNext()) { + net.minecraft.server.v1_12_R1.Chunk chunk = iter.next(); + int cx = chunk.locX; + int cz = chunk.locZ; + if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) { + chunks.add(chunk); + } + } + for (net.minecraft.server.v1_12_R1.Chunk chunk : chunks) { + provider.unloadChunk(chunk, true); + } + } + provider.c(); + + if (unload) { // Unload regions + Map map = RegionFileCache.a; + Iterator> iter = map.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + RegionFile regionFile = entry.getValue(); + regionFile.c(); + iter.remove(); + } + } + whileLocked.run(); + // Load the chunks again + if (unload) { + for (net.minecraft.server.v1_12_R1.Chunk chunk : chunks) { + chunk = provider.loadChunk(chunk.locX, chunk.locZ); + if (chunk != null) { + sendChunk(chunk, 0); + } + } + } + + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + return true; + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + + @Override + public void setHeightMap(FaweChunk chunk, byte[] heightMap) { + CraftChunk craftChunk = (CraftChunk) chunk.getChunk(); + if (craftChunk != null) { + int[] otherMap = craftChunk.getHandle().heightMap; + for (int i = 0; i < heightMap.length; i++) { + int newHeight = heightMap[i] & 0xFF; + int currentHeight = otherMap[i]; + if (newHeight > currentHeight) { + otherMap[i] = newHeight; + } + } + } + } + + @Override + public boolean next(int amount, long time) { + return super.next(amount, time); + } + + @Override + public void setSkyLight(ChunkSection section, int x, int y, int z, int value) { + section.getSkyLightArray().a(x & 15, y & 15, z & 15, value); + } + + @Override + public void setBlockLight(ChunkSection section, int x, int y, int z, int value) { + section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value); + } + + @Override + public World createWorld(final WorldCreator creator) { + final String name = creator.name(); + ChunkGenerator generator = creator.generator(); + final CraftServer server = (CraftServer) Bukkit.getServer(); + final MinecraftServer console = server.getServer(); + final File folder = new File(server.getWorldContainer(), name); + final World world = server.getWorld(name); + final WorldType type = WorldType.getType(creator.type().getName()); + final boolean generateStructures = creator.generateStructures(); + if (world != null) { + return world; + } + if (folder.exists() && !folder.isDirectory()) { + throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder"); + } + TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(Object value) { + try { + Field field = CraftServer.class.getDeclaredField("worlds"); + field.setAccessible(true); + Map existing = (Map) field.get(server); + if (!existing.getClass().getName().contains("SynchronizedMap")) { + field.set(server, Collections.synchronizedMap(existing)); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + }); + if (generator == null) { + generator = server.getGenerator(name); + } + int dimension = 10 + console.worlds.size(); + boolean used = false; + do { + for (final WorldServer ws : console.worlds) { + used = (ws.dimension == dimension); + if (used) { + ++dimension; + break; + } + } + } while (used); + final boolean hardcore = false; + final IDataManager sdm = new ServerNBTManager(server.getWorldContainer(), name, true, server.getHandle().getServer().dataConverterManager); + WorldData worlddata = sdm.getWorldData(); + final WorldSettings worldSettings; + if (worlddata == null) { + worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type); + worldSettings.setGeneratorSettings(creator.generatorSettings()); + worlddata = new WorldData(worldSettings, name); + } else { + worldSettings = null; + } + worlddata.checkName(name); + final WorldServer internal = (WorldServer)new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b(); + startSet(true); // Temporarily allow async chunk load since the world isn't added yet + if (worldSettings != null) { + internal.a(worldSettings); + } + endSet(true); + internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle(); + internal.tracker = new EntityTracker(internal); + internal.addIWorldAccess(new WorldManager(console, internal)); + internal.worldData.setDifficulty(EnumDifficulty.EASY); + internal.setSpawnFlags(true, true); + if (generator != null) { + internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld())); + } + // Add the world + return TaskManager.IMP.sync(new RunnableVal() { + @Override + public void run(World value) { + console.worlds.add(internal); + server.getPluginManager().callEvent(new WorldInitEvent(internal.getWorld())); + server.getPluginManager().callEvent(new WorldLoadEvent(internal.getWorld())); + this.value = internal.getWorld(); + } + }); + } + + @Override + public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) { + DataPaletteBlock dataPalette = lastSection.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + Block block = ibd.getBlock(); + int id = Block.getId(block); + if (FaweCache.hasData(id)) { + return (id << 4) + block.toLegacyData(ibd); + } else { + return id << 4; + } + } + + @Override + public int getBiome(net.minecraft.server.v1_12_R1.Chunk chunk, int x, int z) { + return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)]; + } + + @Override + public int getOpacity(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return ibd.c(); + } + + @Override + public int getBrightness(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return ibd.d(); + } + + @Override + public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) { + DataPaletteBlock dataPalette = section.getBlocks(); + IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15); + return MathMan.pair16(ibd.c(), ibd.d()); + } + + @Override + public void sendChunk(int x, int z, int bitMask) { + net.minecraft.server.v1_12_R1.Chunk chunk = getCachedChunk(getWorld(), x, z); + if (chunk != null) { + sendChunk(chunk, bitMask); + } + } + + @Override + public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) { + try { + PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap(); + boolean watching = false; + boolean[] watchingArr = new boolean[players.length]; + for (int i = 0; i < players.length; i++) { + EntityPlayer player = ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle(); + if (playerManager.a(player, chunk.getX(), chunk.getZ())) { + watchingArr[i] = true; + watching = true; + } + } + if (!watching) return; + final LongAdder size = new LongAdder(); + if (chunk instanceof VisualChunk) { + size.add(((VisualChunk) chunk).size()); + } else if (chunk instanceof CharFaweChunk) { + size.add(((CharFaweChunk) chunk).getTotalCount()); + } else { + chunk.forEachQueuedBlock(new FaweChunkVisitor() { + @Override + public void run(int localX, int y, int localZ, int combined) { + size.add(1); + } + }); + } + if (size.intValue() == 0) return; + PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange(); + ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(); + final PacketDataSerializer buffer = new PacketDataSerializer(byteBuf); + buffer.writeInt(chunk.getX()); + buffer.writeInt(chunk.getZ()); + buffer.d(size.intValue()); + chunk.forEachQueuedBlock(new FaweChunkVisitor() { + @Override + public void run(int localX, int y, int localZ, int combined) { + short index = (short) (localX << 12 | localZ << 8 | y); + if (combined < 16) combined = 0; + buffer.writeShort(index); + buffer.d(combined); + } + }); + packet.a(buffer); + for (int i = 0; i < players.length; i++) { + if (watchingArr[i]) ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle().playerConnection.sendPacket(packet); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + public void refreshChunk(FaweChunk fc) { + net.minecraft.server.v1_12_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ()); + if (chunk != null) { + sendChunk(chunk, fc.getBitMask()); + } + } + + public void sendChunk(net.minecraft.server.v1_12_R1.Chunk nmsChunk, int mask) { + WorldServer w = (WorldServer) nmsChunk.getWorld(); + PlayerChunkMap chunkMap = w.getPlayerChunkMap(); + PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ); + if (playerChunk == null) { + return; + } + if (playerChunk.c.isEmpty()) { + return; + } + if (mask == 0) { + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535); + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(packet); + } + return; + } + // Send chunks + boolean empty = false; + ChunkSection[] sections = nmsChunk.getSections(); + for (int i = 0; i < sections.length; i++) { + if (sections[i] == null) { + sections[i] = emptySection; + empty = true; + } + } + if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) { + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280); + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(packet); + } + mask = 255; + } + PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask); + for (EntityPlayer player : playerChunk.c) { + player.playerConnection.sendPacket(packet); + } + if (empty) { + for (int i = 0; i < sections.length; i++) { + if (sections[i] == emptySection) { + sections[i] = null; + } + } + } + } + + public boolean hasEntities(net.minecraft.server.v1_12_R1.Chunk nmsChunk) { + try { + final Collection[] entities = (Collection[]) getEntitySlices.invoke(nmsChunk); + for (int i = 0; i < entities.length; i++) { + Collection slice = entities[i]; + if (slice != null && !slice.isEmpty()) { + return true; + } + } + } catch (Throwable ignore) {} + return false; + } + + @Override + public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) { + if (mode != RelightMode.NONE) { + for (int i = 0; i < sections.length; i++) { + ChunkSection section = sections[i]; + if (section != null) { + section.a(new NibbleArray()); // Emitted + if (sky) { + section.b(new NibbleArray()); // Skylight + } + } + } + } + return true; + } + + @Override + public void setFullbright(ChunkSection[] sections) { + for (int i = 0; i < sections.length; i++) { + ChunkSection section = sections[i]; + if (section != null) { + byte[] bytes = section.getSkyLightArray().asBytes(); + Arrays.fill(bytes, (byte) 255); + } + } + } + + @Override + public int getSkyLight(ChunkSection section, int x, int y, int z) { + return section.b(x & 15, y & 15, z & 15); + } + + @Override + public int getEmmittedLight(ChunkSection section, int x, int y, int z) { + return section.c(x & 15, y & 15, z & 15); + } + + @Override + public void relightBlock(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.c(EnumSkyBlock.BLOCK, pos); + } + + @Override + public void relightSky(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.c(EnumSkyBlock.SKY, pos); + } + + @Override + public void relight(int x, int y, int z) { + pos.c(x, y, z); + nmsWorld.w(pos); + } + + protected WorldServer nmsWorld; + + @Override + public World getImpWorld() { + World world = super.getImpWorld(); + if (world != null) { + this.nmsWorld = ((CraftWorld) world).getHandle(); + return super.getImpWorld(); + } else { + return null; + } + } + + public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException { + fieldTickingBlockCount.set(section, tickingBlockCount); + fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount); + } + + public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException { + return (int) fieldNonEmptyBlockCount.get(section); + } + + public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException { + fieldSection.set(section, palette); + Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0); + } + + public ChunkSection newChunkSection(int y2, boolean flag, char[] array) { + try { + if (array == null) { + return new ChunkSection(y2, flag); + } else { + return new ChunkSection(y2, flag, array); + } + } catch (Throwable e) { + try { + if (array == null) { + Constructor constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, IBlockData[].class); + return constructor.newInstance(y2, flag, (IBlockData[]) null); + } else { + Constructor constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, char[].class, IBlockData[].class); + return constructor.newInstance(y2, flag, array, (IBlockData[]) null); + } + } catch (Throwable e2) { + throw new RuntimeException(e2); + } + } + } + + @Override + public BukkitChunk_1_12 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map tilesGeneric, Collection[] entitiesGeneric, Set createdEntities, boolean all) throws Exception { + Map tiles = (Map) tilesGeneric; + Collection[] entities = (Collection[]) entitiesGeneric; + // Copy blocks + BukkitChunk_1_12_Copy previous = new BukkitChunk_1_12_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) { + DataPaletteBlock blocks = section.getBlocks(); + 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); + } + } + } + // Copy tiles + if (tiles != null) { + for (Map.Entry entry : tiles.entrySet()) { + TileEntity tile = entry.getValue(); + NBTTagCompound tag = new NBTTagCompound(); + BlockPosition pos = entry.getKey(); + CompoundTag nativeTag = getTag(tile); + previous.setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag); + } + } + // Copy entities + if (entities != null) { + for (Collection entityList : entities) { + for (Entity ent : entityList) { + if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) { + continue; + } + int x = ((int) Math.round(ent.locX) & 15); + int z = ((int) Math.round(ent.locZ) & 15); + int y = ((int) Math.round(ent.locY) & 0xFF); + int i = FaweCache.CACHE_I[y][z][x]; + char[] array = fs.getIdArray(i); + if (array == null) { + continue; + } + int j = FaweCache.CACHE_J[y][z][x]; + if (array[j] != 0) { + String id = EntityTypes.b(ent); + if (id != null) { + NBTTagCompound tag = new NBTTagCompound(); + ent.save(tag); // readEntityIntoTag + CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag); + Map map = ReflectionUtils.getMap(nativeTag.getValue()); + map.put("Id", new StringTag(id)); + previous.setEntity(nativeTag); + } + } + } + } + } + return previous; + } + + protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0); + + @Override + public CompoundTag getTileEntity(net.minecraft.server.v1_12_R1.Chunk chunk, int x, int y, int z) { + Map tiles = chunk.getTileEntities(); + pos.c(x, y, z); + TileEntity tile = tiles.get(pos); + return tile != null ? getTag(tile) : null; + } + + public CompoundTag getTag(TileEntity tile) { + try { + NBTTagCompound tag = new NBTTagCompound(); + tile.save(tag); // readTagIntoEntity + return (CompoundTag) methodToNative.invoke(adapter, tag); + } catch (Exception e) { + MainUtil.handleError(e); + return null; + } + } + + @Deprecated + public boolean unloadChunk(final String world, final Chunk chunk) { + net.minecraft.server.v1_12_R1.Chunk c = ((CraftChunk) chunk).getHandle(); + c.mustSave = false; + if (chunk.isLoaded()) { + chunk.unload(false, false); + } + return true; + } + + @Override + public BukkitChunk_1_12 getFaweChunk(int x, int z) { + return new BukkitChunk_1_12(this, x, z); + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/FaweAdapter_1_12.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/FaweAdapter_1_12.java new file mode 100644 index 00000000..fa8b66b0 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/FaweAdapter_1_12.java @@ -0,0 +1,333 @@ +package com.boydti.fawe.bukkit.v1_12; + +import com.google.common.base.Preconditions; +import com.sk89q.jnbt.ByteArrayTag; +import com.sk89q.jnbt.ByteTag; +import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.DoubleTag; +import com.sk89q.jnbt.EndTag; +import com.sk89q.jnbt.FloatTag; +import com.sk89q.jnbt.IntArrayTag; +import com.sk89q.jnbt.IntTag; +import com.sk89q.jnbt.ListTag; +import com.sk89q.jnbt.LongTag; +import com.sk89q.jnbt.NBTConstants; +import com.sk89q.jnbt.ShortTag; +import com.sk89q.jnbt.StringTag; +import com.sk89q.jnbt.Tag; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; +import com.sk89q.worldedit.entity.BaseEntity; +import com.sk89q.worldedit.internal.Constants; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.annotation.Nullable; +import net.minecraft.server.v1_12_R1.BiomeBase; +import net.minecraft.server.v1_12_R1.BlockPosition; +import net.minecraft.server.v1_12_R1.Entity; +import net.minecraft.server.v1_12_R1.EntityTypes; +import net.minecraft.server.v1_12_R1.MinecraftKey; +import net.minecraft.server.v1_12_R1.NBTBase; +import net.minecraft.server.v1_12_R1.NBTTagByte; +import net.minecraft.server.v1_12_R1.NBTTagByteArray; +import net.minecraft.server.v1_12_R1.NBTTagCompound; +import net.minecraft.server.v1_12_R1.NBTTagDouble; +import net.minecraft.server.v1_12_R1.NBTTagEnd; +import net.minecraft.server.v1_12_R1.NBTTagFloat; +import net.minecraft.server.v1_12_R1.NBTTagInt; +import net.minecraft.server.v1_12_R1.NBTTagIntArray; +import net.minecraft.server.v1_12_R1.NBTTagList; +import net.minecraft.server.v1_12_R1.NBTTagLong; +import net.minecraft.server.v1_12_R1.NBTTagShort; +import net.minecraft.server.v1_12_R1.NBTTagString; +import net.minecraft.server.v1_12_R1.TileEntity; +import net.minecraft.server.v1_12_R1.World; +import net.minecraft.server.v1_12_R1.WorldServer; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.v1_12_R1.CraftWorld; +import org.bukkit.craftbukkit.v1_12_R1.block.CraftBlock; +import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity; +import org.bukkit.event.entity.CreatureSpawnEvent; + +public final class FaweAdapter_1_12 implements BukkitImplAdapter +{ + private final Logger logger = Logger.getLogger(getClass().getCanonicalName()); + private final Field nbtListTagListField; + private final Method nbtCreateTagMethod; + + public FaweAdapter_1_12() throws NoSuchFieldException, NoSuchMethodException { + this.nbtListTagListField = NBTTagList.class.getDeclaredField("list"); + this.nbtListTagListField.setAccessible(true); + + this.nbtCreateTagMethod = NBTBase.class.getDeclaredMethod("createTag", new Class[] { Byte.TYPE }); + this.nbtCreateTagMethod.setAccessible(true); + } + + private static void readTagIntoTileEntity(NBTTagCompound tag, TileEntity tileEntity) + { + tileEntity.a(tag); + } + + private static void readTileEntityIntoTag(TileEntity tileEntity, NBTTagCompound tag) + { + tileEntity.save(tag); + } + + @Nullable + private static String getEntityId(Entity entity) + { + return EntityTypes.b(entity); + } + + @Nullable + private static Entity createEntityFromId(String id, World world) + { + return EntityTypes.a(new MinecraftKey(id), world); + } + + private static void readTagIntoEntity(NBTTagCompound tag, Entity entity) + { + entity.f(tag); + } + + private static void readEntityIntoTag(Entity entity, NBTTagCompound tag) + { + entity.save(tag); + } + + public int getBlockId(Material material) + { + return material.getId(); + } + + public Material getMaterial(int id) + { + return Material.getMaterial(id); + } + + public int getBiomeId(Biome biome) + { + BiomeBase mcBiome = CraftBlock.biomeToBiomeBase(biome); + return mcBiome != null ? BiomeBase.a(mcBiome) : 0; + } + + public Biome getBiome(int id) + { + BiomeBase mcBiome = BiomeBase.getBiome(id); + return CraftBlock.biomeBaseToBiome(mcBiome); + } + + public BaseBlock getBlock(Location location) + { + Preconditions.checkNotNull(location); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + Block bukkitBlock = location.getBlock(); + BaseBlock block = new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData()); + + TileEntity te = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z)); + if (te != null) + { + NBTTagCompound tag = new NBTTagCompound(); + readTileEntityIntoTag(te, tag); + block.setNbtData((CompoundTag)toNative(tag)); + } + return block; + } + + public boolean setBlock(Location location, BaseBlock block, boolean notifyAndLight) + { + Preconditions.checkNotNull(location); + Preconditions.checkNotNull(block); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + + boolean changed = location.getBlock().setTypeIdAndData(block.getId(), (byte)block.getData(), notifyAndLight); + + CompoundTag nativeTag = block.getNbtData(); + if (nativeTag != null) + { + TileEntity tileEntity = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z)); + if (tileEntity != null) + { + NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag); + tag.set("x", new NBTTagInt(x)); + tag.set("y", new NBTTagInt(y)); + tag.set("z", new NBTTagInt(z)); + readTagIntoTileEntity(tag, tileEntity); + } + } + return changed; + } + + public BaseEntity getEntity(org.bukkit.entity.Entity entity) + { + Preconditions.checkNotNull(entity); + + CraftEntity craftEntity = (CraftEntity)entity; + Entity mcEntity = craftEntity.getHandle(); + + String id = getEntityId(mcEntity); + if (id != null) { + NBTTagCompound tag = new NBTTagCompound(); + readEntityIntoTag(mcEntity, tag); + CompoundTag weTag = (CompoundTag) toNative(tag); + return new BaseEntity(id, weTag); + } + return null; + } + + @Nullable + public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state) + { + Preconditions.checkNotNull(location); + Preconditions.checkNotNull(state); + + CraftWorld craftWorld = (CraftWorld)location.getWorld(); + WorldServer worldServer = craftWorld.getHandle(); + + Entity createdEntity = createEntityFromId(state.getTypeId(), craftWorld.getHandle()); + if (createdEntity != null) + { + CompoundTag nativeTag = state.getNbtData(); + if (nativeTag != null) + { + NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag); + for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) { + tag.remove(name); + } + readTagIntoEntity(tag, createdEntity); + } + createdEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); + + worldServer.addEntity(createdEntity, CreatureSpawnEvent.SpawnReason.CUSTOM); + return createdEntity.getBukkitEntity(); + } + return null; + } + + public Tag toNative(NBTBase foreign) { + if (foreign == null) { + return null; + } + if (foreign instanceof NBTTagCompound) { + Map values = new HashMap(); + Set foreignKeys = ((NBTTagCompound) foreign).c(); // map.keySet + + for (String str : foreignKeys) { + NBTBase base = ((NBTTagCompound) foreign).get(str); + values.put(str, toNative(base)); + } + return new CompoundTag(values); + } else if (foreign instanceof NBTTagByte) { + return new ByteTag(((NBTTagByte) foreign).g()); // getByte + } else if (foreign instanceof NBTTagByteArray) { + return new ByteArrayTag(((NBTTagByteArray) foreign).c()); // data + } else if (foreign instanceof NBTTagDouble) { + return new DoubleTag(((NBTTagDouble) foreign).asDouble()); // getDouble + } else if (foreign instanceof NBTTagFloat) { + return new FloatTag(((NBTTagFloat) foreign).i()); // getFloat + } else if (foreign instanceof NBTTagInt) { + return new IntTag(((NBTTagInt) foreign).e()); // getInt + } else if (foreign instanceof NBTTagIntArray) { + return new IntArrayTag(((NBTTagIntArray) foreign).d()); // data + } else if (foreign instanceof NBTTagList) { + try { + return toNativeList((NBTTagList) foreign); + } catch (Throwable e) { + logger.log(Level.WARNING, "Failed to convert NBTTagList", e); + return new ListTag(ByteTag.class, new ArrayList()); + } + } else if (foreign instanceof NBTTagLong) { + return new LongTag(((NBTTagLong) foreign).d()); // getLong + } else if (foreign instanceof NBTTagShort) { + return new ShortTag(((NBTTagShort) foreign).f()); // getShort + } else if (foreign instanceof NBTTagString) { + return new StringTag(((NBTTagString) foreign).c_()); // data + } else if (foreign instanceof NBTTagEnd) { + return new EndTag(); + } else { + throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName()); + } + } + + public ListTag toNativeList(NBTTagList foreign) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { + List values = new ArrayList(); + int type = foreign.g(); + + List foreignList; + foreignList = (List) nbtListTagListField.get(foreign); + for (int i = 0; i < foreign.size(); i++) { + NBTBase element = (NBTBase) foreignList.get(i); + values.add(toNative(element)); // List elements shouldn't have names + } + + Class cls = NBTConstants.getClassFromType(type); + return new ListTag(cls, values); + } + + public NBTBase fromNative(Tag foreign) { + if (foreign == null) { + return null; + } + if (foreign instanceof CompoundTag) { + NBTTagCompound tag = new NBTTagCompound(); + for (Map.Entry entry : ((CompoundTag) foreign) + .getValue().entrySet()) { + tag.set(entry.getKey(), fromNative(entry.getValue())); + } + return tag; + } else if (foreign instanceof ByteTag) { + return new NBTTagByte(((ByteTag) foreign).getValue()); + } else if (foreign instanceof ByteArrayTag) { + return new NBTTagByteArray(((ByteArrayTag) foreign).getValue()); + } else if (foreign instanceof DoubleTag) { + return new NBTTagDouble(((DoubleTag) foreign).getValue()); + } else if (foreign instanceof FloatTag) { + return new NBTTagFloat(((FloatTag) foreign).getValue()); + } else if (foreign instanceof IntTag) { + return new NBTTagInt(((IntTag) foreign).getValue()); + } else if (foreign instanceof IntArrayTag) { + return new NBTTagIntArray(((IntArrayTag) foreign).getValue()); + } else if (foreign instanceof ListTag) { + NBTTagList tag = new NBTTagList(); + ListTag foreignList = (ListTag) foreign; + for (Tag t : foreignList.getValue()) { + tag.add(fromNative(t)); + } + return tag; + } else if (foreign instanceof LongTag) { + return new NBTTagLong(((LongTag) foreign).getValue()); + } else if (foreign instanceof ShortTag) { + return new NBTTagShort(((ShortTag) foreign).getValue()); + } else if (foreign instanceof StringTag) { + return new NBTTagString(((StringTag) foreign).getValue()); + } else if (foreign instanceof EndTag) { + try { + return (NBTBase) nbtCreateTagMethod.invoke(null, (byte) 0); + } catch (Exception e) { + return null; + } + } else { + throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName()); + } + } + +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/MutableGenLayer.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/MutableGenLayer.java new file mode 100644 index 00000000..61dc0b96 --- /dev/null +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/MutableGenLayer.java @@ -0,0 +1,26 @@ +package com.boydti.fawe.bukkit.v1_12; + +import java.util.Arrays; +import net.minecraft.server.v1_12_R1.GenLayer; +import net.minecraft.server.v1_12_R1.IntCache; + +public class MutableGenLayer extends GenLayer { + + private int biome; + + public MutableGenLayer(long seed) { + super(seed); + } + + public MutableGenLayer set(int biome) { + this.biome = biome; + return this; + } + + @Override + public int[] a(int areaX, int areaY, int areaWidth, int areaHeight) { + int[] biomes = IntCache.a(areaWidth * areaHeight); + Arrays.fill(biomes, biome); + return biomes; + } +} diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java index 2558232f..8a2c01c0 100644 --- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java +++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_9/BukkitQueue_1_9_R1.java @@ -10,7 +10,7 @@ import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/core/src/main/java/com/boydti/fawe/Fawe.java b/core/src/main/java/com/boydti/fawe/Fawe.java index 6f2fc2a3..bb684dd5 100644 --- a/core/src/main/java/com/boydti/fawe/Fawe.java +++ b/core/src/main/java/com/boydti/fawe/Fawe.java @@ -35,7 +35,7 @@ import com.sk89q.worldedit.command.BrushCommands; import com.sk89q.worldedit.command.ChunkCommands; import com.sk89q.worldedit.command.ClipboardCommands; import com.sk89q.worldedit.command.FlattenedClipboardTransform; -import com.sk89q.worldedit.command.GeneralCommands; +import com.sk89q.worldedit.command.OptionsCommands; import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.NavigationCommands; @@ -46,7 +46,7 @@ import com.sk89q.worldedit.command.SnapshotCommands; import com.sk89q.worldedit.command.SnapshotUtilCommands; import com.sk89q.worldedit.command.SuperPickaxeCommands; import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolUtilCommands; +import com.sk89q.worldedit.command.BrushOptionsCommands; import com.sk89q.worldedit.command.UtilityCommands; import com.sk89q.worldedit.command.WorldEditCommands; import com.sk89q.worldedit.command.composition.SelectionCommand; @@ -77,6 +77,8 @@ import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.block.ExtentBlockCopy; import com.sk89q.worldedit.function.entity.ExtentEntityCopy; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.BlockMask; import com.sk89q.worldedit.function.mask.FuzzyBlockMask; import com.sk89q.worldedit.function.mask.Mask; @@ -87,6 +89,7 @@ import com.sk89q.worldedit.function.mask.SolidBlockMask; 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.AbstractPattern; import com.sk89q.worldedit.function.pattern.BlockPattern; import com.sk89q.worldedit.function.pattern.ClipboardPattern; import com.sk89q.worldedit.function.pattern.Pattern; @@ -115,6 +118,7 @@ import com.sk89q.worldedit.session.PasteBuilder; import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.command.SimpleDispatcher; +import com.sk89q.worldedit.util.command.fluent.DispatcherNode; import com.sk89q.worldedit.util.command.parametric.ParameterData; import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; import com.sk89q.worldedit.util.command.parametric.ParametricCallable; @@ -133,6 +137,7 @@ import java.lang.management.MemoryUsage; import java.util.Collection; import java.util.Date; import java.util.List; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import javax.annotation.Nullable; @@ -423,8 +428,6 @@ public class Fawe { */ try { // Setting up commands.yml - Commands.load(new File(INSTANCE.IMP.getDirectory(), "commands.yml")); - 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 / brush visualization @@ -433,6 +436,8 @@ public class Fawe { AbstractPlayerActor.inject(); // Don't use exception for getBlockInHand control flow Request.inject(); // Custom pattern extent // Commands + Commands.load(new File(INSTANCE.IMP.getDirectory(), "commands.yml")); + Commands.inject(); // Translations BiomeCommands.inject(); // Translations + Optimizations ChunkCommands.inject(); // Translations + Optimizations GenerationCommands.inject(); // Translations + Optimizations @@ -453,8 +458,9 @@ public class Fawe { ParametricBuilder.inject(); // Translations ParametricCallable.inject(); // Translations ParameterData.inject(); // Translations - ToolUtilCommands.inject(); // Fixes + Translations - GeneralCommands.inject(); // Translations + gmask args + BrushOptionsCommands.inject(); // Fixes + Translations + OptionsCommands.inject(); // Translations + gmask args + DispatcherNode.inject(); // Method command delegate // Formatting MessageBox.inject(); Fragment.inject(); @@ -521,6 +527,7 @@ public class Fawe { HashTagPatternParser.inject(); // Add new patterns DefaultBlockParser.inject(); // Fix block lookups BlockPattern.inject(); // Optimization + AbstractPattern.inject(); // Mask Mask.inject(); // Extend deprecated mask BlockMask.inject(); // Optimizations @@ -530,6 +537,8 @@ public class Fawe { DefaultMaskParser.inject(); // Add new masks Masks.inject(); // Optimizations MaskUnion.inject(); // Optimizations + AbstractMask.inject(); // Serializing + AbstractExtentMask.inject(); // Serializing // Operations Operations.inject(); // Optimizations ExtentBlockCopy.inject(); // Optimizations @@ -688,19 +697,26 @@ public class Fawe { } private ConcurrentHashMap players = new ConcurrentHashMap<>(8, 0.9f, 1); + private ConcurrentHashMap playersUUID = new ConcurrentHashMap<>(8, 0.9f, 1); public void register(FawePlayer player) { players.put(player.getName(), player); + playersUUID.put(player.getUUID(), player); } public void unregister(String name) { - players.remove(name); + FawePlayer player = players.remove(name); + if (player != null) playersUUID.remove(player.getUUID()); } public FawePlayer getCachedPlayer(String name) { return players.get(name); } + public FawePlayer getCachedPlayer(UUID uuid) { + return playersUUID.get(uuid); + } + public Collection getCachedPlayers() { return players.values(); } diff --git a/core/src/main/java/com/boydti/fawe/command/AnvilCommands.java b/core/src/main/java/com/boydti/fawe/command/AnvilCommands.java index c667695f..6092e5bb 100644 --- a/core/src/main/java/com/boydti/fawe/command/AnvilCommands.java +++ b/core/src/main/java/com/boydti/fawe/command/AnvilCommands.java @@ -54,7 +54,7 @@ import java.util.concurrent.TimeUnit; import static com.google.common.base.Preconditions.checkNotNull; -@Command(aliases = "/anvil", desc = "Manipulate billions of blocks: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Anvil-API)") +@Command(aliases = {"anvil", "/anvil"}, desc = "Manipulate billions of blocks: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Anvil-API)") public class AnvilCommands { private final WorldEdit worldEdit; 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 31f398ce..515fe3b6 100644 --- a/core/src/main/java/com/boydti/fawe/config/BBC.java +++ b/core/src/main/java/com/boydti/fawe/config/BBC.java @@ -109,35 +109,18 @@ public enum BBC { BRUSH_RESET("Reset your brush.", "WorldEdit.Brush"), BRUSH_NONE("You aren't holding a brush!", "WorldEdit.Brush"), BRUSH_SCROLL_ACTION_SET("Set scroll action to %s0", "WorldEdit.Brush"), + BRUSH_SCROLL_ACTION_UNSET("Removed scrol action", "WorldEdit.Brush"), BRUSH_VISUAL_MODE_SET("Set visual mode to %s0", "WorldEdit.Brush"), BRUSH_TARGET_MODE_SET("Set target mode to %s0", "WorldEdit.Brush"), - BRUSH_BUTCHER("Butcher brush equiped (%s0)", "WorldEdit.Brush"), - BRUSH_CLIPBOARD("Clipboard brush shape equipped", "WorldEdit.Brush"), - BRUSH_CYLINDER("Cylinder brush shape equipped (%s0 by %s1).", "WorldEdit.Brush"), - BRUSH_EXTINGUISHER("Extinguisher equipped (%s0).", "WorldEdit.Brush"), - BRUSH_GRAVITY("Gravity brush equipped (%s0)", "WorldEdit.Brush"), - BRUSH_HEIGHT("Height brush equipped (%s0)", "WorldEdit.Brush"), + BRUSH_EQUIPPED("Equipped brush %s0", "WorldEdit.Brush"), BRUSH_TRY_OTHER("&cThere are other more suitable brushes e.g.\n&8 - &7//br height [radius=5] [#clipboard|file=null] [rotation=0] [yscale=1.00]", "WorldEdit.Brush"), - BRUSH_COPY("Copy brush equipped (%s0). Left click the base of an object to copy, right click to paste. Increase the brush radius if necessary.", "WorldEdit.Brush"), - BRUSH_COMMAND("Command brush equipped (%s0)", "WorldEdit.Brush"), + BRUSH_COPY("Left click the base of an object to copy, right click to paste. Increase the brush radius if necessary.", "WorldEdit.Brush"), BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"), - BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2. Note: Use the blend brush if you want to smooth overhangs or caves.).", "WorldEdit.Brush"), - BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"), - BRUSH_SCATTER("Scatter brush shape equipped (%s0, %s1).", "WorldEdit.Brush"), - BRUSH_SHATTER("Shatter brush shape equipped (%s0, %s1).", "WorldEdit.Brush"), - BRUSH_POPULATE("Populate brush shape equipped (%s0, %s1).", "WorldEdit.Brush"), - BRUSH_LAYER("Layer brush shape equipped (%s0, %s1).", "WorldEdit.Brush"), - BRUSH_STENCIL("Stencil brush equipped (%s0).", "WorldEdit.Brush"), - BRUSH_SURFACE("Surface brush equipped (%s0).", "WorldEdit.Brush"), - BRUSH_LINE("Line brush shape equipped (%s0).", "WorldEdit.Brush"), - BRUSH_SPLINE("Spline brush shape equipped (%s0). Right click an end to add a shape", "WorldEdit.Brush"), + BRUSH_SMOOTH("Note: Use the blend brush if you want to smooth overhangs or caves.", "WorldEdit.Brush"), + BRUSH_SPLINE("Click to add a point, click the same spot to finish", "WorldEdit.Brush"), BRUSH_SPLINE_PRIMARY_2("Added position, Click the same spot to join!", "WorldEdit.Brush"), BRUSH_SPLINE_SECONDARY_ERROR("Not enough positions set!", "WorldEdit.Brush"), 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_SIZE("Brush size set", "WorldEdit.Brush"), BRUSH_RANGE("Brush size set", "WorldEdit.Brush"), BRUSH_MASK_DISABLED("Brush mask disabled", "WorldEdit.Brush"), @@ -190,12 +173,13 @@ public enum BBC { SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"), - SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"), + SCHEMATIC_FORMAT("Available formats (Name: Lookup names)", "Worldedit.Schematic"), SCHEMATIC_LOADED("%s0 loaded. Paste it with //paste", "Worldedit.Schematic"), SCHEMATIC_SAVED("%s0 saved.", "Worldedit.Schematic"), SCHEMATIC_PAGE("Page must be %s", "WorldEdit.Schematic"), - SCHEMATIC_NONE("No schematics found.", "WorldEdit.Schematic"), - SCHEMATIC_LIST("Available schematics (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"), + SCHEMATIC_NONE("No files found.", "WorldEdit.Schematic"), + SCHEMATIC_LIST("Available files (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"), + SCHEMATIC_LIST_ELEM("&8 - &a%s0 &8- &7%s1", "Worldedit.Schematic"), CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"), CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"), @@ -232,6 +216,8 @@ public enum BBC { COMMAND_SYNTAX("&cUsage: &7%s0", "Error"), NO_PERM("&cYou are lacking the permission node: %s0", "Error"), SETTING_DISABLE("&cLacking setting: %s0","Error"), + BRUSH_NOT_FOUND("&cAvailable brushes: %s0", "Error"), + BRUSH_INCOMPATIBLE("&cBrush not compatible with this version", "Error"), SCHEMATIC_NOT_FOUND("&cSchematic not found: &7%s0", "Error"), NO_REGION("&cYou have no current allowed region", "Error"), NO_MASK("&cYou have no current mask set", "Error"), @@ -316,16 +302,6 @@ public enum BBC { TIP_ROTATE("Tip: Orientate with &c//rotate", "Tips"), TIP_COPY_PATTERN("Tip: To use as a pattern try &c#copy", "Tips"), - // brush - TIP_BRUSH_SPLINE("&7Tip The spline &c//brush &7connects multiple shapes together", "Tips"), - TIP_BRUSH_HEIGHT("&7Tip: The height &c//brush &7smoothly raises or lowers terrain", "Tips"), - TIP_BRUSH_COPY("&7Tip: The copypaste &c//brush &7allows you to easily copy and paste objects", "Tips"), - TIP_BRUSH_MASK("&7Tip: Set a brush destination mask with &c/mask", "Tips"), - TIP_BRUSH_MASK_SOURCE("&7Tip: Set a brush source mask with &c/smask", "Tips"), - TIP_BRUSH_TRANSFORM("&7Tip: Set a brush transform with &c/transform", "Tips"), - TIP_BRUSH_RELATIVE("&7Tip: Use a relative clipboard pattern with //br sphere #~[#copy]", "Tips"), - TIP_BRUSH_COMMAND("&7Tip: Try the command brush &c//br cmd ", "Tips"), - // regen TIP_REGEN_0("Tip: Use a biome with /regen [biome]", "Tips"), TIP_REGEN_1("Tip: Use a seed with /regen [biome] [seed]", "Tips"), 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 dacd07f9..1d4b3c9a 100644 --- a/core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/core/src/main/java/com/boydti/fawe/config/Settings.java @@ -323,13 +323,13 @@ public class Settings extends Config { @Comment("Enable the limiter") public boolean ENABLED = true; @Comment("The interval in ticks") - public int INTERVAL = 1; + public int INTERVAL = 20; @Comment("Max falling blocks per interval (per chunk)") - public int FALLING = 512; + public int FALLING = 64; @Comment("Max physics per interval (per chunk)") - public int PHYSICS = 512; + public int PHYSICS = 8192; @Comment("Max item spawns per interval (per chunk)") - public int ITEMS = 128; + public int ITEMS = 64; } public static class CLIPBOARD { diff --git a/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java b/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java index 9b5e1fc0..b7b3c9c9 100644 --- a/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java +++ b/core/src/main/java/com/boydti/fawe/object/brush/BrushSettings.java @@ -1,18 +1,238 @@ package com.boydti.fawe.object.brush; +import com.boydti.fawe.Fawe; import com.boydti.fawe.object.brush.scroll.ScrollAction; import com.boydti.fawe.object.extent.ResettableExtent; +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.command.tool.BrushTool; import com.sk89q.worldedit.command.tool.brush.Brush; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.util.command.CommandCallable; +import com.sk89q.worldedit.util.command.Dispatcher; +import com.sk89q.worldedit.util.command.ProcessedCallable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; public class BrushSettings { - public Brush brush = null; - public Mask mask = null; - public Mask sourceMask = null; - public ResettableExtent transform = null; - public Pattern material; - public double size = 1; - public String permission; - public ScrollAction scrollAction; + public enum SettingType { + BRUSH, + SIZE, + MASK, + SOURCE_MASK, + TRANSFORM, + FILL, + PERMISSIONS, + SCROLL_ACTION, + } + + private Map constructor = new ConcurrentHashMap<>(); + + private Brush brush = null; + private Mask mask = null; + private Mask sourceMask = null; + private ResettableExtent transform = null; + private Pattern material; + private double size = 1; + private Set permissions; + private ScrollAction scrollAction; + + public BrushSettings() { + this.permissions = new HashSet<>(); + this.constructor.put(SettingType.PERMISSIONS, permissions); + } + + public static BrushSettings get(BrushTool tool, Player player, LocalSession session, Map settings) throws CommandException, InputParseException { + Dispatcher dispatcher = CommandManager.getInstance().getDispatcher(); + Dispatcher brushDispatcher = (Dispatcher) (dispatcher.get("brush").getCallable()); + if (brushDispatcher == null) { + return null; + } + String constructor = (String) settings.get(SettingType.BRUSH.name()); + if (constructor == null) { + return new BrushSettings(); + } + String[] split = constructor.split(" "); + + CommandCallable sphereCommand = ((ProcessedCallable) brushDispatcher.get(split[0]).getCallable()).getParent(); + CommandLocals locals = new CommandLocals(); + locals.put(Actor.class, player); + String args = constructor.substring(constructor.indexOf(' ') + 1); + String[] parentArgs = new String[]{"brush", split[0]}; + BrushSettings bs = (BrushSettings) sphereCommand.call(args, locals, parentArgs); + if (settings.containsKey(SettingType.PERMISSIONS.name())) { + bs.permissions.addAll((Collection) settings.get(SettingType.PERMISSIONS.name())); + } + if (settings.containsKey(SettingType.SIZE.name())) { + bs.size = (double) settings.get(SettingType.SIZE.name()); + } + + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setWorld(player.getWorld()); + parserContext.setSession(session); + + if (settings.containsKey(SettingType.MASK.name())) { + String maskArgs = (String) settings.get(SettingType.MASK.name()); + Mask mask = WorldEdit.getInstance().getMaskFactory().parseFromInput(maskArgs, parserContext); + bs.setMask(mask); + bs.constructor.put(SettingType.MASK, maskArgs); + } + if (settings.containsKey(SettingType.SOURCE_MASK.name())) { + String maskArgs = (String) settings.get(SettingType.SOURCE_MASK.name()); + Mask mask = WorldEdit.getInstance().getMaskFactory().parseFromInput(maskArgs, parserContext); + bs.setSourceMask(mask); + bs.constructor.put(SettingType.SOURCE_MASK, maskArgs); + } + if (settings.containsKey(SettingType.TRANSFORM.name())) { + String transformArgs = (String) settings.get(SettingType.TRANSFORM.name()); + ResettableExtent extent = Fawe.get().getTransformParser().parseFromInput(transformArgs, parserContext); + bs.setTransform(extent); + bs.constructor.put(SettingType.TRANSFORM, transformArgs); + } + if (settings.containsKey(SettingType.FILL.name())) { + String fillArgs = (String) settings.get(SettingType.FILL.name()); + Pattern pattern = WorldEdit.getInstance().getPatternFactory().parseFromInput(fillArgs, parserContext); + bs.setFill(pattern); + bs.constructor.put(SettingType.FILL, fillArgs); + } + if (settings.containsKey(SettingType.SCROLL_ACTION.name())) { + String actionArgs = (String) settings.get(SettingType.SCROLL_ACTION.name()); + ScrollAction action = ScrollAction.fromArguments(tool, player, session, actionArgs, false); + if (action != null) { + bs.setScrollAction(action); + bs.constructor.put(SettingType.SCROLL_ACTION, actionArgs); + } + } + return bs; + } + + public BrushSettings setBrush(Brush brush) { + this.brush = brush; + return this; + } + + public BrushSettings clear() { + brush = null; + mask = null; + sourceMask = null; + transform = null; + material = null; + scrollAction = null; + size = 1; + permissions.clear(); + constructor.clear(); + return this; + } + + public BrushSettings addSetting(SettingType type, String args) { + constructor.put(type, args); + return this; + } + + public Map getSettings() { + return Collections.unmodifiableMap(constructor); + } + + public BrushSettings setMask(Mask mask) { + if (mask == null) constructor.remove(SettingType.MASK); + this.mask = mask; + return this; + } + + public BrushSettings setSourceMask(Mask mask) { + if (mask == null) constructor.remove(SettingType.SOURCE_MASK); + this.sourceMask = mask; + return this; + } + + public BrushSettings setTransform(ResettableExtent transform) { + if (transform == null) constructor.remove(SettingType.TRANSFORM); + this.transform = transform; + return this; + } + + public BrushSettings setFill(Pattern pattern) { + if (pattern == null) constructor.remove(SettingType.FILL); + this.material = pattern; + return this; + } + + public BrushSettings setSize(double size) { + this.size = size; + if (size == -1) { + constructor.remove(SettingType.SIZE); + } else { + constructor.put(SettingType.SIZE, size); + } + return this; + } + + public BrushSettings setScrollAction(ScrollAction scrollAction) { + if (scrollAction == null) constructor.remove(SettingType.SCROLL_ACTION); + this.scrollAction = scrollAction; + return this; + } + + public BrushSettings addPermission(String permission) { + this.permissions.add(permission); + return this; + } + + public BrushSettings addPermissions(String... perms) { + for (String perm : perms) permissions.add(perm); + return this; + } + + public Brush getBrush() { + return brush; + } + + public Mask getMask() { + return mask; + } + + public Mask getSourceMask() { + return sourceMask; + } + + public ResettableExtent getTransform() { + return transform; + } + + public Pattern getMaterial() { + return material; + } + + public double getSize() { + return size; + } + + public Set getPermissions() { + return Collections.unmodifiableSet(permissions); + } + + public ScrollAction getScrollAction() { + return scrollAction; + } + + public boolean canUse(Actor actor) { + for (String perm : getPermissions()) { + if (actor.hasPermission(perm)) return true; + } + return false; + } + } 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 index 371554ba..bb73d8e0 100644 --- 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 @@ -1,10 +1,81 @@ package com.boydti.fawe.object.brush.scroll; +import com.boydti.fawe.config.BBC; +import com.sk89q.worldedit.LocalConfiguration; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.pattern.Pattern; +import com.sk89q.worldedit.session.ClipboardHolder; +import java.io.IOException; public abstract class ScrollAction implements ScrollTool { private BrushTool tool; + public static ScrollAction fromArguments(BrushTool tool, Player player, LocalSession session, String arguments, boolean message) throws InputParseException { + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setWorld(player.getWorld()); + parserContext.setSession(session); + final LocalConfiguration config = WorldEdit.getInstance().getConfiguration(); + String[] split = arguments.split(" "); + switch (split[0].toLowerCase()) { + case "none": + return null; + case "clipboard": + if (split.length != 2) { + if (message) BBC.COMMAND_SYNTAX.send(player, "clipboard [file]"); + return null; + } + String filename = split[1]; + try { + ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, message); + if (clipboards == null) { + return null; + } + return (new ScrollClipboard(tool, session, clipboards)); + } catch (IOException e) { + throw new RuntimeException(e); + } + case "mask": + if (split.length < 2) { + if (message) BBC.COMMAND_SYNTAX.send(player, "mask [mask 1] [mask 2] [mask 3]..."); + return null; + } + Mask[] masks = new Mask[split.length - 1]; + for (int i = 1; i < split.length; i++) { + String arg = split[i]; + masks[i - 1] = WorldEdit.getInstance().getMaskFactory().parseFromInput(arg, parserContext); + } + return (new ScrollMask(tool, masks)); + case "pattern": + if (split.length < 2) { + if (message) BBC.COMMAND_SYNTAX.send(player, "pattern [pattern 1] [pattern 2] [pattern 3]..."); + return null; + } + Pattern[] patterns = new Pattern[split.length - 1]; + for (int i = 1; i < split.length; i++) { + String arg = split[i]; + patterns[i - 1] = WorldEdit.getInstance().getPatternFactory().parseFromInput(arg, parserContext); + } + return (new ScrollPattern(tool, patterns)); + case "range": + return (new ScrollRange(tool)); + case "size": + return (new ScrollSize(tool)); + case "target": + return (new ScrollTarget(tool)); + default: + return null; + + } + } + public ScrollAction(BrushTool tool) { this.tool = tool; } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java index 074da922..c1521cc4 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/BlockTranslateExtent.java @@ -11,7 +11,6 @@ import com.sk89q.worldedit.world.biome.BaseBiome; public class BlockTranslateExtent extends AbstractDelegateExtent { private final int dx,dy,dz; - private final Extent extent; private MutableBlockVector mutable = new MutableBlockVector(); public BlockTranslateExtent(Extent extent, int dx, int dy, int dz) { @@ -19,7 +18,6 @@ public class BlockTranslateExtent extends AbstractDelegateExtent { this.dx = dx; this.dy = dy; this.dz = dz; - this.extent = extent; } @Override @@ -27,7 +25,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent { mutable.mutX((location.getX() + dx)); mutable.mutY((location.getY() + dy)); mutable.mutZ((location.getZ() + dz)); - return extent.setBlock(mutable, block); + return getExtent().setBlock(mutable, block); } @Override @@ -35,7 +33,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent { mutable.mutX(x + dx); mutable.mutY(y + dy); mutable.mutZ(z + dz); - return extent.setBlock(mutable, block); + return getExtent().setBlock(mutable, block); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/extent/Linear3DTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/Linear3DTransform.java index 499b4435..ff41069e 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/Linear3DTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/Linear3DTransform.java @@ -2,17 +2,13 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -import java.util.Arrays; -import java.util.Collection; public class Linear3DTransform extends SelectTransform { - private final Collection extents; private final ResettableExtent[] extentsArray; public Linear3DTransform(ResettableExtent[] extents) { this.extentsArray = extents; - this.extents = Arrays.asList(extents); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/extent/LinearTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/LinearTransform.java index b25f3a20..9ee3aa2f 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/LinearTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/LinearTransform.java @@ -2,18 +2,14 @@ package com.boydti.fawe.object.extent; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -import java.util.Arrays; -import java.util.Collection; public class LinearTransform extends SelectTransform { - private final Collection extents; private final ResettableExtent[] extentsArray; private int index; public LinearTransform(ResettableExtent[] extents) { this.extentsArray = extents; - this.extents = Arrays.asList(extents); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java index 641ee9b8..0c500be6 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/MultiTransform.java @@ -13,20 +13,20 @@ import java.util.Collection; import javax.annotation.Nullable; public class MultiTransform extends RandomTransform { - private AbstractDelegateExtent[] extents; + private ResettableExtent[] extents; public MultiTransform(Collection extents) { for (ResettableExtent extent : extents) add(extent, 1); } public MultiTransform() { - this.extents = new AbstractDelegateExtent[0]; + this.extents = new ResettableExtent[0]; } @Override public void add(ResettableExtent extent, double chance) { super.add(extent, chance); - this.extents = getExtents().toArray(new AbstractDelegateExtent[getExtents().size()]); + this.extents = getExtents().toArray(new ResettableExtent[getExtents().size()]); } @Override public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException { diff --git a/core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java index 406e4719..967e68fc 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/OffsetExtent.java @@ -10,7 +10,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome; public class OffsetExtent extends ResettableExtent { private final int dx, dy, dz; - private MutableBlockVector2D mutable = new MutableBlockVector2D(); + private transient MutableBlockVector2D mutable = new MutableBlockVector2D(); public OffsetExtent(Extent parent, int dx, int dy, int dz) { super(parent); @@ -33,4 +33,10 @@ public class OffsetExtent extends ResettableExtent { public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException { return getExtent().setBlock(x + dx, y + dy, z + dz, block); } + + @Override + public ResettableExtent setExtent(Extent extent) { + mutable = new MutableBlockVector2D(); + return super.setExtent(extent); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java index 6ab83a62..dfc122d2 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java @@ -11,9 +11,9 @@ import com.sk89q.worldedit.world.biome.BaseBiome; public class PositionTransformExtent extends ResettableExtent { - private final MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); + private transient Vector min; private Transform transform; - private Vector min; public PositionTransformExtent(Extent parent, Transform transform) { super(parent); @@ -22,6 +22,7 @@ public class PositionTransformExtent extends ResettableExtent { @Override public ResettableExtent setExtent(Extent extent) { + mutable = new MutableBlockVector(); min = null; return super.setExtent(extent); } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java index 90b2988a..e688090a 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/RandomOffsetTransform.java @@ -10,9 +10,10 @@ import com.sk89q.worldedit.world.biome.BaseBiome; import java.util.SplittableRandom; public class RandomOffsetTransform extends ResettableExtent { + private transient SplittableRandom random; + private transient MutableBlockVector2D mutable = new MutableBlockVector2D(); + private final int dx, dy, dz; - private final SplittableRandom random; - private MutableBlockVector2D mutable = new MutableBlockVector2D(); public RandomOffsetTransform(Extent parent, int dx, int dy, int dz) { super(parent); @@ -47,6 +48,8 @@ public class RandomOffsetTransform extends ResettableExtent { @Override public ResettableExtent setExtent(Extent extent) { + random = new SplittableRandom(); + mutable = new MutableBlockVector2D(); return super.setExtent(extent); } } diff --git a/core/src/main/java/com/boydti/fawe/object/extent/RandomTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/RandomTransform.java index 48fef0ae..00f86930 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/RandomTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/RandomTransform.java @@ -19,10 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class RandomTransform extends SelectTransform { - private final SimpleRandom random; + private SimpleRandom random; private Map weights = new HashMap<>(); - private RandomCollection collection; - private LinkedHashSet extents = new LinkedHashSet<>(); + + private transient RandomCollection collection; + private transient LinkedHashSet extents = new LinkedHashSet<>(); public RandomTransform() { this(new TrueRandom()); @@ -44,6 +45,10 @@ public class RandomTransform extends SelectTransform { @Override public ResettableExtent setExtent(Extent extent) { + if (collection == null) { + collection = RandomCollection.of(weights, random); + extents = new LinkedHashSet<>(weights.keySet()); + } for (AbstractDelegateExtent current : extents) { if (current instanceof ResettableExtent) { ((ResettableExtent) current).setExtent(extent); diff --git a/core/src/main/java/com/boydti/fawe/object/extent/ResettableExtent.java b/core/src/main/java/com/boydti/fawe/object/extent/ResettableExtent.java index 434d292d..011f5a77 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/ResettableExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/ResettableExtent.java @@ -1,14 +1,18 @@ package com.boydti.fawe.object.extent; import com.boydti.fawe.util.ExtentTraverser; +import com.boydti.fawe.util.ReflectionUtils; import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.World; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Field; import static com.google.common.base.Preconditions.checkNotNull; -public class ResettableExtent extends AbstractDelegateExtent { +public class ResettableExtent extends AbstractDelegateExtent implements Serializable { public ResettableExtent(Extent parent) { super(parent); } @@ -23,4 +27,26 @@ public class ResettableExtent extends AbstractDelegateExtent { } return this; } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + Extent extent = getExtent(); + boolean next = extent instanceof ResettableExtent; + stream.writeBoolean(next); + if (next) { + stream.writeObject(extent); + } + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + if (stream.readBoolean()) { + try { + Field field = AbstractDelegateExtent.class.getDeclaredField("extent"); + ReflectionUtils.setFailsafeFieldValue(field, this, stream.readObject()); + } catch (Throwable e) { + e.printStackTrace(); + } + } + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java b/core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java index 77befbbf..33327c25 100644 --- a/core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java +++ b/core/src/main/java/com/boydti/fawe/object/extent/ScaleTransform.java @@ -13,11 +13,12 @@ import com.sk89q.worldedit.world.biome.BaseBiome; import javax.annotation.Nullable; public class ScaleTransform extends ResettableExtent { - private final MutableBlockVector mutable = new MutableBlockVector(); - private final double dx,dy,dz; - private int maxy; + private transient MutableBlockVector mutable = new MutableBlockVector(); + private transient int maxy; + private transient Vector min; + + private final double dx,dy,dz; - private Vector min; public ScaleTransform(Extent parent, double dx, double dy, double dz) { super(parent); @@ -31,6 +32,7 @@ public class ScaleTransform extends ResettableExtent { public ResettableExtent setExtent(Extent extent) { min = null; maxy = extent.getMaximumPoint().getBlockY(); + mutable = new MutableBlockVector(); return super.setExtent(extent); } @@ -111,8 +113,6 @@ public class ScaleTransform extends ResettableExtent { return result; } - - @Nullable @Override public Entity createEntity(Location location, BaseEntity entity) { diff --git a/core/src/main/java/com/boydti/fawe/object/function/block/LegacyBlockReplace.java b/core/src/main/java/com/boydti/fawe/object/function/block/LegacyBlockReplace.java deleted file mode 100644 index 19b4eb9a..00000000 --- a/core/src/main/java/com/boydti/fawe/object/function/block/LegacyBlockReplace.java +++ /dev/null @@ -1,29 +0,0 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by Fernflower decompiler) -// - -package com.boydti.fawe.object.function.block; - -import com.google.common.base.Preconditions; -import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.RegionFunction; -import com.sk89q.worldedit.patterns.Pattern; - -public class LegacyBlockReplace implements RegionFunction { - private final Extent extent; - private Pattern pattern; - - public LegacyBlockReplace(Extent extent, Pattern pattern) { - Preconditions.checkNotNull(extent); - Preconditions.checkNotNull(pattern); - this.extent = extent; - this.pattern = pattern; - } - - public boolean apply(Vector position) throws WorldEditException { - return this.extent.setBlock(position, this.pattern.next(position)); - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/function/mask/AbstractDelegateMask.java b/core/src/main/java/com/boydti/fawe/object/function/mask/AbstractDelegateMask.java index 7c541e1b..2473c625 100644 --- a/core/src/main/java/com/boydti/fawe/object/function/mask/AbstractDelegateMask.java +++ b/core/src/main/java/com/boydti/fawe/object/function/mask/AbstractDelegateMask.java @@ -1,11 +1,12 @@ package com.boydti.fawe.object.function.mask; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class AbstractDelegateMask implements Mask { +public class AbstractDelegateMask extends AbstractMask { private final Mask mask; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java b/core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java index e1e31314..aacf8b12 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/AdjacentAnyMask.java @@ -2,15 +2,16 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask; /** * Just an optimized version of the Adjacent Mask for single adjacency */ -public class AdjacentAnyMask implements Mask { +public class AdjacentAnyMask extends AbstractMask implements ResettableMask { private final Mask mask; - private MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); public AdjacentAnyMask(Mask mask) { this.mask = mask; @@ -20,6 +21,11 @@ public class AdjacentAnyMask implements Mask { return mask; } + @Override + public void reset() { + mutable = new MutableBlockVector(); + } + @Override public boolean test(Vector v) { int x = v.getBlockX(); diff --git a/core/src/main/java/com/boydti/fawe/object/mask/AdjacentMask.java b/core/src/main/java/com/boydti/fawe/object/mask/AdjacentMask.java index 4e9f6d83..0b6c2dd9 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/AdjacentMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/AdjacentMask.java @@ -1,9 +1,10 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask; -public class AdjacentMask implements Mask { +public class AdjacentMask extends AbstractMask { private final int min, max; private final Mask mask; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java b/core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java index 9d27de3b..8139fbbb 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/AngleMask.java @@ -8,48 +8,52 @@ import com.sk89q.worldedit.function.mask.Mask2D; import com.sk89q.worldedit.function.mask.SolidBlockMask; import javax.annotation.Nullable; -public class AngleMask extends SolidBlockMask { +public class AngleMask extends SolidBlockMask implements ResettableMask { public static double ADJACENT_MOD = 0.5; public static double DIAGONAL_MOD = 1 / Math.sqrt(8); private final double max; private final double min; - private final Extent extent; private final boolean overlay; - private MutableBlockVector mutable = new MutableBlockVector(); private int maxY; + private transient MutableBlockVector mutable = new MutableBlockVector(); + public AngleMask(Extent extent, double min, double max, boolean overlay) { super(extent); - this.extent = extent; this.min = min; this.max = max; this.maxY = extent.getMaximumPoint().getBlockY(); this.overlay = overlay; } + @Override + public void reset() { + mutable = new MutableBlockVector(); + } + @Override public boolean test(Vector vector) { int x = vector.getBlockX(); int y = vector.getBlockY(); int z = vector.getBlockZ(); - BaseBlock block = extent.getLazyBlock(x, y, z); + BaseBlock block = getExtent().getLazyBlock(x, y, z); if (!test(block.getId(), block.getData())) { return false; } - block = extent.getLazyBlock(x, y + 1, z); + block = getExtent().getLazyBlock(x, y + 1, z); if (overlay && test(block.getId(), block.getData())) { return false; } double slope; boolean aboveMin; - slope = Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z, y, 0, maxY)) * ADJACENT_MOD; + slope = Math.abs(getExtent().getNearestSurfaceTerrainBlock(x + 1, z, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x - 1, z, y, 0, maxY)) * ADJACENT_MOD; if (slope >= min && max >= Math.max(maxY - y, y)) { return true; } - slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x, z - 1, y, 0, maxY)) * ADJACENT_MOD); - slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD); - slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x - 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x + 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD); + slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x, z - 1, y, 0, maxY)) * ADJACENT_MOD); + slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x + 1, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x - 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD); + slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x - 1, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x + 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD); return (slope >= min && slope <= max); } diff --git a/core/src/main/java/com/boydti/fawe/object/mask/BiomeMask.java b/core/src/main/java/com/boydti/fawe/object/mask/BiomeMask.java index 4020fcca..424b7882 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/BiomeMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/BiomeMask.java @@ -7,15 +7,20 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.world.biome.BaseBiome; -public class BiomeMask extends AbstractExtentMask { +public class BiomeMask extends AbstractExtentMask implements ResettableMask { private final BaseBiome biome; - private MutableBlockVector2D mutable = new MutableBlockVector2D(); + private transient MutableBlockVector2D mutable = new MutableBlockVector2D(); public BiomeMask(Extent extent, BaseBiome biome) { super(extent); this.biome = biome; } + @Override + public void reset() { + mutable = new MutableBlockVector2D(); + } + @Override public boolean test(Vector vector) { Vector2D pos = mutable.setComponents(vector.getBlockX(), vector.getBlockZ()); diff --git a/core/src/main/java/com/boydti/fawe/object/mask/BlockLightMask.java b/core/src/main/java/com/boydti/fawe/object/mask/BlockLightMask.java index 8a81bdf4..ec6d24e2 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/BlockLightMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/BlockLightMask.java @@ -3,23 +3,23 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.object.extent.LightingExtent; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class BlockLightMask implements Mask { +public class BlockLightMask extends AbstractExtentMask { - private final Extent extent; private final int min,max; public BlockLightMask(Extent extent, int min, int max) { - this.extent = extent; + super(extent); this.min = min; this.max = max; } @Override public boolean test(Vector vector) { + Extent extent = getExtent(); if (extent instanceof LightingExtent) { int light = ((LightingExtent) extent).getBlockLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); return light >= min && light <= max; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/BrightnessMask.java b/core/src/main/java/com/boydti/fawe/object/mask/BrightnessMask.java index 26262bf7..e5275a2a 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/BrightnessMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/BrightnessMask.java @@ -3,23 +3,23 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.object.extent.LightingExtent; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class BrightnessMask implements Mask { +public class BrightnessMask extends AbstractExtentMask { - private final Extent extent; private final int min,max; public BrightnessMask(Extent extent, int min, int max) { - this.extent = extent; + super(extent); this.min = min; this.max = max; } @Override public boolean test(Vector vector) { + Extent extent = getExtent(); if (extent instanceof LightingExtent) { int light = ((LightingExtent) extent).getBrightness(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); return light >= min && light <= max; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/DataMask.java b/core/src/main/java/com/boydti/fawe/object/mask/DataMask.java index ea1a1e9d..6afe134e 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/DataMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/DataMask.java @@ -2,22 +2,21 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class DataMask implements Mask, ResettableMask { - - private final Extent extent; +public class DataMask extends AbstractExtentMask implements ResettableMask { public DataMask(Extent extent) { - this.extent = extent; + super(extent); } - int data = -1; + private transient int data = -1; @Override public boolean test(Vector vector) { + Extent extent = getExtent(); if (data != -1) { return extent.getLazyBlock(vector).getData() == data; } else { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/IdDataMask.java b/core/src/main/java/com/boydti/fawe/object/mask/IdDataMask.java index 34ea5f73..d5890ea2 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/IdDataMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/IdDataMask.java @@ -3,22 +3,20 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.FaweCache; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class IdDataMask implements Mask, ResettableMask { - - private final Extent extent; +public class IdDataMask extends AbstractExtentMask implements ResettableMask { + private transient int combined = -1; public IdDataMask(Extent extent) { - this.extent = extent; + super(extent); } - int combined = -1; - @Override public boolean test(Vector vector) { + Extent extent = getExtent(); if (combined != -1) { return FaweCache.getCombined(extent.getLazyBlock(vector)) == combined; } else { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/IdMask.java b/core/src/main/java/com/boydti/fawe/object/mask/IdMask.java index ba9df5d4..83d3cdd9 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/IdMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/IdMask.java @@ -2,22 +2,21 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class IdMask implements Mask, ResettableMask { +public class IdMask extends AbstractExtentMask implements ResettableMask { - private Extent extent; + private transient int id = -1; public IdMask(Extent extent) { - this.extent = extent; + super(extent); } - int id = -1; - @Override public boolean test(Vector vector) { + Extent extent = getExtent(); if (id != -1) { return extent.getLazyBlock(vector).getId() == id; } else { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/LightMask.java b/core/src/main/java/com/boydti/fawe/object/mask/LightMask.java index 6d7b2b12..d17daacc 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/LightMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/LightMask.java @@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.object.extent.LightingExtent; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class LightMask implements Mask { +public class LightMask extends AbstractExtentMask { - private final Extent extent; private final int min,max; public LightMask(Extent extent, int min, int max) { - this.extent = extent; + super(extent); this.min = min; this.max = max; } @Override public boolean test(Vector vector) { - if (extent instanceof LightingExtent) { - int light = ((LightingExtent) extent).getLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + if (getExtent() instanceof LightingExtent) { + int light = ((LightingExtent) getExtent()).getLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); return light >= min && light <= max; } return false; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/OpacityMask.java b/core/src/main/java/com/boydti/fawe/object/mask/OpacityMask.java index 9b5ac73b..0b25a4dd 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/OpacityMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/OpacityMask.java @@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.object.extent.LightingExtent; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class OpacityMask implements Mask { +public class OpacityMask extends AbstractExtentMask { - private final Extent extent; private final int min,max; public OpacityMask(Extent extent, int min, int max) { - this.extent = extent; + super(extent); this.min = min; this.max = max; } @Override public boolean test(Vector vector) { - if (extent instanceof LightingExtent) { - int light = ((LightingExtent) extent).getOpacity(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + if (getExtent() instanceof LightingExtent) { + int light = ((LightingExtent) getExtent()).getOpacity(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); return light >= min && light <= max; } return false; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/PlaneMask.java b/core/src/main/java/com/boydti/fawe/object/mask/PlaneMask.java index 3e7a789f..ea821fb7 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/PlaneMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/PlaneMask.java @@ -1,18 +1,17 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; /** * Restricts the */ -public class PlaneMask implements Mask, ResettableMask { +public class PlaneMask extends AbstractMask implements ResettableMask { - private int mode = -1; - - private int originX = Integer.MAX_VALUE,originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE; + private transient int mode = -1; + private transient int originX = Integer.MAX_VALUE, originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE; @Override public boolean test(Vector vector) { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/RadiusMask.java b/core/src/main/java/com/boydti/fawe/object/mask/RadiusMask.java index db4d0a3f..27019da0 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/RadiusMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/RadiusMask.java @@ -2,12 +2,13 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class RadiusMask implements Mask, ResettableMask{ +public class RadiusMask extends AbstractMask implements ResettableMask{ + private transient Vector pos; private final int minSqr, maxSqr; public RadiusMask(int min, int max) { @@ -20,8 +21,6 @@ public class RadiusMask implements Mask, ResettableMask{ pos = null; } - private Vector pos; - @Override public boolean test(Vector to) { if (pos == null) { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/RandomMask.java b/core/src/main/java/com/boydti/fawe/object/mask/RandomMask.java index 2a5db1bb..e7cf1549 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/RandomMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/RandomMask.java @@ -4,8 +4,8 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.function.mask.AbstractMask; import java.util.SplittableRandom; -public class RandomMask extends AbstractMask { - private final SplittableRandom random; +public class RandomMask extends AbstractMask implements ResettableMask { + private transient SplittableRandom random; private final double threshold; public RandomMask(double threshold) { @@ -17,4 +17,9 @@ public class RandomMask extends AbstractMask { public boolean test(Vector vector) { return random.nextInt() <= threshold; } + + @Override + public void reset() { + random = new SplittableRandom(); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/mask/SkyLightMask.java b/core/src/main/java/com/boydti/fawe/object/mask/SkyLightMask.java index 871172fb..a38f1239 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/SkyLightMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/SkyLightMask.java @@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask; import com.boydti.fawe.object.extent.LightingExtent; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; -public class SkyLightMask implements Mask { +public class SkyLightMask extends AbstractExtentMask { - private final Extent extent; private final int min,max; public SkyLightMask(Extent extent, int min, int max) { - this.extent = extent; + super(extent); this.min = min; this.max = max; } @Override public boolean test(Vector vector) { - if (extent instanceof LightingExtent) { - int light = ((LightingExtent) extent).getSkyLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); + if (getExtent() instanceof LightingExtent) { + int light = ((LightingExtent) getExtent()).getSkyLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); return light >= min && light <= max; } return false; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/SolidPlaneMask.java b/core/src/main/java/com/boydti/fawe/object/mask/SolidPlaneMask.java index 07e8a1c3..2ed185f2 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/SolidPlaneMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/SolidPlaneMask.java @@ -12,8 +12,8 @@ import javax.annotation.Nullable; */ public class SolidPlaneMask extends SolidBlockMask implements ResettableMask { - private int mode = -1; - private MutableBlockVector mutable = new MutableBlockVector(); + private transient int mode = -1; + private transient MutableBlockVector mutable = new MutableBlockVector(); private int originX = Integer.MAX_VALUE,originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE; @@ -84,6 +84,7 @@ public class SolidPlaneMask extends SolidBlockMask implements ResettableMask { @Override public void reset() { mode = -1; + mutable = new MutableBlockVector(); } @Nullable diff --git a/core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java b/core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java index ab9c85cd..3e462067 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/SurfaceMask.java @@ -7,7 +7,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.BlockMask; public class SurfaceMask extends AdjacentAnyMask { - private final Extent extent; + private final transient Extent extent; public SurfaceMask(Extent extent) { super(new BlockMask(extent, new BaseBlock(0))); diff --git a/core/src/main/java/com/boydti/fawe/object/mask/WallMask.java b/core/src/main/java/com/boydti/fawe/object/mask/WallMask.java index b1663dd7..714ce0ed 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/WallMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/WallMask.java @@ -1,9 +1,10 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask; -public class WallMask implements Mask { +public class WallMask extends AbstractMask { private final int min, max; private final Mask mask; diff --git a/core/src/main/java/com/boydti/fawe/object/mask/XAxisMask.java b/core/src/main/java/com/boydti/fawe/object/mask/XAxisMask.java index 2fd4f082..b74b970b 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/XAxisMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/XAxisMask.java @@ -1,16 +1,16 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; /** * Restricts the */ -public class XAxisMask implements Mask, ResettableMask { +public class XAxisMask extends AbstractMask implements ResettableMask { - private int layer = -1; + private transient int layer = -1; @Override public boolean test(Vector vector) { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/YAxisMask.java b/core/src/main/java/com/boydti/fawe/object/mask/YAxisMask.java index 3724606b..cd474636 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/YAxisMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/YAxisMask.java @@ -1,16 +1,16 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; /** * Restricts the */ -public class YAxisMask implements Mask, ResettableMask { +public class YAxisMask extends AbstractMask implements ResettableMask { - private int layer = -1; + private transient int layer = -1; @Override public boolean test(Vector vector) { diff --git a/core/src/main/java/com/boydti/fawe/object/mask/ZAxisMask.java b/core/src/main/java/com/boydti/fawe/object/mask/ZAxisMask.java index 15d5a2ef..15215e15 100644 --- a/core/src/main/java/com/boydti/fawe/object/mask/ZAxisMask.java +++ b/core/src/main/java/com/boydti/fawe/object/mask/ZAxisMask.java @@ -1,16 +1,16 @@ package com.boydti.fawe.object.mask; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.function.mask.AbstractMask; import com.sk89q.worldedit.function.mask.Mask2D; import javax.annotation.Nullable; /** * Restricts the */ -public class ZAxisMask implements Mask, ResettableMask { +public class ZAxisMask extends AbstractMask implements ResettableMask { - private int layer = -1; + private transient int layer = -1; @Override public boolean test(Vector vector) { diff --git a/core/src/main/java/com/boydti/fawe/object/number/LongAdder.java b/core/src/main/java/com/boydti/fawe/object/number/LongAdder.java deleted file mode 100644 index 798887f6..00000000 --- a/core/src/main/java/com/boydti/fawe/object/number/LongAdder.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* - * Source: - * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17 - */ - -package com.boydti.fawe.object.number; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -public final class LongAdder extends Striped64 implements Serializable { - private static final long serialVersionUID = 7249069246863182397L; - - /** - * Version of plus for use in retryUpdate - */ - final long fn(long v, long x) { return v + x; } - - /** - * Creates a new adder with initial sum of zero. - */ - public LongAdder() { - } - - /** - * Adds the given value. - * - * @param x the value to add - */ - public void add(long x) { - Cell[] as; long b, v; int[] hc; Cell a; int n; - if ((as = cells) != null || !casBase(b = base, b + x)) { - boolean uncontended = true; - if ((hc = threadHashCode.get()) == null || - as == null || (n = as.length) < 1 || - (a = as[(n - 1) & hc[0]]) == null || - !(uncontended = a.cas(v = a.value, v + x))) - retryUpdate(x, hc, uncontended); - } - } - - /** - * Equivalent to {@code add(1)}. - */ - public void increment() { - add(1L); - } - - /** - * Equivalent to {@code add(-1)}. - */ - public void decrement() { - add(-1L); - } - - /** - * Returns the current sum. The returned value is NOT an - * atomic snapshot; invocation in the absence of concurrent - * updates returns an accurate result, but concurrent updates that - * occur while the sum is being calculated might not be - * incorporated. - * - * @return the sum - */ - public long sum() { - long sum = base; - Cell[] as = cells; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) - sum += a.value; - } - } - return sum; - } - - /** - * Resets variables maintaining the sum to zero. This method may - * be a useful alternative to creating a new adder, but is only - * effective if there are no concurrent updates. Because this - * method is intrinsically racy, it should only be used when it is - * known that no threads are concurrently updating. - */ - public void reset() { - internalReset(0L); - } - - /** - * Equivalent in effect to {@link #sum} followed by {@link - * #reset}. This method may apply for example during quiescent - * points between multithreaded computations. If there are - * updates concurrent with this method, the returned value is - * not guaranteed to be the final value occurring before - * the reset. - * - * @return the sum - */ - public long sumThenReset() { - long sum = base; - Cell[] as = cells; - base = 0L; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) { - sum += a.value; - a.value = 0L; - } - } - } - return sum; - } - - /** - * Returns the String representation of the {@link #sum}. - * @return the String representation of the {@link #sum} - */ - public String toString() { - return Long.toString(sum()); - } - - /** - * Equivalent to {@link #sum}. - * - * @return the sum - */ - public long longValue() { - return sum(); - } - - /** - * Returns the {@link #sum} as an {@code int} after a narrowing - * primitive conversion. - */ - public int intValue() { - return (int)sum(); - } - - /** - * Returns the {@link #sum} as a {@code float} - * after a widening primitive conversion. - */ - public float floatValue() { - return (float)sum(); - } - - /** - * Returns the {@link #sum} as a {@code double} after a widening - * primitive conversion. - */ - public double doubleValue() { - return (double)sum(); - } - - private void writeObject(ObjectOutputStream s) throws IOException { - s.defaultWriteObject(); - s.writeLong(sum()); - } - - private void readObject(ObjectInputStream s) - throws IOException, ClassNotFoundException { - s.defaultReadObject(); - busy = 0; - cells = null; - base = s.readLong(); - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/number/Striped64.java b/core/src/main/java/com/boydti/fawe/object/number/Striped64.java deleted file mode 100644 index 7a08e074..00000000 --- a/core/src/main/java/com/boydti/fawe/object/number/Striped64.java +++ /dev/null @@ -1,341 +0,0 @@ -package com.boydti.fawe.object.number; - -/* - * Written by Doug Lea with assistance from members of JCP JSR-166 - * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/publicdomain/zero/1.0/ - */ - -/* - * Source: - * http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9 - */ - -import com.boydti.fawe.object.PseudoRandom; -import java.util.Random; - -/** - * A package-local class holding common representation and mechanics - * for classes supporting dynamic striping on 64bit values. The class - * extends Number so that concrete subclasses must publicly do so. - */ -abstract class Striped64 extends Number { - /* - * This class maintains a lazily-initialized table of atomically - * updated variables, plus an extra "base" field. The table size - * is a power of two. Indexing uses masked per-thread hash codes. - * Nearly all declarations in this class are package-private, - * accessed directly by subclasses. - * - * Table entries are of class Cell; a variant of AtomicLong padded - * to reduce cache contention on most processors. Padding is - * overkill for most Atomics because they are usually irregularly - * scattered in memory and thus don't interfere much with each - * other. But Atomic objects residing in arrays will tend to be - * placed adjacent to each other, and so will most often share - * cache lines (with a huge negative performance impact) without - * this precaution. - * - * In part because Cells are relatively large, we avoid creating - * them until they are needed. When there is no contention, all - * updates are made to the base field. Upon first contention (a - * failed CAS on base update), the table is initialized to size 2. - * The table size is doubled upon further contention until - * reaching the nearest power of two greater than or equal to the - * number of CPUS. Table slots remain empty (null) until they are - * needed. - * - * A single spinlock ("busy") is used for initializing and - * resizing the table, as well as populating slots with new Cells. - * There is no need for a blocking lock; when the lock is not - * available, threads try other slots (or the base). During these - * retries, there is increased contention and reduced locality, - * which is still better than alternatives. - * - * Per-thread hash codes are initialized to random values. - * Contention and/or table collisions are indicated by failed - * CASes when performing an update operation (see method - * retryUpdate). Upon a collision, if the table size is less than - * the capacity, it is doubled in size unless some other thread - * holds the lock. If a hashed slot is empty, and lock is - * available, a new Cell is created. Otherwise, if the slot - * exists, a CAS is tried. Retries proceed by "double hashing", - * using a secondary hash (Marsaglia XorShift) to try to find a - * free slot. - * - * The table size is capped because, when there are more threads - * than CPUs, supposing that each thread were bound to a CPU, - * there would exist a perfect hash function mapping threads to - * slots that eliminates collisions. When we reach capacity, we - * search for this mapping by randomly varying the hash codes of - * colliding threads. Because search is random, and collisions - * only become known via CAS failures, convergence can be slow, - * and because threads are typically not bound to CPUS forever, - * may not occur at all. However, despite these limitations, - * observed contention rates are typically low in these cases. - * - * It is possible for a Cell to become unused when threads that - * once hashed to it terminate, as well as in the case where - * doubling the table causes no thread to hash to it under - * expanded mask. We do not try to detect or remove such cells, - * under the assumption that for long-running instances, observed - * contention levels will recur, so the cells will eventually be - * needed again; and for short-lived ones, it does not matter. - */ - - /** - * Padded variant of AtomicLong supporting only raw accesses plus CAS. - * The value field is placed between pads, hoping that the JVM doesn't - * reorder them. - * - * JVM intrinsics note: It would be possible to use a release-only - * form of CAS here, if it were provided. - */ - static final class Cell { - volatile long p0, p1, p2, p3, p4, p5, p6; - volatile long value; - volatile long q0, q1, q2, q3, q4, q5, q6; - Cell(long x) { value = x; } - - final boolean cas(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val); - } - - // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long valueOffset; - static { - try { - UNSAFE = getUnsafe(); - Class ak = Cell.class; - valueOffset = UNSAFE.objectFieldOffset - (ak.getDeclaredField("value")); - } catch (Exception e) { - throw new Error(e); - } - } - - } - - /** - * ThreadLocal holding a single-slot int array holding hash code. - * Unlike the JDK8 version of this class, we use a suboptimal - * int[] representation to avoid introducing a new type that can - * impede class-unloading when ThreadLocals are not removed. - */ - static final ThreadLocal threadHashCode = new ThreadLocal(); - - /** - * Generator of new random hash codes - */ - static final PseudoRandom prng = new PseudoRandom(System.nanoTime()); - - static final Random rng = new Random(); - - /** Number of CPUS, to place bound on table size */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); - - /** - * Table of cells. When non-null, size is a power of 2. - */ - transient volatile Cell[] cells; - - /** - * Base value, used mainly when there is no contention, but also as - * a fallback during table initialization races. Updated via CAS. - */ - transient volatile long base; - - /** - * Spinlock (locked via CAS) used when resizing and/or creating Cells. - */ - transient volatile int busy; - - /** - * Package-private default constructor - */ - Striped64() { - } - - /** - * CASes the base field. - */ - final boolean casBase(long cmp, long val) { - return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val); - } - - /** - * CASes the busy field from 0 to 1 to acquire lock. - */ - final boolean casBusy() { - return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1); - } - - /** - * Computes the function of current and new value. Subclasses - * should open-code this update function for most uses, but the - * virtualized form is needed within retryUpdate. - * - * @param currentValue the current value (of either base or a cell) - * @param newValue the argument from a user update call - * @return result of the update function - */ - abstract long fn(long currentValue, long newValue); - - /** - * Handles cases of updates involving initialization, resizing, - * creating new Cells, and/or contention. See above for - * explanation. This method suffers the usual non-modularity - * problems of optimistic retry code, relying on rechecked sets of - * reads. - * - * @param x the value - * @param hc the hash code holder - * @param wasUncontended false if CAS failed before call - */ - final void retryUpdate(long x, int[] hc, boolean wasUncontended) { - int h; - if (hc == null) { - threadHashCode.set(hc = new int[1]); // Initialize randomly - int r = prng.random(Integer.MAX_VALUE); // Avoid zero to allow xorShift rehash - h = hc[0] = (r == 0) ? 1 : r; - } - else - h = hc[0]; - boolean collide = false; // True if last slot nonempty - for (;;) { - Cell[] as; Cell a; int n; long v; - if ((as = cells) != null && (n = as.length) > 0) { - if ((a = as[(n - 1) & h]) == null) { - if (busy == 0) { // Try to attach new Cell - Cell r = new Cell(x); // Optimistically create - if (busy == 0 && casBusy()) { - boolean created = false; - try { // Recheck under lock - Cell[] rs; int m, j; - if ((rs = cells) != null && - (m = rs.length) > 0 && - rs[j = (m - 1) & h] == null) { - rs[j] = r; - created = true; - } - } finally { - busy = 0; - } - if (created) - break; - continue; // Slot is now non-empty - } - } - collide = false; - } - else if (!wasUncontended) // CAS already known to fail - wasUncontended = true; // Continue after rehash - else if (a.cas(v = a.value, fn(v, x))) - break; - else if (n >= NCPU || cells != as) - collide = false; // At max size or stale - else if (!collide) - collide = true; - else if (busy == 0 && casBusy()) { - try { - if (cells == as) { // Expand table unless stale - Cell[] rs = new Cell[n << 1]; - for (int i = 0; i < n; ++i) - rs[i] = as[i]; - cells = rs; - } - } finally { - busy = 0; - } - collide = false; - continue; // Retry with expanded table - } - h ^= h << 13; // Rehash - h ^= h >>> 17; - h ^= h << 5; - hc[0] = h; // Record index for next time - } - else if (busy == 0 && cells == as && casBusy()) { - boolean init = false; - try { // Initialize table - if (cells == as) { - Cell[] rs = new Cell[2]; - rs[h & 1] = new Cell(x); - cells = rs; - init = true; - } - } finally { - busy = 0; - } - if (init) - break; - } - else if (casBase(v = base, fn(v, x))) - break; // Fall back on using base - } - } - - /** - * Sets base and all cells to the given value. - */ - final void internalReset(long initialValue) { - Cell[] as = cells; - base = initialValue; - if (as != null) { - int n = as.length; - for (int i = 0; i < n; ++i) { - Cell a = as[i]; - if (a != null) - a.value = initialValue; - } - } - } - - // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long baseOffset; - private static final long busyOffset; - static { - try { - UNSAFE = getUnsafe(); - Class sk = Striped64.class; - baseOffset = UNSAFE.objectFieldOffset - (sk.getDeclaredField("base")); - busyOffset = UNSAFE.objectFieldOffset - (sk.getDeclaredField("busy")); - } catch (Exception e) { - throw new Error(e); - } - } - - /** - * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package. - * Replace with a simple call to Unsafe.getUnsafe when integrating - * into a jdk. - * - * @return a sun.misc.Unsafe - */ - private static sun.misc.Unsafe getUnsafe() { - try { - return sun.misc.Unsafe.getUnsafe(); - } catch (SecurityException tryReflectionInstead) {} - try { - return java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public sun.misc.Unsafe run() throws Exception { - Class k = sun.misc.Unsafe.class; - for (java.lang.reflect.Field f : k.getDeclaredFields()) { - f.setAccessible(true); - Object x = f.get(null); - if (k.isInstance(x)) - return k.cast(x); - } - throw new NoSuchFieldError("the Unsafe"); - }}); - } catch (java.security.PrivilegedActionException e) { - throw new RuntimeException("Could not initialize intrinsics", - e.getCause()); - } - } -} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/AbstractExtentPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/AbstractExtentPattern.java new file mode 100644 index 00000000..1e6a8204 --- /dev/null +++ b/core/src/main/java/com/boydti/fawe/object/pattern/AbstractExtentPattern.java @@ -0,0 +1,20 @@ +package com.boydti.fawe.object.pattern; + +import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.pattern.AbstractPattern; + + +import static com.google.common.base.Preconditions.checkNotNull; + +public abstract class AbstractExtentPattern extends AbstractPattern { + private transient final Extent extent; + + public AbstractExtentPattern(Extent extent) { + checkNotNull(extent); + this.extent = extent; + } + + public final Extent getExtent() { + return extent; + } +} diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/AngleColorPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/AngleColorPattern.java index e52f5423..30d19df8 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/AngleColorPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/AngleColorPattern.java @@ -1,26 +1,31 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.Fawe; import com.boydti.fawe.object.DataAngleMask; import com.boydti.fawe.util.TextureUtil; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; +import java.io.IOException; public class AngleColorPattern extends DataAngleMask { - private final TextureUtil util; - private final int maxY; - private final double factor = 1d/196; + private static final double FACTOR = 1d/196; + private transient TextureUtil util; - public AngleColorPattern(TextureUtil util, Extent extent) { + private final boolean randomize; + private final int complexity; + + public AngleColorPattern(Extent extent, int complexity, boolean randomize) { super(extent); - this.util = util; - this.maxY = extent.getMaximumPoint().getBlockY(); + this.complexity = complexity; + this.randomize = randomize; + this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); } public int getColor(int color, int slope) { if (slope == 0) return color; - double newFactor = (196 - Math.min(196, slope)) * factor; + double newFactor = (196 - Math.min(196, slope)) * FACTOR; int newRed = (int) (((color >> 16) & 0xFF) * newFactor); int newGreen = (int) (((color >> 8) & 0xFF) * newFactor); int newBlue = (int) (((color >> 0) & 0xFF) * newFactor); @@ -50,4 +55,9 @@ public class AngleColorPattern extends DataAngleMask { if (newBlock == null) return false; return extent.setBlock(setPosition, newBlock); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/AverageColorPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/AverageColorPattern.java index 924b309f..405c45ae 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/AverageColorPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/AverageColorPattern.java @@ -1,27 +1,31 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.Fawe; import com.boydti.fawe.util.TextureUtil; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import java.awt.Color; +import java.io.IOException; -public class AverageColorPattern extends AbstractPattern { +public class AverageColorPattern extends AbstractExtentPattern { + private transient TextureUtil util; + private final boolean randomize; + private final int complexity; private final int color; - private final Extent extent; - private final TextureUtil util; - public AverageColorPattern(Extent extent, TextureUtil util, int color) { - this.extent = extent; - this.util = util; + public AverageColorPattern(Extent extent, int color, int complexity, boolean randomize) { + super(extent); + this.complexity = complexity; + this.randomize = randomize; + this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); this.color = new Color(color).getRGB(); } @Override public BaseBlock apply(Vector position) { - BaseBlock block = extent.getBlock(position); + BaseBlock block = getExtent().getBlock(position); int currentColor = util.getColor(block); int newColor = util.averageColor(currentColor, color); return util.getNearestBlock(newColor); @@ -37,4 +41,9 @@ public class AverageColorPattern extends AbstractPattern { if (newBlock.equals(block)) return false; return extent.setBlock(setPosition, newBlock); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java index 2db6e115..334c2b82 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/BiomePattern.java @@ -6,21 +6,20 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.biome.BaseBiome; +import java.io.IOException; public class BiomePattern extends ExistingPattern { + private transient MutableBlockVector2D mutable = new MutableBlockVector2D(); private final BaseBiome biome; - private BiomePatternException exception; - private MutableBlockVector2D mutable = new MutableBlockVector2D(); public BiomePattern(Extent extent, BaseBiome biome) { super(extent); this.biome = biome; - this.exception = new BiomePatternException(); } @Override public BaseBlock apply(Vector position) { - throw exception; + throw new BiomePatternException(); } @Override @@ -29,10 +28,7 @@ public class BiomePattern extends ExistingPattern { } public class BiomePatternException extends RuntimeException { - - public BiomePatternException() { - super("Haha, you failed Empire92! Should've done things properly instead of some hacky AF biome pattern.\nHey, you! The one reading this stacktrace, can you do me a favor and report this on GitHub so I can get around to fixing it?"); - } + private BiomePatternException() {} public BiomePattern getPattern() { return BiomePattern.this; @@ -47,4 +43,9 @@ public class BiomePattern extends ExistingPattern { return this; } } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector2D(); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern.java index de337935..97d900da 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern.java @@ -10,17 +10,21 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; +import java.util.UUID; public class BufferedPattern extends AbstractPattern implements ResettablePattern { - private final Pattern pattern; - private final LocalBlockVectorSet set = new LocalBlockVectorSet(); - private final FaweTimer timer; - private final long[] actionTime; + protected transient LocalBlockVectorSet set = new LocalBlockVectorSet(); + protected transient FaweTimer timer; + protected transient long[] actionTime; + + protected final Pattern pattern; + protected final UUID uuid; public BufferedPattern(FawePlayer fp, Pattern parent) { - long[] actionTime = fp.getMeta("lastActionTime"); + this.uuid = fp.getUUID(); + this.actionTime = fp.getMeta("lastActionTime"); if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]); - this.actionTime = actionTime; this.pattern = parent; this.timer = Fawe.get().getTimer(); } @@ -34,7 +38,7 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException { long now = timer.getTick(); try { - if (!set.add(setPosition)) { + if (!set(setPosition)) { return false; } return pattern.apply(extent, setPosition, getPosition); @@ -42,6 +46,10 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter return false; } + public boolean set(Vector pos) { + return set.add(pos); + } + @Override public void reset() { long now = timer.getTick(); @@ -51,4 +59,17 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter actionTime[1] = actionTime[0]; actionTime[0] = now; } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + set = new LocalBlockVectorSet(); + timer = Fawe.get().getTimer(); + FawePlayer fp = Fawe.get().getCachedPlayer(uuid); + if (fp != null) { + this.actionTime = fp.getMeta("lastActionTime"); + if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]); + } else { + actionTime = new long[2]; + } + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern2D.java b/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern2D.java index 4997671a..359388c1 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern2D.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/BufferedPattern2D.java @@ -1,54 +1,17 @@ package com.boydti.fawe.object.pattern; -import com.boydti.fawe.Fawe; import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.object.collection.LocalBlockVectorSet; -import com.boydti.fawe.util.FaweTimer; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; -public class BufferedPattern2D extends AbstractPattern implements ResettablePattern { - private final Pattern pattern; - private final LocalBlockVectorSet set = new LocalBlockVectorSet(); - private final FaweTimer timer; - private final long[] actionTime; +public class BufferedPattern2D extends BufferedPattern { public BufferedPattern2D(FawePlayer fp, Pattern parent) { - long[] actionTime = fp.getMeta("lastActionTime"); - if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]); - this.actionTime = actionTime; - this.pattern = parent; - this.timer = Fawe.get().getTimer(); + super(fp, parent); } @Override - public BaseBlock apply(Vector position) { - return pattern.apply(position); - } - - @Override - public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException { - long now = timer.getTick(); - try { - if (!set.add(setPosition.getBlockX(), 0, setPosition.getBlockZ())) { - return false; - } - return pattern.apply(extent, setPosition, getPosition); - } catch (UnsupportedOperationException ignore) {} - return false; - } - - @Override - public void reset() { - long now = timer.getTick(); - if (now - actionTime[1] > 5) { - set.clear(); - } - actionTime[1] = actionTime[0]; - actionTime[0] = now; + public boolean set(Vector pos) { + return set.add(pos.getBlockX(), 0, pos.getBlockY()); } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/DataPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/DataPattern.java index 0d637cec..a694f923 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/DataPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/DataPattern.java @@ -4,26 +4,23 @@ import com.boydti.fawe.FaweCache; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; import static com.google.common.base.Preconditions.checkNotNull; -public class DataPattern extends AbstractPattern { - private final Extent extent; +public class DataPattern extends AbstractExtentPattern { private final Pattern pattern; public DataPattern(Extent extent, Pattern parent) { - checkNotNull(extent); + super(extent); checkNotNull(parent); - this.extent = extent; this.pattern = parent; } @Override public BaseBlock apply(Vector position) { - BaseBlock oldBlock = extent.getBlock(position); + BaseBlock oldBlock = getExtent().getBlock(position); BaseBlock newBlock = pattern.apply(position); return FaweCache.getBlock(oldBlock.getId(), newBlock.getData()); } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/DesaturatePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/DesaturatePattern.java index 41c3d96d..77955281 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/DesaturatePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/DesaturatePattern.java @@ -1,20 +1,26 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.Fawe; import com.boydti.fawe.util.TextureUtil; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; +import java.io.IOException; public class DesaturatePattern extends AbstractPattern{ - private final TextureUtil util; + private transient TextureUtil util; + private final boolean randomize; + private final int complexity; private final Extent extent; private final double value; - public DesaturatePattern(Extent extent, TextureUtil util, double value) { + public DesaturatePattern(Extent extent, double value, int complexity, boolean randomize) { this.extent = extent; - this.util = util; + this.complexity = complexity; + this.randomize = randomize; + this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); this.value = Math.max(0, Math.min(1, value)); } @Override @@ -55,4 +61,9 @@ public class DesaturatePattern extends AbstractPattern{ } return extent.setBlock(setPosition, newBlock); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/ExistingPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/ExistingPattern.java index 0e0834aa..9df20215 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/ExistingPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/ExistingPattern.java @@ -4,18 +4,15 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; - -public class ExistingPattern extends AbstractPattern { - private final Extent extent; +public class ExistingPattern extends AbstractExtentPattern { public ExistingPattern(Extent extent) { - this.extent = extent; + super(extent); } @Override public BaseBlock apply(Vector position) { - return extent.getBlock(position); + return getExtent().getBlock(position); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java index 72dddf02..a680c31f 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/ExpressionPattern.java @@ -9,6 +9,7 @@ import com.sk89q.worldedit.internal.expression.Expression; import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.internal.expression.runtime.EvaluationException; import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment; +import java.io.IOException; import static com.google.common.base.Preconditions.checkNotNull; @@ -21,7 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class ExpressionPattern extends AbstractPattern { - private final Expression expression; + public String input; + private transient Expression expression; /** * Create a new instance. @@ -29,9 +31,10 @@ public class ExpressionPattern extends AbstractPattern { * @param expression the expression * @throws ExpressionException thrown if there is an error with the expression */ - public ExpressionPattern(String expression) throws ExpressionException { - checkNotNull(expression); - this.expression = Expression.compile(expression, "x", "y", "z"); + public ExpressionPattern(String input) throws ExpressionException { + checkNotNull(input); + this.input = input; + this.expression = Expression.compile(input, "x", "y", "z"); } /** @@ -56,4 +59,13 @@ public class ExpressionPattern extends AbstractPattern { return EditSession.nullBlock; } } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + try { + this.expression = Expression.compile(input, "x", "y", "z"); + } catch (ExpressionException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/FullClipboardPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/FullClipboardPattern.java index fd311690..c703f388 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/FullClipboardPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/FullClipboardPattern.java @@ -9,8 +9,9 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operations; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.regions.Region; +import java.io.IOException; +import java.io.NotSerializableException; import static com.google.common.base.Preconditions.checkNotNull; @@ -18,8 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * A pattern that reads from {@link Clipboard}. */ -public class FullClipboardPattern extends AbstractPattern { - private final Extent extent; +public class FullClipboardPattern extends AbstractExtentPattern { private final Clipboard clipboard; private final MutableBlockVector mutable = new MutableBlockVector(); @@ -29,9 +29,9 @@ public class FullClipboardPattern extends AbstractPattern { * @param clipboard the clipboard */ public FullClipboardPattern(Extent extent, Clipboard clipboard) { + super(extent); checkNotNull(clipboard); this.clipboard = clipboard; - this.extent = extent; } @Override @@ -47,4 +47,8 @@ public class FullClipboardPattern extends AbstractPattern { public BaseBlock apply(Vector position) { throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!"); } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + throw new NotSerializableException("Clipboard cannot be serialized!"); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/IdDataMaskPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/IdDataMaskPattern.java index dcdbaaf7..ae3741af 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/IdDataMaskPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/IdDataMaskPattern.java @@ -4,26 +4,24 @@ import com.boydti.fawe.FaweCache; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; -public class IdDataMaskPattern extends AbstractPattern { - private final Extent extent; +public class IdDataMaskPattern extends AbstractExtentPattern { private final Pattern pattern; - private final int mask; + private final int bitMask; - public IdDataMaskPattern(Extent extent, Pattern parent, int mask) { - this.extent = extent; + public IdDataMaskPattern(Extent extent, Pattern parent, int bitMask) { + super(extent); this.pattern = parent; - this.mask = mask; + this.bitMask = bitMask; } @Override public BaseBlock apply(Vector position) { - BaseBlock oldBlock = extent.getBlock(position); + BaseBlock oldBlock = getExtent().getBlock(position); BaseBlock newBlock = pattern.apply(position); int oldData = oldBlock.getData(); - int newData = newBlock.getData() + oldData - (oldData & mask); + int newData = newBlock.getData() + oldData - (oldData & bitMask); return FaweCache.getBlock(newBlock.getId(), newData); } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/IdPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/IdPattern.java index 26c1abd1..ea121706 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/IdPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/IdPattern.java @@ -4,26 +4,23 @@ import com.boydti.fawe.FaweCache; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; import static com.google.common.base.Preconditions.checkNotNull; -public class IdPattern extends AbstractPattern { - private final Extent extent; +public class IdPattern extends AbstractExtentPattern { private final Pattern pattern; public IdPattern(Extent extent, Pattern parent) { - checkNotNull(extent); + super(extent); checkNotNull(parent); - this.extent = extent; this.pattern = parent; } @Override public BaseBlock apply(Vector position) { - BaseBlock oldBlock = extent.getBlock(position); + BaseBlock oldBlock = getExtent().getBlock(position); BaseBlock newBlock = pattern.apply(position); return FaweCache.getBlock(newBlock.getId(), oldBlock.getData()); } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java index f3f114f2..95da75e0 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/Linear3DBlockPattern.java @@ -6,17 +6,13 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; -import java.util.Arrays; -import java.util.Collection; public class Linear3DBlockPattern extends AbstractPattern { - private final Collection patterns; private final Pattern[] patternsArray; public Linear3DBlockPattern(Pattern[] patterns) { this.patternsArray = patterns; - this.patterns = Arrays.asList(patterns); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java index f7da63b3..1c22a91e 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/LinearBlockPattern.java @@ -6,18 +6,14 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; -import java.util.Arrays; -import java.util.Collection; public class LinearBlockPattern extends AbstractPattern implements ResettablePattern { - private final Collection patterns; private final Pattern[] patternsArray; - private int index; + private transient int index; public LinearBlockPattern(Pattern[] patterns) { this.patternsArray = patterns; - this.patterns = Arrays.asList(patterns); } @Override diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java index 8271e84b..f690170e 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/MaskedPattern.java @@ -7,21 +7,17 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; -import java.util.Arrays; -import java.util.List; public class MaskedPattern extends AbstractPattern { private final PatternExtent patternExtent; private final Pattern secondaryPattern; - private final List patterns; private Mask mask; public MaskedPattern(Mask mask, PatternExtent primary, Pattern secondary) { this.mask = mask; this.patternExtent = primary; this.secondaryPattern = secondary; - this.patterns = Arrays.asList(primary, secondary); } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java index 4e82ec25..9bd8aa27 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoXPattern.java @@ -7,17 +7,17 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; public class NoXPattern extends AbstractPattern { private final Pattern pattern; + private transient MutableBlockVector mutable = new MutableBlockVector(); public NoXPattern(Pattern pattern) { this.pattern = pattern; } - private MutableBlockVector mutable = new MutableBlockVector(); - @Override public BaseBlock apply(Vector pos) { mutable.mutY((pos.getY())); @@ -31,4 +31,9 @@ public class NoXPattern extends AbstractPattern { mutable.mutZ((get.getZ())); return pattern.apply(extent, set, mutable); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java index 8f00a2ae..96b04e38 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoYPattern.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; public class NoYPattern extends AbstractPattern { @@ -16,7 +17,7 @@ public class NoYPattern extends AbstractPattern { this.pattern = pattern; } - private MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); @Override public BaseBlock apply(Vector pos) { @@ -31,4 +32,9 @@ public class NoYPattern extends AbstractPattern { mutable.mutZ((get.getZ())); return pattern.apply(extent, set, mutable); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java index 72f2dafa..a1acbd35 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/NoZPattern.java @@ -7,6 +7,7 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; public class NoZPattern extends AbstractPattern { @@ -16,7 +17,7 @@ public class NoZPattern extends AbstractPattern { this.pattern = pattern; } - private MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); @Override public BaseBlock apply(Vector pos) { @@ -31,4 +32,9 @@ public class NoZPattern extends AbstractPattern { mutable.mutY((get.getY())); return pattern.apply(extent, set, mutable); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java index e5ce4d80..5a1e5e59 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/OffsetPattern.java @@ -7,11 +7,12 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; public class OffsetPattern extends AbstractPattern { private final int dx,dy,dz; - private final MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); private final Pattern pattern; public OffsetPattern(Pattern pattern, int dx, int dy, int dz) { @@ -36,4 +37,9 @@ public class OffsetPattern extends AbstractPattern { mutable.mutZ((get.getZ() + dz)); return pattern.apply(extent, set, mutable); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java index 86164841..ea929d30 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/PatternExtent.java @@ -13,19 +13,25 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.biome.BaseBiome; +import java.io.IOException; import java.util.ArrayList; import java.util.List; import javax.annotation.Nullable; public class PatternExtent extends AbstractPattern implements Extent { private final Pattern pattern; - private BaseBlock block; - private Vector target = new Vector(); + private transient BaseBlock block; + private transient Vector target = new Vector(); public PatternExtent(Pattern pattern) { this.pattern = pattern; } + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + target = new Vector(); + } + @Override public Vector getMinimumPoint() { return new Vector(Integer.MIN_VALUE,0,Integer.MIN_VALUE); diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RandomFullClipboardPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RandomFullClipboardPattern.java index 99ba3a07..39629c49 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/RandomFullClipboardPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RandomFullClipboardPattern.java @@ -13,6 +13,8 @@ import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.world.registry.WorldData; +import java.io.IOException; +import java.io.NotSerializableException; import static com.google.common.base.Preconditions.checkNotNull; @@ -62,4 +64,8 @@ public class RandomFullClipboardPattern extends AbstractPattern { public BaseBlock apply(Vector position) { throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!"); } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + throw new NotSerializableException("Clipboard cannot be serialized!"); + } } diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java index 798de693..2496519b 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RandomOffsetPattern.java @@ -1,6 +1,5 @@ package com.boydti.fawe.object.pattern; -import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; @@ -8,12 +7,16 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; +import java.util.SplittableRandom; public class RandomOffsetPattern extends AbstractPattern { - private final PseudoRandom r = new PseudoRandom(); - private final int dx, dy, dz, dx2, dy2, dz2; + private final int dx, dy, dz; private final Pattern pattern; - private final MutableBlockVector mutable = new MutableBlockVector(); + + private transient int dx2, dy2, dz2; + private transient MutableBlockVector mutable = new MutableBlockVector(); + private transient SplittableRandom r; public RandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) { this.pattern = pattern; @@ -23,6 +26,7 @@ public class RandomOffsetPattern extends AbstractPattern { this.dx2 = dx * 2 + 1; this.dy2 = dy * 2 + 1; this.dz2 = dz * 2 + 1; + this.r = new SplittableRandom(); } @@ -41,4 +45,13 @@ public class RandomOffsetPattern extends AbstractPattern { mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz)); return pattern.apply(extent, set, mutable); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + this.dx2 = dx * 2 + 1; + this.dy2 = dy * 2 + 1; + this.dz2 = dz * 2 + 1; + this.r = new SplittableRandom(); + this.mutable = new MutableBlockVector(); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java index d3dba982..50f75287 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/RelativePattern.java @@ -7,18 +7,18 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; public class RelativePattern extends AbstractPattern implements ResettablePattern { private final Pattern pattern; + private transient Vector origin; + private transient MutableBlockVector mutable = new MutableBlockVector(); public RelativePattern(Pattern pattern) { this.pattern = pattern; } - private Vector origin; - private MutableBlockVector mutable = new MutableBlockVector(); - @Override public BaseBlock apply(Vector pos) { if (origin == null) { @@ -41,6 +41,11 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter return pattern.apply(extent, set, mutable); } + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } + @Override public void reset() { origin = null; diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/SaturatePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/SaturatePattern.java index d1a64b79..f55f8993 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/SaturatePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/SaturatePattern.java @@ -1,5 +1,6 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.Fawe; import com.boydti.fawe.util.TextureUtil; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; @@ -7,15 +8,21 @@ import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import java.awt.Color; +import java.io.IOException; public class SaturatePattern extends AbstractPattern { + private transient TextureUtil util; + private final boolean randomize; + private final int complexity; private final int color; private final Extent extent; - private final TextureUtil util; - public SaturatePattern(Extent extent, TextureUtil util, int color) { + + public SaturatePattern(Extent extent, int color, int complexity, boolean randomize) { this.extent = extent; - this.util = util; + this.complexity = complexity; + this.randomize = randomize; + this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); this.color = new Color(color).getRGB(); } @@ -37,4 +44,9 @@ public class SaturatePattern extends AbstractPattern { if (newBlock.equals(block)) return false; return extent.setBlock(setPosition, newBlock); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/ShadePattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/ShadePattern.java index ed759c21..7262a40e 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/ShadePattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/ShadePattern.java @@ -1,24 +1,29 @@ package com.boydti.fawe.object.pattern; +import com.boydti.fawe.Fawe; import com.boydti.fawe.util.TextureUtil; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; +import java.io.IOException; import static com.google.common.base.Preconditions.checkNotNull; public class ShadePattern extends AbstractPattern{ - private final TextureUtil util; + private transient TextureUtil util; + private final boolean randomize; + private final int complexity; private final Extent extent; private final boolean darken; - public ShadePattern(Extent extent, TextureUtil util, boolean darken) { + public ShadePattern(Extent extent, boolean darken, int complexity, boolean randomize) { checkNotNull(extent); - checkNotNull(util); this.extent = extent; - this.util = util; + this.complexity = complexity; + this.randomize = randomize; + this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); this.darken = darken; } @Override @@ -26,4 +31,9 @@ public class ShadePattern extends AbstractPattern{ BaseBlock block = extent.getBlock(position); return darken ? util.getDarkerBlock(block) : util.getLighterBlock(block); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java index 10373d74..4cfdc22d 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/SolidRandomOffsetPattern.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.pattern; import com.boydti.fawe.FaweCache; -import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; @@ -10,19 +9,28 @@ import com.sk89q.worldedit.blocks.BlockType; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; +import java.io.IOException; +import java.util.SplittableRandom; public class SolidRandomOffsetPattern extends AbstractPattern { - private final PseudoRandom r = new PseudoRandom(); - private final int dx, dy, dz, dx2, dy2, dz2; + private final int dx, dy, dz; private final Pattern pattern; - private final MutableBlockVector mutable = new MutableBlockVector(); - boolean[] solid; + + private transient int dx2, dy2, dz2; + private transient MutableBlockVector mutable; + private transient boolean[] solid; + private SplittableRandom r; + public SolidRandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) { this.pattern = pattern; this.dx = dx; this.dy = dy; this.dz = dz; + init(); + } + + private void init() { this.dx2 = dx * 2 + 1; this.dy2 = dy * 2 + 1; this.dz2 = dz * 2 + 1; @@ -34,6 +42,8 @@ public class SolidRandomOffsetPattern extends AbstractPattern { } } } + this.r = new SplittableRandom(); + this.mutable = new MutableBlockVector(); } @Override @@ -61,4 +71,9 @@ public class SolidRandomOffsetPattern extends AbstractPattern { return pattern.apply(extent, set, get); } } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + init(); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java b/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java index 585bce0b..cb7c7561 100644 --- a/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java +++ b/core/src/main/java/com/boydti/fawe/object/pattern/SurfaceRandomOffsetPattern.java @@ -5,26 +5,28 @@ import com.boydti.fawe.object.PseudoRandom; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.blocks.BaseBlock; -import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.pattern.AbstractPattern; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.visitor.BreadthFirstSearch; +import java.io.IOException; public class SurfaceRandomOffsetPattern extends AbstractPattern { private final Pattern pattern; - private final Extent extent; - private int moves; - private final MutableBlockVector cur = new MutableBlockVector(); - private final MutableBlockVector[] buffer; - private final MutableBlockVector[] allowed; - private MutableBlockVector next; + private transient MutableBlockVector cur; + private transient MutableBlockVector[] buffer; + private transient MutableBlockVector[] allowed; + private transient MutableBlockVector next; - public SurfaceRandomOffsetPattern(Extent extent, Pattern pattern, int distance) { + public SurfaceRandomOffsetPattern(Pattern pattern, int distance) { this.pattern = pattern; - this.extent = extent; this.moves = Math.min(255, distance); + init(); + } + + private void init() { + cur = new MutableBlockVector(); this.buffer = new MutableBlockVector[BreadthFirstSearch.DIAGONAL_DIRECTIONS.length]; for (int i = 0; i < buffer.length; i++) { buffer[i] = new MutableBlockVector(); @@ -88,40 +90,9 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern { BaseBlock block = pattern.apply(v); return FaweCache.canPassThrough(block.getId(), block.getData()); } -// -// @Override -// public BaseBlock apply(Vector position) { -// mutable.mutX((position.getX() + r.nextInt(dx2) - dx)); -// mutable.mutY((position.getY() + r.nextInt(dy2) - dy)); -// mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz)); -// BaseBlock block = pattern.apply(mutable); -// if (solid[FaweCache.getCombined(block)]) { -// if (solid[FaweCache.getCombined(mutable)]) -// mutable.mutY(mutable.getY() + 1); -// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) { -// return block; -// } -// } -// return pattern.apply(position); -// } -// -// private Vector get(Vector input) { -// for (dir : -// BreadthFirstSearch.DIAGONAL_DIRECTIONS) -// } -// -// @Override -// public boolean apply(Extent extent, Vector set, Vector get) throws WorldEditException { -// mutable.mutX((get.getX() + r.nextInt(dx2) - dx)); -// mutable.mutY((get.getY() + r.nextInt(dy2) - dy)); -// mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz)); -// BaseBlock block = pattern.apply(mutable); -// if (solid[FaweCache.getCombined(block)]) { -// mutable.mutY(mutable.getY() + 1); -// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) { -// return pattern.apply(extent, set, mutable); -// } -// } -// return pattern.apply(extent, set, get); -// } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + init(); + } } \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/BaseBlockSerializer.java b/core/src/main/java/com/boydti/fawe/object/serializer/BaseBlockSerializer.java deleted file mode 100644 index 25e333ce..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/BaseBlockSerializer.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.boydti.fawe.FaweCache; -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.sk89q.worldedit.blocks.BaseBlock; -import java.lang.reflect.Type; - -public class BaseBlockSerializer extends JsonSerializable { - @Override - public BaseBlock deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonArray jsonArray = json.getAsJsonArray(); - if (jsonArray.size() != 2) { - throw new JsonParseException("Expected array of 3 length for Vector"); - } - return FaweCache.getBlock(jsonArray.get(0).getAsInt(), jsonArray.get(1).getAsInt()); - } - - @Override - public JsonElement serialize(BaseBlock src, Type typeOfSrc, JsonSerializationContext context) { - JsonArray array = new JsonArray(); - array.add(new JsonPrimitive(src.getId())); - array.add(new JsonPrimitive(src.getData())); - return array; - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/BlockVectorSerializer.java b/core/src/main/java/com/boydti/fawe/object/serializer/BlockVectorSerializer.java deleted file mode 100644 index 48527250..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/BlockVectorSerializer.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.google.gson.JsonArray; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.sk89q.worldedit.MutableBlockVector; -import com.sk89q.worldedit.Vector; -import java.lang.reflect.Type; - -public class BlockVectorSerializer extends JsonSerializable { - - @Override - public JsonElement serialize(Vector src, Type typeOfSrc, JsonSerializationContext context) { - JsonArray array = new JsonArray(); - array.add(new JsonPrimitive(src.getBlockX())); - array.add(new JsonPrimitive(src.getBlockY())); - array.add(new JsonPrimitive(src.getBlockZ())); - return array; - } - - - @Override - public Vector deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - JsonArray jsonArray = json.getAsJsonArray(); - if (jsonArray.size() != 3) { - throw new JsonParseException("Expected array of 3 length for Vector"); - } - int x = jsonArray.get(0).getAsInt(); - int y = jsonArray.get(1).getAsInt(); - int z = jsonArray.get(2).getAsInt(); - return new MutableBlockVector(x, y, z); - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/EditSessionSerializer.java b/core/src/main/java/com/boydti/fawe/object/serializer/EditSessionSerializer.java deleted file mode 100644 index ff614864..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/EditSessionSerializer.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.boydti.fawe.object.FawePlayer; -import com.boydti.fawe.util.EditSessionBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.entity.Player; -import java.lang.reflect.Type; - -public class EditSessionSerializer extends JsonSerializable { - - private final Player player; - - public EditSessionSerializer(Player player) { - this.player = player; - } - - @Override - public EditSession deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return new EditSessionBuilder(player.getWorld()).player(FawePlayer.wrap(player)).build(); - } - - @Override - public JsonElement serialize(EditSession src, Type typeOfSrc, JsonSerializationContext context) { - return null; - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/InheritedExclusion.java b/core/src/main/java/com/boydti/fawe/object/serializer/InheritedExclusion.java deleted file mode 100644 index b06f33a5..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/InheritedExclusion.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.google.gson.ExclusionStrategy; -import com.google.gson.FieldAttributes; -import java.lang.reflect.Field; - -public class InheritedExclusion implements ExclusionStrategy { - public boolean shouldSkipClass(Class arg0) - { - return false; - } - - public boolean shouldSkipField(FieldAttributes fieldAttributes) - { - String fieldName = fieldAttributes.getName(); - Class theClass = fieldAttributes.getDeclaringClass(); - - return isFieldInSuperclass(theClass, fieldName); - } - - private boolean isFieldInSuperclass(Class subclass, String fieldName) - { - Class superclass = subclass.getSuperclass(); - Field field; - - while(superclass != null) - { - field = getField(superclass, fieldName); - - if(field != null) - return true; - - superclass = superclass.getSuperclass(); - } - - return false; - } - - private Field getField(Class theClass, String fieldName) - { - try - { - return theClass.getDeclaredField(fieldName); - } - catch(Exception e) - { - return null; - } - } -} \ No newline at end of file diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/JsonSerializable.java b/core/src/main/java/com/boydti/fawe/object/serializer/JsonSerializable.java deleted file mode 100644 index da44aa27..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/JsonSerializable.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonSerializer; - -public abstract class JsonSerializable implements JsonSerializer, JsonDeserializer { - - public JsonSerializable() { - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/LocalSessionSerializer.java b/core/src/main/java/com/boydti/fawe/object/serializer/LocalSessionSerializer.java deleted file mode 100644 index 9e4022dc..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/LocalSessionSerializer.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.entity.Player; -import java.lang.reflect.Type; - -public class LocalSessionSerializer extends JsonSerializable { - private final Player player; - - public LocalSessionSerializer(Player player) { - this.player = player; - } - - @Override - public LocalSession deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return WorldEdit.getInstance().getSessionManager().get(player); - } - - @Override - public JsonElement serialize(LocalSession src, Type typeOfSrc, JsonSerializationContext context) { - return null; - } -} diff --git a/core/src/main/java/com/boydti/fawe/object/serializer/PlayerSerializer.java b/core/src/main/java/com/boydti/fawe/object/serializer/PlayerSerializer.java deleted file mode 100644 index 177a4a14..00000000 --- a/core/src/main/java/com/boydti/fawe/object/serializer/PlayerSerializer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.boydti.fawe.object.serializer; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonElement; -import com.google.gson.JsonParseException; -import com.google.gson.JsonSerializationContext; -import com.sk89q.worldedit.entity.Player; -import java.lang.reflect.Type; - -public class PlayerSerializer extends JsonSerializable { - private final Player player; - - public PlayerSerializer(Player player) { - this.player = player; - } - @Override - public Player deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return player; - } - - @Override - public JsonElement serialize(Player src, Type typeOfSrc, JsonSerializationContext context) { - return null; - } -} diff --git a/core/src/main/java/com/boydti/fawe/util/CachedTextureUtil.java b/core/src/main/java/com/boydti/fawe/util/CachedTextureUtil.java index 691924cf..36305c53 100644 --- a/core/src/main/java/com/boydti/fawe/util/CachedTextureUtil.java +++ b/core/src/main/java/com/boydti/fawe/util/CachedTextureUtil.java @@ -6,9 +6,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; public class CachedTextureUtil extends DelegateTextureUtil { private final TextureUtil parent; - private Int2ObjectOpenHashMap colorBlockMap; - private Int2ObjectOpenHashMap colorBiomeMap; - private Int2ObjectOpenHashMap colorLayerMap; + private transient Int2ObjectOpenHashMap colorBlockMap; + private transient Int2ObjectOpenHashMap colorBiomeMap; + private transient Int2ObjectOpenHashMap colorLayerMap; public CachedTextureUtil(TextureUtil parent) { super(parent); diff --git a/core/src/main/java/com/boydti/fawe/util/CleanTextureUtil.java b/core/src/main/java/com/boydti/fawe/util/CleanTextureUtil.java index d7aace57..0ccf7d85 100644 --- a/core/src/main/java/com/boydti/fawe/util/CleanTextureUtil.java +++ b/core/src/main/java/com/boydti/fawe/util/CleanTextureUtil.java @@ -10,7 +10,7 @@ public class CleanTextureUtil extends TextureUtil { long min = parent.distances[minIndex]; long max = parent.distances[maxIndex]; for (; minIndex > 0 && parent.distances[minIndex - 1] == min; minIndex--); - for (; maxIndex < parent.distances.length - 2 && parent.distances[maxIndex + 1] == max; maxIndex++); + for (; maxIndex < parent.distances.length - 1 && parent.distances[maxIndex + 1] == max; maxIndex++); int num = maxIndex - minIndex + 1; this.validBiomes = parent.validBiomes; this.blockColors = parent.blockColors; diff --git a/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java b/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java index f9ff1fbe..3da7bf05 100644 --- a/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java +++ b/core/src/main/java/com/boydti/fawe/util/DocumentationPrinter.java @@ -25,13 +25,14 @@ import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.minecraft.util.commands.NestedCommand; import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BrushCommands; +import com.sk89q.worldedit.command.BrushOptionsCommands; import com.sk89q.worldedit.command.ChunkCommands; import com.sk89q.worldedit.command.ClipboardCommands; -import com.sk89q.worldedit.command.GeneralCommands; import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.MaskCommands; import com.sk89q.worldedit.command.NavigationCommands; +import com.sk89q.worldedit.command.OptionsCommands; import com.sk89q.worldedit.command.PatternCommands; import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.SchematicCommands; @@ -41,7 +42,6 @@ import com.sk89q.worldedit.command.SnapshotCommands; import com.sk89q.worldedit.command.SnapshotUtilCommands; import com.sk89q.worldedit.command.SuperPickaxeCommands; import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolUtilCommands; import com.sk89q.worldedit.command.TransformCommands; import com.sk89q.worldedit.command.UtilityCommands; import com.sk89q.worldedit.command.WorldEditCommands; @@ -97,7 +97,6 @@ public final class DocumentationPrinter { stream.println(); StringBuilder builder = new StringBuilder(); writePermissionsWikiTable(stream, builder, "/we ", WorldEditCommands.class); - writePermissionsWikiTable(stream, builder, "/", GeneralCommands.class); writePermissionsWikiTable(stream, builder, "/", UtilityCommands.class); writePermissionsWikiTable(stream, builder, "/", RegionCommands.class); writePermissionsWikiTable(stream, builder, "/", SelectionCommands.class); @@ -106,16 +105,17 @@ public final class DocumentationPrinter { writePermissionsWikiTable(stream, builder, "/", ClipboardCommands.class); writePermissionsWikiTable(stream, builder, "/", GenerationCommands.class); writePermissionsWikiTable(stream, builder, "/", BiomeCommands.class); - writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class); - writePermissionsWikiTable(stream, builder, "/", ToolUtilCommands.class); - writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class); writePermissionsWikiTable(stream, builder, "/anvil ", AnvilCommands.class); writePermissionsWikiTable(stream, builder, "/sp ", SuperPickaxeCommands.class); writePermissionsWikiTable(stream, builder, "/", NavigationCommands.class); - writePermissionsWikiTable(stream, builder, "/", SnapshotCommands.class); + writePermissionsWikiTable(stream, builder, "/snapshot", SnapshotCommands.class); writePermissionsWikiTable(stream, builder, "/", SnapshotUtilCommands.class); writePermissionsWikiTable(stream, builder, "/", ScriptingCommands.class); writePermissionsWikiTable(stream, builder, "/", ChunkCommands.class); + writePermissionsWikiTable(stream, builder, "/", OptionsCommands.class); + writePermissionsWikiTable(stream, builder, "/", BrushOptionsCommands.class); + writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class); + writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class); writePermissionsWikiTable(stream, builder, "/masks ", MaskCommands.class); writePermissionsWikiTable(stream, builder, "/patterns ", PatternCommands.class); writePermissionsWikiTable(stream, builder, "/transforms ", TransformCommands.class); diff --git a/core/src/main/java/com/boydti/fawe/util/StringMan.java b/core/src/main/java/com/boydti/fawe/util/StringMan.java index a72e263e..d65070c7 100644 --- a/core/src/main/java/com/boydti/fawe/util/StringMan.java +++ b/core/src/main/java/com/boydti/fawe/util/StringMan.java @@ -41,6 +41,11 @@ public class StringMan { return -1; } + public static String toProperCase(String s) { + return s.substring(0, 1).toUpperCase() + + s.substring(1); + } + public static List split(String input, char delim) { List result = new ArrayList(); int start = 0; diff --git a/core/src/main/java/com/sk89q/worldedit/BlockWorldVector.java b/core/src/main/java/com/sk89q/worldedit/BlockWorldVector.java index 8ee7de66..af006a67 100644 --- a/core/src/main/java/com/sk89q/worldedit/BlockWorldVector.java +++ b/core/src/main/java/com/sk89q/worldedit/BlockWorldVector.java @@ -1,8 +1,3 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by Fernflower decompiler) -// - package com.sk89q.worldedit; /** @deprecated */ diff --git a/core/src/main/java/com/sk89q/worldedit/LocalSession.java b/core/src/main/java/com/sk89q/worldedit/LocalSession.java index e3edc8de..5bac19e9 100644 --- a/core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -31,7 +31,6 @@ import com.boydti.fawe.object.changeset.FaweChangeSet; import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.TaskManager; import com.boydti.fawe.wrappers.WorldWrapper; import com.sk89q.jchronic.Chronic; import com.sk89q.jchronic.Options; @@ -984,10 +983,12 @@ public class LocalSession { return getBrushTool(item, 0, null, true); } + @Deprecated public BrushTool getBrushTool(Player player) throws InvalidToolBindException { return getBrushTool(player, true); } + @Deprecated public BrushTool getBrushTool(Player player, boolean create) throws InvalidToolBindException { BaseBlock block; try { @@ -1000,12 +1001,13 @@ public class LocalSession { } + @Deprecated public BrushTool getBrushTool(int id, int data, Player player, boolean create) throws InvalidToolBindException { Tool tool = getTool(id, data); if ((tool == null || !(tool instanceof BrushTool))) { if (create) { - tool = new BrushTool("worldedit.brush.sphere"); + tool = new BrushTool(); setTool(id, data, tool, player); } else { return null; diff --git a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java index 2949e3a7..c34915e7 100644 --- a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java +++ b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector.java @@ -1,6 +1,11 @@ package com.sk89q.worldedit; -public class MutableBlockVector extends BlockVector { +import java.io.IOException; +import java.io.Serializable; + +public class MutableBlockVector extends BlockVector implements Serializable { + private transient int x,y,z; + private static ThreadLocal MUTABLE_CACHE = new ThreadLocal() { @Override protected MutableBlockVector initialValue() { @@ -12,8 +17,6 @@ public class MutableBlockVector extends BlockVector { return MUTABLE_CACHE.get().setComponents(x, y, z); } - private int x,y,z; - public MutableBlockVector(Vector v) { this(v.getBlockX(), v.getBlockY(), v.getBlockZ()); } @@ -105,4 +108,16 @@ public class MutableBlockVector extends BlockVector { public int getBlockZ() { return this.z; } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.writeInt(x); + stream.writeByte((byte) y); + stream.writeInt(z); + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + this.x = stream.readInt(); + this.y = stream.readByte() & 0xFF; + this.z = stream.readInt(); + } } diff --git a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector2D.java b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector2D.java index 02fd774d..ff41f82d 100644 --- a/core/src/main/java/com/sk89q/worldedit/MutableBlockVector2D.java +++ b/core/src/main/java/com/sk89q/worldedit/MutableBlockVector2D.java @@ -1,6 +1,9 @@ package com.sk89q.worldedit; -public final class MutableBlockVector2D extends Vector2D { +import java.io.IOException; +import java.io.Serializable; + +public final class MutableBlockVector2D extends Vector2D implements Serializable { private static ThreadLocal MUTABLE_CACHE = new ThreadLocal() { @Override protected MutableBlockVector2D initialValue() { @@ -12,7 +15,7 @@ public final class MutableBlockVector2D extends Vector2D { return MUTABLE_CACHE.get().setComponents(x, z); } - private int x, z; + private transient int x, z; public MutableBlockVector2D() { this.x = 0; @@ -64,4 +67,14 @@ public final class MutableBlockVector2D extends Vector2D { public void mutZ(double z) { this.z = (int) z; } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.writeInt(x); + stream.writeInt(z); + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + this.x = stream.readInt(); + this.z = stream.readInt(); + } } diff --git a/core/src/main/java/com/sk89q/worldedit/Vector.java b/core/src/main/java/com/sk89q/worldedit/Vector.java index 1e60b5c2..2c915832 100644 --- a/core/src/main/java/com/sk89q/worldedit/Vector.java +++ b/core/src/main/java/com/sk89q/worldedit/Vector.java @@ -21,12 +21,14 @@ package com.sk89q.worldedit; import com.sk89q.worldedit.math.transform.AffineTransform; +import java.io.IOException; +import java.io.Serializable; import javax.annotation.Nullable; /** * An immutable 3-dimensional vector. */ -public class Vector implements Comparable { +public class Vector implements Comparable, Serializable { public static final Vector ZERO = new Vector(0, 0, 0); public static final Vector UNIT_X = new Vector(1, 0, 0); @@ -34,9 +36,7 @@ public class Vector implements Comparable { public static final Vector UNIT_Z = new Vector(0, 0, 1); public static final Vector ONE = new Vector(1, 1, 1); - private double x; - private double y; - private double z; + private transient double x, y, z; /** * Construct an instance. @@ -888,6 +888,21 @@ public class Vector implements Comparable { ); } + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + if (!(this instanceof Vector)) { + stream.writeDouble(x); + stream.writeDouble(y); + stream.writeDouble(z); + } + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + if (this instanceof MutableBlockVector) return; + this.x = stream.readDouble(); + this.y = stream.readDouble(); + this.z = stream.readDouble(); + } + public static Class inject() { return Vector.class; } diff --git a/core/src/main/java/com/sk89q/worldedit/Vector2D.java b/core/src/main/java/com/sk89q/worldedit/Vector2D.java index 41edf9c9..4270ace7 100644 --- a/core/src/main/java/com/sk89q/worldedit/Vector2D.java +++ b/core/src/main/java/com/sk89q/worldedit/Vector2D.java @@ -20,18 +20,19 @@ package com.sk89q.worldedit; import com.sk89q.worldedit.math.transform.AffineTransform; +import java.io.IOException; +import java.io.Serializable; /** * An immutable 2-dimensional vector. */ -public class Vector2D { +public class Vector2D implements Serializable { public static final Vector2D ZERO = new Vector2D(0, 0); public static final Vector2D UNIT_X = new Vector2D(1, 0); public static final Vector2D UNIT_Z = new Vector2D(0, 1); public static final Vector2D ONE = new Vector2D(1, 1); - public double x; - public double z; + public transient double x, z; /** * Construct an instance. @@ -665,6 +666,18 @@ public class Vector2D { ); } + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + if (this instanceof MutableBlockVector2D) return; + stream.writeDouble(x); + stream.writeDouble(z); + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + if (this instanceof MutableBlockVector2D) return; + this.x = stream.readDouble(); + this.z = stream.readDouble(); + } + public static Class inject() { return Vector2D.class; } diff --git a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java index bf3fb1b5..0aeaea21 100644 --- a/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java +++ b/core/src/main/java/com/sk89q/worldedit/blocks/BaseBlock.java @@ -21,6 +21,8 @@ package com.sk89q.worldedit.blocks; import com.boydti.fawe.FaweCache; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.jnbt.NBTInputStream; +import com.sk89q.jnbt.NBTOutputStream; import com.sk89q.jnbt.StringTag; import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.CuboidClipboard.FlipDirection; @@ -31,9 +33,11 @@ import com.sk89q.worldedit.foundation.Block; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.world.registry.WorldData; - -import javax.annotation.Nullable; +import java.io.DataInputStream; +import java.io.IOException; +import java.io.Serializable; import java.util.Collection; +import javax.annotation.Nullable; /** * Represents a mutable "snapshot" of a block. @@ -59,7 +63,7 @@ import java.util.Collection; * more appropriate.

*/ @SuppressWarnings("deprecation") -public class BaseBlock extends Block implements TileEntityBlock, Pattern { +public class BaseBlock extends Block implements TileEntityBlock, Pattern, Serializable { /** * Indicates the highest possible block ID (inclusive) that can be used. @@ -79,10 +83,10 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern { // 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; + private transient short id; + private transient short data; @Nullable - private CompoundTag nbtData; + private transient CompoundTag nbtData; /** * Construct a block with the given ID and a data value of 0. @@ -170,6 +174,11 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern { internalSetId(id); } + public void setCombined(int combined) { + setId(FaweCache.getId(combined)); + setData(FaweCache.getData(combined)); + } + /** * Get the block's data value. * @@ -442,6 +451,21 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern { return extent.setBlock(setPosition, this); } + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.writeChar(getCombined()); + stream.writeBoolean(nbtData != null); + if (nbtData != null) { + new NBTOutputStream(stream).writeTag(nbtData); + } + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + setCombined(stream.readChar()); + if (stream.readBoolean()) { + this.nbtData = (CompoundTag) new NBTInputStream(new DataInputStream(stream)).readTag(); + } + } + public static Class inject() { return BaseBlock.class; } diff --git a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java index fa3ac031..c9936ef2 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java @@ -63,7 +63,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION; /** * Implements biome-related commands such as "/biomelist". */ -@Command(aliases = "/biome", desc = "Change, list and inspect biomes") +@Command(aliases = {}, desc = "Change, list and inspect biomes") public class BiomeCommands { private final WorldEdit worldEdit; 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 a14e11ed..8b6ac558 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java @@ -26,6 +26,7 @@ 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.BrushSettings; import com.boydti.fawe.object.brush.CircleBrush; import com.boydti.fawe.object.brush.CommandBrush; import com.boydti.fawe.object.brush.CopyPastaBrush; @@ -50,6 +51,7 @@ import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; import com.boydti.fawe.object.mask.IdMask; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; +import com.sk89q.minecraft.util.commands.CommandLocals; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EmptyClipboardException; @@ -60,7 +62,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.blocks.BlockID; -import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.command.tool.InvalidToolBindException; import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.command.tool.brush.ButcherBrush; import com.sk89q.worldedit.command.tool.brush.ClipboardBrush; @@ -99,7 +101,7 @@ import javafx.scene.paint.Color; /** * Commands to set brush shape. */ -@Command(aliases = { "brush", "br" }, +@Command(aliases = { "brush", "br", "/b" }, desc = "Commands to build and draw from far away. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Brushes)" ) public class BrushCommands extends MethodCommands { @@ -108,6 +110,20 @@ public class BrushCommands extends MethodCommands { super(worldEdit); } + private BrushSettings get(CommandContext context) throws InvalidToolBindException { + BrushSettings bs = new BrushSettings(); + bs.addPermissions(getPermissions()); + CommandLocals locals = context.getLocals(); + if (locals != null) { + String args = (String) locals.get("arguments"); + if (args != null) { + bs.addSetting(BrushSettings.SettingType.BRUSH, args.substring(args.indexOf(' ') + 1)); + } + } + return bs; + } + + @Command( aliases = { "blendball", "bb", "blend" }, usage = "[radius=5]", @@ -118,12 +134,9 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.blendball") - public void blendBallBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { + public BrushSettings blendBallBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new BlendBall(), "worldedit.brush.blendball", player); - player.print(BBC.getPrefix() + BBC.BRUSH_BLEND_BALL.f(radius)); + return get(context).setBrush(new BlendBall()).setSize(radius); } @Command( @@ -135,12 +148,9 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.erode") - public void erodeBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { + public BrushSettings erodeBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new ErodeBrush(), "worldedit.brush.erode", player); - player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius)); + return get(context).setBrush(new ErodeBrush()).setSize(radius); } @Command( @@ -152,12 +162,9 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.pull") - public void pullBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException { + public BrushSettings pullBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new RaiseBrush(), "worldedit.brush.pull", player); - player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius)); + return get(context).setBrush(new RaiseBrush()).setSize(radius); } @Command( @@ -170,13 +177,9 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.sphere") - public void circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius) throws WorldEditException { + public BrushSettings circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setFill(fill); - tool.setBrush(new CircleBrush(player), "worldedit.brush.circle", player); - player.print(BBC.getPrefix() + BBC.BRUSH_CIRCLE.f(radius)); + return get(context).setBrush(new CircleBrush(player)).setSize(radius).setFill(fill); } @Command( @@ -190,14 +193,13 @@ public class BrushCommands extends MethodCommands { max = 3 ) @CommandPermissions("worldedit.brush.recursive") - public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst) throws WorldEditException { + public BrushSettings recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new RecurseBrush(depthFirst), "worldedit.brush.recursive", player); - tool.setMask(new IdMask(editSession)); - tool.setFill(fill); - player.print(BBC.getPrefix() + BBC.BRUSH_RECURSIVE.f(radius)); + return get(context) + .setBrush(new RecurseBrush(depthFirst)) + .setSize(radius) + .setFill(fill) + .setMask(new IdMask(editSession)); } @Command( @@ -214,13 +216,12 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.line") - public void lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat) throws WorldEditException { + public BrushSettings lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line", player); - player.print(BBC.getPrefix() + BBC.BRUSH_LINE.f(radius)); + return get(context) + .setBrush(new LineBrush(shell, select, flat)) + .setSize(radius) + .setFill(fill); } @Command( @@ -235,13 +236,13 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.spline") - public void splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius) throws WorldEditException { + public BrushSettings splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setBrush(new SplineBrush(player, session), "worldedit.brush.spline", player); player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); + return get(context) + .setBrush(new SplineBrush(player, session)) + .setSize(radius) + .setFill(fill); } // final double tension, final double bias, final double continuity, final double quality @@ -256,13 +257,12 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.surfacespline") // 0, 0, 0, 10, 0, - public void surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality) throws WorldEditException { - worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setBrush(new SurfaceSpline(tension, bias, continuity, quality), "worldedit.brush.spline", player); + public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException { player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius)); + worldEdit.checkMaxBrushRadius(radius);return get(context) + .setBrush(new SurfaceSpline(tension, bias, continuity, quality)) + .setSize(radius) + .setFill(fill); } @Command( @@ -277,30 +277,28 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.sphere") - public void sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException { + public BrushSettings sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - + Brush brush; if (hollow) { - tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere", player); + brush = new HollowSphereBrush(); } else { - tool.setBrush(new SphereBrush(), "worldedit.brush.sphere", player); + brush = new SphereBrush(); } if (fill instanceof BlockPattern) { BaseBlock block = ((BlockPattern) fill).getBlock(); switch (block.getId()) { case BlockID.SAND: case BlockID.GRAVEL: - player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius)); BBC.BRUSH_TRY_OTHER.send(player); - return; + break; } } - player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius)); - if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) BBC.TIP_BRUSH_COMMAND.or(BBC.TIP_BRUSH_RELATIVE, BBC.TIP_BRUSH_TRANSFORM, BBC.TIP_BRUSH_MASK_SOURCE, BBC.TIP_BRUSH_MASK, BBC.TIP_BRUSH_COPY, BBC.TIP_BRUSH_HEIGHT, BBC.TIP_BRUSH_SPLINE).send(player); + return get(context) + .setBrush(brush) + .setSize(radius) + .setFill(fill); } @Command( @@ -314,15 +312,13 @@ public class BrushCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.shatter") - public void shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count) throws WorldEditException { + public BrushSettings shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setMask(new ExistingBlockMask(editSession)); - tool.setBrush(new ShatterBrush(count), "worldedit.brush.shatter"); - player.print(BBC.getPrefix() + BBC.BRUSH_SHATTER.f(radius, count)); + return get(context) + .setBrush(new ShatterBrush(count)) + .setSize(radius) + .setFill(fill) + .setMask(new ExistingBlockMask(editSession)); } @Command( @@ -337,23 +333,22 @@ public class BrushCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.stencil") - public void stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate) throws WorldEditException { + public BrushSettings stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); InputStream stream = getHeightmapStream(filename); - tool.setFill(fill); - tool.setSize(radius); HeightBrush brush; try { brush = new StencilBrush(stream, rotation, yscale, onlyWhite, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null); } catch (EmptyClipboardException ignore) { brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null); } - tool.setBrush(brush, "worldedit.brush.height", player); if (randomRotate) { brush.setRandomRotate(true); } - player.print(BBC.getPrefix() + BBC.BRUSH_STENCIL.f(radius)); + return get(context) + .setBrush(brush) + .setSize(radius) + .setFill(fill); } @Command( @@ -368,13 +363,9 @@ public class BrushCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.surface") - public void surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius) throws WorldEditException { + public BrushSettings surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setBrush(new SurfaceSphereBrush(), "worldedit.brush.surface"); - player.print(BBC.getPrefix() + BBC.BRUSH_SURFACE.f(radius)); + return get(context).setBrush(new SurfaceSphereBrush()).setFill(fill).setSize(radius); } @Command( @@ -390,19 +381,18 @@ public class BrushCommands extends MethodCommands { max = 4 ) @CommandPermissions("worldedit.brush.scatter") - public void scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay) throws WorldEditException { + public BrushSettings scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); Brush brush; if (overlay) { brush = new ScatterOverlayBrush((int) points, (int) distance); } else { brush = new ScatterBrush((int) points, (int) distance); } - tool.setBrush(brush, "worldedit.brush.scatter", player); - player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points)); + return get(context) + .setBrush(brush) + .setSize(radius) + .setFill(fill); } @Command( @@ -417,18 +407,18 @@ public class BrushCommands extends MethodCommands { max = 4 ) @CommandPermissions("worldedit.brush.populateschematic") - public void scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") double radius, @Optional("50") double density, @Switch('r') boolean rotate) throws WorldEditException { + public BrushSettings scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") double radius, @Optional("50") double density, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); + + try { ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), clipboard, true); if (clipboards == null) { - return; + return null; } - Brush brush = new PopulateSchem(mask, clipboards, (int) density, rotate); - tool.setBrush(brush, "worldedit.brush.populateschematic", player); - player.print(BBC.getPrefix() + BBC.BRUSH_POPULATE.f(radius, density)); + return get(context) + .setBrush(new PopulateSchem(mask, clipboards, (int) density, rotate)) + .setSize(radius); } catch (IOException e) { throw new RuntimeException(e); } @@ -445,10 +435,8 @@ public class BrushCommands extends MethodCommands { max = 999 ) @CommandPermissions("worldedit.brush.layer") - public void surfaceLayer(Player player, EditSession editSession, LocalSession session, double radius, CommandContext args) throws WorldEditException, InvalidUsageException { + public BrushSettings surfaceLayer(Player player, EditSession editSession, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException, InvalidUsageException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); ParserContext parserContext = new ParserContext(); parserContext.setActor(player); parserContext.setWorld(player.getWorld()); @@ -471,8 +459,9 @@ public class BrushCommands extends MethodCommands { blocks.add(worldEdit.getBlockFactory().parseFromInput(arg, parserContext)); } } - tool.setBrush(new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()])), "worldedit.brush.layer", player); - player.print(BBC.getPrefix() + BBC.BRUSH_LAYER.f(radius, args.getJoinedStrings(1))); + return get(context) + .setBrush(new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()]))) + .setSize(radius); } @Command( @@ -487,13 +476,12 @@ public class BrushCommands extends MethodCommands { max = 5 ) @CommandPermissions("worldedit.brush.splatter") - public void splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid) throws WorldEditException { + public BrushSettings splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); - tool.setBrush(new SplatterBrush((int) points, (int) recursion, solid), "worldedit.brush.splatter", player); - player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points)); + return get(context) + .setBrush(new SplatterBrush((int) points, (int) recursion, solid)) + .setSize(radius) + .setFill(fill); } @Command( @@ -509,12 +497,11 @@ public class BrushCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.scattercommand") - public void scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args) throws WorldEditException { + public BrushSettings scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3)), "worldedit.brush.scattercommand", player); - player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points)); + return get(context) + .setBrush(new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3))) + .setSize(radius); } @Command( @@ -529,21 +516,20 @@ public class BrushCommands extends MethodCommands { max = 3 ) @CommandPermissions("worldedit.brush.cylinder") - public void cylinderBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, - @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException { + public BrushSettings cylinderBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, + @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); worldEdit.checkMaxBrushRadius(height); - - BrushTool tool = session.getBrushTool(player); - tool.setFill(fill); - tool.setSize(radius); + BrushSettings settings = get(context); if (hollow) { - tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder", player); + settings.setBrush(new HollowCylinderBrush(height)); } else { - tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder", player); + settings.setBrush(new CylinderBrush(height)); } - player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius, height)); + settings.setSize(radius) + .setFill(fill); + return settings; } @Command( @@ -558,7 +544,7 @@ public class BrushCommands extends MethodCommands { "stood relative to the copied area when you copied it." ) @CommandPermissions("worldedit.brush.clipboard") - public void clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin) throws WorldEditException { + public BrushSettings clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin, CommandContext context) throws WorldEditException { ClipboardHolder holder = session.getClipboard(); Clipboard clipboard = holder.getClipboard(); @@ -567,10 +553,7 @@ public class BrushCommands extends MethodCommands { worldEdit.checkMaxBrushRadius(size.getBlockX()); worldEdit.checkMaxBrushRadius(size.getBlockY()); worldEdit.checkMaxBrushRadius(size.getBlockZ()); - - BrushTool tool = session.getBrushTool(player); - tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard", player); - player.print(BBC.getPrefix() + BBC.BRUSH_CLIPBOARD.s()); + return get(context).setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin)); } @Command( @@ -585,20 +568,19 @@ public class BrushCommands extends MethodCommands { max = 2 ) @CommandPermissions("worldedit.brush.smooth") - public void smoothBrush(Player player, LocalSession session, EditSession editSession, + public BrushSettings smoothBrush(Player player, LocalSession session, EditSession editSession, @Optional("2") double radius, @Optional("4") int iterations, @Switch('n') - boolean naturalBlocksOnly) throws WorldEditException { + boolean naturalBlocksOnly, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); FawePlayer fp = FawePlayer.wrap(player); FaweLimit limit = Settings.IMP.getLimit(fp); iterations = Math.min(limit.MAX_ITERATIONS, iterations); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - 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"))); + return get(context) + .setBrush(new SmoothBrush(iterations, naturalBlocksOnly)) + .setSize(radius); } @Command( @@ -609,17 +591,15 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.ex") - public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException { + public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(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", player); - BBC.BRUSH_EXTINGUISHER.send(player, radius); - player.print(BBC.getPrefix() + BBC.BRUSH_EXTINGUISHER.f(radius)); + return get(context) + .setBrush(new SphereBrush()) + .setSize(radius) + .setFill(fill) + .setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE))); } @Command( @@ -635,13 +615,12 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.gravity") - public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException { + public BrushSettings gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity", player); - player.print(BBC.getPrefix() + BBC.BRUSH_GRAVITY.f(radius)); + return get(context) + .setBrush(new GravityBrush(fromMaxY)) + .setSize(radius); } @Command( @@ -660,8 +639,8 @@ public class BrushCommands extends MethodCommands { max = 4 ) @CommandPermissions("worldedit.brush.height") - public void heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException { - terrainBrush(player, session, radius, filename, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE); + public BrushSettings heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + return terrainBrush(player, session, radius, filename, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context); } @Command( @@ -678,8 +657,8 @@ public class BrushCommands extends MethodCommands { max = 4 ) @CommandPermissions("worldedit.brush.height") - public void cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException { - terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CYLINDER); + public BrushSettings cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + return terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CYLINDER, context); } @Command( @@ -695,8 +674,8 @@ public class BrushCommands extends MethodCommands { max = 4 ) @CommandPermissions("worldedit.brush.height") - public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException { - terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE); + public BrushSettings flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException { + return terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context); } private InputStream getHeightmapStream(String filename) { @@ -730,11 +709,9 @@ public class BrushCommands extends MethodCommands { return null; } - private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape) throws WorldEditException { + private BrushSettings terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); InputStream stream = getHeightmapStream(filename); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); HeightBrush brush; if (flat) { try { @@ -749,11 +726,12 @@ public class BrushCommands extends MethodCommands { brush = new HeightBrush(stream, rotation, yscale, layers, smooth, null); } } - tool.setBrush(brush, "worldedit.brush.height", player); if (randomRotate) { brush.setRandomRotate(true); } - player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius)); + return get(context) + .setBrush(brush) + .setSize(radius); } @@ -771,12 +749,12 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.copy") - public void copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate) throws WorldEditException { + public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException { worldEdit.checkMaxBrushRadius(radius); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new CopyPastaBrush(player, session, rotate), "worldedit.brush.copy", player); player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius)); + return get(context) + .setBrush(new CopyPastaBrush(player, session, rotate)) + .setSize(radius); } @Command( @@ -792,12 +770,11 @@ public class BrushCommands extends MethodCommands { max = 99 ) @CommandPermissions("worldedit.brush.command") - public void command(Player player, LocalSession session, double radius, CommandContext args) throws WorldEditException { - BrushTool tool = session.getBrushTool(player); + public BrushSettings command(Player player, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException { String cmd = args.getJoinedStrings(1); - tool.setBrush(new CommandBrush(cmd, radius), "worldedit.brush.copy", player); - tool.setSize(radius); - player.print(BBC.getPrefix() + BBC.BRUSH_COMMAND.f(cmd)); + return get(context) + .setBrush(new CommandBrush(cmd, radius)) + .setSize(radius); } @Command( @@ -820,7 +797,7 @@ public class BrushCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.butcher") - public void butcherBrush(Player player, LocalSession session, CommandContext args) throws WorldEditException { + public BrushSettings butcherBrush(Player player, LocalSession session, CommandContext args, CommandContext context) throws WorldEditException { LocalConfiguration config = worldEdit.getConfiguration(); double radius = args.argsLength() > 0 ? args.getDouble(0) : 5; @@ -833,16 +810,15 @@ public class BrushCommands extends MethodCommands { } if (radius > maxRadius && maxRadius != -1) { BBC.TOOL_RADIUS_ERROR.send(player, maxRadius); - return; + return null; } CreatureButcher flags = new CreatureButcher(player); flags.fromCommand(args); - BrushTool tool = session.getBrushTool(player); - tool.setSize(radius); - tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher", player); - player.print(BBC.getPrefix() + BBC.BRUSH_BUTCHER.f(radius)); + return get(context) + .setBrush(new ButcherBrush(flags)) + .setSize(radius); } public static Class inject() { diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java similarity index 57% rename from core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java rename to core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java index a4c780db..2d69356a 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java @@ -3,52 +3,150 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweAPI; import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.brush.BrushSettings; import com.boydti.fawe.object.brush.TargetMode; -import com.boydti.fawe.object.brush.scroll.ScrollClipboard; -import com.boydti.fawe.object.brush.scroll.ScrollMask; -import com.boydti.fawe.object.brush.scroll.ScrollPattern; -import com.boydti.fawe.object.brush.scroll.ScrollRange; -import com.boydti.fawe.object.brush.scroll.ScrollSize; -import com.boydti.fawe.object.brush.scroll.ScrollTarget; +import com.boydti.fawe.object.brush.scroll.ScrollAction; import com.boydti.fawe.object.brush.visualization.VisualMode; import com.boydti.fawe.object.extent.ResettableExtent; +import com.boydti.fawe.object.io.PGZIPOutputStream; +import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.command.tool.BrushTool; -import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.event.platform.CommandEvent; import com.sk89q.worldedit.extension.factory.DefaultMaskParser; import com.sk89q.worldedit.extension.factory.DefaultTransformParser; import com.sk89q.worldedit.extension.factory.HashTagPatternParser; import com.sk89q.worldedit.extension.input.ParserContext; +import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.CommandManager; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.util.command.binding.Switch; import com.sk89q.worldedit.util.command.parametric.Optional; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.nio.file.FileSystems; +import java.util.zip.GZIPInputStream; /** * Tool commands. */ @Command(aliases = {}, desc = "Tool commands") -public class ToolUtilCommands extends MethodCommands { +public class BrushOptionsCommands extends MethodCommands { - public ToolUtilCommands(WorldEdit we) { + public BrushOptionsCommands(WorldEdit we) { super(we); } + @Command( + aliases = { "/savebrush" }, + usage = "[name]", + desc = "Save your current brush", + min = 1 + ) + @CommandPermissions("worldedit.brush.save") + public void saveBrush(Player player, LocalSession session, String name) throws WorldEditException, IOException { + BrushTool tool = session.getBrushTool(player); + if (tool != null) { + name = FileSystems.getDefault().getPath(name).getFileName().toString(); + File folder = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes"); + name = name.endsWith(".jsgz") ? name : name + ".jsgz"; + File file = new File(folder, player.getUniqueId() + File.separator + name); + File parent = file.getParentFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + file.createNewFile(); + try (DataOutputStream out = new DataOutputStream(new PGZIPOutputStream(new FileOutputStream(file)))) { + out.writeUTF(tool.toString()); + } catch (Throwable e) { + e.printStackTrace(); + } + BBC.SCHEMATIC_SAVED.send(player, name); + } else { + BBC.BRUSH_NONE.send(player); + } + } + + @Command( + aliases = { "/loadbrush" }, + desc = "load a brush", + usage = "[name]", + min = 1 + ) + @CommandPermissions("worldedit.brush.load") + public void loadBrush(Player player, LocalSession session, String name) throws WorldEditException, IOException { + name = FileSystems.getDefault().getPath(name).getFileName().toString(); + File folder = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes"); + name = name.endsWith(".jsgz") ? name : name + ".jsgz"; + File file = new File(folder, player.getUniqueId() + File.separator + name); + if (!file.exists()) { + file = new File(folder, name); + } + if (!file.exists()) { + File[] files = folder.listFiles(new FileFilter() { + @Override + public boolean accept(File pathname) { + return false; + } + }); + BBC.BRUSH_NOT_FOUND.send(player, name); + return; + } + try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(file)))) { + String json = in.readUTF(); + BrushTool tool = BrushTool.fromString(player, session, json); + BaseBlock item = player.getBlockInHand(); + session.setTool(item.getId(), item.getData(), tool, player); + BBC.BRUSH_EQUIPPED.send(player, name); + } catch (Throwable e) { + e.printStackTrace(); + BBC.BRUSH_INCOMPATIBLE.send(player); + } + } + + @Command( + aliases = {"/listbrush"}, + desc = "List saved brushes", + usage = "[mine|] [page=1]", + min = 0, + max = -1, + flags = "dnp", + help = "List all brushes in the brush directory\n" + + " -p prints the requested page\n" + ) + @CommandPermissions("worldedit.brush.list") + public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException { + File dir = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes"); + UtilityCommands.list(dir, actor, args, page, null, true); + } + + @Command( + aliases = { "none", "/none" }, + usage = "", + desc = "Unbind a bound tool from your current item", + min = 0, + max = 0 + ) + public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException { + session.setTool(null, player); + BBC.TOOL_NONE.send(player); + } + @Command( aliases = { "/", "," }, usage = "[on|off]", @@ -219,77 +317,22 @@ public class ToolUtilCommands extends MethodCommands { min = 1, max = -1 ) - public void scroll(Player player, EditSession editSession, LocalSession session, CommandContext args) throws WorldEditException { - BrushTool tool = session.getBrushTool(player, false); - if (tool == null) { + public void scroll(Player player, EditSession editSession, LocalSession session, @Optional @Switch('h') boolean offHand, CommandContext args) throws WorldEditException { + BrushTool bt = session.getBrushTool(player, false); + if (bt == null) { BBC.BRUSH_NONE.send(player); return; } - ParserContext parserContext = new ParserContext(); - parserContext.setActor(player); - parserContext.setWorld(player.getWorld()); - parserContext.setSession(session); - parserContext.setExtent(editSession); - final LocalConfiguration config = this.worldEdit.getConfiguration(); - switch (args.getString(0).toLowerCase()) { - case "none": - tool.setScrollAction(null); - break; - case "clipboard": - if (args.argsLength() != 2) { - BBC.COMMAND_SYNTAX.send(player, "clipboard [file]"); - return; - } - String filename = args.getString(1); - try { - ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, true); - if (clipboards == null) { - return; - } - tool.setScrollAction(new ScrollClipboard(tool, session, clipboards)); - break; - } catch (IOException e) { - throw new RuntimeException(e); - } - case "mask": - if (args.argsLength() < 2) { - BBC.COMMAND_SYNTAX.send(player, "mask [mask 1] [mask 2] [mask 3]..."); - return; - } - Mask[] masks = new Mask[args.argsLength() - 1]; - for (int i = 1; i < args.argsLength(); i++) { - String arg = args.getString(i); - masks[i - 1] = worldEdit.getMaskFactory().parseFromInput(arg, parserContext); - } - tool.setScrollAction(new ScrollMask(tool, masks)); - break; - case "pattern": - if (args.argsLength() < 2) { - BBC.COMMAND_SYNTAX.send(player, "pattern [pattern 1] [pattern 2] [pattern 3]..."); - return; - } - Pattern[] patterns = new Pattern[args.argsLength() - 1]; - for (int i = 1; i < args.argsLength(); i++) { - String arg = args.getString(i); - patterns[i - 1] = worldEdit.getPatternFactory().parseFromInput(arg, parserContext); - } - tool.setScrollAction(new ScrollPattern(tool, patterns)); - break; - case "range": - tool.setScrollAction(new ScrollRange(tool)); - break; - case "size": - tool.setScrollAction(new ScrollSize(tool)); - break; - case "target": - tool.setScrollAction(new ScrollTarget(tool)); - break; - default: - BBC.COMMAND_SYNTAX.send(player, "[none|clipboard|mask|pattern|range|size|visual|target]"); - return; - + BrushSettings settings = offHand ? bt.getOffHand() : bt.getContext(); + ScrollAction action = ScrollAction.fromArguments(bt, player, session, args.getJoinedStrings(0), true); + settings.setScrollAction(action); + if (args.getString(0).equalsIgnoreCase("none")) { + BBC.BRUSH_SCROLL_ACTION_UNSET.send(player); + } else if (action != null) { + String full = args.getJoinedStrings(0); + settings.addSetting(BrushSettings.SettingType.SCROLL_ACTION, full); + BBC.BRUSH_SCROLL_ACTION_SET.send(player, full); } - BBC.BRUSH_SCROLL_ACTION_SET.send(player, args.getJoinedStrings(0)); } @Command( @@ -300,36 +343,27 @@ public class ToolUtilCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.options.mask") - public void mask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException { - Tool tool = session.getTool(player); + public void mask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException { + BrushTool tool = session.getBrushTool(player, false); if (tool == null) { player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); return; } - Mask mask; - if (context == null || context.argsLength() == 0) { - mask = null; - } else { - ParserContext parserContext = new ParserContext(); - parserContext.setActor(player); - parserContext.setWorld(player.getWorld()); - parserContext.setSession(session); - parserContext.setExtent(editSession); - mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); - } - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - if (offHand) { - bt.getSecondary().mask = mask; - } else { - ((BrushTool) tool).setMask(mask); - } - } - if (mask == null) { + if (context.argsLength() == 0) { BBC.BRUSH_MASK_DISABLED.send(player); - } else { - BBC.BRUSH_MASK.send(player); + tool.setMask(null); + return; } + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setWorld(player.getWorld()); + parserContext.setSession(session); + parserContext.setExtent(editSession); + Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); + BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); + settings.addSetting(BrushSettings.SettingType.MASK, context.getString(context.argsLength() - 1)); + settings.setMask(mask); + BBC.BRUSH_MASK.send(player); } @Command( @@ -341,36 +375,27 @@ public class ToolUtilCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.options.mask") - public void smask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException { - Tool tool = session.getTool(player); + public void smask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException { + BrushTool tool = session.getBrushTool(player, false); if (tool == null) { player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); return; } - Mask mask; - if (context == null || context.argsLength() == 0) { - mask = null; - } else { - ParserContext parserContext = new ParserContext(); - parserContext.setActor(player); - parserContext.setWorld(player.getWorld()); - parserContext.setSession(session); - parserContext.setExtent(editSession); - mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); - } - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - if (offHand) { - bt.getSecondary().sourceMask = mask; - } else { - ((BrushTool) tool).setSourceMask(mask); - } - } - if (mask == null) { + if (context.argsLength() == 0) { BBC.BRUSH_SOURCE_MASK_DISABLED.send(player); - } else { - BBC.BRUSH_SOURCE_MASK.send(player); + tool.setSourceMask(null); + return; } + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setWorld(player.getWorld()); + parserContext.setSession(session); + parserContext.setExtent(editSession); + Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext); + BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); + settings.addSetting(BrushSettings.SettingType.SOURCE_MASK, context.getString(context.argsLength() - 1)); + settings.setSourceMask(mask); + BBC.BRUSH_SOURCE_MASK.send(player); } @Command( @@ -381,35 +406,27 @@ public class ToolUtilCommands extends MethodCommands { max = -1 ) @CommandPermissions("worldedit.brush.options.transform") - public void transform(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException { - Tool tool = session.getTool(player); + public void transform(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException { + BrushTool tool = session.getBrushTool(player, false); if (tool == null) { + player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); return; } - ResettableExtent transform; - if (context == null || context.argsLength() == 0) { - transform = null; - } else { - ParserContext parserContext = new ParserContext(); - parserContext.setActor(player); - parserContext.setWorld(player.getWorld()); - parserContext.setSession(session); - parserContext.setExtent(editSession); - transform = Fawe.get().getTransformParser().parseFromInput(context.getJoinedStrings(0), parserContext); - } - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - if (offHand) { - bt.getSecondary().transform = transform; - } else { - ((BrushTool) tool).setTransform(transform); - } - } - if (transform == null) { + if (context.argsLength() == 0) { BBC.BRUSH_TRANSFORM_DISABLED.send(player); - } else { - BBC.BRUSH_TRANSFORM.send(player); + tool.setTransform(null); + return; } + ParserContext parserContext = new ParserContext(); + parserContext.setActor(player); + parserContext.setWorld(player.getWorld()); + parserContext.setSession(session); + parserContext.setExtent(editSession); + ResettableExtent transform = Fawe.get().getTransformParser().parseFromInput(context.getJoinedStrings(0), parserContext); + BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); + settings.addSetting(BrushSettings.SettingType.TRANSFORM, context.getString(context.argsLength() - 1)); + settings.setTransform(transform); + BBC.BRUSH_TRANSFORM.send(player); } @Command( @@ -420,16 +437,20 @@ public class ToolUtilCommands extends MethodCommands { max = 1 ) @CommandPermissions("worldedit.brush.options.material") - public void material(Player player, EditSession editSession, LocalSession session, Pattern pattern, @Switch('h') boolean offHand) throws WorldEditException { - Tool tool = session.getTool(player); - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - if (offHand) { - bt.getSecondary().material = pattern; - } else { - ((BrushTool) tool).setFill(pattern); - } + public void material(Player player, EditSession editSession, LocalSession session, Pattern pattern, @Switch('h') boolean offHand, CommandContext context) throws WorldEditException { + BrushTool tool = session.getBrushTool(player, false); + if (tool == null) { + player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); + return; } + if (context.argsLength() == 0) { + BBC.BRUSH_TRANSFORM_DISABLED.send(player); + tool.setFill(null); + return; + } + BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); + settings.setFill(pattern); + settings.addSetting(BrushSettings.SettingType.FILL, context.getString(context.argsLength() - 1)); BBC.BRUSH_MATERIAL.send(player); } @@ -443,11 +464,12 @@ public class ToolUtilCommands extends MethodCommands { @CommandPermissions("worldedit.brush.options.range") public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException { int range = Math.max(0, Math.min(256, args.getInteger(0))); - Tool tool = session.getTool(player); - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - ((BrushTool) tool).setRange(range); + BrushTool tool = session.getBrushTool(player, false); + if (tool == null) { + player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); + return; } + tool.setRange(range); BBC.BRUSH_RANGE.send(player); } @@ -460,23 +482,19 @@ public class ToolUtilCommands extends MethodCommands { ) @CommandPermissions("worldedit.brush.options.size") public void size(Player player, LocalSession session, CommandContext args, @Switch('h') boolean offHand) throws WorldEditException { - int radius = args.getInteger(0); worldEdit.checkMaxBrushRadius(radius); - - Tool tool = session.getTool(player); - if (tool instanceof BrushTool) { - BrushTool bt = (BrushTool) tool; - if (offHand) { - bt.getSecondary().size = radius; - } else { - ((BrushTool) tool).setSize(radius); - } + BrushTool tool = session.getBrushTool(player, false); + if (tool == null) { + player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f()); + return; } + BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext(); + settings.setSize(radius); BBC.BRUSH_SIZE.send(player); } public static Class inject() { - return ToolUtilCommands.class; + return BrushOptionsCommands.class; } } \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java b/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java new file mode 100644 index 00000000..24702ce5 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java @@ -0,0 +1,32 @@ +package com.sk89q.worldedit.command; + +import com.boydti.fawe.config.BBC; +import com.boydti.fawe.object.brush.BrushSettings; +import com.plotsquared.general.commands.Command; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.worldedit.LocalSession; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.command.tool.BrushTool; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.platform.Actor; +import com.sk89q.worldedit.util.command.CallableProcessor; + +public class BrushProcessor implements CallableProcessor { + private final WorldEdit worldEdit; + + public BrushProcessor(WorldEdit worldEdit) { + this.worldEdit = worldEdit; + } + + @Override + public BrushSettings process(CommandLocals locals, BrushSettings settings) throws Command.CommandException, WorldEditException { + Actor actor = locals.get(Actor.class); + LocalSession session = worldEdit.getSessionManager().get(actor); + BrushTool tool = session.getBrushTool((Player) actor); + tool.setPrimary(settings); + tool.setSecondary(settings); + BBC.BRUSH_EQUIPPED.send(actor, ((String) locals.get("arguments")).split(" ")[1]); + return null; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java index 57f7c781..2457a79c 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java @@ -114,7 +114,7 @@ public class GenerationCommands { } @Command( - aliases = { "/image" }, + aliases = { "/image", "/img" }, desc = "Generate an image", usage = " [randomize=true] [complexity=100]", min = 1, diff --git a/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java b/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java index ee08a2c9..1976e2ce 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java @@ -2,6 +2,9 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.config.Commands; import com.sk89q.minecraft.util.commands.Command; +import com.sk89q.minecraft.util.commands.CommandContext; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.Dispatcher; @@ -67,4 +70,30 @@ public class MethodCommands { } return null; } -} + + public String getArguments(CommandContext context) { + CommandLocals locals = context.getLocals(); + if (locals != null) { + return (String) locals.get("arguments"); + } + return null; + } + + public String[] getPermissions() { + try { + StackTraceElement[] stack = new Exception().getStackTrace(); + for (StackTraceElement elem : stack) { + Class clazz = Class.forName(elem.getClassName()); + for (Method method : clazz.getMethods()) { + if (method.getName().equals(elem.getMethodName())) { + CommandPermissions perm = method.getAnnotation(CommandPermissions.class); + if (perm != null) return perm.value(); + } + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return new String[0]; + } +} \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java similarity index 97% rename from core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java rename to core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java index 4c2a897c..5665efdf 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java @@ -25,7 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull; * General WorldEdit commands. */ @Command(aliases = {}, desc = "Player toggles, settings and item info") -public class GeneralCommands { +public class OptionsCommands { private final WorldEdit worldEdit; @@ -34,7 +34,7 @@ public class GeneralCommands { * * @param worldEdit reference to WorldEdit */ - public GeneralCommands(WorldEdit worldEdit) { + public OptionsCommands(WorldEdit worldEdit) { checkNotNull(worldEdit); this.worldEdit = worldEdit; } @@ -117,7 +117,7 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.global-mask") public void gsmask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException { - if (context == null || context.argsLength() == 0) { + if (context.argsLength() == 0) { session.setSourceMask((Mask) null); BBC.SOURCE_MASK_DISABLED.send(player); } else { @@ -141,7 +141,7 @@ public class GeneralCommands { ) @CommandPermissions("worldedit.global-trasnform") public void gtransform(Player player, EditSession editSession, LocalSession session, @Optional CommandContext context) throws WorldEditException { - if (context == null || context.argsLength() == 0) { + if (context.argsLength() == 0) { session.setTransform(null); BBC.TRANSFORM_DISABLED.send(player); } else { @@ -253,6 +253,6 @@ public class GeneralCommands { } public static Class inject() { - return GeneralCommands.class; + return OptionsCommands.class; } } \ No newline at end of file diff --git a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java index c5d75821..a3990b07 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java @@ -119,7 +119,7 @@ public class PatternCommands extends MethodCommands { ) public Pattern anglecolor(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); - return new AngleColorPattern(util, editSession); + return new AngleColorPattern(editSession, (int) maxComplexity, randomize); } @Command( @@ -141,7 +141,7 @@ public class PatternCommands extends MethodCommands { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); Color color = Color.web(arg); java.awt.Color awtColor = new java.awt.Color((float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), (float) color.getOpacity()); - return new SaturatePattern(editSession, util, awtColor.getRGB()); + return new SaturatePattern(editSession, awtColor.getRGB(), (int) maxComplexity, randomize); } @Command( @@ -155,7 +155,7 @@ public class PatternCommands extends MethodCommands { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); Color color = Color.web(arg); java.awt.Color awtColor = new java.awt.Color((float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), (float) color.getOpacity()); - return new AverageColorPattern(editSession, util, awtColor.getRGB()); + return new AverageColorPattern(editSession, awtColor.getRGB(), (int) maxComplexity, randomize); } @Command( @@ -167,7 +167,7 @@ public class PatternCommands extends MethodCommands { ) public Pattern desaturate(EditSession editSession, @Optional("100") double percent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); - return new DesaturatePattern(editSession, util, percent / 100d); + return new DesaturatePattern(editSession, percent / 100d, (int) maxComplexity, randomize); } @Command( @@ -179,7 +179,7 @@ public class PatternCommands extends MethodCommands { ) public Pattern lighten(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); - return new ShadePattern(editSession, util, false); + return new ShadePattern(editSession, false, (int) maxComplexity, randomize); } @Command( @@ -191,7 +191,7 @@ public class PatternCommands extends MethodCommands { ) public Pattern darken(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) { TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity); - return new ShadePattern(editSession, util, true); + return new ShadePattern(editSession, true, (int) maxComplexity, randomize); } @Command( @@ -371,8 +371,8 @@ public class PatternCommands extends MethodCommands { min = 2, max = 2 ) - public Pattern surfacespread(Actor actor, LocalSession session, EditSession editSession, double distance, Pattern pattern) { - return new SurfaceRandomOffsetPattern(editSession, pattern, (int) distance); + public Pattern surfacespread(Actor actor, LocalSession session, double distance, Pattern pattern) { + return new SurfaceRandomOffsetPattern(pattern, (int) distance); } @Command( diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index 103109d9..0f3d5376 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -316,7 +316,7 @@ public class RegionCommands { } @Command( - aliases = { "/set" }, + aliases = { "/set", "/s" }, usage = "[pattern]", desc = "Set all blocks within selection", min = 1, diff --git a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java index 3bf47b19..aa5bb395 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java @@ -24,7 +24,6 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.clipboard.MultiClipboardHolder; import com.boydti.fawe.object.schematic.StructureFormat; import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; import com.sk89q.minecraft.util.commands.Command; import com.sk89q.minecraft.util.commands.CommandContext; import com.sk89q.minecraft.util.commands.CommandException; @@ -53,15 +52,10 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.net.URI; import java.net.URL; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; @@ -78,7 +72,7 @@ public class SchematicCommands { /** * 9 schematics per page fits in the MC chat window. */ - private static final int SCHEMATICS_PER_PAGE = 9; + private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName()); private final WorldEdit worldEdit; @@ -336,154 +330,13 @@ public class SchematicCommands { max = -1, flags = "dnp", help = "List all schematics in the schematics directory\n" + - " -d sorts by date, oldest first\n" + - " -n sorts by date, newest first\n" + - " -p prints the requested page\n" + " -p prints the requested page\n" + + " -f restricts by format\n" ) @CommandPermissions("worldedit.schematic.list") - public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException { + public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page, @Switch('f') String formatName) throws WorldEditException { File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir); - List fileList = new ArrayList<>(); - int len = args.argsLength(); - List filters = new ArrayList<>(); - boolean mine = false; - if (len > 0) { - int max = len; - if (MathMan.isInteger(args.getString(len - 1))) { - page = args.getInteger(--len); - } - for (int i = 0; i < len; i++) { - switch (args.getString(i).toLowerCase()) { - case "me": - case "mine": - mine = true; - break; - default: - filters.add(args.getString(i)); - break; - } - } - } - if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS) { - File playerDir = new File(dir, actor.getUniqueId().toString()); - if (playerDir.exists()) { - fileList.addAll(allFiles(playerDir, true)); - } - if (!mine) { - fileList.addAll(allFiles(dir, false)); - } - } else { - fileList.addAll(allFiles(dir, true)); - } - if (!filters.isEmpty()) { - for (String filter : filters) { - fileList.removeIf(file -> !file.getPath().contains(filter)); - } - } - if (fileList.isEmpty()) { - BBC.SCHEMATIC_NONE.send(actor); - return; - } - File[] files = new File[fileList.size()]; - fileList.toArray(files); - int pageCount = files.length / SCHEMATICS_PER_PAGE + 1; - if (page < 1) { - BBC.SCHEMATIC_PAGE.send(actor, ">0"); - return; - } - if (page > pageCount) { - BBC.SCHEMATIC_PAGE.send(actor, "<" + (pageCount + 1)); - return; - } - - final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; - // cleanup file list - Arrays.sort(files, new Comparator(){ - @Override - public int compare(File f1, File f2) { - int res; - if (sortType == 0) { // use name by default - int p = f1.getParent().compareTo(f2.getParent()); - if (p == 0) { // same parent, compare names - res = f1.getName().compareTo(f2.getName()); - } else { // different parent, sort by that - res = p; - } - } else { - res = Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag - if (sortType == 1) res = -res; // flip date for newest first instead of oldest first - } - return res; - } - }); - - List schematics = listFiles(files, worldEdit.getConfiguration().saveDir, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? actor.getUniqueId() : null); - int offset = (page - 1) * SCHEMATICS_PER_PAGE; - - BBC.SCHEMATIC_LIST.send(actor, page, pageCount); - StringBuilder build = new StringBuilder(); - int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size()); - for (int i = offset; i < limit;) { - build.append(schematics.get(i)); - if (++i != limit) { - build.append("\n"); - } - } - - actor.print(BBC.getPrefix() + build.toString()); - } - - - private List allFiles(File root, boolean recursive) { - File[] files = root.listFiles(); - if (files == null) return new ArrayList<>(); - List fileList = new ArrayList(); - for (File f : files) { - if (recursive && f.isDirectory()) { - List subFiles = allFiles(f, recursive); - if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir - fileList.addAll(subFiles); - } else { - fileList.add(f); - } - } - return fileList; - } - - private List listFiles(File[] files, String prefix, UUID uuid) { - if (prefix == null) prefix = ""; - File root = worldEdit.getWorkingDirectoryFile(prefix); - File dir; - if (uuid != null) { - dir = new File(root, uuid.toString()); - } else { - dir = root; - } - List result = new ArrayList(); - for (File file : files) { - StringBuilder build = new StringBuilder(); - - build.append("\u00a72"); - ClipboardFormat format = ClipboardFormat.findByFile(file); -// boolean inRoot = file.getParentFile().getName().equals(prefix); -// if (inRoot) { -// build.append(file.getName()); -// } else { -// String relative = dir.toURI().relativize(file.toURI()).getPath(); -// build.append(relative); -// } - URI relative = dir.toURI().relativize(file.toURI()); - String name = ""; - if (relative.isAbsolute()) { - relative = root.toURI().relativize(file.toURI()); - name += "../"; - } - name += relative.getPath(); - build.append(name); - build.append(": ").append(format == null ? "Unknown" : format.name()); - result.add(build.toString()); - } - return result; + UtilityCommands.list(dir, actor, args, page, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS); } public static Class inject() { diff --git a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java index b62775ed..4f579398 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java @@ -266,7 +266,7 @@ public class SelectionCommands { } @Command( - aliases = { "/wand" }, + aliases = { "/wand", "/w" }, usage = "", desc = "Get the wand object", min = 0, 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 349c82f3..4db08400 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java @@ -44,7 +44,7 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.util.TreeGenerator; import com.sk89q.worldedit.util.command.parametric.Optional; -@Command(aliases = {"tool"}, desc = "Bind functions to held items: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Tools)") +@Command(aliases = {"brush", "br", "/b", "tool"}, desc = "Bind functions to held items: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Tools)") public class ToolCommands { private final WorldEdit we; @@ -52,6 +52,19 @@ public class ToolCommands { this.we = we; } + @Command( + aliases = { "info", "/info" }, + usage = "", + desc = "Block information tool", + min = 0, + max = 0 + ) + @CommandPermissions("worldedit.tool.info") + public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException { + session.setTool(new QueryTool(), player); + BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand())); + } + @Command( aliases = { "inspect" }, usage = "", @@ -67,31 +80,6 @@ public class ToolCommands { BBC.TOOL_INSPECT.send(player, ItemType.toHeldName(player.getItemInHand())); } - @Command( - aliases = { "none" }, - usage = "", - desc = "Unbind a bound tool from your current item", - min = 0, - max = 0 - ) - public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(null, player); - BBC.TOOL_NONE.send(player); - } - - @Command( - aliases = { "info" }, - usage = "", - desc = "Block information tool", - min = 0, - max = 0 - ) - @CommandPermissions("worldedit.tool.info") - public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException { - session.setTool(new QueryTool(), player); - BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand())); - } - @Command( aliases = { "tree" }, usage = "[type]", diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index d339c7f8..c1987472 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -22,6 +22,7 @@ package com.sk89q.worldedit.command; import com.boydti.fawe.config.BBC; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FawePlayer; +import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.StringMan; import com.google.common.base.Joiner; import com.google.common.util.concurrent.AtomicDouble; @@ -46,6 +47,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.CommandManager; import com.sk89q.worldedit.extension.platform.Platform; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operations; @@ -60,6 +62,7 @@ import com.sk89q.worldedit.regions.CylinderRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandMapping; +import com.sk89q.worldedit.util.command.DelegateCallable; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.PrimaryAliasComparator; import com.sk89q.worldedit.util.command.binding.Text; @@ -68,18 +71,24 @@ import com.sk89q.worldedit.util.command.parametric.ParametricCallable; import com.sk89q.worldedit.util.formatting.ColorCodeBuilder; import com.sk89q.worldedit.util.formatting.component.CommandUsageBox; import com.sk89q.worldedit.world.World; +import java.io.File; +import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; +import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; @@ -89,7 +98,6 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT; */ @Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)") public class UtilityCommands extends MethodCommands { - public UtilityCommands(WorldEdit we) { super(we); } @@ -548,196 +556,363 @@ public class UtilityCommands extends MethodCommands { return null; } + public static void list(File dir, Actor actor, CommandContext args, int page, String formatName, boolean playerFolder) { + List fileList = new ArrayList<>(); + int len = args.argsLength(); + List filters = new ArrayList<>(); + boolean mine = false; + if (len > 0) { + int max = len; + if (MathMan.isInteger(args.getString(len - 1))) { + page = args.getInteger(--len); + } + for (int i = 0; i < len; i++) { + switch (args.getString(i).toLowerCase()) { + case "me": + case "mine": + mine = true; + break; + default: + filters.add(args.getString(i)); + break; + } + } + } + if (playerFolder) { + File playerDir = new File(dir, actor.getUniqueId().toString()); + if (playerDir.exists()) { + fileList.addAll(allFiles(playerDir, true)); + } + if (!mine) { + fileList.addAll(allFiles(dir, false)); + } + } else { + fileList.addAll(allFiles(dir, true)); + } + if (!filters.isEmpty()) { + for (String filter : filters) { + fileList.removeIf(file -> !file.getPath().contains(filter)); + } + } + if (fileList.isEmpty()) { + BBC.SCHEMATIC_NONE.send(actor); + return; + } + if (formatName != null) { + final ClipboardFormat cf = ClipboardFormat.findByAlias(formatName); + fileList = fileList.stream() + .filter(file -> cf.isFormat(file)) + .collect(Collectors.toList()); + + } + File[] files = new File[fileList.size()]; + fileList.toArray(files); + final int perPage = actor instanceof Player ? 8 : 20; // More pages for console + int pageCount = (files.length + perPage - 1) / perPage; + if (page < 1) { + BBC.SCHEMATIC_PAGE.send(actor, ">0"); + return; + } + if (page > pageCount) { + BBC.SCHEMATIC_PAGE.send(actor, "<" + (pageCount + 1)); + return; + } + + final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0; + // cleanup file list + Arrays.sort(files, new Comparator(){ + @Override + public int compare(File f1, File f2) { + int res; + if (sortType == 0) { // use name by default + int p = f1.getParent().compareTo(f2.getParent()); + if (p == 0) { // same parent, compare names + res = f1.getName().compareTo(f2.getName()); + } else { // different parent, sort by that + res = p; + } + } else { + res = Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag + if (sortType == 1) res = -res; // flip date for newest first instead of oldest first + } + return res; + } + }); + + List schematics = listFiles(dir, files, playerFolder ? actor.getUniqueId() : null); + int offset = (page - 1) * perPage; + + StringBuilder build = new StringBuilder(); + int limit = Math.min(offset + perPage, schematics.size()); + for (int i = offset; i < limit;) { + build.append(schematics.get(i)); + if (++i != limit) { + build.append("\n"); + } + } + String heading = BBC.SCHEMATIC_LIST.f(page, pageCount); + actor.print(BBC.getPrefix() + heading + "\n" + build.toString()); + } + + + private static List allFiles(File root, boolean recursive) { + File[] files = root.listFiles(); + if (files == null) return new ArrayList<>(); + List fileList = new ArrayList(); + for (File f : files) { + if (f.isDirectory()) { + if (recursive) { + List subFiles = allFiles(f, recursive); + if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir + fileList.addAll(subFiles); + } + } else { + fileList.add(f); + } + } + return fileList; + } + + private static List listFiles(File root, File[] files, UUID uuid) { + File dir; + if (uuid != null) { + dir = new File(root, uuid.toString()); + } else { + dir = root; + } + List result = new ArrayList(); + for (File file : files) { + ClipboardFormat format = ClipboardFormat.findByFile(file); + URI relative = dir.toURI().relativize(file.toURI()); + String name = ""; + if (relative.isAbsolute()) { + relative = root.toURI().relativize(file.toURI()); + name += "../"; + } + name += relative.getPath(); + String formatName; + if (format == null) { + String[] split = file.getName().split("\\."); + formatName = split.length > 1 ? split[split.length - 1].toUpperCase() : "Unknown"; + } else { + formatName = format.toString(); + } + result.add(BBC.SCHEMATIC_LIST_ELEM.f(name, formatName)); + } + return result; + } + public static void help(CommandContext args, WorldEdit we, Actor actor) { help(args, we, actor, "/", null); } public static void help(CommandContext args, WorldEdit we, Actor actor, String prefix, CommandCallable callable) { - if (callable == null) { - callable = we.getPlatformManager().getCommandManager().getDispatcher(); - } - CommandLocals locals = args.getLocals(); - - int page = -1; - String category = null; - final int perPage = actor instanceof Player ? 8 : 20; // More pages for console - int effectiveLength = args.argsLength(); - - // Detect page from args try { - if (effectiveLength > 0) { - page = args.getInteger(args.argsLength() - 1); - if (page <= 0) { - page = 1; - } else { - page--; - } - effectiveLength--; + if (callable == null) { + callable = we.getPlatformManager().getCommandManager().getDispatcher(); } - } catch (NumberFormatException ignored) { - } + CommandLocals locals = args.getLocals(); - boolean isRootLevel = true; - List visited = new ArrayList(); + int page = -1; + String category = null; + final int perPage = actor instanceof Player ? 8 : 20; // More pages for console + int effectiveLength = args.argsLength(); - // Create the message - if (callable instanceof Dispatcher) { - Dispatcher dispatcher = (Dispatcher) callable; - - // Get a list of aliases - List aliases = new ArrayList(dispatcher.getCommands()); - // Group by callable - - if (page == -1 || effectiveLength > 0) { - Map> grouped = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - for (CommandMapping mapping : aliases) { - CommandCallable c = mapping.getCallable(); - String group; - if (c instanceof ParametricCallable) { - group = ((ParametricCallable) c).getObject().getClass().getSimpleName().replaceAll("Commands", ""); - } else { - group = "Miscellaneous"; - } - ArrayList queue = grouped.get(group); - if (queue == null) { - queue = new ArrayList<>(); - grouped.put(group, queue); - } - queue.add(mapping); - } + // Detect page from args + try { if (effectiveLength > 0) { - String cat = args.getString(0); - ArrayList mappings = effectiveLength == 1 ? grouped.get(cat) : null; - if (mappings == null) { - // Drill down to the command - for (int i = 0; i < effectiveLength; i++) { - String command = args.getString(i); + page = args.getInteger(args.argsLength() - 1); + if (page <= 0) { + page = 1; + } else { + page--; + } + effectiveLength--; + } + } catch (NumberFormatException ignored) { + } - if (callable instanceof Dispatcher) { - // Chop off the beginning / if we're are the root level - if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') { - command = command.substring(1); - } + boolean isRootLevel = true; + List visited = new ArrayList(); - CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel); - if (mapping != null) { - callable = mapping.getCallable(); - } else { - if (isRootLevel) { - Set found = new HashSet<>(); - String arg = args.getString(i).toLowerCase(); - String closest = null; - int distance = Integer.MAX_VALUE; - for (CommandMapping map : aliases) { - String desc = map.getDescription().getDescription(); - if (desc == null) desc = map.getDescription().getHelp(); - if (desc == null) desc = ""; - String[] descSplit = desc.replaceAll("[^A-Za-z0-9]", "").toLowerCase().split(" "); - for (String alias : map.getAllAliases()) { - if (alias.equals(arg)) { - closest = map.getPrimaryAlias(); - distance = 0; - found.add(map.getPrimaryAlias()); - } else if (alias.contains(arg)) { - closest = map.getPrimaryAlias(); - distance = 1; - found.add(map.getPrimaryAlias()); - } else if (StringMan.isEqualIgnoreCaseToAny(arg, descSplit)) { - closest = map.getPrimaryAlias(); - distance = 1; - found.add(map.getPrimaryAlias()); - } else { - int currentDist = StringMan.getLevenshteinDistance(alias, arg); - if (currentDist < distance) { - distance = currentDist; + // Create the message + if (callable instanceof Dispatcher) { + Dispatcher dispatcher = (Dispatcher) callable; + + // Get a list of aliases + List aliases = new ArrayList(dispatcher.getCommands()); + // Group by callable + + if (page == -1 || effectiveLength > 0) { + Map> grouped = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + for (CommandMapping mapping : aliases) { + CommandCallable c = mapping.getCallable(); + String group; + if (c instanceof DelegateCallable) { + c = ((DelegateCallable) c).getParent(); + } + if (c instanceof ParametricCallable) { + Object obj = ((ParametricCallable) c).getObject(); + Command command = obj.getClass().getAnnotation(Command.class); + if (command != null && command.aliases().length != 0) { + group = command.aliases()[0]; + } else { + group = obj.getClass().getSimpleName().replaceAll("Commands", "").replaceAll("Util$", ""); + } + } else if (c instanceof Dispatcher) { + group = mapping.getPrimaryAlias(); + } else { + group = "Unsorted"; + } + group = StringMan.toProperCase(group); + Set queue = grouped.get(group); + if (queue == null) { + queue = new LinkedHashSet<>(); + grouped.put(group, queue); + } + if (c instanceof Dispatcher) { + queue.addAll(((Dispatcher) c).getCommands()); + } else { + queue.add(mapping); + } + } + if (effectiveLength > 0) { + String cat = args.getString(0); + Set mappings = effectiveLength == 1 ? grouped.get(cat) : null; + if (mappings == null) { + // Drill down to the command + for (int i = 0; i < effectiveLength; i++) { + String command = args.getString(i); + + if (callable instanceof Dispatcher) { + // Chop off the beginning / if we're are the root level + if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') { + command = command.substring(1); + } + + CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel); + if (mapping != null) { + callable = mapping.getCallable(); + } else { + if (isRootLevel) { + Set found = new HashSet<>(); + String arg = args.getString(i).toLowerCase(); + String closest = null; + int distance = Integer.MAX_VALUE; + for (CommandMapping map : aliases) { + String desc = map.getDescription().getDescription(); + if (desc == null) desc = map.getDescription().getHelp(); + if (desc == null) desc = ""; + String[] descSplit = desc.replaceAll("[^A-Za-z0-9]", "").toLowerCase().split(" "); + for (String alias : map.getAllAliases()) { + if (alias.equals(arg)) { closest = map.getPrimaryAlias(); + distance = 0; + found.add(map.getPrimaryAlias()); + } else if (alias.contains(arg)) { + closest = map.getPrimaryAlias(); + distance = 1; + found.add(map.getPrimaryAlias()); + } else if (StringMan.isEqualIgnoreCaseToAny(arg, descSplit)) { + closest = map.getPrimaryAlias(); + distance = 1; + found.add(map.getPrimaryAlias()); + } else { + int currentDist = StringMan.getLevenshteinDistance(alias, arg); + if (currentDist < distance) { + distance = currentDist; + closest = map.getPrimaryAlias(); + } } } } + found.add(closest); + BBC.HELP_SUGGEST.send(actor, arg, StringMan.join(found, ", ")); + return; + } else { + actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", + command, Joiner.on(" ").join(visited))); + return; } - found.add(closest); - BBC.HELP_SUGGEST.send(actor, arg, StringMan.join(found, ", ")); - return; - } else { - actor.printError(String.format("The sub-command '%s' under '%s' could not be found.", - command, Joiner.on(" ").join(visited))); - return; } + visited.add(args.getString(i)); + isRootLevel = false; + } else { + actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)", + Joiner.on(" ").join(visited), command)); + return; } - visited.add(args.getString(i)); - isRootLevel = false; - } else { - actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)", - Joiner.on(" ").join(visited), command)); + } + if (!(callable instanceof Dispatcher)) { + actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited)))); return; } - } - if (!(callable instanceof Dispatcher)) { - actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited)))); - return; - } - dispatcher = (Dispatcher) callable; - aliases = new ArrayList(dispatcher.getCommands()); - } else { - aliases = mappings; - } - page = Math.max(0, page); - } else if (grouped.size() > 1) { - StringBuilder message = new StringBuilder(); - message.append(BBC.getPrefix() + BBC.HELP_HEADER_CATEGORIES.s() + "\n"); - StringBuilder builder = new StringBuilder(); - boolean first = true; - for (Map.Entry> entry : grouped.entrySet()) { - String s1 = "&a//help " + entry.getKey(); - String s2 = entry.getValue().size() + ""; - message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n"); - } - message.append(BBC.HELP_HEADER_FOOTER.s()); - actor.print(BBC.color(message.toString())); - return; - } - } -// else - { - Collections.sort(aliases, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); - - // Calculate pagination - int offset = perPage * Math.max(0, page); - int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage); - - // Box - StringBuilder message = new StringBuilder(); - - if (offset >= aliases.size()) { - message.append("&c").append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal)); - } else { - message.append(BBC.getPrefix() + BBC.HELP_HEADER.format(page + 1, pageTotal) + "\n"); - List list = aliases.subList(offset, Math.min(offset + perPage, aliases.size() - 1)); - - boolean first = true; - // Add each command - for (CommandMapping mapping : list) { - CommandCallable c = mapping.getCallable(); - StringBuilder s1 = new StringBuilder(); - s1.append(prefix); - if (!visited.isEmpty()) { - s1.append(Joiner.on(" ").join(visited)); - s1.append(" "); - } - s1.append(mapping.getPrimaryAlias()); - String s2 = mapping.getDescription().getDescription(); - if (c.testPermission(locals)) { - message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n"); + dispatcher = (Dispatcher) callable; + aliases = new ArrayList(dispatcher.getCommands()); } else { - message.append(BBC.HELP_ITEM_DENIED.format(s1, s2) + "\n"); + aliases = new ArrayList<>(mappings); } + page = Math.max(0, page); + } else if (grouped.size() > 1) { + StringBuilder message = new StringBuilder(); + message.append(BBC.getPrefix() + BBC.HELP_HEADER_CATEGORIES.s() + "\n"); + StringBuilder builder = new StringBuilder(); + boolean first = true; + for (Map.Entry> entry : grouped.entrySet()) { + String s1 = "&a//help " + entry.getKey(); + String s2 = entry.getValue().size() + ""; + message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n"); + } + message.append(BBC.HELP_HEADER_FOOTER.s()); + actor.print(BBC.color(message.toString())); + return; } - message.append(BBC.HELP_HEADER_FOOTER.f()); } - actor.print(BBC.color(message.toString())); +// else + { + Collections.sort(aliases, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN)); + + // Calculate pagination + int offset = perPage * Math.max(0, page); + int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage); + + // Box + StringBuilder message = new StringBuilder(); + + if (offset >= aliases.size()) { + message.append("&c").append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal)); + } else { + message.append(BBC.getPrefix() + BBC.HELP_HEADER.format(page + 1, pageTotal) + "\n"); + List list = aliases.subList(offset, Math.min(offset + perPage, aliases.size())); + + boolean first = true; + // Add each command + for (CommandMapping mapping : list) { + CommandCallable c = mapping.getCallable(); + StringBuilder s1 = new StringBuilder(); + s1.append(prefix); + if (!visited.isEmpty()) { + s1.append(Joiner.on(" ").join(visited)); + s1.append(" "); + } + s1.append(mapping.getPrimaryAlias()); + String s2 = mapping.getDescription().getDescription(); + if (c.testPermission(locals)) { + message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n"); + } else { + message.append(BBC.HELP_ITEM_DENIED.format(s1, s2) + "\n"); + } + } + message.append(BBC.HELP_HEADER_FOOTER.f()); + } + actor.print(BBC.color(message.toString())); + } + } else { + actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited)))); } - } else { - actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited)))); + } catch (Throwable e) { + e.printStackTrace(); + throw new RuntimeException(e); } } 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 90c5b77e..00983528 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 @@ -18,6 +18,9 @@ import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.pattern.PatternTraverser; import com.boydti.fawe.util.EditSessionBuilder; import com.boydti.fawe.util.TaskManager; +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.sk89q.minecraft.util.commands.CommandException; import com.sk89q.worldedit.BlockWorldVector; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalConfiguration; @@ -29,6 +32,7 @@ import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.command.tool.brush.Brush; import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.extension.input.InputParseException; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Platform; import com.sk89q.worldedit.extent.inventory.BlockBag; @@ -38,6 +42,11 @@ import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.session.request.Request; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.TargetBlock; +import java.io.IOException; +import java.io.Serializable; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import javax.annotation.Nullable; @@ -45,7 +54,11 @@ import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; -public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool { +public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool, Serializable { +// TODO: + // Serialize methods + // serialize BrushSettings (primary and secondary only if different) + // set transient values e.g. context public enum BrushAction { PRIMARY, @@ -58,20 +71,83 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE; private transient BrushSettings context = new BrushSettings(); - private BrushSettings primary = context; - private BrushSettings secondary = context; + private transient BrushSettings primary = context; + private transient BrushSettings secondary = context; private transient VisualExtent visualExtent; private transient Lock lock = new ReentrantLock(); - /** - * Construct the tool. - * - * @param permission the permission to check before use is allowed - */ public BrushTool(String permission) { - checkNotNull(permission); - this.getContext().permission = permission; + getContext().addPermission(permission); + } + + public BrushTool() { + } + + public static BrushTool fromString(Player player, LocalSession session, String json) throws CommandException, InputParseException { + Gson gson = new Gson(); + Type type = new TypeToken>(){}.getType(); + Map root = gson.fromJson(json, type); + Map primary = (Map) root.get("primary"); + Map secondary = (Map) root.getOrDefault("secondary", primary); + + VisualMode visual = VisualMode.valueOf((String) root.getOrDefault("visual", "NONE")); + TargetMode target = TargetMode.valueOf((String) root.getOrDefault("target", "TARGET_BLOCK_RANGE")); + int range = (int) root.getOrDefault("range", -1); + + BrushTool tool = new BrushTool(); + tool.visualMode = visual; + tool.targetMode = target; + tool.range = range; + + BrushSettings primarySettings = BrushSettings.get(tool, player, session, primary); + tool.setPrimary(primarySettings); + if (primary != secondary) { + BrushSettings secondarySettings = BrushSettings.get(tool, player, session, secondary); + tool.setSecondary(secondarySettings); + } + + return tool; + } + + @Override + public String toString() { + HashMap map = new HashMap<>(); + map.put("primary", primary.getSettings()); + if (primary != secondary) { + map.put("secondary", secondary.getSettings()); + } + if (visualMode != null) { + map.put("visual", visualMode); + } + if (targetMode != TargetMode.TARGET_BLOCK_RANGE) { + map.put("target", targetMode); + } + if (range != -1) { + map.put("range", range); + } + return new Gson().toJson(map); + } + + private void writeObject(java.io.ObjectOutputStream stream) throws IOException { + stream.defaultWriteObject(); + stream.writeBoolean(primary == secondary); + stream.writeObject(primary); + if (primary != secondary) { + stream.writeObject(secondary); + } + } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + lock = new ReentrantLock(); + boolean multi = stream.readBoolean(); + primary = (BrushSettings) stream.readObject(); + if (multi) { + secondary = (BrushSettings) stream.readObject(); + } else { + secondary = primary; + } + context = primary; } public BrushSettings getContext() { @@ -89,13 +165,13 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool @Override public boolean canUse(Actor player) { if (primary == secondary) { - return player.hasPermission(getContext().permission); + return primary.canUse(player); } - return player.hasPermission(primary.permission) && player.hasPermission(secondary.permission); + return primary.canUse(player) && secondary.canUse(player); } public ResettableExtent getTransform() { - return getContext().transform; + return getContext().getTransform(); } public BrushSettings getPrimary() { @@ -106,18 +182,26 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool return secondary; } + public BrushSettings getOffHand() { + return context == primary ? secondary : primary; + } + public void setPrimary(BrushSettings primary) { checkNotNull(primary); + if (this.secondary.getBrush() == null) this.secondary = primary; this.primary = primary; + this.context = primary; } public void setSecondary(BrushSettings secondary) { checkNotNull(secondary); + if (this.primary.getBrush() == null) this.primary = secondary; this.secondary = secondary; + this.context = secondary; } public void setTransform(ResettableExtent transform) { - this.getContext().transform = transform; + getContext().setTransform(transform); } /** @@ -126,7 +210,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return the filter */ public Mask getMask() { - return getContext().mask; + return getContext().getMask(); } /** @@ -135,7 +219,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return the filter */ public Mask getSourceMask() { - return getContext().sourceMask; + return getContext().getSourceMask(); } @Override @@ -153,7 +237,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param filter the filter to set */ public void setMask(Mask filter) { - this.getContext().mask = filter; + this.getContext().setMask(filter); } /** @@ -162,7 +246,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param filter the filter to set */ public void setSourceMask(Mask filter) { - this.getContext().sourceMask = filter; + this.getContext().setSourceMask(filter); } /** @@ -171,15 +255,18 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param brush tbe brush * @param permission the permission */ + @Deprecated public void setBrush(Brush brush, String permission) { setBrush(brush, permission, null); } + @Deprecated public void setBrush(Brush brush, String permission, Player player) { if (player != null) clear(player); BrushSettings current = getContext(); - current.brush = brush; - current.permission = permission; + current.clear(); + current.setBrush(brush); + current.addPermission(permission); } /** @@ -188,7 +275,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return the current brush */ public Brush getBrush() { - return getContext().brush; + return getContext().getBrush(); } /** @@ -197,7 +284,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param material the material */ public void setFill(@Nullable Pattern material) { - this.getContext().material = material; + this.getContext().setFill(material); } /** @@ -206,7 +293,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return the material */ @Nullable public Pattern getMaterial() { - return getContext().material; + return getContext().getMaterial(); } /** @@ -215,7 +302,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @return a radius */ public double getSize() { - return getContext().size; + return getContext().getSize(); } /** @@ -224,7 +311,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool * @param radius a radius */ public void setSize(double radius) { - this.getContext().size = radius; + this.getContext().setSize(radius); } /** @@ -306,6 +393,8 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } BrushSettings current = getContext(); + Brush brush = current.getBrush(); + if (brush == null) return false; EditSession editSession = session.createEditSession(player); Vector target = getPosition(editSession, player); @@ -317,28 +406,31 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } BlockBag bag = session.getBlockBag(player); Request.request().setEditSession(editSession); - if (current.mask != null) { + Mask mask = current.getMask(); + if (mask != null) { Mask existingMask = editSession.getMask(); if (existingMask == null) { - editSession.setMask(current.mask); + editSession.setMask(mask); } else if (existingMask instanceof MaskIntersection) { - ((MaskIntersection) existingMask).add(current.mask); + ((MaskIntersection) existingMask).add(mask); } else { MaskIntersection newMask = new MaskIntersection(existingMask); - newMask.add(current.mask); + newMask.add(mask); editSession.setMask(newMask); } } - if (current.sourceMask != null) { - editSession.addSourceMask(current.sourceMask); + Mask sourceMask = current.getSourceMask(); + if (sourceMask != null) { + editSession.addSourceMask(sourceMask); } - if (current.transform != null) { - editSession.addTransform(current.transform); + ResettableExtent transform = current.getTransform(); + if (transform != null) { + editSession.addTransform(transform); } try { new PatternTraverser(current).reset(editSession); - current.brush.build(editSession, target, current.material, current.size); + brush.build(editSession, target, current.getMaterial(), current.getSize()); } catch (MaxChangedBlocksException e) { player.printError("Max blocks change limit reached."); // Never happens } finally { @@ -366,7 +458,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool } public void setScrollAction(ScrollAction scrollAction) { - this.getContext().scrollAction = scrollAction; + this.getContext().setScrollAction(scrollAction); } public void setTargetMode(TargetMode targetMode) { @@ -388,7 +480,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool @Override public boolean increment(Player player, int amount) { BrushSettings current = getContext(); - ScrollAction tmp = current.scrollAction; + ScrollAction tmp = current.getScrollAction(); if (tmp != null) { tmp.setTool(this); if (tmp.increment(player, amount)) { @@ -439,7 +531,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool case OUTLINE: { BrushSettings current = getContext(); new PatternTraverser(current).reset(editSession); - current.brush.build(editSession, position, current.material, current.size); + current.getBrush().build(editSession, position, current.getMaterial(), current.getSize()); break; } } diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java index 23b48151..a9e847fd 100644 --- a/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java +++ b/core/src/main/java/com/sk89q/worldedit/command/tool/brush/GravityBrush.java @@ -23,7 +23,6 @@ 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.mask.Mask; import com.sk89q.worldedit.function.mask.Masks; import com.sk89q.worldedit.function.pattern.Pattern; @@ -32,7 +31,7 @@ public class GravityBrush implements Brush { private final boolean fullHeight; - public GravityBrush(boolean fullHeight, BrushTool tool) { + public GravityBrush(boolean fullHeight) { this.fullHeight = fullHeight; } diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java index b9f17e08..21af1ff1 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/CommandManager.java @@ -41,12 +41,14 @@ import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.command.BiomeCommands; import com.sk89q.worldedit.command.BrushCommands; +import com.sk89q.worldedit.command.BrushOptionsCommands; +import com.sk89q.worldedit.command.BrushProcessor; import com.sk89q.worldedit.command.ChunkCommands; import com.sk89q.worldedit.command.ClipboardCommands; -import com.sk89q.worldedit.command.GeneralCommands; import com.sk89q.worldedit.command.GenerationCommands; import com.sk89q.worldedit.command.HistoryCommands; import com.sk89q.worldedit.command.NavigationCommands; +import com.sk89q.worldedit.command.OptionsCommands; import com.sk89q.worldedit.command.RegionCommands; import com.sk89q.worldedit.command.SchematicCommands; import com.sk89q.worldedit.command.ScriptingCommands; @@ -55,7 +57,6 @@ import com.sk89q.worldedit.command.SnapshotCommands; import com.sk89q.worldedit.command.SnapshotUtilCommands; import com.sk89q.worldedit.command.SuperPickaxeCommands; import com.sk89q.worldedit.command.ToolCommands; -import com.sk89q.worldedit.command.ToolUtilCommands; import com.sk89q.worldedit.command.UtilityCommands; import com.sk89q.worldedit.command.WorldEditCommands; import com.sk89q.worldedit.command.argument.ReplaceParser; @@ -218,13 +219,13 @@ public final class CommandManager { methodMap.clear(); dispatcher = graph - .group("/anvil", "anvil") + .group("anvil", "/anvil") .describeAs("Anvil command") .registerMethods(new AnvilCommands(worldEdit)).parent() .registerMethods(new BiomeCommands(worldEdit)) .registerMethods(new ChunkCommands(worldEdit)) .registerMethods(new ClipboardCommands(worldEdit)) - .registerMethods(new GeneralCommands(worldEdit)) + .registerMethods(new OptionsCommands(worldEdit)) .registerMethods(new GenerationCommands(worldEdit)) .registerMethods(new HistoryCommands(worldEdit)) .registerMethods(new NavigationCommands(worldEdit)) @@ -232,7 +233,7 @@ public final class CommandManager { .registerMethods(new ScriptingCommands(worldEdit)) .registerMethods(new SelectionCommands(worldEdit)) .registerMethods(new SnapshotUtilCommands(worldEdit)) - .registerMethods(new ToolUtilCommands(worldEdit)) + .registerMethods(new BrushOptionsCommands(worldEdit)) .registerMethods(new ToolCommands(worldEdit)) .registerMethods(new UtilityCommands(worldEdit)) .group("worldedit", "we", "fawe") @@ -241,18 +242,19 @@ public final class CommandManager { .describeAs("Schematic commands for saving/loading areas") .registerMethods(new SchematicCommands(worldEdit)).parent().group("snapshot", "snap") .describeAs("Schematic commands for saving/loading areas") - .registerMethods(new SnapshotCommands(worldEdit)).parent().group("brush", "br").describeAs("Brushing commands") - .registerMethods(new BrushCommands(worldEdit)).register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") + .registerMethods(new SnapshotCommands(worldEdit)).parent().group("brush", "br", "/b", "tool").describeAs("Bind brushes and tools to items") + .registerMethods(new ToolCommands(worldEdit)) + .registerMethods(new BrushOptionsCommands(worldEdit)) + .registerMethods(new BrushCommands(worldEdit), new BrushProcessor(worldEdit)) + .register(adapt(new ShapedBrushCommand(new DeformCommand(), "worldedit.brush.deform")), "deform") .register(adapt(new ShapedBrushCommand(new ApplyCommand(new ReplaceParser(), "Set all blocks within region"), "worldedit.brush.set")), "set") - .register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint").register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply") + .register(adapt(new ShapedBrushCommand(new PaintCommand(), "worldedit.brush.paint")), "paint") + .register(adapt(new ShapedBrushCommand(new ApplyCommand(), "worldedit.brush.apply")), "apply") .register(adapt(new ShapedBrushCommand(new PaintCommand(new TreeGeneratorParser("treeType")), "worldedit.brush.forest")), "forest") .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y-=1", Mode.RAW_COORD), "Raise one block"), "worldedit.brush.raise")), "raise") .register(adapt(new ShapedBrushCommand(ProvidedValue.create(new Deform("y+=1", Mode.RAW_COORD), "Lower one block"), "worldedit.brush.lower")), "lower").parent() .group("superpickaxe", "pickaxe", "sp").describeAs("Super-pickaxe commands") - .registerMethods(new SuperPickaxeCommands(worldEdit)).parent().group("tool") - .describeAs("Bind functions to held items") - .registerMethods(new ToolCommands(worldEdit)) - .registerMethods(new BrushCommands(worldEdit)) + .registerMethods(new SuperPickaxeCommands(worldEdit)) .parent().graph().getDispatcher(); if (platform != null) { platform.registerCommands(dispatcher); @@ -418,6 +420,7 @@ public final class CommandManager { log.log(Level.SEVERE, "An unexpected error occurred while handling a FAWE command", t); } } catch (Throwable e) { + e.printStackTrace(); String message = e.getMessage(); if (message != null) { finalActor.printError(e.getMessage()); diff --git a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java index 2292cfbf..4202e428 100644 --- a/core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java +++ b/core/src/main/java/com/sk89q/worldedit/extension/platform/PlayerProxy.java @@ -1,8 +1,3 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by Fernflower decompiler) -// - package com.sk89q.worldedit.extension.platform; import com.google.common.base.Preconditions; diff --git a/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index e7d4270a..e6ba3b28 100644 --- a/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -45,7 +45,7 @@ import static com.google.common.base.Preconditions.checkNotNull; */ public class AbstractDelegateExtent implements LightingExtent { - private final Extent extent; + private transient final Extent extent; /** * Create a new instance. diff --git a/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractExtentMask.java b/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractExtentMask.java new file mode 100644 index 00000000..6b1cd991 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractExtentMask.java @@ -0,0 +1,25 @@ +package com.sk89q.worldedit.function.mask; + +import com.google.common.base.Preconditions; +import com.sk89q.worldedit.extent.Extent; + +public abstract class AbstractExtentMask extends AbstractMask { + private transient Extent extent; + + protected AbstractExtentMask(Extent extent) { + this.setExtent(extent); + } + + public Extent getExtent() { + return this.extent; + } + + public void setExtent(Extent extent) { + Preconditions.checkNotNull(extent); + this.extent = extent; + } + + public static Class inject() { + return AbstractExtentMask.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractMask.java b/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractMask.java new file mode 100644 index 00000000..073b4c88 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/mask/AbstractMask.java @@ -0,0 +1,31 @@ +/* + * 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 java.io.Serializable; + +/** + * A base class of {@link Mask} that all masks should inherit from. + */ +public abstract class AbstractMask implements Mask, Serializable { + public static Class inject() { + return AbstractMask.class; + } +} 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 index e3bfae1d..2c48e791 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java +++ b/core/src/main/java/com/sk89q/worldedit/function/mask/Mask.java @@ -23,13 +23,13 @@ import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.Vector; - +import java.io.Serializable; import javax.annotation.Nullable; /** * Tests whether a given vector meets a criteria. */ -public interface Mask extends com.sk89q.worldedit.masks.Mask { +public interface Mask extends com.sk89q.worldedit.masks.Mask, Serializable { /** * Returns true if the criteria is met. diff --git a/core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java b/core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java index e7747f94..9b59c98b 100644 --- a/core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java +++ b/core/src/main/java/com/sk89q/worldedit/function/mask/MaskIntersection.java @@ -20,14 +20,16 @@ package com.sk89q.worldedit.function.mask; import com.sk89q.worldedit.Vector; - -import javax.annotation.Nullable; +import java.io.IOException; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.annotation.Nullable; + import static com.google.common.base.Preconditions.checkNotNull; @@ -36,9 +38,9 @@ import static com.google.common.base.Preconditions.checkNotNull; * when a certain position is tested. It serves as a logical AND operation * on a list of masks. */ -public class MaskIntersection extends AbstractMask { +public class MaskIntersection extends AbstractMask implements Serializable { - private final Set masks = new HashSet(); + private transient Set masks = new HashSet(); private Mask[] masksArray; /** @@ -126,4 +128,9 @@ public class MaskIntersection extends AbstractMask { } return new MaskIntersection2D(mask2dList); } + + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + masks = new HashSet(Arrays.asList(masksArray)); + } } diff --git a/core/src/main/java/com/sk89q/worldedit/function/pattern/AbstractPattern.java b/core/src/main/java/com/sk89q/worldedit/function/pattern/AbstractPattern.java new file mode 100644 index 00000000..f5b7662d --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/function/pattern/AbstractPattern.java @@ -0,0 +1,12 @@ +package com.sk89q.worldedit.function.pattern; + +import java.io.Serializable; + +public abstract class AbstractPattern implements Pattern, Serializable { + public AbstractPattern() { + } + + public static Class inject() { + return AbstractPattern.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java b/core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java index 45d6921d..8fceddc0 100644 --- a/core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java +++ b/core/src/main/java/com/sk89q/worldedit/math/transform/AffineTransform.java @@ -3,6 +3,8 @@ package com.sk89q.worldedit.math.transform; import com.sk89q.worldedit.MutableBlockVector; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.math.MathUtils; +import java.io.IOException; +import java.io.Serializable; /** * An affine transform. @@ -11,9 +13,9 @@ import com.sk89q.worldedit.math.MathUtils; * JavaGeom project, * which is licensed under LGPL v2.1.

*/ -public class AffineTransform implements Transform { +public class AffineTransform implements Transform, Serializable{ - private MutableBlockVector mutable = new MutableBlockVector(); + private transient MutableBlockVector mutable = new MutableBlockVector(); /** * coefficients for x coordinate. @@ -303,6 +305,11 @@ public class AffineTransform implements Transform { return String.format("Affine[%g %g %g %g, %g %g %g %g, %g %g %g %g]}", m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23); } + private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + mutable = new MutableBlockVector(); + } + public static Class inject() { return AffineTransform.class; } diff --git a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java index 6e30a069..4f76e9b2 100644 --- a/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java +++ b/core/src/main/java/com/sk89q/worldedit/patterns/Pattern.java @@ -23,12 +23,13 @@ import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.blocks.BaseBlock; import com.sk89q.worldedit.extent.Extent; +import java.io.Serializable; /** * @deprecated See {@link com.sk89q.worldedit.function.pattern.Pattern} */ @Deprecated -public interface Pattern{ +public interface Pattern extends Serializable { /** * Get a block for a position. This return value of this method does diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/CallableProcessor.java b/core/src/main/java/com/sk89q/worldedit/util/command/CallableProcessor.java new file mode 100644 index 00000000..71b44d80 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/util/command/CallableProcessor.java @@ -0,0 +1,10 @@ +package com.sk89q.worldedit.util.command; + +import com.plotsquared.general.commands.Command; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.worldedit.WorldEditException; + +public interface CallableProcessor { + public Object process(CommandLocals locals, T value) throws Command.CommandException, WorldEditException; + +} diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/DelegateCallable.java b/core/src/main/java/com/sk89q/worldedit/util/command/DelegateCallable.java new file mode 100644 index 00000000..70181359 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/util/command/DelegateCallable.java @@ -0,0 +1,37 @@ +package com.sk89q.worldedit.util.command; + +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; +import java.util.List; + +public class DelegateCallable implements CommandCallable { + private final CommandCallable parent; + + public CommandCallable getParent() { + return parent; + } + + public DelegateCallable(CommandCallable parent) { + this.parent = parent; + } + + @Override + public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { + return parent.call(arguments, locals, parentCommands); + } + + @Override + public Description getDescription() { + return parent.getDescription(); + } + + @Override + public boolean testPermission(CommandLocals locals) { + return parent.testPermission(locals); + } + + @Override + public List getSuggestions(String arguments, CommandLocals locals) throws CommandException { + return parent.getSuggestions(arguments, locals); + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/ProcessedCallable.java b/core/src/main/java/com/sk89q/worldedit/util/command/ProcessedCallable.java new file mode 100644 index 00000000..17fa3f32 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/util/command/ProcessedCallable.java @@ -0,0 +1,27 @@ +package com.sk89q.worldedit.util.command; + +import com.sk89q.minecraft.util.commands.CommandException; +import com.sk89q.minecraft.util.commands.CommandLocals; +import com.sk89q.worldedit.WorldEditException; + + +import static com.google.common.base.Preconditions.checkNotNull; + +public class ProcessedCallable extends DelegateCallable { + private final CallableProcessor processor; + + public ProcessedCallable(CommandCallable parent, CallableProcessor processor) { + super(parent); + checkNotNull(processor); + this.processor = processor; + } + + @Override + public Object call(String arguments, CommandLocals locals, String[] parentCommands) throws CommandException { + try { + return processor.process(locals, super.call(arguments, locals, parentCommands)); + } catch (WorldEditException e) { + throw new RuntimeException(e); + } + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java b/core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java new file mode 100644 index 00000000..2669bd63 --- /dev/null +++ b/core/src/main/java/com/sk89q/worldedit/util/command/fluent/DispatcherNode.java @@ -0,0 +1,155 @@ +/* + * 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.util.command.fluent; + +import com.sk89q.worldedit.util.command.CallableProcessor; +import com.sk89q.worldedit.util.command.CommandCallable; +import com.sk89q.worldedit.util.command.Dispatcher; +import com.sk89q.worldedit.util.command.SimpleDispatcher; +import com.sk89q.worldedit.util.command.parametric.ParametricBuilder; + +/** + * A collection of commands. + */ +public class DispatcherNode { + + private final CommandGraph graph; + private final DispatcherNode parent; + private final SimpleDispatcher dispatcher; + + /** + * Create a new instance. + * + * @param graph the root fluent graph object + * @param parent the parent node, or null + * @param dispatcher the dispatcher for this node + */ + public DispatcherNode(CommandGraph graph, DispatcherNode parent, + SimpleDispatcher dispatcher) { + this.graph = graph; + this.parent = parent; + this.dispatcher = dispatcher; + } + + /** + * Set the description. + * + *

This can only be used on {@link DispatcherNode}s returned by + * {@link #group(String...)}.

+ * + * @param description the description + * @return this object + */ + public DispatcherNode describeAs(String description) { + dispatcher.getDescription().setDescription(description); + return this; + } + + /** + * Register a command with this dispatcher. + * + * @param callable the executor + * @param alias the list of aliases, where the first alias is the primary one + */ + public DispatcherNode register(CommandCallable callable, String... alias) { + dispatcher.registerCommand(callable, alias); + return this; + } + + /** + * Build and register a command with this dispatcher using the + * {@link ParametricBuilder} assigned on the root {@link CommandGraph}. + * + * @param object the object provided to the {@link ParametricBuilder} + * @return this object + * @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object) + */ + public DispatcherNode registerMethods(Object object) { + return registerMethods(object, null); + } + + /** + * Build and register a command with this dispatcher using the + * {@link ParametricBuilder} assigned on the root {@link CommandGraph}. + * + * @param object the object provided to the {@link ParametricBuilder} + * @return this object + * @see ParametricBuilder#registerMethodsAsCommands(com.sk89q.worldedit.util.command.Dispatcher, Object) + */ + public DispatcherNode registerMethods(Object object, CallableProcessor processor) { + ParametricBuilder builder = graph.getBuilder(); + if (builder == null) { + throw new RuntimeException("No ParametricBuilder set"); + } + builder.registerMethodsAsCommands(getDispatcher(), object, processor); + return this; + } + + /** + * Create a new command that will contain sub-commands. + * + *

The object returned by this method can be used to add sub-commands. To + * return to this "parent" context, use {@link DispatcherNode#graph()}.

+ * + * @param alias the list of aliases, where the first alias is the primary one + * @return an object to place sub-commands + */ + public DispatcherNode group(String... alias) { + SimpleDispatcher command = new SimpleDispatcher(); + getDispatcher().registerCommand(command, alias); + return new DispatcherNode(graph, this, command); + } + + /** + * Return the parent node. + * + * @return the parent node + * @throws RuntimeException if there is no parent node. + */ + public DispatcherNode parent() { + if (parent != null) { + return parent; + } + + throw new RuntimeException("This node does not have a parent"); + } + + /** + * Get the root command graph. + * + * @return the root command graph + */ + public CommandGraph graph() { + return graph; + } + + /** + * Get the underlying dispatcher of this object. + * + * @return the dispatcher + */ + public Dispatcher getDispatcher() { + return dispatcher; + } + + public static Class inject() { + return DispatcherNode.class; + } +} diff --git a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java index 9df0643a..7e490317 100644 --- a/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java +++ b/core/src/main/java/com/sk89q/worldedit/util/command/parametric/ParametricBuilder.java @@ -29,16 +29,17 @@ import com.sk89q.minecraft.util.commands.CommandPermissions; import com.sk89q.worldedit.command.MethodCommands; import com.sk89q.worldedit.util.auth.Authorizer; import com.sk89q.worldedit.util.auth.NullAuthorizer; +import com.sk89q.worldedit.util.command.CallableProcessor; import com.sk89q.worldedit.util.command.CommandCallable; import com.sk89q.worldedit.util.command.CommandCompleter; import com.sk89q.worldedit.util.command.Dispatcher; import com.sk89q.worldedit.util.command.NullCompleter; +import com.sk89q.worldedit.util.command.ProcessedCallable; import com.sk89q.worldedit.util.command.binding.PrimitiveBindings; import com.sk89q.worldedit.util.command.binding.StandardBindings; import com.sk89q.worldedit.util.command.binding.Switch; import com.thoughtworks.paranamer.CachingParanamer; import com.thoughtworks.paranamer.Paranamer; -import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.util.ArrayList; @@ -154,11 +155,27 @@ public class ParametricBuilder { * @throws com.sk89q.worldedit.util.command.parametric.ParametricException thrown if the commands cannot be registered */ public void registerMethodsAsCommands(Dispatcher dispatcher, Object object) throws ParametricException { + registerMethodsAsCommands(dispatcher, object, null); + } + + /** + * Build a list of commands from methods specially annotated with {@link Command} + * (and other relevant annotations) and register them all with the given + * {@link Dispatcher}. + * + * @param dispatcher the dispatcher to register commands with + * @param object the object contain the methods + * @throws com.sk89q.worldedit.util.command.parametric.ParametricException thrown if the commands cannot be registered + */ + public void registerMethodsAsCommands(Dispatcher dispatcher, Object object, CallableProcessor processor) throws ParametricException { for (Method method : object.getClass().getDeclaredMethods()) { Command definition = method.getAnnotation(Command.class); if (definition != null) { definition = Commands.translate(method.getDeclaringClass(), definition); CommandCallable callable = build(object, method, definition); + if (processor != null) { + callable = new ProcessedCallable(callable, processor); + } if (object instanceof MethodCommands) { ((MethodCommands) object).register(method, callable, dispatcher); } @@ -179,10 +196,7 @@ public class ParametricBuilder { private CommandCallable build(Object object, Method method, Command definition) throws ParametricException { try { - Class clazz = Class.forName("com.sk89q.worldedit.util.command.parametric.ParametricCallable"); - Constructor constructor = clazz.getDeclaredConstructors()[0]; - constructor.setAccessible(true); - return (CommandCallable) constructor.newInstance(this, object, method, definition); + return new ParametricCallable(this, object, method, definition); } catch (Throwable e) { if (e instanceof ParametricException) { throw (ParametricException) e; diff --git a/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java b/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java index 110f4dc7..54af4709 100644 --- a/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java +++ b/favs/src/main/java/com/thevoxelbox/voxelsniper/RangeBlockHelper.java @@ -1,8 +1,3 @@ -// -// Source code recreated from a .class file by IntelliJ IDEA -// (powered by Fernflower decompiler) -// - package com.thevoxelbox.voxelsniper; import org.bukkit.Location; diff --git a/forge110/src/main/java/com/boydti/fawe/forge/v110/ForgeQueue_All.java b/forge110/src/main/java/com/boydti/fawe/forge/v110/ForgeQueue_All.java index af640e5a..2233e428 100644 --- a/forge110/src/main/java/com/boydti/fawe/forge/v110/ForgeQueue_All.java +++ b/forge110/src/main/java/com/boydti/fawe/forge/v110/ForgeQueue_All.java @@ -7,7 +7,7 @@ import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/forge111/src/main/java/com/boydti/fawe/forge/v111/ForgeQueue_All.java b/forge111/src/main/java/com/boydti/fawe/forge/v111/ForgeQueue_All.java index eedcb7cb..efbf0bd2 100644 --- a/forge111/src/main/java/com/boydti/fawe/forge/v111/ForgeQueue_All.java +++ b/forge111/src/main/java/com/boydti/fawe/forge/v111/ForgeQueue_All.java @@ -8,7 +8,7 @@ import com.boydti.fawe.forge.MutableGenLayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/forge1710/src/main/java/com/boydti/fawe/forge/v1710/ForgeQueue_All.java b/forge1710/src/main/java/com/boydti/fawe/forge/v1710/ForgeQueue_All.java index 21b95633..b89b3619 100644 --- a/forge1710/src/main/java/com/boydti/fawe/forge/v1710/ForgeQueue_All.java +++ b/forge1710/src/main/java/com/boydti/fawe/forge/v1710/ForgeQueue_All.java @@ -9,7 +9,7 @@ import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.IntegerPair; import com.boydti.fawe.object.RunnableVal; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/forge189/src/main/java/com/boydti/fawe/forge/v189/ForgeQueue_All.java b/forge189/src/main/java/com/boydti/fawe/forge/v189/ForgeQueue_All.java index bb315157..71f9b491 100644 --- a/forge189/src/main/java/com/boydti/fawe/forge/v189/ForgeQueue_All.java +++ b/forge189/src/main/java/com/boydti/fawe/forge/v189/ForgeQueue_All.java @@ -7,7 +7,7 @@ import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/forge194/src/main/java/com/boydti/fawe/forge/v194/ForgeQueue_All.java b/forge194/src/main/java/com/boydti/fawe/forge/v194/ForgeQueue_All.java index e1eb108a..4a0c10a3 100644 --- a/forge194/src/main/java/com/boydti/fawe/forge/v194/ForgeQueue_All.java +++ b/forge194/src/main/java/com/boydti/fawe/forge/v194/ForgeQueue_All.java @@ -7,7 +7,7 @@ import com.boydti.fawe.forge.ForgePlayer; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.util.MainUtil; import com.boydti.fawe.util.MathMan; diff --git a/sponge/src/main/java/com/boydti/fawe/sponge/v1_11/SpongeQueue_1_11.java b/sponge/src/main/java/com/boydti/fawe/sponge/v1_11/SpongeQueue_1_11.java index 7f1c9bd5..a210f461 100644 --- a/sponge/src/main/java/com/boydti/fawe/sponge/v1_11/SpongeQueue_1_11.java +++ b/sponge/src/main/java/com/boydti/fawe/sponge/v1_11/SpongeQueue_1_11.java @@ -6,7 +6,7 @@ import com.boydti.fawe.example.NMSMappedFaweQueue; import com.boydti.fawe.object.FaweChunk; import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.brush.visualization.VisualChunk; -import com.boydti.fawe.object.number.LongAdder; +import java.util.concurrent.atomic.LongAdder; import com.boydti.fawe.object.visitor.FaweChunkVisitor; import com.boydti.fawe.sponge.SpongePlayer; import com.boydti.fawe.util.MainUtil;