From 53681ccc59f296a52f9b2ccea1b17286abf24c7e Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 29 May 2021 00:47:46 +0200 Subject: [PATCH] Feature/unsafe over reflections (#1082) * Use Unsafe to replace Lock * Start cleaning up everything that has to do with CleanableThreadLocal * Make cancellation work Co-authored-by: NotMyFault --- .../com/boydti/fawe/bukkit/FaweBukkit.java | 22 +- .../mc1_15_2/BukkitAdapter_1_15_2.java | 25 +- .../mc1_16_1/BukkitAdapter_1_16_1.java | 25 +- .../mc1_16_2/BukkitAdapter_1_16_2.java | 32 +- .../mc1_16_5/BukkitAdapter_1_16_5.java | 34 +- .../mc1_16_5/BukkitGetBlocks_1_16_5.java | 2 +- .../FAWEWorldNativeAccess_1_16_R3.java | 4 +- .../mc1_16_5/TuinityRelighter_1_16_5.java | 2 +- .../bukkit/listener/BukkitImageListener.java | 292 --- .../bukkit/listener/CFIPacketListener.java | 338 --- .../bukkit/util/BukkitReflectionUtils.java | 27 - .../src/main/java/com/boydti/fawe/Fawe.java | 10 - .../main/java/com/boydti/fawe/FaweCache.java | 42 +- .../src/main/java/com/boydti/fawe/IFawe.java | 2 - .../com/boydti/fawe/beta/CombinedBlocks.java | 164 -- .../com/boydti/fawe/beta/IQueueExtent.java | 4 +- .../processors/ChunkSendProcessor.java | 89 - .../PersistentChunkSendProcessor.java | 88 - .../com/boydti/fawe/jnbt/anvil/LevelDat.java | 44 - .../com/boydti/fawe/jnbt/anvil/MCAChunk.java | 651 ----- .../com/boydti/fawe/jnbt/anvil/MCAFile.java | 715 ------ .../com/boydti/fawe/jnbt/anvil/MCAWorld.java | 109 - .../fawe/jnbt/anvil/mcatest/MCATest.java | 14 - .../fawe/object/brush/CatenaryBrush.java | 20 +- .../fawe/object/brush/CopyPastaBrush.java | 4 - .../boydti/fawe/object/brush/HeightBrush.java | 79 - .../boydti/fawe/object/brush/LineBrush.java | 20 +- .../boydti/fawe/object/brush/SplineBrush.java | 21 +- .../fawe/object/brush/SurfaceSpline.java | 10 +- .../fawe/object/brush/sweep/SweepBrush.java | 5 - .../visualization/ImmutableVirtualWorld.java | 93 - .../brush/visualization/VirtualWorld.java | 46 - .../brush/visualization/VisualExtent.java | 70 - .../brush/visualization/VisualMode.java | 7 - .../brush/visualization/VisualQueue.java | 31 - .../brush/visualization/cfi/CFIDrawer.java | 146 -- .../cfi/HeightMapMCAGenerator.java | 2136 ----------------- .../brush/visualization/cfi/MCAWriter.java | 210 -- .../boydti/fawe/object/change/CFIChange.java | 61 - .../fawe/object/changeset/CFIChangeSet.java | 105 - .../collection/CleanableThreadLocal.java | 122 +- .../collection/IterableThreadLocal.java | 54 - .../collection/VariableThreadLocal.java | 17 - .../boydti/fawe/util/EditSessionBuilder.java | 3 +- .../com/boydti/fawe/util/ReflectionUtils.java | 580 ----- .../boydti/fawe/util/ReflectionUtils9.java | 77 - .../com/sk89q/worldedit/LocalSession.java | 50 +- .../worldedit/command/ToolUtilCommands.java | 26 - .../worldedit/command/tool/BrushTool.java | 124 +- .../com/sk89q/worldedit/entity/Player.java | 10 - .../worldedit/extension/platform/Actor.java | 17 - .../extension/platform/PlatformManager.java | 23 - .../com/sk89q/worldedit/extent/Extent.java | 4 + .../worldedit/session/request/Request.java | 15 +- 54 files changed, 92 insertions(+), 6829 deletions(-) delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/BukkitImageListener.java delete mode 100644 worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/CFIPacketListener.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ChunkSendProcessor.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/PersistentChunkSendProcessor.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/LevelDat.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/mcatest/MCATest.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/ImmutableVirtualWorld.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VirtualWorld.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/CFIDrawer.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/MCAWriter.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/change/CFIChange.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/object/collection/VariableThreadLocal.java delete mode 100644 worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils9.java diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java index 77e4b854c..d77b67a28 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/FaweBukkit.java @@ -9,8 +9,6 @@ import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.BukkitQueueHandler; import com.boydti.fawe.bukkit.adapter.NMSAdapter; import com.boydti.fawe.bukkit.listener.BrushListener; -import com.boydti.fawe.bukkit.listener.BukkitImageListener; -import com.boydti.fawe.bukkit.listener.CFIPacketListener; import com.boydti.fawe.bukkit.listener.ChunkListener9; import com.boydti.fawe.bukkit.listener.RenderListener; import com.boydti.fawe.bukkit.regions.GriefPreventionFeature; @@ -57,8 +55,6 @@ public class FaweBukkit implements IFawe, Listener { private ItemUtil itemUtil; private boolean listeningImages; - private BukkitImageListener imageListener; - private CFIPacketListener packetListener; private final boolean chunksStretched; private final FAWEPlatformAdapterImpl platformAdapter; @@ -102,26 +98,14 @@ public class FaweBukkit implements IFawe, Listener { }); } - @Override // Please don't delete this again, it's WIP - public void registerPacketListener() { - PluginManager manager = Bukkit.getPluginManager(); - if (packetListener == null && manager.getPlugin("ProtocolLib") != null) { - packetListener = new CFIPacketListener(plugin); - } - } - @Override public QueueHandler getQueueHandler() { return new BukkitQueueHandler(); } @Override public synchronized ImageViewer getImageViewer(com.sk89q.worldedit.entity.Player player) { - if (listeningImages && imageListener == null) { - return null; - } try { listeningImages = true; - registerPacketListener(); PluginManager manager = Bukkit.getPluginManager(); if (manager.getPlugin("PacketListenerApi") == null) { @@ -140,11 +124,7 @@ public class FaweBukkit implements IFawe, Listener { fos.write(jarData); } } - BukkitImageViewer viewer = new BukkitImageViewer(BukkitAdapter.adapt(player)); - if (imageListener == null) { - this.imageListener = new BukkitImageListener(plugin); - } - return viewer; + return new BukkitImageViewer(BukkitAdapter.adapt(player)); } catch (Throwable ignored) { } return null; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java index a32a24cf2..8977655ae 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitAdapter_1_15_2.java @@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.BitArray; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.math.BlockVector3; @@ -63,9 +62,6 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { public static final Field fieldTickingBlockCount; public static final Field fieldNonEmptyBlockCount; - private static final Field fieldDirtyCount; - private static final Field fieldDirtyBits; - private static final Field fieldBiomeArray; private final static MethodHandle methodGetVisibleChunk; @@ -76,6 +72,7 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { private static final int CHUNKSECTION_SHIFT; private static final Field fieldLock; + private static final long fieldLockOffset; static { try { @@ -93,11 +90,6 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); fieldNonEmptyBlockCount.setAccessible(true); - fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount"); - fieldDirtyCount.setAccessible(true); - fieldDirtyBits = PlayerChunk.class.getDeclaredField("r"); - fieldDirtyBits.setAccessible(true); - fieldBiomeArray = BiomeStorage.class.getDeclaredField("g"); fieldBiomeArray.setAccessible(true); @@ -109,12 +101,10 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { declaredSetLightNibbleArray.setAccessible(true); methodSetLightNibbleArray = MethodHandles.lookup().unreflect(declaredSetLightNibbleArray); - Field tmp = DataPaletteBlock.class.getDeclaredField("j"); - ReflectionUtils.setAccessibleNonFinal(tmp); - fieldLock = tmp; - fieldLock.setAccessible(true); - Unsafe unsafe = UnsafeUtils.getUNSAFE(); + fieldLock = DataPaletteBlock.class.getDeclaredField("j"); + fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class); int scale = unsafe.arrayIndexScale(ChunkSection[].class); if ((scale & (scale - 1)) != 0) { @@ -141,16 +131,17 @@ public final class BukkitAdapter_1_15_2 extends NMSAdapter { //todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS? try { synchronized (section) { + Unsafe unsafe = UnsafeUtils.getUNSAFE(); DataPaletteBlock blocks = section.getBlocks(); - ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks); + ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset); if (currentLock instanceof DelegateLock) { return (DelegateLock) currentLock; } DelegateLock newLock = new DelegateLock(currentLock); - fieldLock.set(blocks, newLock); + unsafe.putObject(blocks, fieldLockOffset, newLock); return newLock; } - } catch (IllegalAccessException e) { + } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java index 06b81d549..a2229f20d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitAdapter_1_16_1.java @@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.BitArrayUnstretched; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.math.BlockVector3; @@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { public static final Field fieldTickingBlockCount; public static final Field fieldNonEmptyBlockCount; - private static final Field fieldDirtyCount; - private static final Field fieldDirtyBits; - private static final Field fieldBiomeArray; private final static MethodHandle methodGetVisibleChunk; @@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { private static final int CHUNKSECTION_SHIFT; private static final Field fieldLock; + private static final long fieldLockOffset; static { try { @@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); fieldNonEmptyBlockCount.setAccessible(true); - fieldDirtyCount = PlayerChunk.class.getDeclaredField("dirtyCount"); - fieldDirtyCount.setAccessible(true); - fieldDirtyBits = PlayerChunk.class.getDeclaredField("r"); - fieldDirtyBits.setAccessible(true); - fieldBiomeArray = BiomeStorage.class.getDeclaredField("g"); fieldBiomeArray.setAccessible(true); @@ -106,12 +98,10 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { declaredGetVisibleChunk.setAccessible(true); methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk); - Field tmp = DataPaletteBlock.class.getDeclaredField("j"); - ReflectionUtils.setAccessibleNonFinal(tmp); - fieldLock = tmp; - fieldLock.setAccessible(true); - Unsafe unsafe = UnsafeUtils.getUNSAFE(); + fieldLock = DataPaletteBlock.class.getDeclaredField("j"); + fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class); int scale = unsafe.arrayIndexScale(ChunkSection[].class); if ((scale & (scale - 1)) != 0) { @@ -138,16 +128,17 @@ public final class BukkitAdapter_1_16_1 extends NMSAdapter { //todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS? try { synchronized (section) { + Unsafe unsafe = UnsafeUtils.getUNSAFE(); DataPaletteBlock blocks = section.getBlocks(); - ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks); + ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset); if (currentLock instanceof DelegateLock) { return (DelegateLock) currentLock; } DelegateLock newLock = new DelegateLock(currentLock); - fieldLock.set(blocks, newLock); + unsafe.putObject(blocks, fieldLockOffset, newLock); return newLock; } - } catch (IllegalAccessException e) { + } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitAdapter_1_16_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitAdapter_1_16_2.java index 7a69eee9f..afeab946d 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitAdapter_1_16_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitAdapter_1_16_2.java @@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.BitArrayUnstretched; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.math.BlockVector3; @@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter { public static final Field fieldTickingBlockCount; public static final Field fieldNonEmptyBlockCount; - private static final Field fieldDirty; - private static final Field fieldDirtyBlocks; - private static final Field fieldBiomeArray; private static final MethodHandle methodGetVisibleChunk; @@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter { private static final int CHUNKSECTION_SHIFT; private static final Field fieldLock; + private static final long fieldLockOffset; static { try { @@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter { fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); fieldNonEmptyBlockCount.setAccessible(true); - fieldDirty = PlayerChunk.class.getDeclaredField("p"); - fieldDirty.setAccessible(true); - fieldDirtyBlocks = PlayerChunk.class.getDeclaredField("dirtyBlocks"); - fieldDirtyBlocks.setAccessible(true); - fieldBiomeArray = BiomeStorage.class.getDeclaredField("h"); fieldBiomeArray.setAccessible(true); @@ -106,25 +98,16 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter { declaredGetVisibleChunk.setAccessible(true); methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk); - Field tmp = DataPaletteBlock.class.getDeclaredField("j"); - ReflectionUtils.setAccessibleNonFinal(tmp); - fieldLock = tmp; - fieldLock.setAccessible(true); - Unsafe unsafe = UnsafeUtils.getUNSAFE(); + fieldLock = DataPaletteBlock.class.getDeclaredField("j"); + fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class); int scale = unsafe.arrayIndexScale(ChunkSection[].class); if ((scale & (scale - 1)) != 0) { throw new Error("data type scale not a power of two"); } CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); - - Class clsShortArraySet; - try { //paper - clsShortArraySet = Class.forName(new String(new char[]{'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'})); - } catch (Throwable t) { // still using spigot boo - clsShortArraySet = Class.forName(new String(new char[]{'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't', '.', 'l', 'i', 'b', 's', '.', 'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'})); - } } catch (RuntimeException e) { throw e; } catch (Throwable rethrow) { @@ -145,16 +128,17 @@ public final class BukkitAdapter_1_16_2 extends NMSAdapter { //todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS? try { synchronized (section) { + Unsafe unsafe = UnsafeUtils.getUNSAFE(); DataPaletteBlock blocks = section.getBlocks(); - ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks); + ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset); if (currentLock instanceof DelegateLock) { return (DelegateLock) currentLock; } DelegateLock newLock = new DelegateLock(currentLock); - fieldLock.set(blocks, newLock); + unsafe.putObject(blocks, fieldLockOffset, newLock); return newLock; } - } catch (IllegalAccessException e) { + } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java index 19e03a22d..9b15adefc 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java @@ -7,7 +7,6 @@ import com.boydti.fawe.bukkit.adapter.NMSAdapter; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.BitArrayUnstretched; import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.ReflectionUtils; import com.boydti.fawe.util.TaskManager; import com.mojang.datafixers.util.Either; import com.sk89q.worldedit.math.BlockVector3; @@ -63,9 +62,6 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { public static final Field fieldTickingBlockCount; public static final Field fieldNonEmptyBlockCount; - private static final Field fieldDirty; - private static final Field fieldDirtyBlocks; - private static final Field fieldBiomeArray; private static final MethodHandle methodGetVisibleChunk; @@ -74,6 +70,7 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { private static final int CHUNKSECTION_SHIFT; private static final Field fieldLock; + private static final long fieldLockOffset; static { try { @@ -94,11 +91,6 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount"); fieldNonEmptyBlockCount.setAccessible(true); - fieldDirty = PlayerChunk.class.getDeclaredField("p"); - fieldDirty.setAccessible(true); - fieldDirtyBlocks = PlayerChunk.class.getDeclaredField("dirtyBlocks"); - fieldDirtyBlocks.setAccessible(true); - fieldBiomeArray = BiomeStorage.class.getDeclaredField("h"); fieldBiomeArray.setAccessible(true); @@ -106,25 +98,16 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { declaredGetVisibleChunk.setAccessible(true); methodGetVisibleChunk = MethodHandles.lookup().unreflect(declaredGetVisibleChunk); - Field tmp = DataPaletteBlock.class.getDeclaredField("j"); - ReflectionUtils.setAccessibleNonFinal(tmp); - fieldLock = tmp; - fieldLock.setAccessible(true); - Unsafe unsafe = UnsafeUtils.getUNSAFE(); + fieldLock = DataPaletteBlock.class.getDeclaredField("j"); + fieldLockOffset = unsafe.objectFieldOffset(fieldLock); + CHUNKSECTION_BASE = unsafe.arrayBaseOffset(ChunkSection[].class); int scale = unsafe.arrayIndexScale(ChunkSection[].class); if ((scale & (scale - 1)) != 0) { throw new Error("data type scale not a power of two"); } CHUNKSECTION_SHIFT = 31 - Integer.numberOfLeadingZeros(scale); - - Class clsShortArraySet; - try { //paper - clsShortArraySet = Class.forName(new String(new char[]{'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'})); - } catch (Throwable t) { // still using spigot boo - clsShortArraySet = Class.forName(new String(new char[]{'o', 'r', 'g', '.', 'b', 'u', 'k', 'k', 'i', 't', '.', 'c', 'r', 'a', 'f', 't', 'b', 'u', 'k', 'k', 'i', 't', '.', 'l', 'i', 'b', 's', '.', 'i', 't', '.', 'u', 'n', 'i', 'm', 'i', '.', 'd', 's', 'i', '.', 'f', 'a', 's', 't', 'u', 't', 'i', 'l', '.', 's', 'h', 'o', 'r', 't', 's', '.', 'S', 'h', 'o', 'r', 't', 'A', 'r', 'r', 'a', 'y', 'S', 'e', 't'})); - } } catch (RuntimeException e) { throw e; } catch (Throwable rethrow) { @@ -145,16 +128,17 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { //todo there has to be a better way to do this. Maybe using a() in DataPaletteBlock which acquires the lock in NMS? try { synchronized (section) { + Unsafe unsafe = UnsafeUtils.getUNSAFE(); DataPaletteBlock blocks = section.getBlocks(); - ReentrantLock currentLock = (ReentrantLock) fieldLock.get(blocks); + ReentrantLock currentLock = (ReentrantLock) unsafe.getObject(blocks, fieldLockOffset); if (currentLock instanceof DelegateLock) { return (DelegateLock) currentLock; } DelegateLock newLock = new DelegateLock(currentLock); - fieldLock.set(blocks, newLock); + unsafe.putObject(blocks, fieldLockOffset, newLock); return newLock; } - } catch (IllegalAccessException e) { + } catch (Throwable e) { e.printStackTrace(); throw new RuntimeException(e); } @@ -191,7 +175,7 @@ public final class BukkitAdapter_1_16_5 extends NMSAdapter { } } - public static void sendChunk(WorldServer nmsWorld, int chunkX, int chunkZ, int mask, boolean lighting) { + public static void sendChunk(WorldServer nmsWorld, int chunkX, int chunkZ, boolean lighting) { PlayerChunk playerChunk = getPlayerChunk(nmsWorld, chunkX, chunkZ); if (playerChunk == null) { return; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java index 848758437..8dca055a8 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java @@ -689,7 +689,7 @@ public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBl @Override public synchronized void send(int mask, boolean lighting) { - BukkitAdapter_1_16_5.sendChunk(world, chunkX, chunkZ, mask, lighting); + BukkitAdapter_1_16_5.sendChunk(world, chunkX, chunkZ, lighting); } @Override diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java index c5e2c3dd9..94819b6e5 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java @@ -214,7 +214,7 @@ public class FAWEWorldNativeAccess_1_16_R3 implements WorldNativeAccess cc.chunk.setType(cc.position, cc.blockData, sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE))); for (IntPair chunk : cachedChunksToSend) { - BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, 0, false); + BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, false); } } }; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/TuinityRelighter_1_16_5.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/TuinityRelighter_1_16_5.java index 1043843c4..b902eee97 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/TuinityRelighter_1_16_5.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/TuinityRelighter_1_16_5.java @@ -180,7 +180,7 @@ public class TuinityRelighter_1_16_5 implements Relighter { int x = pos.x; int z = pos.z; if (delay) { // we still need to send the block changes of that chunk - BukkitAdapter_1_16_5.sendChunk(world, x, z, -1, false); + BukkitAdapter_1_16_5.sendChunk(world, x, z, false); } world.getChunkProvider().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/BukkitImageListener.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/BukkitImageListener.java deleted file mode 100644 index 176167e36..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/BukkitImageListener.java +++ /dev/null @@ -1,292 +0,0 @@ -package com.boydti.fawe.bukkit.listener; - -import com.boydti.fawe.bukkit.util.image.BukkitImageViewer; -import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; -import com.boydti.fawe.util.image.ImageViewer; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitPlayer; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.block.Block; -import org.bukkit.entity.Entity; -import org.bukkit.entity.ItemFrame; -import org.bukkit.entity.Player; -import org.bukkit.event.Event; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.player.PlayerEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EquipmentSlot; -import org.bukkit.plugin.Plugin; - -import java.util.Collection; -import java.util.List; - -public class BukkitImageListener implements Listener { - - private Location mutable = new Location(Bukkit.getWorlds().get(0), 0, 0, 0); - - public BukkitImageListener(Plugin plugin) { - Bukkit.getPluginManager().registerEvents(this, plugin); - } - - //TODO Fix along with CFI code 2020-02-04 - /* - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onPlayerInteractEntity(AsyncPlayerChatEvent event) { - Set recipients = event.getRecipients(); - Iterator iter = recipients.iterator(); - while (iter.hasNext()) { - Player player = iter.next(); - BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player); - CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings"); - if (player.equals(event.getPlayer()) || !bukkitPlayer.hasMeta() || settings == null || !settings.hasGenerator()) { - continue; - } - - String name = player.getName().toLowerCase(Locale.ROOT); - if (!event.getMessage().toLowerCase(Locale.ROOT).contains(name)) { - ArrayDeque buffered = bukkitPlayer.getMeta("CFIBufferedMessages"); - if (buffered == null) { - bukkitPlayer.setMeta("CFIBufferedMessaged", buffered = new ArrayDeque<>()); - } - String full = String.format(event.getFormat(), event.getPlayer().getDisplayName(), - event.getMessage()); - buffered.add(full); - iter.remove(); - } - } - }*/ - - @EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) - public void onHangingBreakByEntity(HangingBreakByEntityEvent event) { - if (!(event.getRemover() instanceof Player)) { - return; - } - handleInteract(event, (Player) event.getRemover(), event.getEntity(), false); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { - if (!(event.getDamager() instanceof Player)) { - return; - } - handleInteract(event, (Player) event.getDamager(), event.getEntity(), false); - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerInteract(PlayerInteractEvent event) { - if (event.useItemInHand() == Event.Result.DENY) { - return; - } - - Player player = event.getPlayer(); - BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player); - if (bukkitPlayer.getMeta("CFISettings") == null) { - return; - } - try { - if (event.getHand() == EquipmentSlot.OFF_HAND) { - return; - } - } catch (NoSuchFieldError | NoSuchMethodError ignored) { - } - - List target = player.getLastTwoTargetBlocks(null, 100); - if (target.isEmpty()) { - return; - } - - Block targetBlock = target.get(0); - World world = player.getWorld(); - mutable.setWorld(world); - mutable.setX(targetBlock.getX() + 0.5); - mutable.setY(targetBlock.getY() + 0.5); - mutable.setZ(targetBlock.getZ() + 0.5); - Collection entities = world.getNearbyEntities(mutable, 0.46875, 0, 0.46875); - - if (!entities.isEmpty()) { - Action action = event.getAction(); - boolean primary = - action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK; - - double minDist = Integer.MAX_VALUE; - ItemFrame minItemFrame = null; - - for (Entity entity : entities) { - if (entity instanceof ItemFrame) { - ItemFrame itemFrame = (ItemFrame) entity; - Location loc = itemFrame.getLocation(); - double dx = loc.getX() - mutable.getX(); - double dy = loc.getY() - mutable.getY(); - double dz = loc.getZ() - mutable.getZ(); - double dist = dx * dx + dy * dy + dz * dz; - if (dist < minDist) { - minItemFrame = itemFrame; - minDist = dist; - } - } - } - if (minItemFrame != null) { - handleInteract(event, minItemFrame, primary); - if (event.isCancelled()) { - return; - } - } - } - } - - @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - handleInteract(event, event.getRightClicked(), true); - } - - private BukkitImageViewer get(HeightMapMCAGenerator generator) { - if (generator == null) { - return null; - } - - ImageViewer viewer = generator.getImageViewer(); - if (!(viewer instanceof BukkitImageViewer)) { - return null; - } - - return (BukkitImageViewer) viewer; - } - - private void handleInteract(PlayerEvent event, Entity entity, boolean primary) { - handleInteract(event, event.getPlayer(), entity, primary); - } - - private void handleInteract(Event event, Player player, Entity entity, boolean primary) { - //todo fix with cfi code 2020-02-04 - /* - if (!(entity instanceof ItemFrame)) { - return; - } - ItemFrame itemFrame = (ItemFrame) entity; - - BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player); - CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings"); - HeightMapMCAGenerator generator = settings == null ? null : settings.getGenerator(); - BukkitImageViewer viewer = get(generator); - if (viewer == null) { - return; - } - - if (itemFrame.getRotation() != Rotation.NONE) { - itemFrame.setRotation(Rotation.NONE); - } - - LocalSession session = bukkitPlayer.getSession(); - BrushTool tool; - try { - tool = session.getBrushTool(bukkitPlayer, false); - } catch (InvalidToolBindException e) { - return; - } - - ItemFrame[][] frames = viewer.getItemFrames(); - if (frames == null || tool == null) { - viewer.selectFrame(itemFrame); - player.updateInventory(); - TaskManager.IMP.laterAsync(() -> viewer.view(generator), 1); - return; - } - - BrushSettings context = primary ? tool.getPrimary() : tool.getSecondary(); - Brush brush = context.getBrush(); - if (brush == null) { - return; - } - tool.setContext(context); - - if (event instanceof Cancellable) { - ((Cancellable) event).setCancelled(true); - } - - Location target = itemFrame.getLocation(); - Location source = player.getLocation(); - - double yawRad = Math.toRadians(source.getYaw() + 90d); - double pitchRad = Math.toRadians(-source.getPitch()); - - double a = Math.cos(pitchRad); - double xRat = Math.cos(yawRad) * a; - double zRat = Math.sin(yawRad) * a; - - BlockFace facing = itemFrame.getFacing(); - double thickness = 1 / 32D + 1 / 128D; - double modX = facing.getModX(); - double modZ = facing.getModZ(); - double dx = source.getX() - target.getX() - modX * thickness; - double dy = source.getY() + player.getEyeHeight() - target.getY(); - double dz = source.getZ() - target.getZ() - modZ * thickness; - - double offset; - double localX; - if (modX != 0) { - offset = dx / xRat; - localX = (-modX) * (dz - offset * zRat); - } else { - offset = dz / zRat; - localX = (modZ) * (dx - offset * xRat); - } - double localY = dy - offset * Math.sin(pitchRad); - int localPixelX = (int) ((localX + 0.5) * 128); - int localPixelY = (int) ((localY + 0.5) * 128); - - UUID uuid = itemFrame.getUniqueId(); - for (int blockX = 0; blockX < frames.length; blockX++) { - for (int blockY = 0; blockY < frames[0].length; blockY++) { - if (uuid.equals(frames[blockX][blockY].getUniqueId())) { - int pixelX = localPixelX + blockX * 128; - int pixelY = (128 * frames[0].length) - (localPixelY + blockY * 128 + 1); - - int width = generator.getWidth(); - int length = generator.getLength(); - int worldX = (int) (pixelX * width / (frames.length * 128d)); - int worldZ = (int) (pixelY * length / (frames[0].length * 128d)); - - if (worldX < 0 || worldX > width || worldZ < 0 || worldZ > length) { - return; - } - - bukkitPlayer.runAction(() -> { - BlockVector3 wPos = BlockVector3.at(worldX, 0, worldZ); - viewer.refresh(); - int topY = generator - .getNearestSurfaceTerrainBlock(wPos.getBlockX(), wPos.getBlockZ(), 255, - 0, 255); - wPos = wPos.withY(topY); - - EditSession es = new EditSessionBuilder(bukkitPlayer.getWorld()).player(bukkitPlayer) - .combineStages(false).autoQueue(false).blockBag(null).limitUnlimited() - .build(); - ExtentTraverser last = new ExtentTraverser(es.getExtent()).last(); - Extent extent = last.get(); - if (extent instanceof IQueueExtent) { - last = last.previous(); - } - last.setNext(generator); - try { - brush.build(es, wPos, context.getMaterial(), context.getSize()); - } catch (WorldEditException e) { - e.printStackTrace(); - } - es.flushQueue(); - viewer.view(generator); - }, true, true); - - return; - } - } - }*/ - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/CFIPacketListener.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/CFIPacketListener.java deleted file mode 100644 index 59f391fbd..000000000 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/listener/CFIPacketListener.java +++ /dev/null @@ -1,338 +0,0 @@ -package com.boydti.fawe.bukkit.listener; - -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.object.RunnableVal3; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.ChunkCoordIntPair; -import com.comphenix.protocol.wrappers.EnumWrappers; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldedit.bukkit.BukkitPlayer; -import com.sk89q.worldedit.event.platform.BlockInteractEvent; -import com.sk89q.worldedit.event.platform.Interaction; -import com.sk89q.worldedit.extension.platform.PlatformManager; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerTeleportEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.PlayerInventory; -import org.bukkit.plugin.Plugin; - -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -/** - * The CFIPacketListener handles packets for editing the {@link VirtualWorld}. - * - *

- * The virtual world will be displayed inside the current world. Block/Chunk/Movement packets - * need to be handled properly. - *

- */ -public class CFIPacketListener implements Listener { - - private final Plugin plugin; - private final ProtocolManager protocolmanager; - - public CFIPacketListener(Plugin plugin) { - this.plugin = plugin; - this.protocolmanager = ProtocolLibrary.getProtocolManager(); - - // Direct digging to the virtual world - registerBlockEvent(PacketType.Play.Client.BLOCK_DIG, false, new RunnableVal3() { - @Override - public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) { - try { - Player plr = event.getPlayer(); - BlockVector3 realPos = pt.add(gen.getOrigin().toBlockPoint()); - if (!sendBlockChange(plr, gen, pt, Interaction.HIT)) { - gen.setBlock(pt, BlockTypes.AIR.getDefaultState()); - } - } catch (WorldEditException e) { - e.printStackTrace(); - } - } - }); - - // Direct placing to the virtual world - RunnableVal3 placeTask = new RunnableVal3() { - @Override - public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) { - try { - Player plr = event.getPlayer(); - List hands = event.getPacket().getHands().getValues(); - - EnumWrappers.Hand enumHand = hands.isEmpty() ? EnumWrappers.Hand.MAIN_HAND : hands.get(0); - PlayerInventory inv = plr.getInventory(); - ItemStack hand = enumHand == EnumWrappers.Hand.MAIN_HAND ? inv.getItemInMainHand() : inv.getItemInOffHand(); - if (hand.getType().isBlock()) { - Material type = hand.getType(); - switch (type) { - case AIR: - case CAVE_AIR: - case VOID_AIR: - break; - default: { - BlockState block = BukkitAdapter.asBlockState(hand); - if (block != null) { - gen.setBlock(pt, block); - return; - } - } - } - } - pt = getRelPos(event, gen); - sendBlockChange(plr, gen, pt, Interaction.OPEN); - } catch (WorldEditException e) { - e.printStackTrace(); - } - } - }; - registerBlockEvent(PacketType.Play.Client.BLOCK_PLACE, true, placeTask); - registerBlockEvent(PacketType.Play.Client.USE_ITEM, true, placeTask); - - // Cancel block change packets where the real world overlaps with the virtual one - registerBlockEvent(PacketType.Play.Server.BLOCK_CHANGE, false, new RunnableVal3() { - @Override - public void run(PacketEvent event, VirtualWorld gen, BlockVector3 pt) { - // Do nothing - } - }); - - // Modify chunk packets where the real world overlaps with the virtual one - protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MAP_CHUNK) { - @Override - public void onPacketSending(PacketEvent event) { - if (!event.isServerPacket() || FaweCache.IMP.CHUNK_FLAG.get().get()) { - return; - } - VirtualWorld gen = getGenerator(event); - if (gen != null) { - BlockVector3 origin = gen.getOrigin().toBlockPoint(); - PacketContainer packet = event.getPacket(); - StructureModifier ints = packet.getIntegers(); - int cx = ints.read(0); - int cz = ints.read(1); - - int ocx = origin.getBlockX() >> 4; - int ocz = origin.getBlockZ() >> 4; - - if (gen.contains(BlockVector3.at((cx - ocx) << 4, 0, (cz - ocz) << 4))) { - event.setCancelled(true); - gen.refreshChunk(cx - ocx, cz - ocz); - } - } - } - }); - - // The following few listeners are to ignore block collisions where the virtual and real world overlap - - protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.ENTITY_VELOCITY) { - @Override - public void onPacketSending(PacketEvent event) { - if (!event.isServerPacket()) { - return; - } - - Player player = event.getPlayer(); - Location pos = player.getLocation(); - VirtualWorld gen = getGenerator(event); - if (gen != null) { - BlockVector3 origin = gen.getOrigin().toBlockPoint(); - BlockVector3 pt = BlockVector3.at(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); - - StructureModifier ints = event.getPacket().getIntegers(); - int id = ints.read(0); - int mx = ints.read(1); - int my = ints.read(2); - int mz = ints.read(3); - - if (gen.contains(pt.subtract(origin)) && mx == 0 && my == 0 && mz == 0) { - event.setCancelled(true); - } - } - } - }); - - protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.POSITION) { - @Override - public void onPacketSending(PacketEvent event) { - if (!event.isServerPacket()) { - return; - } - - Player player = event.getPlayer(); - Location pos = player.getLocation(); - VirtualWorld gen = getGenerator(event); - if (gen != null) { - BlockVector3 origin = gen.getOrigin().toBlockPoint(); - BlockVector3 from = BlockVector3.at(pos.getBlockX(), pos.getBlockY(), pos.getBlockZ()); - - PacketContainer packet = event.getPacket(); - StructureModifier doubles = packet.getDoubles(); - BlockVector3 to = BlockVector3.at(doubles.read(0), doubles.read(1), doubles.read(2)); - if (gen.contains(to.subtract(origin)) && from.distanceSq(to) < 8) { - int id = packet.getIntegers().read(0); - PacketContainer reply = new PacketContainer(PacketType.Play.Client.TELEPORT_ACCEPT); - reply.getIntegers().write(0, id); - try { - protocolmanager.recieveClientPacket(player, reply); - } catch (IllegalAccessException | InvocationTargetException e) { - e.printStackTrace(); - } - event.setCancelled(true); - } - } - } - }); - - protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, PacketType.Play.Server.MULTI_BLOCK_CHANGE) { - @Override - public void onPacketSending(PacketEvent event) { - if (!event.isServerPacket()) { - return; - } - - VirtualWorld gen = getGenerator(event); - if (gen != null) { - PacketContainer packet = event.getPacket(); - ChunkCoordIntPair chunk = packet.getChunkCoordIntPairs().read(0); - BlockVector3 origin = gen.getOrigin().toBlockPoint(); - int cx = chunk.getChunkX() - (origin.getBlockX() >> 4); - int cz = chunk.getChunkZ() - (origin.getBlockX() >> 4); - if (gen.contains(BlockVector3.at(cx << 4, 0, cz << 4))) { - event.setCancelled(true); - } - } - } - }); - } - - @EventHandler - public void onTeleport(PlayerTeleportEvent event) { - final Player player = event.getPlayer(); - VirtualWorld gen = getGenerator(player); - if (gen != null) { - Location from = event.getFrom(); - Location to = event.getTo(); - if (to.getWorld().equals(from.getWorld()) && to.distanceSquared(from) < 8) { - event.setTo(player.getLocation()); - event.setCancelled(true); - player.setVelocity(player.getVelocity()); - } - } - } - - private boolean sendBlockChange(Player plr, VirtualWorld gen, BlockVector3 pt, Interaction action) { - PlatformManager platform = WorldEdit.getInstance().getPlatformManager(); - com.sk89q.worldedit.entity.Player actor = BukkitAdapter.adapt(plr); - com.sk89q.worldedit.util.Location location = new com.sk89q.worldedit.util.Location(actor.getWorld(), pt.toVector3()); - BlockInteractEvent toCall = new BlockInteractEvent(actor, location, action); - platform.handleBlockInteract(toCall); - if (toCall.isCancelled() || action == Interaction.OPEN) { - BlockVector3 realPos = pt.add(gen.getOrigin().toBlockPoint()); - BlockState block = gen.getBlock(pt); - sendBlockChange(plr, realPos, block); - return true; - } - return false; - } - - private void sendBlockChange(Player plr, BlockVector3 pt, BlockState block) { - plr.sendBlockChange(new Location(plr.getWorld(), pt.getBlockX(), pt.getBlockY(), pt.getBlockZ()), BukkitAdapter.adapt(block)); - } - - private VirtualWorld getGenerator(PacketEvent event) { - return getGenerator(event.getPlayer()); - } - - private VirtualWorld getGenerator(Player player) { - BukkitPlayer bukkitPlayer = BukkitAdapter.adapt(player); - VirtualWorld vw = bukkitPlayer.getSession().getVirtualWorld(); - if (vw != null) { - return vw; - } - // CFICommands.CFISettings settings = bukkitPlayer.getMeta("CFISettings"); - // if (settings != null && settings.hasGenerator() && settings.getGenerator().hasPacketViewer()) { - // return settings.getGenerator(); - // } - return null; - } - - private BlockVector3 getRelPos(PacketEvent event, VirtualWorld generator) { - PacketContainer packet = event.getPacket(); - StructureModifier position = packet.getBlockPositionModifier(); - BlockPosition loc = position.readSafely(0); - if (loc == null) { - return null; - } - BlockVector3 origin = generator.getOrigin().toBlockPoint(); - return BlockVector3.at(loc.getX() - origin.getBlockX(), loc.getY() - origin.getBlockY(), loc.getZ() - origin.getBlockZ()); - } - - private void handleBlockEvent(PacketEvent event, boolean relative, RunnableVal3 task) { - VirtualWorld gen = getGenerator(event); - if (gen != null) { - BlockVector3 pt = getRelPos(event, gen); - if (pt != null) { - if (relative) { - pt = getRelative(event, pt); - } - if (gen.contains(pt)) { - event.setCancelled(true); - task.run(event, gen, pt); - } - } - } - } - - private void registerBlockEvent(PacketType type, boolean relative, RunnableVal3 task) { - protocolmanager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.NORMAL, type) { - @Override - public void onPacketReceiving(final PacketEvent event) { - if (type.isClient() || event.isServerPacket()) { - handleBlockEvent(event, relative, task); - } - } - - @Override - public void onPacketSending(PacketEvent event) { - onPacketReceiving(event); - } - }); - } - - private BlockVector3 getRelative(PacketEvent container, BlockVector3 pt) { - PacketContainer packet = container.getPacket(); - StructureModifier dirs = packet.getDirections(); - EnumWrappers.Direction dir = dirs.readSafely(0); - if (dir == null) { - return pt; - } - switch (dir.ordinal()) { - case 0: return pt.add(0, -1, 0); - case 1: return pt.add(0, 1, 0); - case 2: return pt.add(0, 0, -1); - case 3: return pt.add(0, 0, 1); - case 4: return pt.add(-1, 0, 0); - case 5: return pt.add(1, 0, 0); - default: return pt; - } - } -} diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/BukkitReflectionUtils.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/BukkitReflectionUtils.java index aa91f4a60..dd2be9725 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/BukkitReflectionUtils.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/util/BukkitReflectionUtils.java @@ -41,33 +41,6 @@ public class BukkitReflectionUtils { } } - - /** - * Get class for name. Replace {nms} to net.minecraft.server.V*. Replace {cb} to org.bukkit.craftbukkit.V*. Replace - * {nm} to net.minecraft - * - * @param classes possible class paths - * @return RefClass object - * @throws RuntimeException if no class found - */ - public static ReflectionUtils.RefClass getRefClass(final String... classes) - throws RuntimeException { - if (preClassM == null) { - init(); - } - for (String className : classes) { - try { - className = className.replace("{cb}", preClassB).replace("{nms}", preClassM) - .replace("{nm}", "net.minecraft"); - return ReflectionUtils.getRefClass(Class.forName(className)); - } catch (final ClassNotFoundException ignored) { - } - } - throw new RuntimeException( - "no class found: " + classes[0].replace("{cb}", preClassB).replace("{nms}", preClassM) - .replace("{nm}", "net.minecraft")); - } - public static Class getNmsClass(final String name) { final String className = "net.minecraft.server." + getVersion() + "." + name; return ReflectionUtils.getClass(className); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java index 514de4a33..53f5b26d3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/Fawe.java @@ -2,7 +2,6 @@ package com.boydti.fawe; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.brush.visualization.VisualQueue; import com.boydti.fawe.util.CachedTextureUtil; import com.boydti.fawe.util.CleanTextureUtil; import com.boydti.fawe.util.FaweTimer; @@ -82,7 +81,6 @@ public class Fawe { */ private final FaweTimer timer; private FaweVersion version; - private VisualQueue visualQueue; private TextureUtil textures; @@ -148,7 +146,6 @@ public class Fawe { // Delayed worldedit setup TaskManager.IMP.later(() -> { try { - visualQueue = new VisualQueue(3); WEManager.IMP.managers.addAll(Fawe.this.implementation.getMaskManagers()); } catch (Throwable ignored) { } @@ -208,13 +205,6 @@ public class Fawe { return timer; } - /** - * Get the visual queue. - */ - public VisualQueue getVisualQueue() { - return visualQueue; - } - /** * The FAWE version. * diff --git a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java index ac058a88d..d711cd72b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/FaweCache.java @@ -9,7 +9,6 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.BitArray; import com.boydti.fawe.object.collection.BitArrayUnstretched; import com.boydti.fawe.object.collection.CleanableThreadLocal; -import com.boydti.fawe.object.collection.VariableThreadLocal; import com.boydti.fawe.object.exception.FaweBlockBagException; import com.boydti.fawe.object.exception.FaweChunkLoadException; import com.boydti.fawe.object.exception.FaweException; @@ -80,23 +79,19 @@ public enum FaweCache implements Trimable { @Override public synchronized boolean trim(boolean aggressive) { - if (aggressive) { - CleanableThreadLocal.cleanAll(); - } else { - CHUNK_FLAG.clean(); - BYTE_BUFFER_8192.clean(); - BLOCK_TO_PALETTE.clean(); - PALETTE_TO_BLOCK.clean(); - BLOCK_STATES.clean(); - SECTION_BLOCKS.clean(); - PALETTE_CACHE.clean(); - PALETTE_TO_BLOCK_CHAR.clean(); - INDEX_STORE.clean(); + CHUNK_FLAG.clean(); + BYTE_BUFFER_8192.clean(); + BLOCK_TO_PALETTE.clean(); + PALETTE_TO_BLOCK.clean(); + BLOCK_STATES.clean(); + SECTION_BLOCKS.clean(); + PALETTE_CACHE.clean(); + PALETTE_TO_BLOCK_CHAR.clean(); + INDEX_STORE.clean(); - MUTABLE_VECTOR3.clean(); - MUTABLE_BLOCKVECTOR3.clean(); - SECTION_BITS_TO_CHAR.clean(); - } + MUTABLE_VECTOR3.clean(); + MUTABLE_BLOCKVECTOR3.clean(); + SECTION_BITS_TO_CHAR.clean(); for (Entry, Pool> entry : REGISTERED_POOLS.entrySet()) { Pool pool = entry.getValue(); pool.clear(); @@ -158,12 +153,9 @@ public enum FaweCache implements Trimable { */ public final CleanableThreadLocal CHUNK_FLAG = new CleanableThreadLocal<>(AtomicBoolean::new); // resets to false - public final CleanableThreadLocal LONG_BUFFER_1024 = new CleanableThreadLocal<>(() -> new long[1024]); public final CleanableThreadLocal BYTE_BUFFER_8192 = new CleanableThreadLocal<>(() -> new byte[8192]); - public final VariableThreadLocal BYTE_BUFFER_VAR = new VariableThreadLocal(); - public final CleanableThreadLocal BLOCK_TO_PALETTE = new CleanableThreadLocal<>(() -> { int[] result = new int[BlockTypesCache.states.length]; Arrays.fill(result, Integer.MAX_VALUE); @@ -186,8 +178,6 @@ public enum FaweCache implements Trimable { public final CleanableThreadLocal INDEX_STORE = new CleanableThreadLocal<>(() -> new int[256]); - public final CleanableThreadLocal HEIGHT_STORE = new CleanableThreadLocal<>(() -> new int[256]); - /** * Holds data for a palette used in a chunk section */ @@ -314,14 +304,6 @@ public enum FaweCache implements Trimable { return toPaletteUnstretched(layerOffset, null, blocks); } - /** - * Convert raw int array to unstretched palette (1.16) - * @return palette - */ - public Palette toPaletteUnstretched(int layerOffset, int[] blocks) { - return toPaletteUnstretched(layerOffset, blocks, null); - } - private Palette toPaletteUnstretched(int layerOffset, int[] blocksInts, char[] blocksChars) { int[] blockToPalette = BLOCK_TO_PALETTE.get(); int[] paletteToBlock = PALETTE_TO_BLOCK.get(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java b/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java index 4859ed6d3..cc4ebd733 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/IFawe.java @@ -23,8 +23,6 @@ public interface IFawe { return null; } - public default void registerPacketListener() {} - String getPlatform(); UUID getUUID(String name); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java deleted file mode 100644 index d03a3e9ec..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/CombinedBlocks.java +++ /dev/null @@ -1,164 +0,0 @@ -package com.boydti.fawe.beta; - -import com.boydti.fawe.FaweCache; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class CombinedBlocks implements IBlocks { - private final IBlocks secondary; - private final IBlocks primary; - private final int addMask; - - /** - * TODO Add a constructor here to satisfy checkstyle. - * - * @param addMask - bitMask for force sending sections, else 0 to send the primary ones - */ - public CombinedBlocks(IBlocks secondary, IBlocks primary, int addMask) { - this.secondary = secondary; - this.primary = primary; - this.addMask = addMask == 0 ? 0 : addMask & secondary.getBitMask(); - } - - @Override - public int getBitMask() { - int bitMask = addMask; - for (int layer = 0; layer < FaweCache.IMP.CHUNK_LAYERS; layer++) { - if (primary.hasSection(layer)) { - bitMask |= (1 << layer); - } - } - return bitMask; - } - - @Override - public void removeSectionLighting(int layer, boolean sky) { - primary.removeSectionLighting(layer, sky); - secondary.removeSectionLighting(layer, sky); - } - - @Override - public boolean hasSection(int layer) { - return primary.hasSection(layer) || secondary.hasSection(layer); - } - - @Override - public char[] load(int layer) { - if (primary.hasSection(layer)) { - char[] blocks = primary.load(layer); - if (secondary.hasSection(layer) && primary != secondary) { - int i = 0; - for (; i < 4096; i++) { - if (blocks[i] == 0) { - break; - } - } - if (i != 4096) { - char[] fallback = secondary.load(layer); - for (; i < 4096; i++) { - if (blocks[i] == 0) { - blocks[i] = fallback[i]; - } - } - } - } - return blocks; - } - return secondary.load(layer); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - BlockState block = primary.getBlock(x, y, z); - if (block.getBlockType() == BlockTypes.__RESERVED__) { - return secondary.getBlock(x, y, z); - } - return block; - } - - @Override - public Map getTiles() { - Map tiles = primary.getTiles(); - if (primary != secondary) { - if (tiles.isEmpty()) { - return secondary.getTiles(); - } - Map otherTiles = secondary.getTiles(); - if (!otherTiles.isEmpty()) { - HashMap copy = null; - for (Map.Entry entry : otherTiles.entrySet()) { - BlockVector3 pos = entry.getKey(); - BlockState block = primary.getBlock(pos.getX(), pos.getY(), pos.getZ()); - if (block.getBlockType() == BlockTypes.__RESERVED__) { - if (copy == null) { - copy = new HashMap<>(tiles); - } - copy.put(pos, entry.getValue()); - } - } - if (copy != null) { - return copy; - } - } - } - return tiles; - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - CompoundTag tile = primary.getTile(x, y, z); - if (tile != null) { - return tile; - } - return secondary.getTile(x, y, z); - } - - @Override - public Set getEntities() { - Set joined = primary.getEntities(); - if (primary != secondary) { - Set ents2 = secondary.getEntities(); - if (joined.isEmpty()) { - return ents2; - } - if (ents2.isEmpty()) { - return joined; - } - joined = new HashSet<>(joined); - joined.addAll(ents2); - } - return joined; - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - BiomeType biome = primary.getBiomeType(x, y, z); - if (biome == null) { - return secondary.getBiomeType(x, y, z); - } - return biome; - } - - @Override - public IBlocks reset() { - return null; - } - - @Override - public boolean trim(boolean aggressive) { - return false; - } - - @Override - public boolean trim(boolean aggressive, int layer) { - return false; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java index 28b41a2e4..37eb6bcc3 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/IQueueExtent.java @@ -75,12 +75,12 @@ public interface IQueueExtent extends Flushable, Trimable, ICh @Override default BlockVector3 getMinimumPoint() { - return BlockVector3.at(-30000000, 0, -30000000); + return BlockVector3.at(-30000000, getMinY(), -30000000); } @Override default BlockVector3 getMaximumPoint() { - return BlockVector3.at(30000000, FaweCache.IMP.WORLD_MAX_Y, 30000000); + return BlockVector3.at(30000000, getMaxY(), 30000000); } void setFastMode(boolean fastMode); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ChunkSendProcessor.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ChunkSendProcessor.java deleted file mode 100644 index bd15871fa..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/ChunkSendProcessor.java +++ /dev/null @@ -1,89 +0,0 @@ -package com.boydti.fawe.beta.implementation.processors; - -import com.boydti.fawe.beta.CombinedBlocks; -import com.boydti.fawe.beta.IBatchProcessor; -import com.boydti.fawe.beta.IBlocks; -import com.boydti.fawe.beta.IChunk; -import com.boydti.fawe.beta.IChunkGet; -import com.boydti.fawe.beta.IChunkSet; -import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.world.World; - -import java.util.Collection; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Future; -import java.util.function.Supplier; - -public class ChunkSendProcessor implements IBatchProcessor { - private final Supplier> players; - private final World world; - private final boolean full; - - public ChunkSendProcessor(World world, Supplier> players) { - this(world, players, false); - } - - public ChunkSendProcessor(World world, Supplier> players, boolean full) { - this.players = players; - this.world = world; - this.full = full; - } - - public World getWorld() { - return world; - } - - public Supplier> getPlayers() { - return players; - } - - @Override - public IChunkSet processSet(IChunk chunk, IChunkGet get, IChunkSet set) { - int chunkX = chunk.getX(); - int chunkZ = chunk.getZ(); - IBlocks blocks; - boolean full = this.full; - if (full) { - blocks = set; - } else { - blocks = combine(chunk, get, set); - if (set.hasBiomes()) { - full = true; - } - } - ChunkPacket packet = new ChunkPacket(chunkX, chunkZ, () -> blocks, full); - Collection stream = this.players.get(); - if (stream == null) { - world.sendFakeChunk(null, packet); - } else { - for (Player player : stream) { - if (player.getWorld().equals(world)) { - world.sendFakeChunk(player, packet); - } - } - } - return set; - } - - @Override - public Future postProcessSet(IChunk chunk, IChunkGet get, IChunkSet set) { - // Doesn't need to do anything - return CompletableFuture.completedFuture(set); - } - - public IBlocks combine(IChunk chunk, IChunkGet get, IChunkSet set) { - return new CombinedBlocks(get, set, 0); - } - - @Override - public Extent construct(Extent child) { - throw new UnsupportedOperationException("Processing only"); - } - - @Override - public ProcessorScope getScope() { - return ProcessorScope.READING_SET_BLOCKS; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/PersistentChunkSendProcessor.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/PersistentChunkSendProcessor.java deleted file mode 100644 index c2c4add4e..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/processors/PersistentChunkSendProcessor.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.boydti.fawe.beta.implementation.processors; - -import com.boydti.fawe.beta.CombinedBlocks; -import com.boydti.fawe.beta.IBlocks; -import com.boydti.fawe.beta.IChunk; -import com.boydti.fawe.beta.IChunkGet; -import com.boydti.fawe.beta.IChunkSet; -import com.boydti.fawe.beta.implementation.IChunkExtent; -import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.boydti.fawe.util.MathMan; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.world.World; -import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; -import it.unimi.dsi.fastutil.longs.Long2ObjectMap; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.function.Supplier; - -public class PersistentChunkSendProcessor extends ChunkSendProcessor { - private final Long2ObjectLinkedOpenHashMap current; - @Nullable - private Long2ObjectLinkedOpenHashMap previous; - private IChunkExtent queue; - - public PersistentChunkSendProcessor(World world, PersistentChunkSendProcessor previous, Supplier> players) { - super(world, players); - this.current = new Long2ObjectLinkedOpenHashMap<>(); - this.previous = previous != null ? previous.current : null; - } - - public void init(IChunkExtent queue) { - this.queue = queue; - } - - @Override - public IBlocks combine(IChunk chunk, IChunkGet get, IChunkSet set) { - int chunkX = chunk.getX(); - int chunkZ = chunk.getZ(); - long pair = MathMan.pairInt(chunkX, chunkZ); - char bitMask = (char) (set.hasBiomes() ? Character.MAX_VALUE : set.getBitMask()); - synchronized (this) { - current.put(pair, (Character) bitMask); - if (previous != null) { - Character lastValue = previous.remove(pair); - if (lastValue != null) { - bitMask |= lastValue; - } - } - } - return new CombinedBlocks(get, set, bitMask); - } - - public void flush() { - clear(previous); - previous = null; - } - - public void clear() { - if (queue == null) { - throw new IllegalStateException("Queue is not provided"); - } - clear(current); - current.clear(); - queue = null; - } - - public void clear(Long2ObjectLinkedOpenHashMap current) { - if (current != null && !current.isEmpty()) { - Collection players = getPlayers().get(); - for (Long2ObjectMap.Entry entry : current.long2ObjectEntrySet()) { - long pair = entry.getLongKey(); - int chunkX = MathMan.unpairIntX(pair); - int chunkZ = MathMan.unpairIntY(pair); - BlockVector2 pos = BlockVector2.at(chunkX, chunkZ); - Supplier chunk = () -> queue.getOrCreateChunk(pos.getX(), pos.getZ()); - ChunkPacket packet = new ChunkPacket(pos.getX(), pos.getZ(), chunk, true); - char bitMask = entry.getValue(); - if (players == null) { - getWorld().sendFakeChunk(null, packet); - } else { - players.forEach(player -> getWorld().sendFakeChunk(player, packet)); - } - } - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/LevelDat.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/LevelDat.java deleted file mode 100644 index 4ee85f8ae..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/LevelDat.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.boydti.fawe.jnbt.anvil; - -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.NBTOutputStream; -import it.unimi.dsi.fastutil.io.FastBufferedInputStream; -import it.unimi.dsi.fastutil.io.FastBufferedOutputStream; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; - -import static com.google.common.base.Preconditions.checkArgument; - -public class LevelDat { - private final File file; - private CompoundTag tag; - - public LevelDat(File file) { - checkArgument(file.exists()); - this.file = file; - } - - public void load() throws IOException { - try (NBTInputStream nis = new NBTInputStream(new FastBufferedInputStream(new GZIPInputStream(new FastBufferedInputStream(new FileInputStream(file)))))) { - this.tag = (CompoundTag) nis.readNamedTag().getTag(); - } - } - - public void save() throws IOException { - if (this.tag != null) { - try (NBTOutputStream nos = new NBTOutputStream(new FastBufferedOutputStream(new GZIPOutputStream(new FastBufferedOutputStream(new FileOutputStream(file)))))) { - nos.writeNamedTag("", tag); - } - } - } - - public CompoundTag getTag() { - return tag; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java deleted file mode 100644 index 8b55fa318..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAChunk.java +++ /dev/null @@ -1,651 +0,0 @@ -package com.boydti.fawe.jnbt.anvil; - -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.beta.Filter; -import com.boydti.fawe.beta.IChunk; -import com.boydti.fawe.beta.IChunkSet; -import com.boydti.fawe.beta.IQueueExtent; -import com.boydti.fawe.beta.implementation.filter.block.ChunkFilterBlock; -import com.boydti.fawe.beta.implementation.lighting.HeightMapType; -import com.boydti.fawe.jnbt.streamer.StreamDelegate; -import com.boydti.fawe.jnbt.streamer.ValueReader; -import com.boydti.fawe.object.collection.BitArray; -import com.boydti.fawe.object.collection.BlockVector3ChunkMap; -import com.boydti.fawe.util.MathMan; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.ListTag; -import com.sk89q.jnbt.NBTConstants; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.jnbt.NBTOutputStream; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.registry.state.Property; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.Future; -import javax.annotation.Nullable; - -public class MCAChunk implements IChunk { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - public final boolean[] hasSections = new boolean[16]; - - public boolean hasBiomes = false; - public final BiomeType[] biomes = new BiomeType[1024]; - - public final char[] blocks = new char[65536]; - - public final BlockVector3ChunkMap tiles = new BlockVector3ChunkMap<>(); - public final Map entities = new HashMap<>(); - public long inhabitedTime = System.currentTimeMillis(); - public long lastUpdate; - - public int modified; - public boolean deleted; - - public int chunkX; - public int chunkZ; - - private boolean createCopy = false; - - public MCAChunk() {} - - private boolean readLayer(Section section) { - if (section.palette == null || section.layer == -1 || section.blocksLength == -1 || section.palette[section.palette.length - 1] == null || section.blocks == null) { - // not initialized - return false; - } - - int bitsPerEntry = MathMan.log2nlz(section.palette.length - 1); - BitArray bitArray = new BitArray(bitsPerEntry, 4096, section.blocks); - char[] buffer = FaweCache.IMP.SECTION_BITS_TO_CHAR.get(); - bitArray.toRaw(buffer); - int offset = section.layer << 12; - for (int i = 0; i < buffer.length; i++) { - BlockState block = section.palette[buffer[i]]; - blocks[offset + i] = block.getOrdinalChar(); - } - - section.layer = -1; - section.blocksLength = -1; - section.blocks = null; - section.palette = null; - return true; - } - - private static class Section { - public int layer = -1; - public long[] blocks; - public int blocksLength = -1; - public BlockState[] palette; - } - - public MCAChunk(NBTInputStream nis, int chunkX, int chunkZ, boolean readPos) throws IOException { - this.chunkX = chunkX; - this.chunkZ = chunkZ; - read(nis, readPos); - } - - @Override - public void init(IQueueExtent extent, int x, int z) { - if (x != chunkX || z != chunkZ) { - throw new UnsupportedOperationException("Not reuse capable"); - } - } - - public void read(NBTInputStream nis, boolean readPos) throws IOException { - StreamDelegate root = createDelegate(nis, readPos); - nis.readNamedTagLazy(root); - } - - public StreamDelegate createDelegate(NBTInputStream nis, boolean readPos) { - StreamDelegate root = new StreamDelegate(); - StreamDelegate level = root.add("").add("Level"); - - level.add("InhabitedTime").withLong((i, v) -> inhabitedTime = v); - level.add("LastUpdate").withLong((i, v) -> lastUpdate = v); - - if (readPos) { - level.add("xPos").withInt((i, v) -> MCAChunk.this.chunkX = v); - level.add("zPos").withInt((i, v) -> MCAChunk.this.chunkZ = v); - } - - Section section = new Section(); - - StreamDelegate layers = level.add("Sections"); - StreamDelegate layer = layers.add(); - layer.withInfo((length, type) -> { - section.layer = -1; - section.blocksLength = -1; - }); - layer.add("Y").withInt((i, y) -> section.layer = y); - layer.add("Palette").withElem((ValueReader>) (index, map) -> { - String name = (String) map.get("Name"); - BlockType type = BlockTypes.get(name); - BlockState state = type.getDefaultState(); - Map properties = (Map) map.get("Properties"); - if (properties != null) { - for (Map.Entry entry : properties.entrySet()) { - String key = entry.getKey(); - String value = entry.getValue(); - Property property = type.getProperty(key); - state = state.with(property, property.getValueFor(value)); - } - } - section.palette[index] = state; - readLayer(section); - }); - StreamDelegate blockStates = layer.add("BlockStates"); - blockStates.withInfo((length, type) -> { - if (section.blocks == null) { - section.blocks = FaweCache.IMP.LONG_BUFFER_1024.get(); - } - section.blocksLength = length; - }); - blockStates.withLong((index, value) -> section.blocks[index] = value); - level.add("TileEntities").withElem((ValueReader>) (index, value) -> { - CompoundTag tile = FaweCache.IMP.asTag(value); - int x = tile.getInt("x") & 15; - int y = tile.getInt("y"); - int z = tile.getInt("z") & 15; - tiles.put(x, y, z, tile); - }); - level.add("Entities").withElem((ValueReader>) (index, value) -> { - CompoundTag entity = FaweCache.IMP.asTag(value); - entities.put(entity.getUUID(), entity); - }); - level.add("Biomes").withInt((index, value) -> biomes[index] = BiomeTypes.getLegacy(value)); - - return root; - } - - @Override - public int getX() { - return chunkX; - } - - @Override - public int getZ() { - return chunkZ; - } - - @Override - public boolean hasSection(int layer) { - return hasSections[layer]; - } - - public void setPosition(int X, int Z) { - this.chunkX = X; - this.chunkZ = Z; - } - - @Override - public MCAChunk reset() { - return this.reset(true); - } - - public MCAChunk reset(boolean full) { - if (!tiles.isEmpty()) { - tiles.clear(); - } - if (!entities.isEmpty()) { - entities.clear(); - } - modified = 0; - deleted = false; - hasBiomes = false; - if (full) { - for (int i = 0; i < 65536; i++) { - blocks[i] = BlockID.AIR; - } - } - Arrays.fill(hasSections, false); - return this; - } - - public void write(NBTOutputStream nbtOut) throws IOException { - int[] blockToPalette = FaweCache.IMP.BLOCK_TO_PALETTE.get(); - int[] paletteToBlock = FaweCache.IMP.PALETTE_TO_BLOCK.get(); - long[] blockstates = FaweCache.IMP.BLOCK_STATES.get(); - int[] blocksCopy = FaweCache.IMP.SECTION_BLOCKS.get(); - - nbtOut.writeNamedTagName("", NBTConstants.TYPE_COMPOUND); - nbtOut.writeNamedTag("DataVersion", 1631); - nbtOut.writeLazyCompoundTag("Level", out -> { - out.writeNamedTag("Status", "decorated"); - out.writeNamedTag("xPos", getX()); - out.writeNamedTag("zPos", getZ()); - if (entities.isEmpty()) { - out.writeNamedEmptyList("Entities"); - } else { - out.writeNamedTag("Entities", new ListTag(CompoundTag.class, new ArrayList<>(entities.values()))); - } - if (tiles.isEmpty()) { - out.writeNamedEmptyList("TileEntities"); - } else { - out.writeNamedTag("TileEntities", new ListTag(CompoundTag.class, - new ArrayList<>(tiles.values()))); - } - out.writeNamedTag("InhabitedTime", inhabitedTime); - out.writeNamedTag("LastUpdate", lastUpdate); - if (hasBiomes) { - int type = NBTConstants.TYPE_BYTE_ARRAY; - out.writeNamedTagName("Biomes", type); - out.writeInt(biomes.length); - for (BiomeType biome : biomes) { - out.write(biome.getLegacyId()); - } - } - int len = 0; - for (boolean hasSection : hasSections) { - if (hasSection) { - len++; - } - } - out.writeNamedTagName("Sections", NBTConstants.TYPE_LIST); - nbtOut.writeByte(NBTConstants.TYPE_COMPOUND); - nbtOut.writeInt(len); - - for (int layer = 0; layer < hasSections.length; layer++) { - if (!hasSections[layer]) { - continue; - } - out.writeNamedTag("Y", (byte) layer); - - int blockIndexStart = layer << 12; - int blockIndexEnd = blockIndexStart + 4096; - int num_palette = 0; - try { - for (int i = blockIndexStart, j = 0; i < blockIndexEnd; i++, j++) { - int ordinal = blocks[i]; - int palette = blockToPalette[ordinal]; - if (palette == Integer.MAX_VALUE) { - //BlockState state = BlockTypesCache.states[ordinal]; - blockToPalette[ordinal] = palette = num_palette; - paletteToBlock[num_palette] = ordinal; - num_palette++; - } - blocksCopy[j] = palette; - } - - for (int i = 0; i < num_palette; i++) { - blockToPalette[paletteToBlock[i]] = Integer.MAX_VALUE; - } - - out.writeNamedTagName("Palette", NBTConstants.TYPE_LIST); - out.writeByte(NBTConstants.TYPE_COMPOUND); - out.writeInt(num_palette); - - for (int i = 0; i < num_palette; i++) { - int ordinal = paletteToBlock[i]; - BlockState state = BlockTypesCache.states[ordinal]; - BlockType type = state.getBlockType(); - out.writeNamedTag("Name", type.getId()); - - // Has no properties - if (type.getDefaultState() != state) { - // Write properties - out.writeNamedTagName("Properties", NBTConstants.TYPE_COMPOUND); - for (Property property : type.getProperties()) { - String key = property.getName(); - Object value = state.getState(property); - String valueStr = value.toString(); - if (Character.isUpperCase(valueStr.charAt(0))) { - LOGGER.warn("Invalid uppercase value {}", value); - valueStr = valueStr.toLowerCase(Locale.ROOT); - } - out.writeNamedTag(key, valueStr); - } - out.writeEndTag(); - } - out.writeEndTag(); - } - - - // BlockStates - int bitsPerEntry = MathMan.log2nlz(num_palette - 1); - int blockBitArrayEnd = (bitsPerEntry * 4096) >> 6; - if (num_palette == 1) { - // Set a value, because minecraft needs it for some reason - blockstates[0] = 0; - blockBitArrayEnd = 1; - } else { - BitArray bitArray = new BitArray(bitsPerEntry, 4096, blockstates); - bitArray.fromRaw(blocksCopy); - } - - out.writeNamedTagName("BlockStates", NBTConstants.TYPE_LONG_ARRAY); - out.writeInt(blockBitArrayEnd); - for (int i = 0; i < blockBitArrayEnd; i++) { - out.writeLong(blockstates[i]); - } - - - /* out.writeNamedTagName("BlockLight", NBTConstants.TYPE_BYTE_ARRAY); - out.writeInt(2048); - out.write(blockLight, layer << 11, 1 << 11); - - out.writeNamedTagName("SkyLight", NBTConstants.TYPE_BYTE_ARRAY); - out.writeInt(2048); - out.write(skyLight, layer << 11, 1 << 11); */ - - - out.writeEndTag(); - - // cleanup - } catch (Throwable e) { - Arrays.fill(blockToPalette, Integer.MAX_VALUE); - e.printStackTrace(); - throw e; - } - } - }); - nbtOut.writeEndTag(); - } - - public FastByteArrayOutputStream toBytes(byte[] buffer) throws IOException { - if (buffer == null) { - buffer = new byte[8192]; - } - FastByteArrayOutputStream buffered = new FastByteArrayOutputStream(buffer); - try (NBTOutputStream nbtOut = new NBTOutputStream(buffered)) { - write(nbtOut); - } - return buffered; - } - - public long getInhabitedTime() { - return inhabitedTime; - } - - public long getLastUpdate() { - return lastUpdate; - } - - public void setInhabitedTime(long inhabitedTime) { - this.inhabitedTime = inhabitedTime; - } - - public void setLastUpdate(long lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public void setDeleted(boolean deleted) { - setModified(); - this.deleted = deleted; - } - - public boolean isDeleted() { - return deleted; - } - - @Override - public boolean isEmpty() { - if (deleted) { - return true; - } - for (boolean hasSection : hasSections) { - if (hasSection) { - return false; - } - } - return true; - } - - public boolean isModified() { - return modified != 0; - } - - public int getModified() { - return modified; - } - - public final void setModified() { - this.modified++; - } - - @Override - public int getBitMask() { - int bitMask = 0; - for (int section = 0; section < hasSections.length; section++) { - if (hasSections[section]) { - bitMask += 1 << section; - } - } - return bitMask; - } - - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) { - setModified(); - if (tile != null) { - tiles.put(x, y, z, tile); - } else { - return tiles.remove(x, y, z) != null; - } - return true; - } - - @Override public void setBlockLight(int x, int y, int z, int value) { - - } - - @Override public void setSkyLight(int x, int y, int z, int value) { - - } - - @Override public void setHeightMap(HeightMapType type, int[] heightMap) { - - } - - @Override public void removeSectionLighting(int layer, boolean sky) { - } - - @Override public void setFullBright(int layer) { - } - - @Override - public void setLightLayer(int layer, char[] toSet) { - } - - @Override - public void setSkyLightLayer(int layer, char[] toSet) { - } - - @Override - public void setEntity(CompoundTag entityTag) { - setModified(); - long least = entityTag.getLong("UUIDLeast"); - long most = entityTag.getLong("UUIDMost"); - entities.put(new UUID(most, least), entityTag); - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - return this.biomes[(y >> 2) << 4 | (z >> 2) << 2 | x >> 2]; - } - - @Override - public BiomeType[] getBiomes() { - return this.biomes; - } - - @Override public char[][] getLight() { - return new char[0][]; - } - - @Override public char[][] getSkyLight() { - return new char[0][]; - } - - @Override - public boolean setBiome(BlockVector3 pos, BiomeType biome) { - return this.setBiome(pos.getX(), pos.getY(), pos.getZ(), biome); - } - - @Override - public boolean setBiome(int x, int y, int z, BiomeType biome) { - setModified(); - biomes[(y >> 2) << 4 | (z >> 2) << 2 | x >> 2] = biome; - return true; - } - - @Override - public Set getEntities() { - return new HashSet<>(entities.values()); - } - - @Override - public Map getTiles() { - return tiles == null ? Collections.emptyMap() : tiles; - } - - @Override - public CompoundTag getTile(int x, int y, int z) { - if (tiles == null || tiles.isEmpty()) { - return null; - } - short pair = MathMan.tripleBlockCoord(x, y, z); - return tiles.get(pair); - } - - private final int getIndex(int x, int y, int z) { - return x | (z << 4) | (y << 8); - } - - public int getBlockOrdinal(int x, int y, int z) { - return blocks[x | (z << 4) | (y << 8)]; - } - - @Override - public BlockState getBlock(int x, int y, int z) { - int ordinal = getBlockOrdinal(x, y, z); - return BlockState.getFromOrdinal(ordinal); - } - - //TODO implement lighting - @Override public int getSkyLight(int x, int y, int z) { - return 0; - } - - @Override public int getEmmittedLight(int x, int y, int z) { - return 0; - } - - @Override public int[] getHeightMap(HeightMapType type) { - return new int[256]; - } - - @Override - public BaseBlock getFullBlock(int x, int y, int z) { - BlockState block = getBlock(x, y, z); - return block.toBaseBlock(this, x, y, z); - } - - @Override - public Set getEntityRemoves() { - return new HashSet<>(); - } - - @Override - public > boolean setBlock(int x, int y, int z, B holder) { - setBlock(x, y, z, holder.getOrdinalChar()); - holder.applyTileEntity(this, x, y, z); - return true; - } - - @Override - public void setBlocks(int layer, char[] data) { - int offset = layer << 12; - System.arraycopy(data, 0, blocks, offset, 4096); - } - - @Override - public char[] load(int layer) { - char[] tmp = FaweCache.IMP.SECTION_BITS_TO_CHAR.get(); - int offset = layer << 12; - System.arraycopy(blocks, offset, tmp, 0, 4096); - return tmp; - } - - public void setBlock(int x, int y, int z, char ordinal) { - blocks[getIndex(x, y, z)] = ordinal; - } - - public void setBiome(BiomeType biome) { - Arrays.fill(this.biomes, biome); - } - - @Override - public void removeEntity(UUID uuid) { - entities.remove(uuid); - } - - @Override - public boolean trim(boolean aggressive) { - return isEmpty(); - } - - @Override - public boolean trim(boolean aggressive, int layer) { - return hasSection(layer); - } - - @Override - public CompoundTag getEntity(UUID uuid) { - return this.entities.get(uuid); - } - - @Override public void setCreateCopy(boolean createCopy) { - this.createCopy = createCopy; - } - - @Override public boolean isCreateCopy() { - return createCopy; - } - - @Override - public void setLightingToGet(char[][] lighting) {} - - @Override - public void setSkyLightingToGet(char[][] lighting) {} - - @Override - public void setHeightmapToGet(HeightMapType type, int[] data) {} - - @Override - public Future call(IChunkSet set, Runnable finalize) { - return null; - } - - @Override - public void filterBlocks(Filter filter, ChunkFilterBlock block, @Nullable Region region, boolean full) { - try { - block.filter(this, this, this, filter, region, full); - } finally { - filter.finishChunk(this); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java deleted file mode 100644 index 2825b1c5f..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAFile.java +++ /dev/null @@ -1,715 +0,0 @@ -package com.boydti.fawe.jnbt.anvil; - -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.beta.Trimable; -import com.boydti.fawe.beta.implementation.IChunkExtent; -import com.boydti.fawe.beta.implementation.processors.ExtentBatchProcessorHolder; -import com.boydti.fawe.object.RunnableVal4; -import com.boydti.fawe.object.io.BufferedRandomAccessFile; -import com.boydti.fawe.object.io.FastByteArrayInputStream; -import com.boydti.fawe.util.MainUtil; -import com.boydti.fawe.util.MathMan; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.jnbt.NBTInputStream; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.World; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream; -import org.apache.logging.log4j.Logger; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.RandomAccessFile; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; -import java.util.stream.IntStream; -import java.util.zip.Deflater; -import java.util.zip.Inflater; -import java.util.zip.InflaterInputStream; - -/** - * Chunk format: http://minecraft.gamepedia.com/Chunk_format#Entity_format - * e.g., `.Level.Entities.#` (Starts with a . as the root tag is unnamed) - * Note: This class isn't thread safe. You can use it in an async thread, but not multiple at the same time - */ -public class MCAFile extends ExtentBatchProcessorHolder implements Trimable, IChunkExtent { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private static Field fieldBuf2; - - static { - try { - fieldBuf2 = InflaterInputStream.class.getDeclaredField("buf"); - fieldBuf2.setAccessible(true); - } catch (Throwable e) { - e.printStackTrace(); - } - } - - private final ForkJoinPool pool; - private final byte[] locations; - private boolean readLocations; - - private File file; - private RandomAccessFile raf; - - private boolean deleted; - private int X; - private int Z; - private MCAChunk[] chunks; - private boolean[] chunkInitialized; - private Object[] locks; - private Deflater deflater = new Deflater(1, false); - - public MCAFile(ForkJoinPool pool) { - this.pool = pool; - this.locations = new byte[4096]; - this.chunks = new MCAChunk[32 * 32]; - this.chunkInitialized = new boolean[this.chunks.length]; - this.locks = new Object[this.chunks.length]; - for (int i = 0; i < locks.length; i++) { - locks[i] = new Object(); - } - } - - @Override - public boolean trim(boolean aggressive) { - boolean hasChunk = false; - for (int i = 0; i < chunkInitialized.length; i++) { - if (!chunkInitialized[i]) { - chunks[i] = null; - } else { - hasChunk = true; - } - } - return !hasChunk; - } - - public MCAFile init(File file) throws FileNotFoundException { - String[] split = file.getName().split("\\."); - int X = Integer.parseInt(split[1]); - int Z = Integer.parseInt(split[2]); - return init(file, X, Z); - } - - public MCAFile init(File file, int mcrX, int mcrZ) throws FileNotFoundException { - if (raf != null) { - flush(true); - for (int i = 0; i < 4096; i++) { - locations[i] = 0; - } - try { - raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - raf = null; - } - deleted = false; - Arrays.fill(chunkInitialized, false); - readLocations = false; - this.X = mcrX; - this.Z = mcrZ; - this.file = file; - if (!file.exists()) { - throw new FileNotFoundException(file.getName()); - } - return this; - } - - public MCAFile init(World world, int mcrX, int mcrZ) throws FileNotFoundException { - return init(new File(world.getStoragePath().toFile(), File.separator + "regions" + File.separator + "r." + mcrX + "." + mcrZ + ".mca")); - } - - @Override - public BlockVector3 getMinimumPoint() { - return BlockVector3.at(this.X << 9, 0, this.Z << 9); - } - - @Override - public BlockVector3 getMaximumPoint() { - return BlockVector3.at((this.X << 9) + 511, FaweCache.IMP.WORLD_MAX_Y, (this.Z << 9) + 511); - } - - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { -// final IChunk chunk = getChunk(x >> 4, z >> 4); -// return chunk.setTile(x & 15, y, z & 15, tile); - return false; - } - - public int getIndex(int chunkX, int chunkZ) { - return ((chunkX & 31) << 2) + ((chunkZ & 31) << 7); - } - - - private RandomAccessFile getRaf() throws FileNotFoundException { - if (this.raf == null) { - this.raf = new RandomAccessFile(file, "rw"); - } - return this.raf; - } - - private void readHeader() throws IOException { - if (!readLocations) { - readLocations = true; - getRaf(); - if (raf.length() < 8192) { - raf.setLength(8192); - } else { - raf.seek(0); - raf.readFully(locations); - } - } - } - - public void clear() { - if (raf != null) { - try { - raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - deleted = false; - readLocations = false; - Arrays.fill(chunkInitialized, false); - } - - public void setDeleted(boolean deleted) { - this.deleted = deleted; - } - - public boolean isDeleted() { - return deleted; - } - - public int getX() { - return X; - } - - public int getZ() { - return Z; - } - - public RandomAccessFile getRandomAccessFile() { - return raf; - } - - public File getFile() { - return file; - } - - public MCAChunk getCachedChunk(int cx, int cz) { - int pair = getIndex(cx, cz); - MCAChunk chunk = chunks[pair]; - if (chunk != null && chunkInitialized[pair]) { - return chunk; - } - return null; - } - - public void setChunk(MCAChunk chunk) { - int cx = chunk.getX(); - int cz = chunk.getZ(); - int pair = getIndex(cx, cz); - chunks[pair] = chunk; - } - - @Override - public MCAChunk getOrCreateChunk(int chunkX, int chunkZ) { - try { - return getChunk(chunkX, chunkZ); - } catch (IOException e) { - // TODO generate? - return null; - } - } - - public MCAChunk getChunk(int cx, int cz) throws IOException { - int pair = getIndex(cx, cz); - MCAChunk chunk = chunks[pair]; - if (chunk == null) { - Object lock = locks[pair]; - synchronized (lock) { - chunk = chunks[pair]; - if (chunk == null) { - chunk = new MCAChunk(); - chunk.setPosition(cx, cz); - chunks[pair] = chunk; - } - } - } else if (chunkInitialized[pair]) { - return chunk; - } - synchronized (chunk) { - if (!chunkInitialized[pair]) { - readChunk(chunk, pair); - chunkInitialized[pair] = true; - } - } - return chunk; - } - - private MCAChunk readChunk(MCAChunk chunk, int i) throws IOException { - int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i + 2] & 0xFF))) << 12; - if (offset == 0) { - return null; - } - int size = (locations[i + 3] & 0xFF) << 12; - try (NBTInputStream nis = getChunkIS(offset)) { - chunk.read(nis, false); - } - //TODO multithreaded - return chunk; - } - - /** - * CX, CZ, OFFSET, SIZE - * - * @param onEach - * @throws IOException - */ - public void forEachSortedChunk(RunnableVal4 onEach) throws IOException { - char[] offsets = new char[(int) (raf.length() / 4096) - 2]; - Arrays.fill(offsets, Character.MAX_VALUE); - char i = 0; - for (int z = 0; z < 32; z++) { - for (int x = 0; x < 32; x++, i += 4) { - int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i + 2] & 0xFF))) - 2; - int size = locations[i + 3] & 0xFF; - if (size != 0) { - if (offset < offsets.length) { - offsets[offset] = i; - } else { - LOGGER.debug("Ignoring invalid offset " + offset); - } - } - } - } - for (i = 0; i < offsets.length; i++) { - int index = offsets[i]; - if (index != Character.MAX_VALUE) { - int offset = i + 2; - int size = locations[index + 3] & 0xFF; - int index2 = index >> 2; - int x = (index2) & 31; - int z = (index2) >> 5; - onEach.run(x, z, offset << 12, size << 12); - } - } - } - - /** - * @param onEach cx, cz, offset, size - */ - public void forEachChunk(RunnableVal4 onEach) { - int i = 0; - for (int z = 0; z < 32; z++) { - for (int x = 0; x < 32; x++, i += 4) { - int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i + 2] & 0xFF))); - int size = locations[i + 3] & 0xFF; - if (size != 0) { - onEach.run(x, z, offset << 12, size << 12); - } - } - } - } - - public void forEachChunk(Consumer onEach) { - int i = 0; - for (int z = 0; z < 32; z++) { - for (int x = 0; x < 32; x++, i += 4) { - int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i + 2] & 0xFF))); - int size = locations[i + 3] & 0xFF; - if (size != 0) { - try { - onEach.accept(getChunk(x, z)); - } catch (Throwable ignored) { - } - } - } - } - } - - public int getOffset(int cx, int cz) { - int i = getIndex(cx, cz); - int offset = (((locations[i] & 0xFF) << 16) + ((locations[i + 1] & 0xFF) << 8) + ((locations[i + 2] & 0xFF))); - return offset << 12; - } - - public int getSize(int cx, int cz) { - int i = getIndex(cx, cz); - return (locations[i + 3] & 0xFF) << 12; - } - - public FastByteArrayInputStream getChunkCompressedBytes(int offset) throws IOException { - if (offset == 0) { - return null; - } - synchronized (raf) { - raf.seek(offset); - int size = raf.readInt(); - int compression = raf.read(); - byte[] data = FaweCache.IMP.BYTE_BUFFER_VAR.get(size); - raf.readFully(data, 0, size); - FastByteArrayInputStream result = new FastByteArrayInputStream(data, 0, size); - return result; - } - } - - private NBTInputStream getChunkIS(int offset) throws IOException { - try { - return getChunkIS(getChunkCompressedBytes(offset)); - } catch (IllegalAccessException unlikely) { - unlikely.printStackTrace(); - return null; - } - } - - private NBTInputStream getChunkIS(InputStream is) throws IllegalAccessException { - InflaterInputStream iis = new InflaterInputStream(is, new Inflater(), 1); - fieldBuf2.set(iis, FaweCache.IMP.BYTE_BUFFER_8192.get()); - BufferedInputStream bis = new BufferedInputStream(iis); - NBTInputStream nis = new NBTInputStream(bis); - return nis; - } - - /** - * @param onEach chunk - */ - public void forEachCachedChunk(Consumer onEach) { - for (int i = 0; i < chunks.length; i++) { - MCAChunk chunk = chunks[i]; - if (chunk != null && this.chunkInitialized[i]) { - onEach.accept(chunk); - } - } - } - - public List getCachedChunks() { - int size = (int) IntStream.range(0, chunks.length) - .filter(i -> chunks[i] != null && this.chunkInitialized[i]).count(); - ArrayList list = new ArrayList<>(size); - for (int i = 0; i < chunks.length; i++) { - MCAChunk chunk = chunks[i]; - if (chunk != null && this.chunkInitialized[i]) { - list.add(chunk); - } - } - return list; - } - - private FastByteArrayOutputStream toBytes(MCAChunk chunk) throws IOException { - if (chunk.isDeleted()) { - return null; - } - byte[] writeBuffer = FaweCache.IMP.BYTE_BUFFER_VAR.get(4096); - FastByteArrayOutputStream uncompressed = chunk.toBytes(writeBuffer); - if (uncompressed.array.length > writeBuffer.length) { - FaweCache.IMP.BYTE_BUFFER_VAR.set(uncompressed.array); - } - writeBuffer = uncompressed.array; - byte[] buffer = FaweCache.IMP.BYTE_BUFFER_8192.get(); - int length = uncompressed.length; - uncompressed.reset(); - // cheat, reusing the same buffer to read/write - int compressedLength = MainUtil.compress(uncompressed.array, length, buffer, uncompressed, deflater); - return uncompressed; - } - - private void writeSafe(RandomAccessFile raf, int offset, byte[] data, int length) throws IOException { - int len = length + 5; - raf.seek(offset); - if (raf.length() - offset < len) { - raf.setLength(((offset + len + 4095) / 4096) * 4096); - } - // Length of remaining data - raf.writeInt(length + 1); - // Compression type - raf.write(2); - raf.write(data, 0, length); - } - - private void writeHeader(RandomAccessFile raf, int cx, int cz, int offsetMedium, int sizeByte, boolean writeTime) throws IOException { - int i = getIndex(cx, cz); - locations[i] = (byte) (offsetMedium >> 16); - locations[i + 1] = (byte) (offsetMedium >> 8); - locations[i + 2] = (byte) (offsetMedium); - locations[i + 3] = (byte) sizeByte; - raf.seek(i); - raf.write((offsetMedium >> 16)); - raf.write((offsetMedium >> 8)); - raf.write((offsetMedium >> 0)); - raf.write(sizeByte); - raf.seek(i + 4096); - if (offsetMedium == 0 && sizeByte == 0) { - raf.writeInt(0); - } else { - raf.writeInt((int) (System.currentTimeMillis() / 1000L)); - } - } - - public void close() { - if (raf == null) { - return; - } - synchronized (raf) { - if (raf != null) { - flush(true); - try { - raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - raf = null; - } - } - } - - public boolean isModified() { - if (isDeleted()) { - return true; - } - for (int i = 0; i < chunks.length; i++) { - MCAChunk chunk = chunks[i]; - if (chunk != null && this.chunkInitialized[i]) { - if (chunk.isModified() || chunk.isDeleted()) { - return true; - } - } - } - return false; - } - - /** - * Write the chunk to the file - * @param wait - If the flush method needs to wait for the pool - */ - public void flush(boolean wait) { - synchronized (raf) { - // If the file is marked as deleted, nothing is written - if (isDeleted()) { - clear(); - file.delete(); - return; - } - // Chunks that need to be relocated - Int2ObjectOpenHashMap relocate = new Int2ObjectOpenHashMap<>(); - // The position of each chunk - final Int2ObjectOpenHashMap offsetMap = new Int2ObjectOpenHashMap<>(); // Offset -> - // The data of each modified chunk - final Int2ObjectOpenHashMap> compressedMap = new Int2ObjectOpenHashMap<>(); - // The data of each chunk that needs to be moved - final Int2ObjectOpenHashMap> append = new Int2ObjectOpenHashMap<>(); - // Get the current time for the chunk timestamp - long now = System.currentTimeMillis(); - - // Load the chunks into the append or compressed map - final ForkJoinPool finalPool = this.pool; - - - boolean modified = false; - for (int i = 0; i < chunks.length; i++) { - if (this.chunkInitialized[i]) { - MCAChunk chunk = chunks[i]; - if (chunk != null && chunk.isModified() && !chunk.isDeleted()) { - modified = true; - ForkJoinTask future = pool.submit(() -> { - FastByteArrayOutputStream compressed = toBytes(chunk); - return Arrays.copyOf(compressed.array, compressed.length); - }); - } - } - } -// -// forEachCachedChunk(chunk -> { -// if (chunk.isModified() || chunk.isDeleted()) { -// modified[0] = true; -// chunk.setLastUpdate(now); -// if (!chunk.isDeleted()) { -// MCAFile.this.pool.submit(() -> { -// try { -// byte[] compressed = toBytes(chunk); -// int pair = MathMan.pair((short) (chunk.getX() & 31), (short) (chunk.getZ() & 31)); -// Int2ObjectOpenHashMap map; -// if (getOffset(chunk.getX(), chunk.getZ()) == 0) { -// map = append; -// } else { -// map = compressedMap; -// } -// synchronized (map) { -// map.put(pair, compressed); -// } -// } catch (Throwable e) { -// e.printStackTrace(); -// } -// }); -// } -// } -// }); - - if (!modified) { - // Not modified, do nothing - return; - } - // If any changes were detected - file.setLastModified(now); - - // Load the offset data into the offset map - forEachChunk(new RunnableVal4() { - @Override - public void run(Integer cx, Integer cz, Integer offset, Integer size) { - short pair1 = MathMan.pairByte((byte) (cx & 31), (byte) (cz & 31)); - short pair2 = (short) (size >> 12); - offsetMap.put((int) offset, (Integer) MathMan.pair(pair1, pair2)); - } - }); - - int start = 8192; - int written = start; - int end = 8192; - int nextOffset = 8192; - try { - for (int count = 0; count < offsetMap.size(); count++) { - // Get the previous position of the next chunk - Integer loc = offsetMap.get(nextOffset); - while (loc == null) { - nextOffset += 4096; - loc = offsetMap.get(nextOffset); - } - int offset = nextOffset; - - // Get the x/z from the paired location - short cxz = MathMan.unpairX(loc); - int cx = MathMan.unpairShortX(cxz); - int cz = MathMan.unpairShortY(cxz); - - // Get the size from the pair - int size = MathMan.unpairY(loc) << 12; - - nextOffset += size; - end = Math.min(start + size, end); - int pair = getIndex(cx, cz); - - Future future = null; - byte[] newBytes = relocate.get(pair); - int newBytesLength = 0; - - // newBytes is null if the chunk isn't modified or marked for moving - if (newBytes == null) { - MCAChunk cached = getCachedChunk(cx, cz); - // If the previous offset marks the current write position (start) then we only write the header - if (offset == start) { - if (cached == null || !cached.isModified()) { - writeHeader(raf, cx, cz, start >> 12, size >> 12, true); - start += size; - written = start + size; - continue; - } else { - future = compressedMap.get(pair); - } - } else { - // The chunk needs to be moved, fetch the data if necessary - future = compressedMap.get(pair); - if (future == null) { - if (cached == null || !cached.isDeleted()) { - FastByteArrayInputStream result = getChunkCompressedBytes(getOffset(cx, cz)); - newBytes = result.array; - newBytesLength = result.length; - } - } - } - } else { - newBytesLength = newBytes.length; - } - if (future != null) { - newBytes = future.get(); - newBytesLength = newBytes.length; - } - - if (newBytes == null) { - writeHeader(raf, cx, cz, 0, 0, false); - continue; - } - - // The length to be written (compressed data + 5 byte chunk header) - int len = newBytesLength + 5; - int oldSize = (size + 4095) >> 12; - int newSize = (len + 4095) >> 12; - int nextOffset2 = end; - - // If the current write position (start) + length of data to write (len) are longer than the position of the next chunk, we need to move the next chunks - while (start + len > end) { - Integer nextLoc = offsetMap.get(nextOffset2); - if (nextLoc != null) { - short nextCXZ = MathMan.unpairX(nextLoc); - int nextCX = MathMan.unpairShortX(nextCXZ); - int nextCZ = MathMan.unpairShortY(nextCXZ); - MCAChunk cached = getCachedChunk(nextCX, nextCZ); - if (cached == null || !cached.isModified()) { - FastByteArrayInputStream tmp = getChunkCompressedBytes(nextOffset2); - byte[] nextBytes = Arrays.copyOf(tmp.array, tmp.length); - relocate.put(MathMan.pair((short) (nextCX & 31), (short) (nextCZ & 31)), nextBytes); - } - int nextSize = MathMan.unpairY(nextLoc) << 12; - end += nextSize; - nextOffset2 += nextSize; - } else { - end += 4096; - nextOffset2 += 4096; - } - } - // Write the chunk + chunk header - writeSafe(raf, start, newBytes, newBytesLength); - // Write the location data (beginning of file) - writeHeader(raf, cx, cz, start >> 12, newSize, true); - - written = start + newBytesLength + 5; - start += newSize << 12; - } - - // Write all the chunks which need to be appended - if (!append.isEmpty()) { - for (Int2ObjectMap.Entry> entry : append.int2ObjectEntrySet()) { - int pair = entry.getIntKey(); - short cx = MathMan.unpairX(pair); - short cz = MathMan.unpairY(pair); - byte[] bytes = entry.getValue().get(); - int len = bytes.length + 5; - int newSize = (len + 4095) >> 12; - writeSafe(raf, start, bytes, bytes.length); - writeHeader(raf, cx, cz, start >> 12, newSize, true); - written = start + bytes.length + 5; - start += newSize << 12; - } - } - // Round the file length, since the vanilla server doesn't like it for some reason - raf.setLength(4096 * ((written + 4095) / 4096)); - if (raf instanceof BufferedRandomAccessFile) { - ((BufferedRandomAccessFile) raf).flush(); - } - raf.close(); - } catch (Throwable e) { - e.printStackTrace(); - } - if (wait) { - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - } - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java deleted file mode 100644 index ebc8bf1c3..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/MCAWorld.java +++ /dev/null @@ -1,109 +0,0 @@ -package com.boydti.fawe.jnbt.anvil; - -import com.boydti.fawe.beta.IChunkGet; -import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.world.AbstractWorld; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -import java.io.File; -import java.io.IOException; -import java.util.Set; -import javax.annotation.Nullable; - -import static com.google.common.base.Preconditions.checkArgument; - -public class MCAWorld extends AbstractWorld { - private final File path; - - public MCAWorld(File path) { - checkArgument(path.isDirectory()); - this.path = path; - } - - @Override - public String getName() { - return path.getName(); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) throws WorldEditException { - return false; - } - - - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return false; - } - - @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) throws WorldEditException { - return false; - } - - @Override - public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) throws WorldEditException { - return SideEffectSet.none().getSideEffectsToApply(); - } - - @Override - public boolean clearContainerBlockContents(BlockVector3 position) { - return false; - } - - @Override - public void dropItem(Vector3 position, BaseItemStack item) { - - } - - @Override - public void simulateBlockMine(BlockVector3 position) { - - } - - @Override - public boolean regenerate(Region region, EditSession editSession) { - return false; - } - - @Override - public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { - return false; - } - - @Override - public BlockVector3 getSpawnPosition() { - return null; - } - - @Override - public void refreshChunk(int chunkX, int chunkZ) { - - } - - @Override - public IChunkGet get(int x, int z) { - return null; - } - - @Override - public void sendFakeChunk(@Nullable Player player, ChunkPacket packet) { - - } - - @Override - public void flush() {} -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/mcatest/MCATest.java b/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/mcatest/MCATest.java deleted file mode 100644 index 8c962316a..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/jnbt/anvil/mcatest/MCATest.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.boydti.fawe.jnbt.anvil.mcatest; - -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; - -import java.io.File; -import java.io.IOException; - -public class MCATest { - public MCATest() throws IOException { - File file = new File("plugins/FastAsyncWorldEdit/tobitower.schematic"); - Clipboard loaded = ClipboardFormats.findByFile(file).load(file); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CatenaryBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CatenaryBrush.java index ccab0a490..d313ca968 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CatenaryBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CatenaryBrush.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.config.Caption; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.WorldEditException; @@ -35,16 +34,13 @@ public class CatenaryBrush implements Brush, ResettableTool { @Override public void build(EditSession editSession, BlockVector3 pos2, final Pattern pattern, double size) throws MaxChangedBlocksException { - boolean visual = editSession.getExtent() instanceof VisualExtent; Player player = editSession.getPlayer(); if (player == null) { return; //todo throw error } if (pos1 == null || pos2.equals(pos1)) { - if (!visual) { - pos1 = pos2; - player.print(Caption.of("fawe.worldedit.brush.brush.line.primary", pos2)); - } + pos1 = pos2; + player.print(Caption.of("fawe.worldedit.brush.brush.line.primary", pos2)); return; } if (this.vertex == null) { @@ -67,14 +63,12 @@ public class CatenaryBrush implements Brush, ResettableTool { } catch (WorldEditException e) { e.printStackTrace(); } - if (!visual) { - player.print(Caption.of("fawe.worldedit.brush.brush.line.secondary")); - if (!select) { - pos1 = null; - return; - } - pos1 = pos2; + player.print(Caption.of("fawe.worldedit.brush.brush.line.secondary")); + if (!select) { + pos1 = null; + return; } + pos1 = pos2; } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java index e6e03ce6c..c5104129b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/CopyPastaBrush.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.config.Caption; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.clipboard.ResizableClipboardBuilder; import com.boydti.fawe.object.function.NullRegionFunction; import com.boydti.fawe.object.function.mask.AbstractDelegateMask; @@ -56,9 +55,6 @@ public class CopyPastaBrush implements Brush, ResettableTool { } ClipboardHolder clipboard = session.getExistingClipboard(); if (clipboard == null) { - if (editSession.getExtent() instanceof VisualExtent) { - return; - } Mask mask = editSession.getMask(); if (mask == null) { mask = Masks.alwaysTrue(); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java index ac03d8923..271e717cb 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/HeightBrush.java @@ -4,7 +4,6 @@ import com.boydti.fawe.config.Caption; import com.boydti.fawe.object.brush.heightmap.HeightMap; import com.boydti.fawe.object.brush.heightmap.RotatableHeightMap; import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap; -import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.EditSession; @@ -74,84 +73,6 @@ public class HeightBrush implements Brush { HeightMap map = getHeightMap(); map.setSize(size); - Extent queue = editSession.getExtent(); - // Optimized application of height map - if (queue instanceof HeightMapMCAGenerator) { - HeightMapMCAGenerator hmmg = (HeightMapMCAGenerator) queue; - - byte[] metaHeight = hmmg.getMetaData().getMeta("PRECISION_HEIGHT"); - if (metaHeight == null) { - hmmg.getMetaData().setMeta("PRECISION_HEIGHT", metaHeight = new byte[hmmg.getArea()]); - } - - int bx = position.getBlockX(); - int bz = position.getBlockZ(); - - int minIndex = -(size * 2) - 1; - int width = hmmg.getWidth(); - - int minX = Math.max(-size, -bx); - int minZ = Math.max(-size, -bz); - int maxX = Math.min(size, hmmg.getWidth() - 1 - bx); - int maxZ = Math.min(size, hmmg.getLength() - 1 - bz); - - int zIndex = (bz + minZ) * width; - for (int z = minZ; z <= maxZ; z++, zIndex += width) { - int zz = bz + z; - int index = zIndex + (bx + minX); - if (index < minIndex) { - continue; - } - if (index >= metaHeight.length) { - break; - } - for (int x = minX; x <= maxX; x++, index++) { - if (index < 0) { - continue; - } - if (index >= metaHeight.length) { - break; - } - - int xx = bx + x; - int currentBlockHeight = hmmg.getHeight(index); - int currentLayer = metaHeight[index] & 0xFF; - - double addHeight = heightMap.getHeight(x, z) * yscale; - int addBlockHeight = (int) addHeight; - int addLayer = (int) ((addHeight - addBlockHeight) * 256); - - int newLayer = addLayer + currentLayer; - int newBlockHeight = currentBlockHeight + addBlockHeight; - - int newLayerAbs = MathMan.absByte(newLayer); - - if (newLayerAbs >= 256) { - int newLayerBlocks = (newLayer >> 8); - newBlockHeight += newLayerBlocks; - newLayer -= newLayerBlocks << 8; - } - - hmmg.setHeight(index, newBlockHeight); - metaHeight[index] = (byte) newLayer; - } - } - - if (smooth) { - BlockVector2 min = BlockVector2.at(Math.max(0, bx - size), Math.max(0, bz - size)); - BlockVector2 max = BlockVector2.at(Math.min(hmmg.getWidth() - 1, bx + size), Math.min(hmmg.getLength() - 1, bz + size)); - hmmg.smooth(min, max, 8, 1); - - if (size > 20) { - int smoothSize = size + 8; - min = BlockVector2.at(Math.max(0, bx - smoothSize), Math.max(0, bz - smoothSize)); - max = BlockVector2.at(Math.min(hmmg.getWidth() - 1, bx + smoothSize), Math.min(hmmg.getLength() - 1, bz + smoothSize)); - hmmg.smooth(min, max, 1, 1); - } - } - - return; - } Mask mask = editSession.getMask(); if (mask == Masks.alwaysTrue() || mask == Masks.alwaysTrue2D()) { mask = null; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java index 72e0122a0..01d3ccad1 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/LineBrush.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.config.Caption; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.MaxChangedBlocksException; import com.sk89q.worldedit.command.tool.brush.Brush; @@ -23,22 +22,17 @@ public class LineBrush implements Brush, ResettableTool { @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { - boolean visual = editSession.getExtent() instanceof VisualExtent; if (pos1 == null) { - if (!visual) { - pos1 = position; - editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.brush.line.primary", position)); - } + pos1 = position; + editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.brush.line.primary", position)); return; } editSession.drawLine(pattern, pos1, position, size, !shell, flat); - if (!visual) { - editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.brush.line.secondary")); - if (!select) { - pos1 = null; - } else { - pos1 = position; - } + editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.brush.line.secondary")); + if (!select) { + pos1 = null; + } else { + pos1 = position; } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java index aca3ebd08..47f6cb71a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SplineBrush.java @@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.FaweCache; import com.boydti.fawe.config.Caption; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.visitor.DFSRecursiveVisitor; import com.sk89q.worldedit.EditSession; @@ -53,11 +52,6 @@ public class SplineBrush implements Brush, ResettableTool { } else { mask = new MaskIntersection(mask, new IdMask(editSession)); } - boolean visualization = editSession.getExtent() instanceof VisualExtent; - if (visualization && positionSets.isEmpty()) { - return; - } - int originalSize = numSplines; boolean newPos = !position.equals(this.position); this.position = position; if (newPos) { @@ -94,9 +88,7 @@ public class SplineBrush implements Brush, ResettableTool { } this.positionSets.add(points); player.print(Caption.of("fawe.worldedit.brush.spline.primary.2")); - if (!visualization) { - return; - } + return; } if (positionSets.size() < 2) { player.print(Caption.of("fawe.worldedit.brush.brush.spline.secondary.error")); @@ -110,7 +102,6 @@ public class SplineBrush implements Brush, ResettableTool { double tension = 0; double bias = 0; double continuity = 0; - double quality = 10; final List nodes = new ArrayList<>(centroids.size()); @@ -121,7 +112,6 @@ public class SplineBrush implements Brush, ResettableTool { n.setContinuity(continuity); nodes.add(n); } - int samples = numSplines; for (int i = 0; i < numSplines; i++) { List currentSpline = new ArrayList<>(); for (ArrayList points : positionSets) { @@ -132,13 +122,8 @@ public class SplineBrush implements Brush, ResettableTool { editSession.drawSpline(pattern, currentSpline, 0, 0, 0, 10, 0, true); } player.print(Caption.of("fawe.worldedit.brush.spline.secondary")); - if (visualization) { - numSplines = originalSize; - positionSets.remove(positionSets.size() - 1); - } else { - positionSets.clear(); - numSplines = 0; - } + positionSets.clear(); + numSplines = 0; } private Vector3 getCentroid(Collection points) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SurfaceSpline.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SurfaceSpline.java index d4a58cd1b..aaa0ebb46 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SurfaceSpline.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/SurfaceSpline.java @@ -1,7 +1,6 @@ package com.boydti.fawe.object.brush; import com.boydti.fawe.config.Caption; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.collection.LocalBlockVectorSet; import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.EditSession; @@ -36,7 +35,6 @@ public class SurfaceSpline implements Brush { @Override public void build(EditSession editSession, BlockVector3 pos, Pattern pattern, double radius) throws MaxChangedBlocksException { int maxY = editSession.getMaxY(); - boolean vis = editSession.getExtent() instanceof VisualExtent; if (path.isEmpty() || !pos.equals(path.get(path.size() - 1))) { int max = editSession.getNearestSurfaceTerrainBlock(pos.getBlockX(), pos.getBlockZ(), pos.getBlockY(), 0, editSession.getMaxY()); if (max == -1) { @@ -44,9 +42,7 @@ public class SurfaceSpline implements Brush { } path.add(BlockVector3.at(pos.getBlockX(), max, pos.getBlockZ())); editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.spline.primary.2")); - if (!vis) { - return; - } + return; } final List nodes = new ArrayList<>(path.size()); final KochanekBartelsInterpolation interpol = new KochanekBartelsInterpolation(); @@ -103,9 +99,7 @@ public class SurfaceSpline implements Brush { } } editSession.setBlocks(newSet, pattern); - if (!vis) { - path.clear(); - } + path.clear(); } editSession.getPlayer().print(Caption.of("fawe.worldedit.brush.spline.secondary")); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java index d5f17e5f8..d4b3dcdbf 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/sweep/SweepBrush.java @@ -2,7 +2,6 @@ package com.boydti.fawe.object.brush.sweep; import com.boydti.fawe.config.Caption; import com.boydti.fawe.object.brush.ResettableTool; -import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.LocalSession; @@ -40,10 +39,6 @@ public class SweepBrush implements Brush, ResettableTool { @Override public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException { - boolean visualization = editSession.getExtent() instanceof VisualExtent; - if (visualization && positions.isEmpty()) { - return; - } boolean newPos = !position.equals(this.position); this.position = position; diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/ImmutableVirtualWorld.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/ImmutableVirtualWorld.java deleted file mode 100644 index c45cf846e..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/ImmutableVirtualWorld.java +++ /dev/null @@ -1,93 +0,0 @@ -package com.boydti.fawe.object.brush.visualization; - -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.weather.WeatherType; - -import javax.annotation.Nullable; - -public abstract class ImmutableVirtualWorld implements VirtualWorld { - @Override - public int getMaxY() { - return 255; - } - - @Override - public boolean regenerateChunk(int x, int z, @Nullable BiomeType biome, @Nullable Long seed) { - return unsupported(); - } - - @Override - public BiomeType getBiome(BlockVector3 position) { - return BiomeTypes.FOREST; - } - - @Override - public String getName() { - return Integer.toString(hashCode()); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block, boolean notifyAndLight) throws WorldEditException { - return setBlock(position, block); - } - - @Override - public int getBlockLightLevel(BlockVector3 position) { - return 0; - } - - @Override - public boolean clearContainerBlockContents(BlockVector3 position) { - return unsupported(); - } - - @Override - public void dropItem(Vector3 position, BaseItemStack item) { - unsupported(); - } - - @Override - public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, BlockVector3 position) throws MaxChangedBlocksException { - return unsupported(); - } - - - @Override - public boolean regenerate(Region region, EditSession editSession) { - return unsupported(); - } - - private boolean unsupported() { - throw new UnsupportedOperationException("World is immutable"); - } - - @Override - public > boolean setBlock(BlockVector3 pt, B block) throws WorldEditException { - return unsupported(); - } - - @Override - public void simulateBlockMine(BlockVector3 position) { - unsupported(); - } - - @Override - public void setWeather(WeatherType weatherType) { - unsupported(); - } - - @Override - public void setWeather(WeatherType weatherType, long duration) { - unsupported(); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VirtualWorld.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VirtualWorld.java deleted file mode 100644 index 53426eec5..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VirtualWorld.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.boydti.fawe.object.brush.visualization; - -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.event.platform.BlockInteractEvent; -import com.sk89q.worldedit.event.platform.PlayerInputEvent; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.world.SimpleWorld; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -import java.io.Closeable; -import java.io.IOException; - -public interface VirtualWorld extends SimpleWorld, Closeable { - Vector3 getOrigin(); - - @Override - default BaseBlock getFullBlock(int x, int y, int z) { - return getBlock(x, y, z).toBaseBlock(); - } - - @Override - int getMaxY(); - - @Override - > boolean setBlock(BlockVector3 pt, B block) throws WorldEditException; - - Player getPlayer(); - - void update(); - - @Override - default void close() throws IOException { - close(true); - } - - void close(boolean update) throws IOException; - - default void handleBlockInteract(Player player, BlockVector3 pos, BlockInteractEvent event) { - } - - default void handlePlayerInput(Player player, PlayerInputEvent event) { - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java deleted file mode 100644 index 73ab7309b..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualExtent.java +++ /dev/null @@ -1,70 +0,0 @@ -package com.boydti.fawe.object.brush.visualization; - -import com.boydti.fawe.beta.IQueueExtent; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extent.AbstractDelegateExtent; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; - -import javax.annotation.Nullable; - -public class VisualExtent extends AbstractDelegateExtent { - public static final BlockType VISUALIZE_BLOCK_DEFAULT = BlockTypes.BLACK_STAINED_GLASS; - private final BlockType visualizeBlock; - private final Player player; - - public VisualExtent(Extent parent, Player player) { - this(parent, player, VISUALIZE_BLOCK_DEFAULT); - } - - public VisualExtent(Extent parent, Player player, BlockType visualizeBlock) { - super(parent); - this.visualizeBlock = visualizeBlock; - this.player = player; - } - - @Override - public boolean setBlock(BlockVector3 location, BlockStateHolder block) throws WorldEditException { - return setBlock(location.getBlockX(), location.getBlockY(), location.getBlockZ(), block); - } - - @Override - public boolean setBlock(int x, int y, int z, BlockStateHolder block) throws WorldEditException { - if (block.getMaterial().isAir()) { - return super.setBlock(x, y, z, block); - } else { - return super.setBlock(x, y, z, visualizeBlock.getDefaultState()); - } - } - - @Nullable - @Override - public Operation commit() { - IQueueExtent queue = (IQueueExtent) getExtent(); - return null; - } - - @Override - public boolean setBiome(BlockVector2 position, BiomeType biome) { - // Do nothing - return false; - } - - @Override - public boolean setBiome(BlockVector3 position, BiomeType biome) { - // Do nothing - return false; - } - - public void clear() { - IQueueExtent queue = (IQueueExtent) getExtent(); - queue.cancel(); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java deleted file mode 100644 index 8979312ed..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.boydti.fawe.object.brush.visualization; - -public enum VisualMode { - NONE, - POINT, - OUTLINE -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java deleted file mode 100644 index 617979b56..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/VisualQueue.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.boydti.fawe.object.brush.visualization; - -import com.boydti.fawe.object.task.SingleThreadIntervalQueue; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.command.tool.BrushTool; -import com.sk89q.worldedit.command.tool.Tool; -import com.sk89q.worldedit.entity.Player; - -public class VisualQueue extends SingleThreadIntervalQueue { - - public VisualQueue(int interval) { - super(interval); - } - - @Override - public void operate(Player player) { - LocalSession session = player.getSession(); - Tool tool = session.getTool(player); - if (tool instanceof BrushTool) { - BrushTool brushTool = (BrushTool) tool; - if (brushTool.getVisualMode() != VisualMode.NONE) { - try { - brushTool.visualize(BrushTool.BrushAction.PRIMARY, player); - } catch (Throwable e) { - WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); - } - } - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/CFIDrawer.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/CFIDrawer.java deleted file mode 100644 index 566711e88..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/CFIDrawer.java +++ /dev/null @@ -1,146 +0,0 @@ -package com.boydti.fawe.object.brush.visualization.cfi; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.util.MathMan; -import com.boydti.fawe.util.TextureUtil; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockTypes; - -import java.awt.image.BufferedImage; -import java.awt.image.DataBufferInt; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; - -public final class CFIDrawer { - private final HeightMapMCAGenerator gen; - private final TextureUtil tu; - private final ForkJoinPool pool; - - public CFIDrawer(HeightMapMCAGenerator generator, TextureUtil textureUtil) { - this.gen = generator; - this.tu = textureUtil; - this.pool = new ForkJoinPool(); - } - - public CFIDrawer(HeightMapMCAGenerator generator) { - this(generator, Fawe.get().getCachedTextureUtil(false, 0, 100)); - } - - public BufferedImage draw() { - BufferedImage img = new BufferedImage(gen.getWidth(), gen.getLength(), BufferedImage.TYPE_INT_RGB); - final char[] overlay = gen.overlay == null ? gen.floor.get() : gen.overlay.get(); - final char[] floor = gen.floor.get(); - final char[] main = gen.main.get(); - final byte[] heights = gen.heights.get(); - final byte[] biomes = gen.biomes.get(); - final int waterHeight = gen.primitives.waterHeight; - final int width = gen.getWidth(); - final int length = gen.getLength(); - - int[] raw = ((DataBufferInt) img.getRaster().getDataBuffer()).getData(); - - int parallelism = pool.getParallelism(); - int size = (heights.length + parallelism - 1) / parallelism; - for (int i = 0; i < parallelism; i++) { - int start = i * size; - int end = Math.min(heights.length, start + size); - pool.submit((Runnable) () -> { - for (int index = start; index < end; index++) { - int height = (heights[index] & 0xFF); - char ordinal; - if ((ordinal = overlay[index]) == 0) { - height--; - ordinal = floor[index]; - if (ordinal == 0) { - height--; - ordinal = main[index]; - } - } - // draw ordinal - int color; - switch (ordinal >> 4) { - case 2: - color = getAverageBiomeColor(biomes, width, index); - break; - case 78: - color = (0xDD << 16) + (0xDD << 8) + (0xDD << 0); - break; - default: - color = tu.getColor(BlockTypes.getFromStateOrdinal(ordinal)); - break; - } - int slope = getSlope(heights, width, index, height); - if (slope != 0) { - slope = (slope << 3) + (slope << 2); - int r = MathMan.clamp(((color >> 16) & 0xFF) + slope, 0, 255); - int g = MathMan.clamp(((color >> 8) & 0xFF) + slope, 0, 255); - int b = MathMan.clamp(((color >> 0) & 0xFF) + slope, 0, 255); - color = (r << 16) + (g << 8) + (b << 0); - } - if (height + 1 < waterHeight) { - char waterId = gen.primitives.waterOrdinal; - int waterColor = 0; - switch (waterId) { - case BlockID.WATER: - color = tu.averageColor((0x11 << 16) + (0x66 << 8) + (0xCC), color); - break; - case BlockID.LAVA: - color = (0xCC << 16) + (0x33 << 8) + (0); - break; - default: - color = tu.getColor(BlockTypes.getFromStateOrdinal(waterId)); - break; - } - } - raw[index] = color; - } - }); - } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - pool.shutdownNow(); - return img; - } - - private final int getAverageBiomeColor(byte[] biomes, int width, int index) { - int c0 = tu.getBiome(biomes[index] & 0xFF).grassCombined; - int c2 = getBiome(biomes, index + 1 + width, index); - int c1 = getBiome(biomes, index - 1 - width, index); - // int c3 = getBiome(biomes, index + width, index); - // int c4 = getBiome(biomes, index - width, index); - int r = ((c0 >> 16) & 0xFF) + ((c1 >> 16) & 0xFF) + ((c2 >> 16) & 0xFF); // + ((c3 >> 16) & 0xFF) + ((c4 >> 16) & 0xFF); - int g = ((c0 >> 8) & 0xFF) + ((c1 >> 8) & 0xFF) + ((c2 >> 8) & 0xFF); // + ((c3 >> 8) & 0xFF) + ((c4 >> 8) & 0xFF); - int b = ((c0) & 0xFF) + ((c1) & 0xFF) + ((c2) & 0xFF); // + ((c3) & 0xFF) + ((c4) & 0xFF); - r = r * 85 >> 8; - g = g * 85 >> 8; - b = b * 85 >> 8; - return (r << 16) + (g << 8) + (b); - } - - private final int getBiome(byte[] biomes, int newIndex, int index) { - if (newIndex < 0 || newIndex >= biomes.length) { - newIndex = index; - } - int biome = biomes[newIndex] & 0xFF; - return tu.getBiome(biome).grassCombined; - } - - private int getSlope(byte[] heights, int width, int index, int height) { - return ( - + getHeight(heights, index + 1, height) - // + getHeight(heights, index + width, height) - + getHeight(heights, index + width + 1, height) - - getHeight(heights, index - 1, height) - // - getHeight(heights, index - width, height) - - getHeight(heights, index - width - 1, height) - ); - } - - private int getHeight(byte[] heights, int index, int height) { - if (index < 0 || index >= heights.length) { - return height; - } - return heights[index] & 0xFF; - } -} - - diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java deleted file mode 100644 index 80ba36633..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/HeightMapMCAGenerator.java +++ /dev/null @@ -1,2136 +0,0 @@ -package com.boydti.fawe.object.brush.visualization.cfi; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.FaweCache; -import com.boydti.fawe.beta.IBlocks; -import com.boydti.fawe.beta.IChunkGet; -import com.boydti.fawe.beta.IChunkSet; -import com.boydti.fawe.beta.implementation.blocks.FallbackChunkGet; -import com.boydti.fawe.beta.implementation.filter.block.ArrayFilterBlock; -import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.boydti.fawe.jnbt.anvil.MCAChunk; -import com.boydti.fawe.object.FaweInputStream; -import com.boydti.fawe.object.FaweOutputStream; -import com.boydti.fawe.object.Metadatable; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; -import com.boydti.fawe.object.change.StreamChange; -import com.boydti.fawe.object.changeset.CFIChangeSet; -import com.boydti.fawe.object.collection.DifferentialArray; -import com.boydti.fawe.object.collection.DifferentialBlockBuffer; -import com.boydti.fawe.object.collection.LocalBlockVector2DSet; -import com.boydti.fawe.object.collection.SummedAreaTable; -import com.boydti.fawe.object.exception.FaweChunkLoadException; -import com.boydti.fawe.util.CachedTextureUtil; -import com.boydti.fawe.util.RandomTextureUtil; -import com.boydti.fawe.util.ReflectionUtils; -import com.boydti.fawe.util.TextureUtil; -import com.boydti.fawe.util.image.Drawable; -import com.boydti.fawe.util.image.ImageViewer; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.EditSession; -import com.sk89q.worldedit.LocalSession; -import com.sk89q.worldedit.MaxChangedBlocksException; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.blocks.BaseItemStack; -import com.sk89q.worldedit.entity.Player; -import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.operation.Operation; -import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MutableBlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.math.transform.AffineTransform; -import com.sk89q.worldedit.math.transform.Transform; -import com.sk89q.worldedit.regions.CuboidRegion; -import com.sk89q.worldedit.regions.Region; -import com.sk89q.worldedit.session.ClipboardHolder; -import com.sk89q.worldedit.util.Identifiable; -import com.sk89q.worldedit.util.Location; -import com.sk89q.worldedit.util.SideEffect; -import com.sk89q.worldedit.util.SideEffectSet; -import com.sk89q.worldedit.util.TreeGenerator; -import com.sk89q.worldedit.world.World; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; -import com.sk89q.worldedit.world.block.BlockID; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; -import com.sk89q.worldedit.world.block.BlockType; -import com.sk89q.worldedit.world.block.BlockTypes; -import com.sk89q.worldedit.world.block.BlockTypesCache; -import org.apache.logging.log4j.Logger; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; -import java.util.function.Supplier; -import javax.annotation.Nullable; - -public class HeightMapMCAGenerator extends MCAWriter implements StreamChange, Drawable, VirtualWorld { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private final MutableBlockVector3 mutable = new MutableBlockVector3(); - - private final DifferentialBlockBuffer blocks; - protected final DifferentialArray heights; - protected final DifferentialArray biomes; - protected final DifferentialArray floor; - protected final DifferentialArray main; - protected DifferentialArray overlay; - protected Metadatable metaData = new Metadatable(); - protected TextureUtil textureUtil; - - protected final CFIPrimitives primitives = new CFIPrimitives(); - private CFIPrimitives oldPrimitives = new CFIPrimitives(); - - @Override - public void flush() {} - - public final class CFIPrimitives implements Cloneable { - - int waterHeight; - int floorThickness; - int worldThickness; - boolean randomVariation = true; - int biomePriority; - char waterOrdinal = BlockTypes.WATER.getDefaultState().getOrdinalChar(); - char bedrockOrdinal = BlockTypes.BEDROCK.getDefaultState().getOrdinalChar(); - boolean modifiedMain; - - @Override - public boolean equals(Object obj) { - if (obj == null || !(obj instanceof CFIPrimitives)) { - return false; - } - try { - for (Field field : CFIPrimitives.class.getDeclaredFields()) { - if (field.get(this) != field.get(obj)) { - return false; - } - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - return true; - } - - @Override - protected Object clone() throws CloneNotSupportedException { - return super.clone(); - } - } - - @Override - public void flushChanges(FaweOutputStream out) throws IOException { - heights.flushChanges(out); - biomes.flushChanges(out); - floor.flushChanges(out); - main.flushChanges(out); - out.writeBoolean(overlay != null); - if (overlay != null) { - overlay.flushChanges(out); - } - try { - for (Field field : ReflectionUtils - .sortFields(CFIPrimitives.class.getDeclaredFields())) { - Object now = field.get(primitives); - Object old = field.get(oldPrimitives); - boolean diff = old != now; - out.writeBoolean(diff); - if (diff) { - out.writePrimitive(old); - out.writePrimitive(now); - } - } - resetPrimitives(); - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } - - blocks.flushChanges(out); - } - - public boolean isModified() { - return blocks.isModified() || - heights.isModified() || - biomes.isModified() || - overlay != null && overlay.isModified() || - !primitives.equals(oldPrimitives); - } - - private void resetPrimitives() throws CloneNotSupportedException { - oldPrimitives = (CFIPrimitives) primitives.clone(); - } - - @Override - public void undoChanges(FaweInputStream in) throws IOException { - heights.undoChanges(in); - biomes.undoChanges(in); - floor.undoChanges(in); - main.undoChanges(in); - if (in.readBoolean()) { - overlay.undoChanges(in); - } - try { - for (Field field : ReflectionUtils - .sortFields(CFIPrimitives.class.getDeclaredFields())) { - if (in.readBoolean()) { - field.set(primitives, in.readPrimitive(field.getType())); // old - in.readPrimitive(field.getType()); // new - } - } - resetPrimitives(); - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } - blocks.undoChanges(in); - } - - @Override - public void redoChanges(FaweInputStream in) throws IOException { - heights.redoChanges(in); - biomes.redoChanges(in); - floor.redoChanges(in); - main.redoChanges(in); - if (in.readBoolean()) { - overlay.redoChanges(in); - } - - try { - for (Field field : ReflectionUtils - .sortFields(CFIPrimitives.class.getDeclaredFields())) { - if (in.readBoolean()) { - in.readPrimitive(field.getType()); // old - field.set(primitives, in.readPrimitive(field.getType())); // new - } - } - resetPrimitives(); - } catch (Throwable neverHappens) { - neverHappens.printStackTrace(); - } - - blocks.clearChanges(); // blocks.redoChanges(in); Unsupported - } - - // @Override TODO NOT IMPLEMENTED - public void addEditSession(EditSession session) { - session.setFastMode(true); - this.editSession = session; - } - - // Used for visualizing the world on a map - private ImageViewer viewer; - // Used for visualizing the world by sending chunk packets - // These three variables should be set together - // private IQueueExtent packetQueue; - private Player player; - private BlockVector2 chunkOffset = BlockVector2.ZERO; - private EditSession editSession; - // end - - public HeightMapMCAGenerator(BufferedImage img, File regionFolder) { - this(img.getWidth(), img.getHeight(), regionFolder); - setHeight(img); - } - - public HeightMapMCAGenerator(int width, int length, File regionFolder) { - super(width, length, regionFolder); - - blocks = new DifferentialBlockBuffer(width, length); - heights = new DifferentialArray<>(new byte[getArea()]); - biomes = new DifferentialArray<>(new byte[getArea()]); - floor = new DifferentialArray<>(new char[getArea()]); - main = new DifferentialArray<>(new char[getArea()]); - - char stone = BlockTypes.STONE.getDefaultState().getOrdinalChar(); - char grass = BlockTypes.GRASS_BLOCK.getDefaultState().getOrdinalChar(); - Arrays.fill(main.getCharArray(), stone); - Arrays.fill(floor.getCharArray(), grass); - } - - public Metadatable getMetaData() { - return metaData; - } - - @Override - public Vector3 getOrigin() { - return Vector3.at(chunkOffset.getBlockX() << 4, 0, chunkOffset.getBlockZ() << 4); - } - - public boolean hasPacketViewer() { - return player != null; - } - - public void setPacketViewer(Player player) { - this.player = player; - if (player != null) { - Location pos = player.getLocation(); - this.chunkOffset = BlockVector2 - .at(1 + (pos.getBlockX() >> 4), 1 + (pos.getBlockZ() >> 4)); - } - } - - public Player getOwner() { - return player; - } - - private char[][][] getChunkArray(int x, int z) { - char[][][][][] blocksData = blocks.get(); - if (blocksData == null) { - return null; - } - char[][][][] arr = blocksData[z]; - return arr != null ? arr[x] : null; - } - - public void setImageViewer(ImageViewer viewer) { - this.viewer = viewer; - } - - public ImageViewer getImageViewer() { - return viewer; - } - - @Override - public void update() { - if (viewer != null) { - viewer.view(this); - } - if (chunkOffset != null && player != null) { - World world = player.getWorld(); - - int lenCX = (getWidth() + 15) >> 4; - int lenCZ = (getLength() + 15) >> 4; - - Location position = player.getLocation(); - int pcx = (position.getBlockX() >> 4) - chunkOffset.getBlockX(); - int pcz = (position.getBlockZ() >> 4) - chunkOffset.getBlockZ(); - - int scx = Math.max(0, pcx - 15); - int scz = Math.max(0, pcz - 15); - int ecx = Math.min(lenCX - 1, pcx + 15); - int ecz = Math.min(lenCZ - 1, pcz + 15); - - for (int chunkZ = scz; chunkZ <= ecz; chunkZ++) { - for (int chunkX = scx; chunkX <= ecx; chunkX++) { - refreshChunk(world, chunkX, chunkZ); - } - } - } - - } - - public void refreshChunk(World world, int chunkX, int chunkZ) { - Supplier blocksSupplier = () -> getChunk(chunkX, chunkZ); - int realChunkX = chunkX + chunkOffset.getBlockX(); - int realChunkZ = chunkZ + chunkOffset.getBlockZ(); - ChunkPacket packet = new ChunkPacket(realChunkX, realChunkZ, blocksSupplier, true); - world.sendFakeChunk(player, packet); - } - - @Override - public void sendFakeChunk(@Nullable Player player, ChunkPacket packet) { - if (this.player != null) { - player.getWorld().sendFakeChunk(player, packet); - } - } - - @Override - public void refreshChunk(int chunkX, int chunkZ) { - if (chunkOffset != null && player != null) { - refreshChunk(player.getWorld(), chunkX, chunkZ); - } - } - - public IChunkSet getChunk(int chunkX, int chunkZ) { - // TODO don't generate new Writeable MCA chunk - MCAChunk tmp = new MCAChunk(); - int bx = chunkX << 4; - int bz = chunkZ << 4; - write(tmp, bx, bx + 15, bz, bz + 15); - return tmp; - } - - public TextureUtil getRawTextureUtil() { - if (textureUtil == null) { - textureUtil = Fawe.get().getTextureUtil(); - } - return this.textureUtil; - } - - public TextureUtil getTextureUtil() { - if (textureUtil == null) { - textureUtil = Fawe.get().getTextureUtil(); - } - try { - if (primitives.randomVariation) { - return new RandomTextureUtil(textureUtil); - } else if (textureUtil instanceof CachedTextureUtil) { - return textureUtil; - } else { - return new CachedTextureUtil(textureUtil); - } - } catch (FileNotFoundException neverHappens) { - neverHappens.printStackTrace(); - return null; - } - } - - public void setBedrock(BlockState bedrock) { - this.primitives.bedrockOrdinal = bedrock.getOrdinalChar(); - } - - public void setFloorThickness(int floorThickness) { - this.primitives.floorThickness = floorThickness; - } - - public void setWorldThickness(int height) { - this.primitives.worldThickness = height; - } - - public void setWaterHeight(int waterHeight) { - this.primitives.waterHeight = waterHeight; - } - - public void setWater(BlockState water) { - this.primitives.waterOrdinal = water.getOrdinalChar(); - } - - public void setTextureRandomVariation(boolean randomVariation) { - this.primitives.randomVariation = randomVariation; - } - - public boolean getTextureRandomVariation() { - return this.primitives.randomVariation; - } - - public void setTextureUtil(TextureUtil textureUtil) { - this.textureUtil = textureUtil; - } - - public void smooth(BufferedImage img, boolean white, int radius, int iterations) { - smooth(img, null, white, radius, iterations); - } - - public void smooth(Mask mask, int radius, int iterations) { - smooth(null, mask, false, radius, iterations); - } - - public void smooth(BlockVector2 min, BlockVector2 max, int radius, int iterations) { - int snowLayer = BlockTypes.SNOW.getDefaultState().getOrdinalChar(); - int snowBlock = BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar(); - - char[] floor = this.floor.get(); - byte[] heights = this.heights.get(); - - int width = getWidth(); - int length = getLength(); - - int minX = min.getBlockX(); - int minZ = min.getBlockZ(); - - int maxX = max.getBlockX(); - int maxZ = max.getBlockZ(); - - int tableWidth = maxX - minX + 1; - int tableLength = maxZ - minZ + 1; - int smoothArea = tableWidth * tableLength; - - long[] copy = new long[smoothArea]; - char[] layers = new char[smoothArea]; - - SummedAreaTable table = new SummedAreaTable(copy, layers, tableWidth, radius); - for (int j = 0; j < iterations; j++) { - { // Copy to table - int localIndex = 0; - int zIndex = minZ * getWidth(); - for (int z = minZ; z <= maxZ; z++, zIndex += getWidth()) { - int index = zIndex + minX; - for (int x = minX; x <= maxX; x++, index++, localIndex++) { - int combined = floor[index]; - if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) { - layers[localIndex] = (char) ( - ((heights[index] & 0xFF) << 3) + (floor[index] - >> BlockTypesCache.BIT_OFFSET) - 7); - } else { - layers[localIndex] = (char) ((heights[index] & 0xFF) << 3); - } - } - } - } - // Process table - table.processSummedAreaTable(); - // Copy from table - int localIndex = 0; - int zIndex = minZ * getWidth(); - for (int z = minZ, localZ = 0; z <= maxZ; z++, localZ++, zIndex += getWidth()) { - int index = zIndex + minX; - for (int x = minX, localX = 0; x <= maxX; x++, localX++, index++, localIndex++) { - int y = heights[index] & 0xFF; - int newHeight = table.average(localX, localZ, localIndex); - setLayerHeight(index, newHeight); - } - } - } - } - - private final void setLayerHeight(int index, int height) { - int blockHeight = height >> 3; - int layerHeight = height & 0x7; - setLayerHeight(index, blockHeight, layerHeight); - } - - private final void setLayerHeight(int index, int blockHeight, int layerHeight) { - int floorState = floor.get()[index]; - switch (floorState) { - case BlockID.SNOW: - case BlockID.SNOW_BLOCK: - if (layerHeight != 0) { - this.heights.setByte(index, (byte) (blockHeight + 1)); - this.floor.setInt(index, - BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight); - } else { - this.heights.setByte(index, (byte) blockHeight); - this.floor - .setInt(index, BlockTypes.SNOW_BLOCK.getDefaultState().getOrdinalChar()); - } - break; - default: - this.heights.setByte(index, (byte) blockHeight); - break; - } - } - - private final void setLayerHeightRaw(int index, int height) { - int blockHeight = height >> 3; - int layerHeight = height & 0x7; - setLayerHeightRaw(index, blockHeight, layerHeight); - } - - private final void setLayerHeightRaw(int index, int blockHeight, int layerHeight) { - int floorState = floor.get()[index]; - switch (floorState) { - case BlockID.SNOW: - case BlockID.SNOW_BLOCK: - if (layerHeight != 0) { - this.heights.getByteArray()[index] = (byte) (blockHeight + 1); - this.overlay.getCharArray()[index] = (char) ( - BlockTypes.SNOW.getDefaultState().getOrdinalChar() + layerHeight); - } else { - this.heights.getByteArray()[index] = (byte) blockHeight; - this.overlay.getCharArray()[index] = BlockTypes.SNOW_BLOCK.getDefaultState() - .getOrdinalChar(); - } - break; - default: - this.heights.getByteArray()[index] = (byte) blockHeight; - break; - } - } - - private void smooth(BufferedImage img, Mask mask, boolean white, int radius, int iterations) { - char[] floor = this.floor.get(); - byte[] heights = this.heights.get(); - - long[] copy = new long[heights.length]; - char[] layers = new char[heights.length]; - - this.floor.record(() -> HeightMapMCAGenerator.this.heights.record(() -> { - int width = getWidth(); - int length = getLength(); - SummedAreaTable table = new SummedAreaTable(copy, layers, width, radius); - for (int j = 0; j < iterations; j++) { - for (int i = 0; i < heights.length; i++) { - int combined = floor[i]; - if (BlockTypes.getFromStateOrdinal(combined) == BlockTypes.SNOW) { - layers[i] = (char) ( - ((heights[i] & 0xFF) << 3) + (floor[i] >> BlockTypesCache.BIT_OFFSET) - - 7); - } else { - layers[i] = (char) ((heights[i] & 0xFF) << 3); - } - } - int index = 0; - table.processSummedAreaTable(); - if (img != null) { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - int newHeight = table.average(x, z, index); - setLayerHeightRaw(index, newHeight); - } - } - } - } else if (mask != null) { - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights[index] & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - int newHeight = table.average(x, z, index); - setLayerHeightRaw(index, newHeight); - } - } - } - } else { - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int newHeight = table.average(x, z, index); - setLayerHeightRaw(index, newHeight); - } - } - } - } - })); - } - - public void setHeight(BufferedImage img) { - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - heights.setByte(index, (byte) (img.getRGB(x, z) >> 8)); - } - } - } - - public void addCaves() throws WorldEditException { - CuboidRegion region = new CuboidRegion(BlockVector3.at(0, 0, 0), - BlockVector3.at(getWidth() - 1, 255, getLength() - 1)); - addCaves(region); - } - - @Deprecated - public void addSchems(Mask mask, List clipboards, int rarity, boolean rotate) - throws WorldEditException { - CuboidRegion region = new CuboidRegion(BlockVector3.at(0, 0, 0), - BlockVector3.at(getWidth() - 1, 255, getLength() - 1)); - addSchems(region, mask, clipboards, rarity, rotate); - } - - public void addSchems(BufferedImage img, Mask mask, List clipboards, - int rarity, int distance, boolean randomRotate) throws WorldEditException { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - double doubleRarity = rarity / 100d; - int index = 0; - AffineTransform identity = new AffineTransform(); - LocalBlockVector2DSet placed = new LocalBlockVector2DSet(); - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - int height = img.getRGB(x, z) & 0xFF; - if (height == 0 - || ThreadLocalRandom.current().nextInt(256) > height * doubleRarity) { - continue; - } - mutable.mutX(x); - mutable.mutY(y); - if (!mask.test(mutable)) { - continue; - } - if (placed.containsRadius(x, z, distance)) { - continue; - } - placed.add(x, z); - ClipboardHolder holder = clipboards - .get(ThreadLocalRandom.current().nextInt(clipboards.size())); - if (randomRotate) { - int rotate = ThreadLocalRandom.current().nextInt(4) * 90; - if (rotate != 0) { - holder.setTransform(new AffineTransform() - .rotateY(ThreadLocalRandom.current().nextInt(4) * 90)); - } else { - holder.setTransform(identity); - } - } - Clipboard clipboard = holder.getClipboard(); - Transform transform = holder.getTransform(); - if (transform.isIdentity()) { - clipboard.paste(this, mutable, false); - } else { - clipboard.paste(this, mutable, false, transform); - } - if (x + distance < getWidth()) { - x += distance; - index += distance; - } else { - break; - } - } - } - } - - public void addSchems(Mask mask, List clipboards, int rarity, int distance, - boolean randomRotate) throws WorldEditException { - int scaledRarity = 256 * rarity / 100; - int index = 0; - AffineTransform identity = new AffineTransform(); - LocalBlockVector2DSet placed = new LocalBlockVector2DSet(); - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - if (ThreadLocalRandom.current().nextInt(256) > scaledRarity) { - continue; - } - mutable.mutX(x); - mutable.mutY(y); - if (!mask.test(mutable)) { - continue; - } - if (placed.containsRadius(x, z, distance)) { - continue; - } - mutable.mutY(y + 1); - placed.add(x, z); - ClipboardHolder holder = clipboards - .get(ThreadLocalRandom.current().nextInt(clipboards.size())); - if (randomRotate) { - int rotate = ThreadLocalRandom.current().nextInt(4) * 90; - if (rotate != 0) { - holder.setTransform(new AffineTransform() - .rotateY(ThreadLocalRandom.current().nextInt(4) * 90)); - } else { - holder.setTransform(identity); - } - } - Clipboard clipboard = holder.getClipboard(); - Transform transform = holder.getTransform(); - if (transform.isIdentity()) { - clipboard.paste(this, mutable, false); - } else { - clipboard.paste(this, mutable, false, transform); - } - if (x + distance < getWidth()) { - x += distance; - index += distance; - } else { - break; - } - } - } - } - - public void addOre(Mask mask, Pattern material, int size, int frequency, int rarity, int minY, - int maxY) throws WorldEditException { - CuboidRegion region = new CuboidRegion(BlockVector3.at(0, 0, 0), - BlockVector3.at(getWidth() - 1, 255, getLength() - 1)); - addOre(region, mask, material, size, frequency, rarity, minY, maxY); - } - - public void addDefaultOres(Mask mask) throws WorldEditException { - addOres(new CuboidRegion(BlockVector3.at(0, 0, 0), - BlockVector3.at(getWidth() - 1, 255, getLength() - 1)), mask); - } - - @Override - public BlockVector3 getMinimumPoint() { - return BlockVector3.at(0, 0, 0); - } - - @Override - public Player getPlayer() { - return player; - } - - @Override - public BlockVector3 getMaximumPoint() { - return BlockVector3.at(getWidth() - 1, 255, getLength() - 1); - } - - @Override - public Set applySideEffects(BlockVector3 position, BlockState previousType, SideEffectSet sideEffectSet) - throws WorldEditException{ - return SideEffectSet.none().getSideEffectsToApply(); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block) - throws WorldEditException { - return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block, SideEffectSet sideEffects) - throws WorldEditException { - return setBlock(position.getBlockX(), position.getBlockY(), position.getBlockZ(), block); - } - - private boolean setBlock(int x, int y, int z, char combined) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - return false; - } - int height = heights.getByte(index) & 0xFF; - switch (y - height) { - case 0: - floor.setInt(index, combined); - return true; - case 1: - char mainId = overlay.getChar(index); - char floorId = overlay.getChar(index); - floor.setInt(index, combined); - - byte currentHeight = heights.getByte(index); - currentHeight++; - heights.setByte(index, currentHeight); - if (mainId == floorId) { - return true; - } - y--; - combined = floorId; - default: - try { - blocks.set(x, y, z, combined); - return true; - } catch (IndexOutOfBoundsException ignored) { - return false; - } - } - } - - @Override - public boolean setBiome(int x, int y, int z, BiomeType biome) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - return false; - } - biomes.setByte(index, (byte) biome.getInternalId()); - return true; - } - -// @Override TODO NOT IMPLEMENTED -// public FaweChunk getFaweChunk(int chunkX, int chunkZ) { -// return new SimpleIntFaweChunk(this, chunkX, chunkZ); -// } -// -// @Override -// public FaweChunk getSnapshot(int chunkX, int chunkZ) { -// return getSnapshot(null, chunkX, chunkZ); -// } -// -// private FaweChunk getSnapshot(final MCAChunk chunk, int chunkX, int chunkZ) { -// return new LazyFaweChunk(this, chunkX, chunkZ) { -// @Override -// public MCAChunk getChunk() { -// MCAChunk tmp = chunk; -// if (tmp == null) { -// tmp = new MCAChunk(); -// } -// tmp.setLoc(HeightMapMCAGenerator.this, chunkX, chunkZ); -// int cbx = chunkX << 4; -// int cbz = chunkZ << 4; -// int csx = Math.max(0, cbx); -// int csz = Math.max(0, cbz); -// int cex = Math.min(getWidth(), cbx + 15); -// int cez = Math.min(getLength(), cbz + 15); -// write(tmp, csx, cex, csz, cez); -// tmp.setLoc(HeightMapMCAGenerator.this, getX(), getZ()); -// return tmp; -// } -// -// @Override -// public void addToQueue() { -// MCAChunk cached = getCachedChunk(); -// if (cached != null) setChunk(cached); -// } -// }; -// } -// -// @Override -// public Collection getFaweChunks() { -// return Collections.emptyList(); -// } -// -// @Override -// public void setChunk(FaweChunk chunk) { -// int[][] src = chunk.getCombinedIdArrays(); -// for (int i = 0; i < src.length; i++) { -// if (src[i] != null) { -// int bx = chunk.getX() << 4; -// int bz = chunk.getZ() << 4; -// int by = i << 4; -// for (int layer = i; layer < src.length; layer++) { -// int[] srcLayer = src[layer]; -// if (srcLayer != null) { -// int index = 0; -// for (int y = 0; y < 16; y++) { -// int yy = by + y; -// for (int z = 0; z < 16; z++) { -// int zz = bz + z; -// for (int x = 0; x < 16; x++, index++) { -// int combined = srcLayer[index]; -// if (combined != 0) { -// setBlock(bx + x, yy, zz, combined); -// } -// } -// } -// } -// } -// } -// break; -// } -// } -// } - - @Nullable - @Override - public Path getStoragePath() { - return getFolder().toPath(); - } - - @Override - public int getMinY() { - return 0; - } - - @Override - public boolean regenerateChunk(int x, int z, @Nullable BiomeType biome, @Nullable Long seed) { - // Unsupported - return false; - } - - @Nullable - @Override - public Operation commit() { - EditSession curES = editSession; - if (curES != null && isModified()) { - try { - update(); - Player esPlayer = curES.getPlayer(); - UUID uuid = esPlayer != null ? esPlayer.getUniqueId() : Identifiable.CONSOLE; - try { - curES.setRawChangeSet(new CFIChangeSet(this, uuid)); - } catch (IOException e) { - e.printStackTrace(); - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - return null; - } - - @Override - public void close(boolean update) { - if (chunkOffset != null && player != null && update) { - World world = player.getWorld(); - - int lenCX = getWidth() + 15 >> 4; - int lenCZ = getLength() + 15 >> 4; - - int OX = chunkOffset.getBlockX(); - int OZ = chunkOffset.getBlockZ(); - - Location position = player.getLocation(); - int pcx = (position.getBlockX() >> 4) - OX; - int pcz = (position.getBlockZ() >> 4) - OZ; - - int scx = Math.max(0, pcx - 10); - int scz = Math.max(0, pcz - 10); - int ecx = Math.min(lenCX - 1, pcx + 10); - int ecz = Math.min(lenCZ - 1, pcz + 10); - - for (int cz = scz; cz <= ecz; cz++) { - for (int cx = scx; cx <= ecx; cx++) { - world.refreshChunk(cx + OX, cz + OZ); - } - } - } - if (player != null) { - player.deleteMeta("CFISettings"); - LocalSession session = player.getSession(); - session.clearHistory(); - } - player = null; - chunkOffset = null; - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) throws FaweChunkLoadException { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - index = Math.floorMod(index, getArea()); - } - return BiomeTypes.get(biomes.getByte(index)); - } - - public int getOrdinal(int x, int y, int z) throws FaweChunkLoadException { - int index = z * getWidth() + x; - if (y < 0) { - return 0; - } - if (index < 0 || index >= getArea() || x < 0 || x >= getWidth()) { - return 0; - } - int height = heights.getByte(index) & 0xFF; - if (y > height) { - if (y == height + 1) { - return overlay != null ? overlay.getChar(index) : 0; - } - if (blocks != null) { - short chunkX = (short) (x >> 4); - short chunkZ = (short) (z >> 4); - char[][][] map = getChunkArray(chunkX, chunkZ); - if (map != null) { - int combined = get(map, x, y, z); - if (combined != 0) { - return combined; - } - } - } - if (y <= primitives.waterHeight) { - return primitives.waterOrdinal; - } - return 0; - } else if (y == height) { - return overlay.getChar(index); - } else { - if (blocks != null) { - short chunkX = (short) (x >> 4); - short chunkZ = (short) (z >> 4); - char[][][] map = getChunkArray(chunkX, chunkZ); - if (map != null) { - int combined = get(map, x, y, z); - if (combined != 0) { - return combined; - } - } - } - return overlay.getChar(index); - } - } - - @Override - public > boolean setBlock(int x, int y, int z, B block) - throws WorldEditException { - return this.setBlock(x, y, z, block.getOrdinalChar()); - } - - @Override - public BiomeType getBiome(BlockVector3 position) { - return getBiomeType(position.getBlockX(), position.getBlockY(), position.getBlockZ()); - } - - @Override - public BlockState getBlock(BlockVector3 position) { - return getBlock(position.getX(), position.getY(), position.getZ()); - } - - public BlockState getFloor(int x, int z) { - int index = z * getWidth() + x; - return BlockState.getFromOrdinal(overlay.getChar(index)); - } - - public int getHeight(int x, int z) { - int index = z * getWidth() + x; - return heights.getByte(index) & 0xFF; - } - - public int getHeight(int index) { - return heights.getByte(index) & 0xFF; - } - - public > void setFloor(int x, int z, B block) { - int index = z * getWidth() + x; - floor.setInt(index, block.getOrdinalChar()); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - return BlockState.getFromOrdinal(getOrdinal(x, y, z)); - } - - @Override - public int getNearestSurfaceLayer(int x, int z, int y, int minY, int maxY) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - index = Math.floorMod(index, getArea()); - } - return ((heights.getByte(index) & 0xFF) << 3) + (overlay.getChar(index) & 0xFF) + 1; - } - - @Override - public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - index = Math.floorMod(index, getArea()); - } - return heights.getByte(index) & 0xFF; - } - - @Override - public int getNearestSurfaceTerrainBlock(int x, int z, int y, int minY, int maxY, int failedMin, - int failedMax) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - index = Math.floorMod(index, getArea()); - } - return heights.getByte(index) & 0xFF; - } - - public void setBiome(BufferedImage img, BiomeType biome, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - byte biomeByte = (byte) biome.getInternalId(); - biomes.record(new Runnable() { - @Override - public void run() { - byte[] biomeArr = biomes.get(); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - biomeArr[index] = biomeByte; - } - } - } - } - }); - } - - @Override - public BufferedImage draw() { - return new CFIDrawer(this).draw(); - } - - public void setBiomePriority(int value) { - this.primitives.biomePriority = value * 65536 / 100 - 32768; - } - - public int getBiomePriority() { - return (primitives.biomePriority + 32768) * 100 / 65536; - } - - public void setBlockAndBiomeColor(BufferedImage img, Mask mask, BufferedImage imgMask, - boolean whiteOnly) { - if (mask == null && imgMask == null) { - setBlockAndBiomeColor(img); - return; - } - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - TextureUtil textureUtil = getTextureUtil(); - - int widthIndex = img.getWidth() - 1; - int heightIndex = img.getHeight() - 1; - int maxIndex = getArea() - 1; - - biomes.record(() -> floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - byte[] biomesArr = biomes.get(); - - int index = 0; - char[] buffer = new char[2]; - for (int z = 0; z < img.getHeight(); z++) { - mutable.mutZ(z); - for (int x = 0; x < img.getWidth(); x++, index++) { - if (mask != null) { - mutable.mutX(z); - mutable.mutY(heights.getByte(index) & 0xFF); - if (!mask.test(mutable)) { - continue; - } - } - if (imgMask != null) { - int height = imgMask.getRGB(x, z) & 0xFF; - if (height != 255 && (height <= 0 || !whiteOnly || ThreadLocalRandom - .current().nextInt(256) > height)) { - continue; - } - } - int color = img.getRGB(x, z); - if (textureUtil - .getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) { - char combined = buffer[0]; - mainArr[index] = combined; - floorArr[index] = combined; - } - biomesArr[index] = (byte) buffer[1]; - } - } - }))); - } - - public void setBlockAndBiomeColor(BufferedImage img) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - TextureUtil textureUtil = getTextureUtil(); - int heightIndex = img.getHeight() - 1; - - biomes.record(() -> floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - byte[] biomesArr = biomes.get(); - - char[] buffer = new char[2]; - int index = 0; - for (int y = 0; y < img.getHeight(); y++) { - for (int x = 0; x < img.getWidth(); x++, index++) { - int color = img.getRGB(x, y); - if (textureUtil - .getIsBlockCloserThanBiome(buffer, color, primitives.biomePriority)) { - char combined = buffer[0]; - mainArr[index] = combined; - floorArr[index] = combined; - } - biomesArr[index] = (byte) buffer[1]; - } - } - }))); - } - - public void setBiomeColor(BufferedImage img) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - TextureUtil textureUtil = getTextureUtil(); - - biomes.record(() -> { - byte[] biomesArr = biomes.get(); - int index = 0; - for (int y = 0; y < img.getHeight(); y++) { - for (int x = 0; x < img.getWidth(); x++) { - int color = img.getRGB(x, y); - TextureUtil.BiomeColor biome = textureUtil.getNearestBiome(color); - if (biome != null) { - biomesArr[index] = (byte) biome.id; - } - index++; - } - } - }); - } - - public void setColor(BufferedImage img, BufferedImage mask, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - if (mask.getWidth() != getWidth() || mask.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - TextureUtil textureUtil = getTextureUtil(); - - floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = mask.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - int color = img.getRGB(x, z); - BlockType block = textureUtil.getNearestBlock(color); - if (block != null) { - char combined = block.getDefaultState().getOrdinalChar(); - mainArr[index] = combined; - floorArr[index] = combined; - } - } - } - } - })); - } - - public void setColor(BufferedImage img, Mask mask) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - TextureUtil textureUtil = getTextureUtil(); - - floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - - int index = 0; - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - mutable.mutX(x); - mutable.mutY(heights.getByte(index) & 0xFF); - if (mask.test(mutable)) { - int color = img.getRGB(x, z); - BlockType block = textureUtil.getNearestBlock(color); - if (block != null) { - char combined = block.getDefaultState().getOrdinalChar(); - mainArr[index] = combined; - floorArr[index] = combined; - } - } - } - } - })); - } - - public void setColor(BufferedImage img) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - TextureUtil textureUtil = getTextureUtil(); - - floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - - int index = 0; - for (int z = 0; z < img.getHeight(); z++) { - for (int x = 0; x < img.getWidth(); x++) { - int color = img.getRGB(x, z); - BlockType block = textureUtil.getNearestBlock(color); - if (block != null) { - char combined = block.getDefaultState().getOrdinalChar(); - mainArr[index] = combined; - floorArr[index] = combined; - } - index++; - } - } - })); - } - - public void setColorWithGlass(BufferedImage img) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - TextureUtil textureUtil = getTextureUtil(); - - floor.record(() -> main.record(() -> { - char[] mainArr = main.get(); - char[] floorArr = floor.get(); - - int index = 0; - for (int y = 0; y < img.getHeight(); y++) { - for (int x = 0; x < img.getWidth(); x++) { - int color = img.getRGB(x, y); - BlockType[] layer = textureUtil.getNearestLayer(color); - if (layer != null) { - floorArr[index] = layer[0].getDefaultState().getOrdinalChar(); - mainArr[index] = layer[1].getDefaultState().getOrdinalChar(); - } - index++; - } - } - })); - } - - public void setBiome(Mask mask, BiomeType biome) { - int index = 0; - byte biomeByte = (byte) biome.getInternalId(); - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - biomes.setByte(index, biomeByte); - } - } - } - } - - public void setOverlay(BufferedImage img, Pattern pattern, boolean white) { - if (pattern instanceof BlockStateHolder) { - setOverlay(img, ((BlockStateHolder) pattern).getOrdinalChar(), white); - } else if (pattern instanceof BlockType) { - setOverlay(img, ((BlockType) pattern).getDefaultState().getOrdinalChar(), white); - } else { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - - overlay.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, overlay.get(), heights.get(), - getWidth(), getLength(), 1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - filter.init(x, z, index); - pattern.apply(this, filter, filter); - } - } - } - }); - - } - } - - public void setMain(BufferedImage img, Pattern pattern, boolean white) { - if (pattern instanceof BlockStateHolder) { - setMain(img, ((BlockStateHolder) pattern).getOrdinalChar(), white); - } else { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - - main.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - filter.init(x, z, index); - pattern.apply(this, filter, filter); - } - } - } - }); - } - } - - public void setFloor(BufferedImage img, Pattern pattern, boolean white) { - if (pattern instanceof BlockStateHolder) { - setFloor(img, ((BlockStateHolder) pattern).getOrdinalChar(), white); - } else { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - - floor.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, floor.get(), heights.get(), - getWidth(), getLength(), 1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - filter.init(x, z, index); - pattern.apply(this, filter, filter); - } - } - } - }); - } - } - - public void setColumn(BufferedImage img, Pattern pattern, boolean white) { - if (pattern instanceof BlockStateHolder) { - setColumn(img, ((BlockStateHolder) pattern).getOrdinalChar(), white); - } else { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - - main.record(() -> floor.record(() -> { - ArrayFilterBlock filterFloor = new ArrayFilterBlock(this, floor.get(), - heights.get(), getWidth(), getLength(), 0); - ArrayFilterBlock filterMain = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - filterFloor.init(x, z, index); - filterMain.init(x, z, index); - - pattern.apply(this, filterFloor, filterFloor); - pattern.apply(this, filterMain, filterMain); - } - } - } - })); - } - } - - public void setOverlay(Mask mask, Pattern pattern) { - if (pattern instanceof BlockStateHolder) { - setOverlay(mask, ((BlockStateHolder) pattern).getOrdinalChar()); - } else { - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - overlay.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, overlay.get(), heights.get(), - getWidth(), getLength(), 1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - filter.init(x, z, index); - if (mask.test(filter)) { - pattern.apply(this, filter, filter); - } - } - } - }); - - } - } - - public void setFloor(Mask mask, Pattern pattern) { - if (pattern instanceof BlockStateHolder) { - setFloor(mask, ((BlockStateHolder) pattern).getOrdinalChar()); - } else { - floor.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, floor.get(), heights.get(), - getWidth(), getLength(), 0); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - filter.init(x, z, index); - if (mask.test(filter)) { - pattern.apply(this, filter, filter); - } - } - } - }); - } - } - - public void setMain(Mask mask, Pattern pattern) { - if (pattern instanceof BlockStateHolder) { - setMain(mask, ((BlockStateHolder) pattern).getOrdinalChar()); - } else { - main.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - primitives.modifiedMain = true; - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - if (mask.test(filter)) { - pattern.apply(this, filter, filter); - } - } - } - }); - } - } - - public void setColumn(Mask mask, Pattern pattern) { - if (pattern instanceof BlockStateHolder) { - setColumn(mask, ((BlockStateHolder) pattern).getOrdinalChar()); - } else { - floor.record(() -> main.record(() -> { - ArrayFilterBlock floorFilter = new ArrayFilterBlock(this, floor.get(), - heights.get(), getWidth(), getLength(), 0); - ArrayFilterBlock mainFilter = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - primitives.modifiedMain = true; - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - floorFilter.init(x, z, index); - mainFilter.init(x, z, index); - if (mask.test(mainFilter)) { - pattern.apply(this, mainFilter, mainFilter); - } - if (mask.test(floorFilter)) { - pattern.apply(this, floorFilter, floorFilter); - } - } - } - })); - - } - } - - public void setBiome(BiomeType biome) { - biomes.record(() -> Arrays.fill(biomes.get(), (byte) biome.getInternalId())); - } - - public void setFloor(Pattern value) { - if (value instanceof BlockStateHolder) { - setFloor(((BlockStateHolder) value).getOrdinalChar()); - } else { - floor.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, floor.get(), heights.get(), - getWidth(), getLength(), 0); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - filter.init(x, z, index); - value.apply(this, filter, filter); - } - } - }); - } - } - - public void setColumn(Pattern value) { - if (value instanceof BlockStateHolder) { - setColumn(((BlockStateHolder) value).getOrdinalChar()); - } else { - main.record(() -> floor.record(() -> { - ArrayFilterBlock floorFilter = new ArrayFilterBlock(this, floor.get(), - heights.get(), getWidth(), getLength(), 0); - ArrayFilterBlock mainFilter = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - floorFilter.init(x, z, index); - mainFilter.init(x, z, index); - value.apply(this, floorFilter, floorFilter); - value.apply(this, mainFilter, mainFilter); - } - } - })); - } - } - - public void setMain(Pattern value) { - if (value instanceof BlockStateHolder) { - setMain(((BlockStateHolder) value).getOrdinalChar()); - } else { - main.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, main.get(), heights.get(), - getWidth(), getLength(), -1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - filter.init(x, z, index); - value.apply(this, filter, filter); - } - } - }); - } - } - - public void setOverlay(Pattern value) { - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - if (value instanceof BlockStateHolder) { - setOverlay(((BlockStateHolder) value).getOrdinalChar()); - } else { - overlay.record(() -> { - ArrayFilterBlock filter = new ArrayFilterBlock(this, overlay.get(), heights.get(), - getWidth(), getLength(), 1); - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - filter.init(x, z, index); - value.apply(this, filter, filter); - } - } - }); - } - } - - public void setHeight(int x, int z, int height) { - int index = z * getWidth() + x; - if (index < 0 || index >= getArea()) { - return; - } - heights.setByte(index, (byte) height); - } - - public void setHeight(int index, int height) { - heights.setByte(index, (byte) height); - } - - public void setHeights(int value) { - heights.record(() -> Arrays.fill(heights.get(), (byte) value)); - } - - @Override - public boolean shouldWrite(int chunkX, int chunkZ) { - return true; - } - - @Override - public MCAChunk write(MCAChunk chunk, int csx, int cex, int csz, int cez) { - byte[] heights = this.heights.get(); - byte[] biomes = this.biomes.get(); - char[] main = this.main.get(); - char[] floor = this.floor.get(); - char[] overlay = this.overlay != null ? this.overlay.get() : null; - try { - int[] indexes = FaweCache.IMP.INDEX_STORE.get(); - - int index; - int maxY = 0; - int minY = Integer.MAX_VALUE; - int[] heightMap = FaweCache.IMP.HEIGHT_STORE.get(); - int globalIndex; - for (int z = csz; z <= cez; z++) { - globalIndex = z * getWidth() + csx; - index = (z & 15) << 4; - for (int x = csx; x <= cex; x++, index++, globalIndex++) { - indexes[index] = globalIndex; - int height = heights[globalIndex] & 0xFF; - heightMap[index] = height; - maxY = Math.max(maxY, height); - minY = Math.min(minY, height); - } - } - boolean hasOverlay = this.overlay != null; - if (hasOverlay) { - maxY++; - } - int maxLayer = maxY >> 4; - for (int layer = 0; layer <= maxLayer; layer++) { - chunk.hasSections[layer] = true; - } - if (primitives.waterHeight != 0) { - int maxIndex = primitives.waterHeight << 8; - Arrays.fill(chunk.blocks, 0, maxIndex, primitives.waterOrdinal); - } - - if (primitives.modifiedMain) { // If the main block is modified, we can't short circuit this - for (int z = csz; z <= cez; z++) { - index = (z & 15) << 4; - for (int x = csx; x <= cex; x++, index++) { - globalIndex = indexes[index]; - char mainCombined = main[globalIndex]; - for (int y = 0; y < minY; y++) { - chunk.blocks[index + (y << 8)] = mainCombined; - } - } - } - } else { - int maxIndex = minY << 8; - Arrays.fill(chunk.blocks, 0, maxIndex, (char) BlockID.STONE); - } - - final boolean hasFloorThickness = - primitives.floorThickness != 0 || primitives.worldThickness != 0; - if (primitives.worldThickness != 0) { - int endLayer = minY - primitives.worldThickness + 1 >> 4; - for (int layer = 0; layer < endLayer; layer++) { - chunk.hasSections[layer] = false; - } - } - - for (int z = csz; z <= cez; z++) { - index = (z & 15) << 4; - for (int x = csx; x <= cex; x++, index++) { - globalIndex = indexes[index]; - int height = heightMap[index]; - int maxMainY = height; - int minMainY = minY; - - char mainCombined = main[globalIndex]; - - char floorCombined = floor[globalIndex]; - if (hasFloorThickness) { - if (x > 0) { - maxMainY = Math.min(heights[globalIndex - 1] & 0xFF, maxMainY); - } - if (x < getWidth() - 1) { - maxMainY = Math.min(heights[globalIndex + 1] & 0xFF, maxMainY); - } - if (z > 0) { - maxMainY = Math.min(heights[globalIndex - getWidth()] & 0xFF, maxMainY); - } - if (z < getLength() - 1) { - maxMainY = Math.min(heights[globalIndex + getWidth()] & 0xFF, maxMainY); - } - - int min = maxMainY; - - if (primitives.floorThickness != 0) { - maxMainY = Math.max(0, maxMainY - (primitives.floorThickness - 1)); - for (int y = maxMainY; y <= height; y++) { - chunk.blocks[index + (y << 8)] = floorCombined; - } - } else { - chunk.blocks[index + (height << 8)] = floorCombined; - } - - if (primitives.worldThickness != 0) { - minMainY = Math.max(minY, min - primitives.worldThickness + 1); - for (int y = minY; y < minMainY; y++) { - chunk.blocks[index + (y << 8)] = BlockID.AIR; - } - } - - } else { - chunk.blocks[index + (height << 8)] = floorCombined; - } - - for (int y = minMainY; y < maxMainY; y++) { - chunk.blocks[index + (y << 8)] = mainCombined; - } - - if (hasOverlay) { - char overlayCombined = overlay[globalIndex]; - int overlayIndex = index + (height + 1 << 8); - chunk.blocks[overlayIndex] = overlayCombined; - } - - if (primitives.bedrockOrdinal != 0) { - chunk.blocks[index] = primitives.bedrockOrdinal; - } - } - } - - char[][][] localBlocks = getChunkArray(chunk.getX(), chunk.getZ()); - if (localBlocks != null) { - index = 0; - for (int layer = 0; layer < 16; layer++) { - int by = layer << 4; - int ty = by + 15; - for (int y = by; y <= ty; y++, index += 256) { - char[][] yBlocks = localBlocks[y]; - if (yBlocks != null) { - chunk.hasSections[layer] = true; - for (int z = 0; z < yBlocks.length; z++) { - char[] zBlocks = yBlocks[z]; - if (zBlocks != null) { - int zIndex = index + (z << 4); - for (int x = 0; x < zBlocks.length; x++, zIndex++) { - char combined = zBlocks[x]; - if (combined == 0) { - continue; - } - chunk.blocks[zIndex] = combined; - } - } - } - } - } - } - } - - for (int i = 0; i < 256; i++) { - byte biomeId = biomes[indexes[i]]; - if (biomeId != 0) { - chunk.biomes[i] = BiomeTypes.get(biomeId); - } - } - - - } catch (Throwable e) { - e.printStackTrace(); - } - return chunk; - } - - private void setUnsafe(char[][][] map, char combined, int x, int y, int z) { - char[][] yMap = map[y]; - if (yMap == null) { - map[y] = yMap = new char[16][]; - } - char[] zMap = yMap[z]; - if (zMap == null) { - yMap[z] = zMap = new char[16]; - } - zMap[x] = combined; - } - - private int get(char[][][] map, int x, int y, int z) { - char[][] yMap = map[y]; - if (yMap == null) { - return 0; - } - char[] zMap = yMap[z & 15]; - if (zMap == null) { - return 0; - } - return zMap[x & 15]; - } - - private void setOverlay(Mask mask, int combined) { - int index = 0; - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - overlay.setInt(index, combined); - } - } - } - } - - private void setFloor(Mask mask, int combined) { - int index = 0; - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - floor.setInt(index, combined); - } - } - } - } - - private void setMain(Mask mask, int combined) { - primitives.modifiedMain = true; - int index = 0; - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - main.setInt(index, combined); - } - } - } - } - - private void setColumn(Mask mask, int combined) { - primitives.modifiedMain = true; - int index = 0; - for (int z = 0; z < getLength(); z++) { - mutable.mutZ(z); - for (int x = 0; x < getWidth(); x++, index++) { - int y = heights.getByte(index) & 0xFF; - mutable.mutX(x); - mutable.mutY(y); - if (mask.test(mutable)) { - floor.setInt(index, combined); - main.setInt(index, combined); - } - } - } - } - - private void setFloor(char value) { - floor.record(() -> Arrays.fill(floor.get(), value)); - } - - private void setColumn(char value) { - setFloor(value); - setMain(value); - } - - private void setMain(char value) { - primitives.modifiedMain = true; - main.record(() -> Arrays.fill(main.get(), value)); - } - - private void setOverlay(char value) { - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - overlay.record(() -> Arrays.fill(overlay.get(), value)); - } - - private void setOverlay(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - if (overlay == null) { - overlay = new DifferentialArray<>(new char[getArea()]); - } - - overlay.record(() -> { - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - overlay.get()[index] = combined; - } - } - } - }); - } - - private void setMain(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - - main.record(() -> { - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - main.get()[index] = combined; - } - } - } - }); - } - - private void setFloor(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - - floor.record(() -> { - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - floor.get()[index] = combined; - } - } - } - }); - } - - private void setColumn(BufferedImage img, char combined, boolean white) { - if (img.getWidth() != getWidth() || img.getHeight() != getLength()) { - throw new IllegalArgumentException( - "Input image dimensions do not match the current height map!"); - } - primitives.modifiedMain = true; - - main.record(() -> floor.record(() -> { - int index = 0; - for (int z = 0; z < getLength(); z++) { - for (int x = 0; x < getWidth(); x++, index++) { - int height = img.getRGB(x, z) & 0xFF; - if (height == 255 || height > 0 && !white && ThreadLocalRandom.current() - .nextInt(256) <= height) { - main.get()[index] = combined; - floor.get()[index] = combined; - } - } - } - })); - } - - @Override - public int getMaxY() { - return 255; - } - - @Override - public String getName() { - File folder = getFolder(); - if (folder != null) { - String name = folder.getName(); - if (name.equalsIgnoreCase("region")) { - return folder.getParentFile().getName(); - } - return name; - } - return Integer.toString(hashCode()); - } - - @Override - public > boolean setBlock(BlockVector3 position, B block, - boolean notifyAndLight) throws WorldEditException { - return setBlock(position, block); - } - - // These aren't implemented yet... - @Override - public boolean setTile(int x, int y, int z, CompoundTag tile) throws WorldEditException { - return false; - } - - @Override - public int getBlockLightLevel(BlockVector3 position) { - return 0; - } - - @Override - public boolean clearContainerBlockContents(BlockVector3 position) { - return false; - } - - @Override - public boolean regenerate(Region region, EditSession editSession) { - return false; - } - - @Override - public boolean generateTree(TreeGenerator.TreeType type, EditSession editSession, - BlockVector3 position) throws MaxChangedBlocksException { - return false; - } - - @Override - public void dropItem(Vector3 position, BaseItemStack item) { - // TODO Auto-generated method stub - - } - - @Override - public boolean playEffect(Vector3 position, int type, int data) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean notifyAndLightBlock(BlockVector3 position, BlockState previousType) - throws WorldEditException { - // TODO Auto-generated method stub - return false; - } - - @Override - public BlockVector3 getSpawnPosition() { - // TODO Auto-generated method stub - return null; - } - - @Override - public IChunkGet get(int x, int z) { - LOGGER.debug("Should not be using buffering with HMMG"); - return new FallbackChunkGet(this, x, z); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/MCAWriter.java b/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/MCAWriter.java deleted file mode 100644 index 878df9fa7..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/brush/visualization/cfi/MCAWriter.java +++ /dev/null @@ -1,210 +0,0 @@ -package com.boydti.fawe.object.brush.visualization.cfi; - -import com.boydti.fawe.jnbt.anvil.MCAChunk; -import com.boydti.fawe.object.collection.CleanableThreadLocal; -import com.boydti.fawe.object.io.BufferedRandomAccessFile; -import com.boydti.fawe.util.MainUtil; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.world.block.BlockID; -import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.concurrent.ForkJoinPool; -import java.util.concurrent.TimeUnit; -import java.util.zip.Deflater; - -public abstract class MCAWriter implements Extent { - private File folder; - private final int length; - private final int width; - private final int area; - private int OX; - private int OZ; - - - public MCAWriter(int width, int length, File regionFolder) { - this.folder = regionFolder; - this.width = width; - this.length = length; - this.area = width * length; - } - - public final File getFolder() { - return folder; - } - - public void setFolder(File folder) { - this.folder = folder; - } - - public final int getWidth() { - return width; - } - - public final int getLength() { - return length; - } - - /** - * Set the MCA file offset (each mca file is 512 blocks) - * - A negative value will shift the map negative - * - This only applies to generation, not block get/set - * - * @param mcaOX - * @param mcaOZ - */ - public void setMCAOffset(int mcaOX, int mcaOZ) { - OX = mcaOX << 9; - OZ = mcaOZ << 9; - } - - public int getOffsetX() { - return OX; - } - - public int getOffsetZ() { - return OZ; - } - - public final int getArea() { - return area; - } - - public abstract boolean shouldWrite(int chunkX, int chunkZ); - - public abstract MCAChunk write(MCAChunk input, int startX, int endX, int startZ, int endZ); - - private static CleanableThreadLocal createCache() { - return new CleanableThreadLocal<>(() -> { - MCAChunk chunk = new MCAChunk(); - Arrays.fill(chunk.blocks, (char) BlockID.AIR); -// Arrays.fill(chunk.skyLight, (byte) 255); - return chunk; - }); - } - - public void generate() throws IOException { - if (!folder.exists()) { - folder.mkdirs(); - } - final ForkJoinPool pool = new ForkJoinPool(); - int tcx = (width - 1) >> 4; - int tcz = (length - 1) >> 4; - try (CleanableThreadLocal chunkStore = createCache()) { - final ThreadLocal byteStore1 = ThreadLocal.withInitial(() -> new byte[500000]); - final ThreadLocal byteStore2 = ThreadLocal.withInitial(() -> new byte[500000]); - final ThreadLocal deflateStore = ThreadLocal - .withInitial(() -> new Deflater(Deflater.BEST_SPEED, false)); - byte[] fileBuf = new byte[1 << 16]; - int mcaXMin = 0; - int mcaZMin = 0; - int mcaXMax = mcaXMin + ((width - 1) >> 9); - int mcaZMax = mcaZMin + ((length - 1) >> 9); - - final byte[] header = new byte[4096]; - - for (int mcaZ = mcaXMin; mcaZ <= mcaZMax; mcaZ++) { - for (int mcaX = mcaXMin; mcaX <= mcaXMax; mcaX++) { - File file = new File(folder, "r." + (mcaX + (getOffsetX() >> 9)) + "." + (mcaZ + (getOffsetZ() >> 9)) + ".mca"); - if (!file.exists()) { - file.createNewFile(); - } - final BufferedRandomAccessFile raf = new BufferedRandomAccessFile(file, "rw", fileBuf); - final byte[][] compressed = new byte[1024][]; - int bx = mcaX << 9; - int bz = mcaZ << 9; - int scx = bx >> 4; - int ecx = Math.min(scx + 31, tcx); - int scz = bz >> 4; - int ecz = Math.min(scz + 31, tcz); - for (int cz = scz; cz <= ecz; cz++) { - final int csz = cz << 4; - final int cez = Math.min(csz + 15, length - 1); - for (int cx = scx; cx <= ecx; cx++) { - final int csx = cx << 4; - final int cex = Math.min(csx + 15, width - 1); - final int fcx = cx; - final int fcz = cz; - if (shouldWrite(cx, cz)) { - pool.submit(() -> { - try { - MCAChunk chunk = chunkStore.get(); - chunk.reset(); - chunk.setPosition(fcx, fcz); - chunk = write(chunk, csx, cex, csz, cez); - if (chunk != null) { - // Generation offset - chunk.setPosition(fcx + (getOffsetX() >> 4), fcz + (getOffsetZ() >> 4)); - - // Compress - FastByteArrayOutputStream uncompressed = chunk.toBytes(byteStore1.get()); - int len = uncompressed.length; - uncompressed.reset(); - MainUtil.compress(uncompressed.array, len , byteStore2.get(), uncompressed, deflateStore.get()); - byte[] clone = Arrays.copyOf(uncompressed.array, uncompressed.length); - - // TODO optimize (avoid cloning) by add a synchronized block and write to the RAF here instead of below - compressed[((fcx & 31)) + ((fcz & 31) << 5)] = clone; - } - } catch (Throwable e) { - e.printStackTrace(); - } - }); - } - } - } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - pool.submit(() -> { - try { - int totalLength = 8192; - for (byte[] compressedBytes : compressed) { - if (compressedBytes != null) { - int blocks = ((4095 + compressedBytes.length + 5) / 4096) * 4096; - totalLength += blocks; - } - } - raf.setLength(totalLength); - int offset = 8192; - for (int i = 0; i < compressed.length; i++) { - byte[] compressedBytes = compressed[i]; - if (compressedBytes != null) { - // Set header - int index = i << 2; - int offsetMedium = offset >> 12; - int blocks = ((4095 + compressedBytes.length + 5) / 4096); - header[index] = (byte) (offsetMedium >> 16); - header[index + 1] = (byte) ((offsetMedium >> 8)); - header[index + 2] = (byte) ((offsetMedium >> 0)); - header[index + 3] = (byte) (blocks); - // Write bytes - raf.seek(offset); - raf.writeInt(compressedBytes.length + 1); - raf.write(2); - raf.write(compressedBytes); - offset += blocks * 4096; - } - } - raf.seek(0); - raf.write(header); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - raf.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - } - } - pool.awaitQuiescence(Long.MAX_VALUE, TimeUnit.MILLISECONDS); - pool.shutdown(); - CleanableThreadLocal.clean(byteStore1); - CleanableThreadLocal.clean(byteStore2); - CleanableThreadLocal.clean(deflateStore); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/change/CFIChange.java b/worldedit-core/src/main/java/com/boydti/fawe/object/change/CFIChange.java deleted file mode 100644 index ecbb55dc8..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/change/CFIChange.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.boydti.fawe.object.change; - -import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; -import com.boydti.fawe.util.ExtentTraverser; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.history.UndoContext; -import com.sk89q.worldedit.history.change.Change; -import com.sk89q.worldedit.internal.util.LogManagerCompat; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.IOException; - -import static com.google.common.base.Preconditions.checkNotNull; - -public class CFIChange implements Change { - - private static final Logger LOGGER = LogManagerCompat.getLogger(); - - private final File file; - - public CFIChange(File file) { - checkNotNull(file); - this.file = file; - } - - private HeightMapMCAGenerator getQueue(UndoContext context) { - ExtentTraverser found = new ExtentTraverser<>(context.getExtent()).find(HeightMapMCAGenerator.class); - if (found != null) { - return found.get(); - } - LOGGER.debug("FAWE does not support: " + context.getExtent() + " for " + getClass() + " (bug Empire92)"); - return null; - } - - @Override - public void undo(UndoContext context) throws WorldEditException { - HeightMapMCAGenerator queue = getQueue(context); - if (queue != null) { - try { - queue.undoChanges(file); - } catch (IOException e) { - e.printStackTrace(); - } - queue.update(); - } - } - - @Override - public void redo(UndoContext context) throws WorldEditException { - HeightMapMCAGenerator queue = getQueue(context); - if (queue != null) { - try { - queue.redoChanges(file); - } catch (IOException e) { - e.printStackTrace(); - } - queue.update(); - } - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java b/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java deleted file mode 100644 index 7fe5c9f3a..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/changeset/CFIChangeSet.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.boydti.fawe.object.changeset; - -import com.boydti.fawe.Fawe; -import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.brush.visualization.cfi.HeightMapMCAGenerator; -import com.boydti.fawe.object.change.CFIChange; -import com.boydti.fawe.util.MainUtil; -import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.history.change.Change; -import com.sk89q.worldedit.world.biome.BiomeType; - -import java.io.File; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; - -public class CFIChangeSet extends AbstractChangeSet { - - private static final Map> NEXT_INDEX = new ConcurrentHashMap<>(); - - private final File file; - - public CFIChangeSet(HeightMapMCAGenerator hmmg, UUID uuid) throws IOException { - super(hmmg); - final String hmmgId = hmmg.getId(); - final File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.IMP.PATHS.HISTORY + File.separator + uuid + File.separator + "CFI" + File.separator + hmmgId); - - final int max = NEXT_INDEX.computeIfAbsent(uuid, _uuid -> new HashMap<>()) - .compute(hmmgId, (_hmmgId, id) -> (id == null ? MainUtil.getMaxFileId(folder) : id) + 1) - 1; - - this.file = new File(folder, max + ".cfi"); - File parent = this.file.getParentFile(); - if (!parent.exists()) { - this.file.getParentFile().mkdirs(); - } - if (!this.file.exists()) { - this.file.createNewFile(); - } - hmmg.flushChanges(file); - } - - @Override - public void close() { - } - - @Override - public void closeAsync() { - } - - @Override - public void add(int x, int y, int z, int combinedFrom, int combinedTo) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public void addTileCreate(CompoundTag tag) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public void addTileRemove(CompoundTag tag) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public void addEntityRemove(CompoundTag tag) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public void addEntityCreate(CompoundTag tag) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public void addBiomeChange(int x, int y, int z, BiomeType from, BiomeType to) { - throw new UnsupportedOperationException("Only CFI operations are supported"); - } - - @Override - public Iterator getIterator(boolean redo) { - return Collections.singleton(new CFIChange(file)).iterator(); - } - - @Override - public int size() { - return 1; - } - - @Override - public boolean isRecordingChanges() { - // TODO Auto-generated method stub - return false; - } - - @Override - public void setRecordChanges(boolean recordChanges) { - // TODO Auto-generated method stub - - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/CleanableThreadLocal.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/CleanableThreadLocal.java index e7369f397..69fa34cbc 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/CleanableThreadLocal.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/CleanableThreadLocal.java @@ -16,10 +16,10 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -public class CleanableThreadLocal extends ThreadLocal implements Closeable { +public class CleanableThreadLocal extends ThreadLocal implements AutoCloseable { private final Supplier supplier; private final Function modifier; - private LongAdder count = new LongAdder(); + private final LongAdder count = new LongAdder(); // what is that supposed to do? public CleanableThreadLocal(Supplier supplier) { this(supplier, Function.identity()); @@ -51,123 +51,7 @@ public class CleanableThreadLocal extends ThreadLocal implements Closeable } public void clean() { - if (count.sumThenReset() > 0) { - CleanableThreadLocal.clean(this); - } - } - - public List getAll() { - List list = new ArrayList<>(); - iterate(this, new Consumer() { - Method methodGetEntry; - Field fieldValue; - @Override - public void accept(Object tlm) { - try { - if (methodGetEntry == null) { - methodGetEntry = tlm.getClass().getDeclaredMethod("getEntry", ThreadLocal.class); - methodGetEntry.setAccessible(true); - } - Object entry = methodGetEntry.invoke(tlm, CleanableThreadLocal.this); - if (entry != null) { - if (fieldValue == null) { - fieldValue = entry.getClass().getDeclaredField("value"); - fieldValue.setAccessible(true); - } - Object value = fieldValue.get(entry); - if (value != null) { - list.add((T) value); - } - } - } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | NoSuchFieldException e) { - throw new RuntimeException(e); - } - } - }); - return list; - } - - public static void iterate(ThreadLocal instance, Consumer withMap) { - try { - Thread[] threads = MainUtil.getThreads(); - Field tl = Thread.class.getDeclaredField("threadLocals"); - tl.setAccessible(true); - for (Thread thread : threads) { - if (thread != null) { - Object tlm = tl.get(thread); - if (tlm != null) { - withMap.accept(tlm); - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static void clean(ThreadLocal instance) { - iterate(instance, new Consumer() { - Method methodRemove; - @Override - public void accept(Object tlm) { - try { - if (methodRemove == null) { - methodRemove = tlm.getClass().getDeclaredMethod("remove", ThreadLocal.class); - methodRemove.setAccessible(true); - } - if (methodRemove != null) { - try { - methodRemove.invoke(tlm, instance); - } catch (Throwable ignored) { - } - } - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - } - }); - } - - public static void cleanAll() { - try { - // Get a reference to the thread locals table of the current thread - Thread thread = Thread.currentThread(); - Field threadLocalsField = Thread.class.getDeclaredField("threadLocals"); - threadLocalsField.setAccessible(true); - Object threadLocalTable = threadLocalsField.get(thread); - - // Get a reference to the array holding the thread local variables inside the - // ThreadLocalMap of the current thread - Class threadLocalMapClass = Class.forName("java.lang.ThreadLocal$ThreadLocalMap"); - Field tableField = threadLocalMapClass.getDeclaredField("table"); - tableField.setAccessible(true); - Object table = tableField.get(threadLocalTable); - - // The key to the ThreadLocalMap is a WeakReference object. The referent field of this object - // is a reference to the actual ThreadLocal variable - Field referentField = Reference.class.getDeclaredField("referent"); - referentField.setAccessible(true); - - for (int i = 0; i < Array.getLength(table); i++) { - // Each entry in the table array of ThreadLocalMap is an Entry object - // representing the thread local reference and its value - Object entry = Array.get(table, i); - if (entry != null) { - // Get a reference to the thread local object and remove it from the table - ThreadLocal threadLocal = (ThreadLocal)referentField.get(entry); - clean(threadLocal); - } - } - } catch (Exception e) { - // We will tolerate an exception here and just log it - throw new IllegalStateException(e); - } - } - - @Override - protected void finalize() throws Throwable { - clean(this); - super.finalize(); + remove(); } @Override diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java deleted file mode 100644 index 5e7dadae1..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/IterableThreadLocal.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.boydti.fawe.object.collection; - -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.ConcurrentLinkedDeque; -import java.util.function.Supplier; - -public class IterableThreadLocal extends ThreadLocal implements Iterable { - private final ConcurrentLinkedDeque allValues = new ConcurrentLinkedDeque<>(); - private final Supplier supplier; - - public IterableThreadLocal(Supplier supplier) { - this.supplier = supplier; - } - - @Override - protected final T initialValue() { - T value = init(); - if (value != null) { - synchronized (this) { - allValues.add(value); - } - } - return value; - } - - @Override - public final Iterator iterator() { - return getAll().iterator(); - } - - public T init() { - return supplier.get(); - } - - public void clean() { - if (!allValues.isEmpty()) { - synchronized (this) { - CleanableThreadLocal.clean(this); - allValues.clear(); - } - } - } - public final Collection getAll() { - return Collections.unmodifiableCollection(allValues); - } - - @Override - protected void finalize() throws Throwable { - CleanableThreadLocal.clean(this); - super.finalize(); - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/VariableThreadLocal.java b/worldedit-core/src/main/java/com/boydti/fawe/object/collection/VariableThreadLocal.java deleted file mode 100644 index 8c5da3c55..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/collection/VariableThreadLocal.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.boydti.fawe.object.collection; - -public class VariableThreadLocal extends CleanableThreadLocal { - public VariableThreadLocal() { - super(() -> null); - } - - public byte[] get(int size) { - byte[] existing = get(); - if (existing == null || existing.length < size) { - int padded = ((size + 4095) / 4096) * 4096; - existing = new byte[padded]; - set(existing); - } - return existing; - } -} diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java index e3f867907..0d94ad8c7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/EditSessionBuilder.java @@ -18,7 +18,6 @@ import com.boydti.fawe.object.HistoryExtent; import com.boydti.fawe.object.NullChangeSet; import com.boydti.fawe.object.RegionWrapper; import com.boydti.fawe.object.RelightMode; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.changeset.AbstractChangeSet; import com.boydti.fawe.object.changeset.BlockBagChangeSet; import com.boydti.fawe.object.changeset.DiskStorageHistory; @@ -379,7 +378,7 @@ public class EditSessionBuilder { } } if (allowedRegions == null) { - if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions") && !(root instanceof VirtualWorld)) { + if (player != null && !player.hasPermission("fawe.bypass") && !player.hasPermission("fawe.bypass.regions")) { allowedRegions = player.getCurrentRegions(); } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java b/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java index a7c8a3dc7..1db81251f 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils.java @@ -4,16 +4,12 @@ import org.jetbrains.annotations.NotNull; import java.lang.invoke.MethodHandles; import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.Comparator; -import java.util.List; public class ReflectionUtils { @@ -21,10 +17,6 @@ public class ReflectionUtils { return t.isInstance(o) ? t.cast(o) : null; } - public static > T addEnum(Class enumType, String enumName) { - return ReflectionUtils9.addEnum(enumType, enumName); - } - public static void setAccessibleNonFinal(Field field) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { // let's make the field accessible field.setAccessible(true); @@ -52,21 +44,6 @@ public class ReflectionUtils { field.set(target, value); } - private static void blankField(Class enumClass, String fieldName) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - for (Field field : Class.class.getDeclaredFields()) { - if (field.getName().contains(fieldName)) { - AccessibleObject.setAccessible(new Field[] { field }, true); - setFailsafeFieldValue(field, enumClass, null); - break; - } - } - } - - static void cleanEnumCache(Class enumClass) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException { - blankField(enumClass, "enumConstantDirectory"); // Sun (Oracle?!?) JDK 1.5/6 - blankField(enumClass, "enumConstants"); // IBM JDK - } - public static Object getHandle(Object wrapper) { final Method getHandle = makeMethod(wrapper.getClass(), "getHandle"); return callMethod(getHandle, wrapper); @@ -98,108 +75,6 @@ public class ReflectionUtils { } } - @SuppressWarnings("unchecked") - public static Constructor makeConstructor(Class clazz, Class... parameterTypes) { - try { - return (Constructor) clazz.getConstructor(parameterTypes); - } catch (NoSuchMethodException ex) { - return null; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - public static T callConstructor(Constructor constructor, Object... parameters) { - if (constructor == null) { - throw new RuntimeException("No such constructor"); - } - constructor.setAccessible(true); - try { - return constructor.newInstance(parameters); - } catch (InvocationTargetException ex) { - throw new RuntimeException(ex.getCause()); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - public static Field makeField(Class clazz, String name) { - try { - return clazz.getDeclaredField(name); - } catch (NoSuchFieldException ex) { - return null; - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - public static Field findField(Class clazz, Class type, int hasMods, int noMods) { - for (Field field : clazz.getDeclaredFields()) { - if (type == null || type.isAssignableFrom(field.getType())) { - int mods = field.getModifiers(); - if ((mods & hasMods) == hasMods && (mods & noMods) == 0) { - return setAccessible(field); - } - } - } - return null; - } - - public static Field findField(Class clazz, Class type) { - for (Field field : clazz.getDeclaredFields()) { - if (field.getType() == type) { - return setAccessible(field); - } - } - return null; - } - - public static Method findMethod(Class clazz, Class returnType, Class... params) { - return findMethod(clazz, 0, returnType, params); - } - - public static Method findMethod(Class clazz, int index, int hasMods, int noMods, Class returnType, Class... params) { - outer: - for (Method method : sortMethods(clazz.getDeclaredMethods())) { - if (returnType == null || method.getReturnType() == returnType) { - Class[] mp = method.getParameterTypes(); - int mods = method.getModifiers(); - if ((mods & hasMods) != hasMods || (mods & noMods) != 0) { - continue; - } - if (params == null) { - if (index-- == 0) { - return setAccessible(method); - } else { - continue; - } - } - if (mp.length == params.length) { - for (int i = 0; i < mp.length; i++) { - if (mp[i] != params[i]) { - continue outer; - } - } - if (index-- == 0) { - return setAccessible(method); - } else { - continue; - } - } - } - } - return null; - } - - public static Method findMethod(Class clazz, int index, Class returnType, Class... params) { - return findMethod(clazz, index, 0, 0, returnType, params); - } - - public static Method[] sortMethods(Method[] methods) { - Arrays.sort(methods, Comparator.comparing(Method::getName)); - return methods; - } - public static Field[] sortFields(Field[] fields) { Arrays.sort(fields, Comparator.comparing(Field::getName)); return fields; @@ -220,15 +95,6 @@ public class ReflectionUtils { } } - public static void setField(@NotNull Field field, Object instance, Object value) { - field.setAccessible(true); - try { - field.set(instance, value); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - public static Class getClass(String name) { try { return Class.forName(name); @@ -244,450 +110,4 @@ public class ReflectionUtils { return null; } } - - - /** - * Get a {@link RefClass} object by its original {@link Class}. - * - * @param clazz class - * @return RefClass based on passed class - */ - public static RefClass getRefClass(Class clazz) { - return new RefClass(clazz); - } - - /** - * A utility to simplify work with reflections. - */ - public static class RefClass { - - private final Class clazz; - - private RefClass(Class clazz) { - this.clazz = clazz; - } - - public Class getClazz() { - return this.clazz; - } - - /** - * See {@link Class#isInstance(Object)}. - * - * @param object the object to check - * @return true if object is an instance of this class - */ - public boolean isInstance(Object object) { - return this.clazz.isInstance(object); - } - - /** - * Get an existing method by name and types. The {@code types} parameter accepts both {@link Class} - * and {@link RefClass} objects. - * - * @param name name - * @param types method parameters - * @return RefMethod object - * @throws RuntimeException if method not found - */ - public RefMethod getMethod(String name, Object... types) { - try { - final Class[] classes = new Class[types.length]; - int i = 0; - for (Object e : types) { - if (e instanceof Class) { - classes[i++] = (Class) e; - } else if (e instanceof RefClass) { - classes[i++] = ((RefClass) e).getClazz(); - } else { - classes[i++] = e.getClass(); - } - } - try { - return new RefMethod(this.clazz.getMethod(name, classes)); - } catch (NoSuchMethodException ignored) { - return new RefMethod(this.clazz.getDeclaredMethod(name, classes)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Get an existing constructor by types.The {@code types} parameter accepts both {@link Class} - * and {@link RefClass} objects. - * - * @param types parameters - * @return RefMethod object - * @throws RuntimeException if constructor not found - */ - public RefConstructor getConstructor(Object... types) { - try { - final Class[] classes = new Class[types.length]; - int i = 0; - for (Object e : types) { - if (e instanceof Class) { - classes[i++] = (Class) e; - } else if (e instanceof RefClass) { - classes[i++] = ((RefClass) e).getClazz(); - } else { - classes[i++] = e.getClass(); - } - } - try { - return new RefConstructor(this.clazz.getConstructor(classes)); - } catch (NoSuchMethodException ignored) { - return new RefConstructor(this.clazz.getDeclaredConstructor(classes)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Find a method by type parameters. The {@code types} parameter accepts both {@link Class} - * and {@link RefClass} objects. - * - * @param types parameters - * @return RefMethod object - * @throws RuntimeException if method not found - */ - public RefMethod findMethod(Object... types) { - final Class[] classes = new Class[types.length]; - int t = 0; - for (Object e : types) { - if (e instanceof Class) { - classes[t++] = (Class) e; - } else if (e instanceof RefClass) { - classes[t++] = ((RefClass) e).getClazz(); - } else { - classes[t++] = e.getClass(); - } - } - final List methods = new ArrayList<>(); - Collections.addAll(methods, this.clazz.getMethods()); - Collections.addAll(methods, this.clazz.getDeclaredMethods()); - findMethod: - for (Method m : methods) { - final Class[] methodTypes = m.getParameterTypes(); - if (methodTypes.length != classes.length) { - continue; - } - for (Class aClass : classes) { - if (!Arrays.equals(classes, methodTypes)) { - continue findMethod; - } - return new RefMethod(m); - } - } - throw new RuntimeException("no such method"); - } - - /** - * Find a method by name. - * - * @param names possible names of method - * @return RefMethod object - * @throws RuntimeException if method not found - */ - public RefMethod findMethodByName(String... names) { - final List methods = new ArrayList<>(); - Collections.addAll(methods, this.clazz.getMethods()); - Collections.addAll(methods, this.clazz.getDeclaredMethods()); - for (Method m : methods) { - for (String name : names) { - if (m.getName().equals(name)) { - return new RefMethod(m); - } - } - } - throw new RuntimeException("no such method"); - } - - /** - * Find a method by return value. - * - * @param type type of returned value - * @return RefMethod - * @throws RuntimeException if method not found - */ - public RefMethod findMethodByReturnType(RefClass type) { - return this.findMethodByReturnType(type.clazz); - } - - /** - * Find a method by return value. - * - * @param type type of returned value - * @return RefMethod - * @throws RuntimeException if method not found - */ - public RefMethod findMethodByReturnType(Class type) { - if (type == null) { - type = void.class.getComponentType(); - } - final List methods = new ArrayList<>(); - Collections.addAll(methods, this.clazz.getMethods()); - Collections.addAll(methods, this.clazz.getDeclaredMethods()); - for (Method m : methods) { - if (type.equals(m.getReturnType())) { - return new RefMethod(m); - } - } - throw new RuntimeException("no such method"); - } - - /** - * Find the constructor by the number of arguments. - * - * @param number number of arguments - * @return RefConstructor - * @throws RuntimeException if constructor not found - */ - public RefConstructor findConstructor(int number) { - final List> constructors = new ArrayList<>(); - Collections.addAll(constructors, this.clazz.getConstructors()); - Collections.addAll(constructors, this.clazz.getDeclaredConstructors()); - for (Constructor m : constructors) { - if (m.getParameterTypes().length == number) { - return new RefConstructor(m); - } - } - throw new RuntimeException("no such constructor"); - } - - /** - * Get the field by name. - * - * @param name field name - * @return RefField - * @throws RuntimeException if field not found - */ - public RefField getField(String name) { - try { - try { - return new RefField(this.clazz.getField(name)); - } catch (NoSuchFieldException ignored) { - return new RefField(this.clazz.getDeclaredField(name)); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Find the field by type. - * - * @param type field type - * @return RefField - * @throws NoSuchFieldException if field not found - */ - public RefField findField(RefClass type) throws NoSuchFieldException { - return this.findField(type.clazz); - } - - /** - * Find the field by type. - * - * @param type field type - * @return RefField - * @throws RuntimeException if field not found - */ - public RefField findField(Class type) throws NoSuchFieldException { - if (type == null) { - type = void.class; - } - final List fields = new ArrayList<>(); - Collections.addAll(fields, this.clazz.getFields()); - Collections.addAll(fields, this.clazz.getDeclaredFields()); - for (Field f : fields) { - if (type.equals(f.getType())) { - return new RefField(f); - } - } - throw new NoSuchFieldException(); - } - } - - - /** - * Method reflection wrapper. - */ - public static class RefMethod { - - private final Method method; - - private RefMethod(Method method) { - this.method = method; - method.setAccessible(true); - } - - public Method getMethod() { - return this.method; - } - - public RefClass getRefClass() { - return new RefClass(this.method.getDeclaringClass()); - } - - public RefClass getReturnRefClass() { - return new RefClass(this.method.getReturnType()); - } - - /** - * Apply method to object. - * - * @param e object to which the method is applied - * @return RefExecutor with method call(...) - */ - public RefExecutor of(Object e) { - return new RefExecutor(e); - } - - /** - * Call static method. - * - * @param params sent parameters - * @return return value - */ - public Object call(Object... params) { - try { - return this.method.invoke(null, params); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - public class RefExecutor { - - final Object executor; - - public RefExecutor(Object executor) { - this.executor = executor; - } - - /** - * Invokes the method on the selected object. - * - * @param params sent parameters - * @return return value - * @throws RuntimeException if something went wrong - */ - public Object call(Object... params) { - try { - return RefMethod.this.method.invoke(this.executor, params); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } - - - /** - * Constructor wrapper. - */ - public static class RefConstructor { - - private final Constructor constructor; - - private RefConstructor(Constructor constructor) { - this.constructor = constructor; - constructor.setAccessible(true); - } - - public Constructor getConstructor() { - return this.constructor; - } - - public RefClass getRefClass() { - return new RefClass(this.constructor.getDeclaringClass()); - } - - /** - * Create and initialize a new instance of constructor's declaring class. - * - * @param params parameters for constructor - * @return new object - * @throws RuntimeException if something went wrong - */ - public Object create(Object... params) { - try { - return this.constructor.newInstance(params); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - - public static class RefField { - - private final Field field; - - private RefField(Field field) { - this.field = field; - field.setAccessible(true); - } - - public Field getField() { - return this.field; - } - - public RefClass getRefClass() { - return new RefClass(this.field.getDeclaringClass()); - } - - /** - * Returns a wrapper to the class of the field's returning type. - */ - public RefClass getFieldRefClass() { - return new RefClass(this.field.getType()); - } - - /** - * Apply the field on object. - * - * @param e applied object - * @return RefExecutor with getter and setter - */ - public RefExecutor of(Object e) { - return new RefExecutor(e); - } - - public class RefExecutor { - - final Object executor; - - public RefExecutor(Object e) { - this.executor = e; - } - - /** - * Set field value for applied object. - * - * @param param value - */ - public void set(Object param) { - try { - RefField.this.field.set(this.executor, param); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - /** - * Get field value for the applied object. - * - * @return value of field - */ - public Object get() { - try { - return RefField.this.field.get(this.executor); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils9.java b/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils9.java deleted file mode 100644 index aba4d40a5..000000000 --- a/worldedit-core/src/main/java/com/boydti/fawe/util/ReflectionUtils9.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.boydti.fawe.util; - -import sun.misc.Unsafe; - -import java.lang.reflect.AccessibleObject; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -public class ReflectionUtils9 { - public static > T addEnum(Class enumType, String enumName) { - - // 0. Sanity checks - if (!Enum.class.isAssignableFrom(enumType)) { - throw new RuntimeException("class " + enumType + " is not an instance of Enum"); - } - // 1. Lookup "$VALUES" holder in enum class and get previous enum instances - Field valuesField = null; - Field[] fields = enumType.getDeclaredFields(); - for (Field field : fields) { - if (field.getName().contains("$VALUES")) { - valuesField = field; - break; - } - } - AccessibleObject.setAccessible(new Field[]{valuesField}, true); - - try { - - // 2. Copy it - T[] previousValues = (T[]) valuesField.get(enumType); - List values = new ArrayList<>(Arrays.asList(previousValues)); - - // 3. build new enum - T newValue = (T) makeEnum(enumType, // The target enum class - enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED - values.size()); // can be used to pass values to the enum constructor - - // 4. add new value - values.add(newValue); - - // 5. Set new values field - try { - ReflectionUtils.setFailsafeFieldValue(valuesField, null, - values.toArray((T[]) Array.newInstance(enumType, 0))); - } catch (Throwable e) { - Field ordinalField = Enum.class.getDeclaredField("ordinal"); - ReflectionUtils.setFailsafeFieldValue(ordinalField, newValue, 0); - } - - // 6. Clean enum cache - ReflectionUtils.cleanEnumCache(enumType); - return newValue; - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e.getMessage(), e); - } - } - - public static Object makeEnum(Class enumClass, String value, int ordinal) throws Exception { - Constructor constructor = Unsafe.class.getDeclaredConstructors()[0]; - constructor.setAccessible(true); - Unsafe unsafe = (Unsafe) constructor.newInstance(); - Object instance = unsafe.allocateInstance(enumClass); - - Field ordinalField = Enum.class.getDeclaredField("ordinal"); - ReflectionUtils.setFailsafeFieldValue(ordinalField, instance, 0); - - Field nameField = Enum.class.getDeclaredField("name"); - ReflectionUtils.setFailsafeFieldValue(nameField, instance, value); - - return instance; - } -} diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index f15eda1a8..127ae1fb0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -24,7 +24,6 @@ import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweInputStream; import com.boydti.fawe.object.FaweLimit; import com.boydti.fawe.object.FaweOutputStream; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.changeset.DiskStorageHistory; import com.boydti.fawe.object.clipboard.MultiClipboardHolder; import com.boydti.fawe.object.collection.SparseBitSet; @@ -80,6 +79,8 @@ import com.sk89q.worldedit.world.item.ItemTypes; import com.sk89q.worldedit.world.snapshot.experimental.Snapshot; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -92,15 +93,12 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; -import java.util.Random; import java.util.TimeZone; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.stream.Collectors; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import static com.google.common.base.Preconditions.checkNotNull; @@ -159,7 +157,6 @@ public class LocalSession implements TextureHolder { private transient UUID uuid; private transient volatile long historySize = 0; - private transient VirtualWorld virtual; private transient BlockVector3 cuiTemporaryBlock; @SuppressWarnings("unused") private transient EditSession.ReorderMode reorderMode = EditSession.ReorderMode.MULTI_STAGE; @@ -752,35 +749,6 @@ public class LocalSession implements TextureHolder { return selector.getRegion(); } - @Nullable - public VirtualWorld getVirtualWorld() { - synchronized (dirty) { - return virtual; - } - } - - public void setVirtualWorld(@Nullable VirtualWorld world) { - VirtualWorld tmp; - synchronized (dirty) { - tmp = this.virtual; - if (tmp == world) { - return; - } - this.virtual = world; - } - if (tmp != null) { - try { - tmp.close(world == null); - } catch (IOException e) { - e.printStackTrace(); - } - } - if (world != null) { - Fawe.imp().registerPacketListener(); - world.update(); - } - } - /** * Get the selection world. * @@ -1234,10 +1202,6 @@ public class LocalSession implements TextureHolder { } } } - if (player != null && previous instanceof BrushTool) { - BrushTool brushTool = (BrushTool) previous; - brushTool.clear(player); - } } /** @@ -1723,14 +1687,4 @@ public class LocalSession implements TextureHolder { this.transform = transform; } - public void unregisterTools(Player player) { - synchronized (tools) { - for (Tool tool : tools.values()) { - if (tool instanceof BrushTool) { - ((BrushTool) tool).clear(player); - } - } - } - } - } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java index 533e98a80..ca67e6437 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java @@ -23,7 +23,6 @@ import com.boydti.fawe.config.Caption; import com.boydti.fawe.object.brush.BrushSettings; import com.boydti.fawe.object.brush.TargetMode; import com.boydti.fawe.object.brush.scroll.Scroll; -import com.boydti.fawe.object.brush.visualization.VisualMode; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.StringMan; import com.google.common.collect.Iterables; @@ -231,31 +230,6 @@ public class ToolUtilCommands { } } - @Command( - name = "visualize", - aliases = {"visual", "vis", "/visualize", "/visual", "/vis"}, - desc = "Toggle between different visualization modes", - descFooter = "Toggle between different visualization modes\n" - + "0 = No visualization\n" - + "1 = Single block at target position\n" - + "2 = Glass showing what blocks will be changed" - ) - @CommandPermissions("worldedit.brush.visualize") - public void visual(Player player, LocalSession session, - @Arg(name = "mode", desc = "int", def = "0") - @Range(from = 0, to = 2) - int mode) throws WorldEditException { - BrushTool tool = session.getBrushTool(player, false); - if (tool == null) { - player.print(Caption.of("fawe.worldedit.brush.brush.none")); - return; - } - VisualMode[] modes = VisualMode.values(); - VisualMode newMode = modes[MathMan.wrap(mode, 0, modes.length - 1)]; - tool.setVisualMode(player, newMode); - player.print(Caption.of("fawe.worldedit.brush.brush.visual.mode.set", newMode)); - } - @Command( name = "target", aliases = {"tar", "/target", "/tar"}, diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java index 68776357b..ef9432b2a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java @@ -19,10 +19,8 @@ package com.sk89q.worldedit.command.tool; -import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.implementation.IChunkExtent; import com.boydti.fawe.beta.implementation.processors.NullProcessor; -import com.boydti.fawe.beta.implementation.processors.PersistentChunkSendProcessor; import com.boydti.fawe.config.Caption; import com.boydti.fawe.object.brush.BrushSettings; import com.boydti.fawe.object.brush.MovableTool; @@ -30,8 +28,6 @@ import com.boydti.fawe.object.brush.ResettableTool; import com.boydti.fawe.object.brush.TargetMode; import com.boydti.fawe.object.brush.scroll.Scroll; import com.boydti.fawe.object.brush.scroll.ScrollTool; -import com.boydti.fawe.object.brush.visualization.VisualExtent; -import com.boydti.fawe.object.brush.visualization.VisualMode; import com.boydti.fawe.object.extent.ResettableExtent; import com.boydti.fawe.object.mask.MaskedTargetBlock; import com.boydti.fawe.object.pattern.PatternTraverser; @@ -93,7 +89,6 @@ public class BrushTool protected static int MAX_RANGE = 500; protected static int DEFAULT_RANGE = 240; // 500 is laggy as the default protected int range = -1; - private VisualMode visualMode = VisualMode.NONE; private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE; private Mask traceMask = null; private int targetOffset; @@ -102,8 +97,6 @@ public class BrushTool private transient BrushSettings secondary = new BrushSettings(); private transient BrushSettings context = primary; - private transient PersistentChunkSendProcessor visualExtent; - private transient BaseItem holder; /** @@ -517,26 +510,6 @@ public class BrushTool update(); } - public void setVisualMode(Player player, VisualMode visualMode) { - if (visualMode == null) { - visualMode = VisualMode.NONE; - } - if (this.visualMode != visualMode) { - if (this.visualMode != VisualMode.NONE) { - clear(player); - } - this.visualMode = visualMode; - if (visualMode != VisualMode.NONE) { - try { - queueVisualization(player); - } catch (Throwable e) { - WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); - } - } - } - update(); - } - public TargetMode getTargetMode() { return targetMode; } @@ -545,114 +518,19 @@ public class BrushTool return targetOffset; } - public VisualMode getVisualMode() { - return visualMode; - } - @Override public boolean increment(Player player, int amount) { BrushSettings current = getContext(); Scroll tmp = current.getScrollAction(); if (tmp != null) { tmp.setTool(this); - if (tmp.increment(player, amount)) { - if (visualMode != VisualMode.NONE) { - try { - queueVisualization(player); - } catch (Throwable e) { - WorldEdit.getInstance().getPlatformManager().handleThrowable(e, player); - } - } - return true; - } - } - if (visualMode != VisualMode.NONE) { - clear(player); + return tmp.increment(player, amount); } return false; } - public void queueVisualization(Player player) { - Fawe.get().getVisualQueue().queue(player); - } - - @Deprecated - public synchronized void visualize(BrushTool.BrushAction action, Player player) - throws WorldEditException { - VisualMode mode = getVisualMode(); - if (mode == VisualMode.NONE) { - return; - } - BrushSettings current = getContext(); - Brush brush = current.getBrush(); - if (brush == null) { - return; - } - - EditSessionBuilder builder = - new EditSessionBuilder(player.getWorld()).command(current.toString()).player(player) - .allowedRegionsEverywhere().autoQueue(false).blockBag(null).changeSetNull() - .fastmode(true).combineStages(true); - EditSession editSession = builder.build(); - - World world = editSession.getWorld(); - Supplier> players = () -> Collections.singleton(player); - - PersistentChunkSendProcessor newVisualExtent = - new PersistentChunkSendProcessor(world, this.visualExtent, players); - ExtentTraverser traverser = - new ExtentTraverser<>(editSession).find(IChunkExtent.class); - if (traverser == null) { - throw new IllegalStateException("No queue found"); - } - - IChunkExtent chunkExtent = traverser.get(); - if (this.visualExtent != null) { - this.visualExtent.init(chunkExtent); - } - newVisualExtent.init(chunkExtent); - - editSession.addProcessor(newVisualExtent); - editSession.addProcessor(NullProcessor.getInstance()); - - BlockVector3 position = getPosition(editSession, player); - if (position != null) { - switch (mode) { - case POINT: - editSession.setBlock(position, VisualExtent.VISUALIZE_BLOCK_DEFAULT); - break; - case OUTLINE: { - new PatternTraverser(current).reset(editSession); - brush.build(editSession, position, current.getMaterial(), current.getSize()); - break; - } - default: - throw new IllegalStateException("Unexpected value: " + mode); - } - } - editSession.flushQueue(); - - if (visualExtent != null) { - // clear old data - visualExtent.flush(); - } - visualExtent = newVisualExtent; - newVisualExtent.flush(); - } - - public void clear(Player player) { - Fawe.get().getVisualQueue().dequeue(player); - if (visualExtent != null) { - visualExtent.clear(); - } - } - @Override public boolean move(Player player) { - if (visualMode != VisualMode.NONE) { - queueVisualization(player); - return true; - } return false; } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java index e9eb62c99..dd37fdc47 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/entity/Player.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.entity; import com.boydti.fawe.Fawe; import com.boydti.fawe.config.Caption; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard; import com.boydti.fawe.regions.FaweMaskManager; import com.boydti.fawe.util.MainUtil; @@ -385,14 +384,6 @@ public interface Player extends Entity, Actor { * @return Editing world */ default World getWorldForEditing() { - VirtualWorld virtual = getSession().getVirtualWorld(); - if (virtual != null) { - return virtual; - } -// CFICommands.CFISettings cfi = getMeta("CFISettings"); -// if (cfi != null && cfi.hasGenerator() && cfi.getGenerator().hasPacketViewer()) { -// return cfi.getGenerator(); -// } return WorldEdit.getInstance().getPlatformManager().getWorldForEditing(getWorld()); } @@ -404,7 +395,6 @@ public interface Player extends Entity, Actor { getSession().setClipboard(null); if (Settings.IMP.HISTORY.DELETE_ON_LOGOUT) { getSession().clearHistory(); - getSession().unregisterTools(this); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index 4ead8d92d..b131c87bd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -22,7 +22,6 @@ package com.sk89q.worldedit.extension.platform; import com.boydti.fawe.Fawe; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.FaweLimit; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.util.task.InterruptableCondition; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.entity.MapMetadatable; @@ -242,22 +241,6 @@ public interface Actor extends Identifiable, SessionOwner, Subject, MapMetadatab } } } - VirtualWorld world = getSession().getVirtualWorld(); - if (world != null) { - if (close) { - try { - world.close(false); - } catch (IOException e) { - e.printStackTrace(); - } - } else { - try { - world.close(false); - } catch (IOException e) { - e.printStackTrace(); - } - } - } return cancelled; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index e9feb5d7f..5cf46afb7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -21,7 +21,6 @@ package com.sk89q.worldedit.extension.platform; import com.boydti.fawe.config.Caption; import com.boydti.fawe.config.Settings; -import com.boydti.fawe.object.brush.visualization.VirtualWorld; import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.object.pattern.PatternTraverser; import com.boydti.fawe.wrappers.LocationMaskedPlayerWrapper; @@ -347,18 +346,6 @@ public class PlatformManager { try { Vector3 vector = location.toVector(); - VirtualWorld virtual = session.getVirtualWorld(); - if (virtual != null) { - if (Settings.IMP.EXPERIMENTAL.OTHER) { - LOGGER.info("virtualWorld was not null in handlePlayerInput()"); - } - - virtual.handleBlockInteract(player, vector.toBlockPoint(), event); - if (event.isCancelled()) { - return; - } - } - if (event.getType() == Interaction.HIT) { // superpickaxe is special because its primary interaction is a left click, not a right click // in addition, it is implicitly bound to all pickaxe items, not just a single tool item @@ -421,16 +408,6 @@ public class PlatformManager { // making changes to the world Player player = createProxyActor(event.getPlayer()); LocalSession session = worldEdit.getSessionManager().get(player); - VirtualWorld virtual = session.getVirtualWorld(); - if (virtual != null) { - if (Settings.IMP.EXPERIMENTAL.OTHER) { - LOGGER.info("virtualWorld was not null in handlePlayerInput()"); - } - virtual.handlePlayerInput(player, event); - if (event.isCancelled()) { - return; - } - } try { switch (event.getInputType()) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java index ae60100c0..c5946ddb7 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/Extent.java @@ -507,6 +507,10 @@ public interface Extent extends InputExtent, OutputExtent { return true; } + default int getMinY() { + return 0; + } + default int getMaxY() { return 255; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/Request.java b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/Request.java index a94e0ced8..7dbc9b08b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/Request.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/session/request/Request.java @@ -19,22 +19,25 @@ package com.sk89q.worldedit.session.request; -import com.boydti.fawe.object.collection.CleanableThreadLocal; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.World; -import java.util.List; import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Describes the current request using a {@link ThreadLocal}. */ public final class Request { - private static final CleanableThreadLocal threadLocal = new CleanableThreadLocal<>(Request::new); + private static final ThreadLocal threadLocal = ThreadLocal.withInitial(Request::new); + // TODO any better way to deal with this? + private static final Map requests = new ConcurrentHashMap<>(); @Nullable private World world; @@ -49,10 +52,11 @@ public final class Request { private boolean valid; private Request() { + requests.put(Thread.currentThread(), this); } - public static List getAll() { - return threadLocal.getAll(); + public static Collection getAll() { + return requests.values(); } /** @@ -154,6 +158,7 @@ public final class Request { public static void reset() { request().invalidate(); threadLocal.remove(); + requests.remove(Thread.currentThread()); } /**