From f69b1bfb2102d2aaf5f8bf6a44c168dcd08edde4 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 17:09:18 +0000 Subject: [PATCH 01/24] properly load nms chunk for lighting operations --- .../adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 14 +++++++------- .../adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java | 14 +++++++------- .../adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java | 14 +++++++------- .../adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java | 14 +++++++------- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index 55080de5f..6a23beeee 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -150,7 +150,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl public void setHeightmapToGet(HeightMapType type, int[] data) { BitArray bitArray = new BitArray(9, 256); bitArray.fromRaw(data); - nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); + getChunk().heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); } public int getChunkZ() { @@ -176,7 +176,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl @Override public void removeSectionLighting(int layer, boolean sky) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); if (nibble != null) { lightUpdate = true; @@ -188,7 +188,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl } } if (sky) { - SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPositionSky = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky); if (nibble != null) { lightUpdate = true; @@ -225,7 +225,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl public int getSkyLight(int x, int y, int z) { int layer = y >> 4; if (skyLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -245,7 +245,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl public int getEmmittedLight(int x, int y, int z) { int layer = y >> 4; if (blockLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -352,7 +352,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl private void updateGet(BukkitGetBlocks_1_15_2 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { synchronized (get) { - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = sections.clone(); this.reset(); @@ -451,7 +451,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl synchronized (this) { synchronized (lock) { lock.untilFree(); - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = null; this.reset(); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index acef040e3..5baadd20a 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -151,7 +151,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl public void setHeightmapToGet(HeightMapType type, int[] data) { BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256); bitArray.fromRaw(data); - nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); + getChunk().heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); } public int getChunkZ() { @@ -177,7 +177,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl @Override public void removeSectionLighting(int layer, boolean sky) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); if (nibble != null) { lightUpdate = true; @@ -189,7 +189,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl } } if (sky) { - SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPositionSky = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky); if (nibble != null) { lightUpdate = true; @@ -226,7 +226,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl @Override public int getSkyLight(int x, int y, int z) { int layer = y >> 4; if (skyLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -245,7 +245,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl @Override public int getEmmittedLight(int x, int y, int z) { int layer = y >> 4; if (blockLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -352,7 +352,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl private void updateGet(BukkitGetBlocks_1_16_1 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { synchronized (get) { - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = sections.clone(); this.reset(); @@ -451,7 +451,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl synchronized (this) { synchronized (lock) { lock.untilFree(); - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = null; this.reset(); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java index 94d8e2b15..8e62d54db 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java @@ -151,7 +151,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl public void setHeightmapToGet(HeightMapType type, int[] data) { BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256); bitArray.fromRaw(data); - nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); + getChunk().heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); } public int getChunkZ() { @@ -177,7 +177,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl @Override public void removeSectionLighting(int layer, boolean sky) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); if (nibble != null) { lightUpdate = true; @@ -189,7 +189,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl } } if (sky) { - SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPositionSky = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky); if (nibble != null) { lightUpdate = true; @@ -227,7 +227,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl public int getSkyLight(int x, int y, int z) { int layer = y >> 4; if (skyLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -247,7 +247,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl public int getEmmittedLight(int x, int y, int z) { int layer = y >> 4; if (blockLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -355,7 +355,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl private void updateGet(BukkitGetBlocks_1_16_2 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { synchronized (get) { - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = sections.clone(); this.reset(); @@ -454,7 +454,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl synchronized (this) { synchronized (lock) { lock.untilFree(); - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = null; this.reset(); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java index 37a26a089..c78063452 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java @@ -151,7 +151,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl public void setHeightmapToGet(HeightMapType type, int[] data) { BitArrayUnstretched bitArray = new BitArrayUnstretched(9, 256); bitArray.fromRaw(data); - nmsChunk.heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); + getChunk().heightMap.get(HeightMap.Type.valueOf(type.name())).a(bitArray.getData()); } public int getChunkZ() { @@ -177,7 +177,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl @Override public void removeSectionLighting(int layer, boolean sky) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibble = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); if (nibble != null) { lightUpdate = true; @@ -189,7 +189,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } } if (sky) { - SectionPosition sectionPositionSky = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPositionSky = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleSky = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPositionSky); if (nibble != null) { lightUpdate = true; @@ -227,7 +227,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl public int getSkyLight(int x, int y, int z) { int layer = y >> 4; if (skyLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.SKY).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -247,7 +247,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl public int getEmmittedLight(int x, int y, int z) { int layer = y >> 4; if (blockLight[layer] == null) { - SectionPosition sectionPosition = SectionPosition.a(nmsChunk.getPos(), layer); + SectionPosition sectionPosition = SectionPosition.a(getChunk().getPos(), layer); NibbleArray nibbleArray = world.getChunkProvider().getLightEngine().a(EnumSkyBlock.BLOCK).a(sectionPosition); // If the server hasn't generated the section's NibbleArray yet, it will be null if (nibbleArray == null) { @@ -355,7 +355,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl private void updateGet(BukkitGetBlocks_1_16_4 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { synchronized (get) { - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = sections.clone(); this.reset(); @@ -454,7 +454,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl synchronized (this) { synchronized (lock) { lock.untilFree(); - if (this.nmsChunk != nmsChunk) { + if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; this.sections = null; this.reset(); From b1e8c6c3ba6128d228fcafb4bdb6b230c2d3d215 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 17:09:44 +0000 Subject: [PATCH 02/24] Synchronizing on accessing a lock is pointless. --- .../fawe/beta/implementation/lighting/NMSRelighter.java | 2 +- .../src/main/java/com/sk89q/worldedit/EditSession.java | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java index cccda08c3..a7cdcd6b7 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java @@ -95,7 +95,7 @@ public class NMSRelighter implements Relighter { } @Override - public synchronized ReentrantLock getLock() { + public ReentrantLock getLock() { return lightingLock; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 36870aeef..5ace70cbf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -1099,7 +1099,7 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { try { if (relighter != null && !(relighter instanceof NullRelighter)) { // Only relight once! - if (!relighter.getLock().tryLock()) { + if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING && !relighter.getLock().tryLock()) { relighter.getLock().lock(); relighter.getLock().unlock(); } else { @@ -1109,6 +1109,9 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { relighter.fixSkyLighting(); relighter.fixBlockLighting(); } + if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { + relighter.getLock().unlock(); + } } } } catch (Throwable e) { From b066ca83491f079f51506063c2babc703fa9050e Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 17:10:08 +0000 Subject: [PATCH 03/24] only relight blocks that have light --- .../boydti/fawe/beta/implementation/lighting/NMSRelighter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java index a7cdcd6b7..37c38005a 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java @@ -1000,7 +1000,7 @@ public class NMSRelighter implements Relighter { BlockMaterial material = state.getMaterial(); int opacity = material.getLightOpacity(); int brightness = material.getLightValue(); - if (brightness != iChunk.getEmmittedLight(x, y, z)) { + if (brightness > 0 && brightness != iChunk.getEmmittedLight(x, y, z)) { addLightUpdate(bx + x, y, bz + z); } From 97209d5680f6a7585f123919c957b83ea9db17ee Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 17:24:14 +0000 Subject: [PATCH 04/24] better locking of lighting and use correct method for relight without removing first Fixes #847 --- .../implementation/lighting/NMSRelighter.java | 9 ++++++++ .../lighting/NullRelighter.java | 5 +++++ .../implementation/lighting/Relighter.java | 7 +++++++ .../java/com/sk89q/worldedit/EditSession.java | 21 ++++++++----------- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java index 37c38005a..87f368f06 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NMSRelighter.java @@ -71,6 +71,7 @@ public class NMSRelighter implements Relighter { private final int maxY; private final boolean calculateHeightMaps; private final ReentrantLock lightingLock; + private final AtomicBoolean finished = new AtomicBoolean(false); private boolean removeFirst; public NMSRelighter(IQueueExtent queue, boolean calculateHeightMaps) { @@ -99,6 +100,11 @@ public class NMSRelighter implements Relighter { return lightingLock; } + @Override + public boolean isFinished() { + return finished.get(); + } + @Override public synchronized void removeAndRelight(boolean sky) { removeFirst = true; fixLightingSafe(sky); @@ -839,10 +845,12 @@ public class NMSRelighter implements Relighter { } if (Settings.IMP.LIGHTING.ASYNC) { queue.flush(); + finished.set(true); } else { TaskManager.IMP.sync(new RunnableVal() { @Override public void run(Object value) { queue.flush(); + finished.set(true); } }); } @@ -873,6 +881,7 @@ public class NMSRelighter implements Relighter { Fawe.imp().getPlatformAdapter().sendChunk(chunk.getOrCreateGet(), bitMask, true); iter.remove(); } + finished.set(true); } }; if (Settings.IMP.LIGHTING.ASYNC) { diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NullRelighter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NullRelighter.java index fe9eb28b3..1c345df1b 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NullRelighter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/NullRelighter.java @@ -53,4 +53,9 @@ public class NullRelighter implements Relighter { public ReentrantLock getLock() { return null; } + + @Override + public boolean isFinished() { + return true; + } } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/Relighter.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/Relighter.java index 99f809075..61fbc2d87 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/Relighter.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/lighting/Relighter.java @@ -70,6 +70,13 @@ public interface Relighter { ReentrantLock getLock(); + /** + * Returns true if the Relighter has been flushed + * + * @return true if finished + */ + boolean isFinished(); + class SkipReason { public static final byte NONE = 0; public static final byte AIR = 1; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 5ace70cbf..2036a419f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -1098,18 +1098,15 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { limit.set(originalLimit); try { if (relighter != null && !(relighter instanceof NullRelighter)) { - // Only relight once! - if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING && !relighter.getLock().tryLock()) { - relighter.getLock().lock(); - relighter.getLock().unlock(); - } else { - if (Settings.IMP.LIGHTING.REMOVE_FIRST) { - relighter.removeAndRelight(true); - } else { - relighter.fixSkyLighting(); - relighter.fixBlockLighting(); - } - if (Settings.IMP.LIGHTING.DELAY_PACKET_SENDING) { + // Don't relight twice! + if (!relighter.isFinished() && relighter.getLock().tryLock()) { + try { + if (Settings.IMP.LIGHTING.REMOVE_FIRST) { + relighter.removeAndRelight(true); + } else { + relighter.fixLightingSafe(true); + } + } finally { relighter.getLock().unlock(); } } From eaa9872294b8a012dcd3554af63db3ea2a4595b8 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 17:36:50 +0000 Subject: [PATCH 05/24] Revert this for now as it had unintended consquences --- .../java/com/sk89q/worldedit/EditSession.java | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java index 2036a419f..194eb697a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -1201,10 +1201,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { // Pick how we're going to visit blocks RecursiveVisitor visitor = new DirectionalVisitor(mask, replace, origin, direction, (int) (radius * 2 + 1)); - // With queue enabled, FAWE may start attempting to place chunks before the operation is finished. - // This is unnacceptable for recursive operations. - disableQueue(); - // Start at the origin visitor.visit(origin); @@ -1263,10 +1259,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { visitor = new DownwardVisitor(mask, replace, origin.getBlockY(), (int) (radius * 2 + 1)); } - // With queue enabled, FAWE may start attempting to place chunks before the operation is finished. - // This is unnacceptable for recursive operations. - disableQueue(); - // Start at the origin visitor.visit(origin); @@ -1747,10 +1739,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { } RecursiveVisitor visitor = new RecursiveVisitor(mask, replace, (int) (radius * 2 + 1)); - // With queue enabled, FAWE may start attempting to place chunks before the operation is finished. - // This is unnacceptable for recursive operations. - disableQueue(); - // Around the origin in a 3x3 block for (BlockVector3 position : CuboidRegion.fromCenter(origin, 1)) { if (mask.test(position)) { @@ -1792,10 +1780,6 @@ public class EditSession extends PassthroughExtent implements AutoCloseable { BlockReplace replace = new BlockReplace(this, fluid.getDefaultState()); NonRisingVisitor visitor = new NonRisingVisitor(mask, replace); - // With queue enabled, FAWE may start attempting to place chunks before the operation is finished. - // This is unnacceptable for recursive operations. - disableQueue(); - // Around the origin in a 3x3 block for (BlockVector3 position : CuboidRegion.fromCenter(origin, 1)) { if (liquidMask.test(position)) { From e94e3b7b05c33b23f284fded10de986c8a8c6829 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 18:17:18 +0000 Subject: [PATCH 06/24] Only forcefully submit a chunk if we hold the monitor. - Properly ensures we don't try to submit chunks that already have a monitor (prevent the FAWE-freezing) - We can't detect if "no" threads hold the chunk's monitor, but equally that would also be kinda very bad practice. --- .../queue/SingleThreadQueueExtent.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java index 25c64cbcf..6569ec61c 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java @@ -250,8 +250,19 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen // - memory is low & queue size > num threads + 8 // - queue size > target size and primary queue has less than num threads submissions if (enabledQueue && ((lowMem && size > Settings.IMP.QUEUE.PARALLEL_THREADS + 8) || (size > Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized()))) { - chunk = chunks.removeFirst(); - final Future future = submitUnchecked(chunk); + int i = 0; + boolean found = false; + while (i < chunks.size() && (chunk = chunks.get(i)) != null) { + if (Thread.holdsLock(chunk)) { + found = true; + break; + } + i++; + } + Future future = null; + if (found) { + future = submitUnchecked(chunk); + } if (future != null && !future.isDone()) { final int targetSize; if (lowMem) { From be9866ddb3ecd90e7e422779f2db0f586023d6f1 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 19:02:51 +0000 Subject: [PATCH 07/24] Fix a lot of FAWE-freezing properly - Add a "loadPrivately" method to be used when GetChunks are called to avoid synchronocity issues with super classes being used on different threads - Synchronise the call method so we're not attempting to call whilst also loading/updating --- .../adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 16 ++++++++++++---- .../adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java | 16 ++++++++++++---- .../adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java | 16 ++++++++++++---- .../adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java | 16 ++++++++++++---- .../beta/implementation/blocks/CharBlocks.java | 2 -- .../queue/SingleThreadQueueExtent.java | 15 ++------------- 6 files changed, 50 insertions(+), 31 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index 6a23beeee..a2ab70498 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -376,7 +376,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl } @Override - public > T call(IChunkSet set, Runnable finalizer) { + public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; copy = createCopy ? new BukkitGetBlocks_1_15_2_Copy(world) : null; try { @@ -424,7 +424,7 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl char[] setArr = set.load(layer).clone(); if (createCopy) { - copy.storeSection(layer, load(layer).clone()); + copy.storeSection(layer, loadPrivately(layer).clone()); } ChunkSection newSection; @@ -458,12 +458,12 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl } else if (existingSection != getSections(false)[layer]) { this.sections[layer] = existingSection; this.reset(); - } else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { + } else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) { this.reset(layer); } else if (lock.isModified()) { this.reset(layer); } - newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::load, setArr, fastmode); + newSection = BukkitAdapter_1_15_2.newChunkSection(layer, this::loadPrivately, setArr, fastmode); if (!BukkitAdapter_1_15_2.setSectionAtomic(sections, existingSection, newSection, layer)) { log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); } else { @@ -676,6 +676,14 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl } } + private char[] loadPrivately(int layer) { + if (super.sections[layer].isFull()) { + return super.blocks[layer]; + } else { + return BukkitGetBlocks_1_15_2.this.update(layer, null); + } + } + @Override public synchronized void send(int mask, boolean lighting) { BukkitAdapter_1_15_2.sendChunk(world, chunkX, chunkZ, mask, lighting); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index 5baadd20a..1656fcb60 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -376,7 +376,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl } @Override - public > T call(IChunkSet set, Runnable finalizer) { + public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; copy = createCopy ? new BukkitGetBlocks_1_16_1_Copy(world) : null; try { @@ -424,7 +424,7 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl char[] setArr = set.load(layer).clone(); if (createCopy) { - copy.storeSection(layer, load(layer).clone()); + copy.storeSection(layer, loadPrivately(layer).clone()); } ChunkSection newSection; @@ -458,13 +458,13 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl } else if (existingSection != getSections(false)[layer]) { this.sections[layer] = existingSection; this.reset(); - } else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { + } else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) { this.reset(layer); } else if (lock.isModified()) { this.reset(layer); } newSection = BukkitAdapter_1_16_1 - .newChunkSection(layer, this::load, setArr, fastmode); + .newChunkSection(layer, this::loadPrivately, setArr, fastmode); if (!BukkitAdapter_1_16_1 .setSectionAtomic(sections, existingSection, newSection, layer)) { log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); @@ -678,6 +678,14 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl } } + private char[] loadPrivately(int layer) { + if (super.sections[layer].isFull()) { + return super.blocks[layer]; + } else { + return BukkitGetBlocks_1_16_1.this.update(layer, null); + } + } + @Override public synchronized void send(int mask, boolean lighting) { BukkitAdapter_1_16_1.sendChunk(world, chunkX, chunkZ, mask, lighting); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java index 8e62d54db..4e7167274 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java @@ -379,7 +379,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl } @Override - public > T call(IChunkSet set, Runnable finalizer) { + public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; copy = createCopy ? new BukkitGetBlocks_1_16_2_Copy(world) : null; try { @@ -427,7 +427,7 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl char[] setArr = set.load(layer).clone(); if (createCopy) { - copy.storeSection(layer, load(layer).clone()); + copy.storeSection(layer, loadPrivately(layer).clone()); } ChunkSection newSection; @@ -461,13 +461,13 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl } else if (existingSection != getSections(false)[layer]) { this.sections[layer] = existingSection; this.reset(); - } else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { + } else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) { this.reset(layer); } else if (lock.isModified()) { this.reset(layer); } newSection = BukkitAdapter_1_16_2 - .newChunkSection(layer, this::load, setArr, fastmode); + .newChunkSection(layer, this::loadPrivately, setArr, fastmode); if (!BukkitAdapter_1_16_2 .setSectionAtomic(sections, existingSection, newSection, layer)) { log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); @@ -681,6 +681,14 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl } } + private char[] loadPrivately(int layer) { + if (super.sections[layer].isFull()) { + return super.blocks[layer]; + } else { + return BukkitGetBlocks_1_16_2.this.update(layer, null); + } + } + @Override public synchronized void send(int mask, boolean lighting) { BukkitAdapter_1_16_2.sendChunk(world, chunkX, chunkZ, mask, lighting); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java index c78063452..2a6d84bfa 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java @@ -379,7 +379,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } @Override - public > T call(IChunkSet set, Runnable finalizer) { + public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world) : null; try { @@ -427,7 +427,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl char[] setArr = set.load(layer).clone(); if (createCopy) { - copy.storeSection(layer, load(layer).clone()); + copy.storeSection(layer, loadPrivately(layer).clone()); } ChunkSection newSection; @@ -461,13 +461,13 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } else if (existingSection != getSections(false)[layer]) { this.sections[layer] = existingSection; this.reset(); - } else if (!Arrays.equals(update(layer, new char[4096]), load(layer))) { + } else if (!Arrays.equals(update(layer, new char[4096]), loadPrivately(layer))) { this.reset(layer); } else if (lock.isModified()) { this.reset(layer); } newSection = BukkitAdapter_1_16_4 - .newChunkSection(layer, this::load, setArr, fastmode); + .newChunkSection(layer, this::loadPrivately, setArr, fastmode); if (!BukkitAdapter_1_16_4 .setSectionAtomic(sections, existingSection, newSection, layer)) { log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); @@ -681,6 +681,14 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } } + private char[] loadPrivately(int layer) { + if (super.sections[layer].isFull()) { + return super.blocks[layer]; + } else { + return BukkitGetBlocks_1_16_4.this.update(layer, null); + } + } + @Override public synchronized void send(int mask, boolean lighting) { BukkitAdapter_1_16_4.sendChunk(world, chunkX, chunkZ, mask, lighting); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java index 4a10276e5..e656cdb9d 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/blocks/CharBlocks.java @@ -9,8 +9,6 @@ import org.jetbrains.annotations.Range; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.concurrent.locks.ReentrantLock; - public abstract class CharBlocks implements IBlocks { public static final Logger logger = LoggerFactory.getLogger(CharBlocks.class); diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java index 6569ec61c..25c64cbcf 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java @@ -250,19 +250,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen // - memory is low & queue size > num threads + 8 // - queue size > target size and primary queue has less than num threads submissions if (enabledQueue && ((lowMem && size > Settings.IMP.QUEUE.PARALLEL_THREADS + 8) || (size > Settings.IMP.QUEUE.TARGET_SIZE && Fawe.get().getQueueHandler().isUnderutilized()))) { - int i = 0; - boolean found = false; - while (i < chunks.size() && (chunk = chunks.get(i)) != null) { - if (Thread.holdsLock(chunk)) { - found = true; - break; - } - i++; - } - Future future = null; - if (found) { - future = submitUnchecked(chunk); - } + chunk = chunks.removeFirst(); + final Future future = submitUnchecked(chunk); if (future != null && !future.isDone()) { final int targetSize; if (lowMem) { From 05d7558873077625260c68bf6e40c52dbf268b32 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 20:30:22 +0000 Subject: [PATCH 08/24] Don't print stack trace of FaweExceptions from submitted chunks Addresses #353 --- .../queue/SingleThreadQueueExtent.java | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java index 25c64cbcf..5f03b4cab 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java @@ -16,11 +16,14 @@ import com.boydti.fawe.beta.implementation.processors.EmptyBatchProcessor; import com.boydti.fawe.beta.implementation.processors.ExtentBatchProcessorHolder; import com.boydti.fawe.beta.implementation.processors.ProcessorScope; import com.boydti.fawe.config.Settings; +import com.boydti.fawe.object.exception.FaweException; import com.boydti.fawe.util.MathMan; import com.boydti.fawe.util.MemUtil; import com.google.common.util.concurrent.Futures; import com.sk89q.worldedit.extent.Extent; import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; @@ -35,6 +38,9 @@ import java.util.concurrent.locks.ReentrantLock; */ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent { + // Don't bother with the full classpath. + private static final Logger log = LoggerFactory.getLogger("SingleThreadQueueExtent"); + // Pool discarded chunks for reuse (can safely be cleared by another thread) // private static final ConcurrentLinkedQueue CHUNK_POOL = new ConcurrentLinkedQueue<>(); // Chunks currently being queued / worked on @@ -291,7 +297,15 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen while (future != null) { future = (Future) future.get(); } - } catch (InterruptedException | ExecutionException e) { + } catch (FaweException messageOnly) { + log.warn(messageOnly.getMessage()); + } catch (ExecutionException e) { + if (e.getCause() instanceof FaweException) { + log.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage()); + } else { + e.printStackTrace(); + } + } catch (InterruptedException e) { e.printStackTrace(); } } @@ -302,7 +316,15 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen while (first != null) { first = (Future) first.get(); } - } catch (InterruptedException | ExecutionException e) { + } catch (FaweException messageOnly) { + log.warn(messageOnly.getMessage()); + } catch (ExecutionException e) { + if (e.getCause() instanceof FaweException) { + log.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage()); + } else { + e.printStackTrace(); + } + } catch (InterruptedException e) { e.printStackTrace(); } } @@ -313,7 +335,15 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen if (next.isDone()) { try { next = (Future) next.get(); - } catch (InterruptedException | ExecutionException e) { + } catch (FaweException messageOnly) { + log.warn(messageOnly.getMessage()); + } catch (ExecutionException e) { + if (e.getCause() instanceof FaweException) { + log.warn(e.getCause().getClass().getCanonicalName() + ": " + e.getCause().getMessage()); + } else { + e.printStackTrace(); + } + } catch (InterruptedException e) { e.printStackTrace(); } } else { From fd1ed637032ebb73c8b51fec76556be4388e8805 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 13 Jan 2021 23:50:29 +0000 Subject: [PATCH 09/24] Don't confirm twice every time - I channelled my inner Jesse on this one. --- .../command/util/annotation/Confirm.java | 51 +++++++++++++++++++ .../platform/PlatformCommandManager.java | 9 ++-- .../extension/platform/binding/Bindings.java | 13 ++++- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java index 290dca4b6..01557bb04 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java @@ -19,11 +19,15 @@ import org.enginehub.piston.exception.StopExecutionException; import org.enginehub.piston.inject.InjectAnnotation; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; +import org.enginehub.piston.inject.MemoizingValueAccess; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; @@ -45,6 +49,9 @@ public @interface Confirm { REGION { @Override public boolean passes(Actor actor, InjectedValueAccess context, double value) { + if (checkExisting(context)) { + return true; + } Region region = context.injectedValue(Key.of(Region.class, Selection.class)).orElseThrow(IncompleteRegionException::new); BlockVector3 pos1 = region.getMinimumPoint(); BlockVector3 pos2 = region.getMaximumPoint(); @@ -62,6 +69,9 @@ public @interface Confirm { RADIUS { @Override public boolean passes(Actor actor, InjectedValueAccess context, double value) { + if (checkExisting(context)) { + return true; + } int max = WorldEdit.getInstance().getConfiguration().maxRadius; if (max != -1 && value > max) { actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.radius", @@ -74,6 +84,9 @@ public @interface Confirm { LIMIT { @Override public boolean passes(Actor actor, InjectedValueAccess context, double value) { + if (checkExisting(context)) { + return true; + } int max = 50; //TODO configurable, get Key.of(Method.class) @Limit if (max != -1 && value > max) { actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.confirm.limit", @@ -86,6 +99,9 @@ public @interface Confirm { ALWAYS { @Override public boolean passes(Actor actor, InjectedValueAccess context, double value) { + if (checkExisting(context)) { + return true; + } actor.print(TranslatableComponent.of("fawe.cancel.worldedit.cancel.reason.confirm")); return confirm(actor, context); } @@ -96,6 +112,13 @@ public @interface Confirm { } public T check(Actor actor, InjectedValueAccess context, T value) { + boolean isSuggestion = context.injectedValue(Key.of(boolean.class)).orElse(false); + if (isSuggestion) { + return value; + } + if (checkExisting(context)) { + return value; + } if (!passes(actor, context, value.doubleValue())) { throw new StopExecutionException(TextComponent.empty()); } @@ -130,6 +153,16 @@ public @interface Confirm { try { lock.lock(); actor.setMeta("cmdConfirm", wait); + try { + // This is really dumb but also stops the double //confirm requirement... + Field f = MemoizingValueAccess.class.getDeclaredField("memory"); + f.setAccessible(true); + Map, Optional> memory = (Map, Optional>) f.get(context); + memory.put(Key.of(ReentrantLock.class), Optional.of(lock)); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + // Waits till 15 seconds then returns false unless awakened if (condition.await(15, TimeUnit.SECONDS)) { return true; } @@ -141,5 +174,23 @@ public @interface Confirm { } return false; } + + boolean checkExisting(InjectedValueAccess context) { + Optional lock = context.injectedValue(Key.of(ReentrantLock.class)); + try { + // This is really dumb but also stops the double //confirm requirement... + Field f = MemoizingValueAccess.class.getDeclaredField("memory"); + f.setAccessible(true); + Map, Optional> memory = (Map, Optional>) f.get(context); + } catch (NoSuchFieldException | IllegalAccessException e) { + e.printStackTrace(); + } + if (lock.isPresent()) { + // lock if locked will be held by current thread unless something has gone REALLY wrong + // in which case this is the least of our worries... + return true; + } + return false; + } } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index dc4741215..3bb76fe2f 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -609,7 +609,7 @@ public final class PlatformCommandManager { if (actor == null) { context = globalInjectedValues; } else { - context = initializeInjectedValues(args::toString, actor, null); + context = initializeInjectedValues(args::toString, actor, null, false); } return parseCommand(args, context); } @@ -688,7 +688,7 @@ public final class PlatformCommandManager { } } - MemoizingValueAccess context = initializeInjectedValues(event::getArguments, actor, event); + MemoizingValueAccess context = initializeInjectedValues(event::getArguments, actor, event, false); ThrowableSupplier task = () -> commandManager.execute(context, ImmutableList.copyOf(split)); @@ -800,7 +800,7 @@ public final class PlatformCommandManager { getCommandManager(), actor, "//help"); } - private MemoizingValueAccess initializeInjectedValues(Arguments arguments, Actor actor, Event event) { + private MemoizingValueAccess initializeInjectedValues(Arguments arguments, Actor actor, Event event, boolean isSuggestions) { InjectedValueStore store = MapBackedValueStore.create(); store.injectValue(Key.of(Actor.class), ValueProvider.constant(actor)); if (actor instanceof Player) { @@ -817,6 +817,7 @@ public final class PlatformCommandManager { localSession.tellVersion(actor); return Optional.of(localSession); }); + store.injectValue(Key.of(boolean.class), context -> Optional.of(isSuggestions)); store.injectValue(Key.of(InjectedValueStore.class), ValueProvider.constant(store)); store.injectValue(Key.of(Event.class), ValueProvider.constant(event)); return MemoizingValueAccess.wrap( @@ -841,7 +842,7 @@ public final class PlatformCommandManager { List argStrings = split.stream() .map(Substring::getSubstring) .collect(Collectors.toList()); - MemoizingValueAccess access = initializeInjectedValues(() -> arguments, event.getActor(), event); + MemoizingValueAccess access = initializeInjectedValues(() -> arguments, event.getActor(), event, true); ImmutableSet suggestions; try { suggestions = commandManager.getSuggestions(access, argStrings); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java index ba0916961..38f31c4a3 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/binding/Bindings.java @@ -7,7 +7,9 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent; import org.enginehub.piston.CommandManager; import org.enginehub.piston.converter.ArgumentConverter; import org.enginehub.piston.converter.ConversionResult; +import org.enginehub.piston.converter.FailedConversion; import org.enginehub.piston.converter.SuccessfulConversion; +import org.enginehub.piston.exception.StopExecutionException; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.InjectedValueStore; import org.enginehub.piston.inject.Key; @@ -97,7 +99,11 @@ public class Bindings { @Override public ConversionResult convert(String s, InjectedValueAccess access) { - return SuccessfulConversion.fromSingle(invoke(s, argsFunc, access, method)); + Object o = invoke(s, argsFunc, access, method); + if (o == null) { + return FailedConversion.from(new NullPointerException()); + } + return SuccessfulConversion.fromSingle(o); } }); } @@ -118,7 +124,10 @@ public class Bindings { } return method.invoke(this, args); } catch (IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); + if (!(e.getCause() instanceof StopExecutionException)) { + throw new RuntimeException(e); + } + return null; } } } From ac7347882778ba1cecdeb121f8406e03482257cc Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 12:39:57 +0000 Subject: [PATCH 10/24] Fix bad/needless code - Fixes #852 --- .../command/util/annotation/Confirm.java | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java index 01557bb04..ef386d44b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java @@ -155,11 +155,9 @@ public @interface Confirm { actor.setMeta("cmdConfirm", wait); try { // This is really dumb but also stops the double //confirm requirement... - Field f = MemoizingValueAccess.class.getDeclaredField("memory"); - f.setAccessible(true); - Map, Optional> memory = (Map, Optional>) f.get(context); - memory.put(Key.of(ReentrantLock.class), Optional.of(lock)); - } catch (NoSuchFieldException | IllegalAccessException e) { + Map, Optional> memory = (Map, Optional>) Reflect.memory.get(context); + memory.put(Key.of(InterruptableCondition.class), Optional.of(wait)); + } catch (IllegalAccessException e) { e.printStackTrace(); } // Waits till 15 seconds then returns false unless awakened @@ -176,21 +174,25 @@ public @interface Confirm { } boolean checkExisting(InjectedValueAccess context) { - Optional lock = context.injectedValue(Key.of(ReentrantLock.class)); + Optional lock = context.injectedValue(Key.of(InterruptableCondition.class)); + // lock if locked will be held by current thread unless something has gone REALLY wrong + // in which case this is the least of our worries... + return lock.isPresent(); + } + } + + class Reflect { + static final Field memory; + static { + Field f; try { - // This is really dumb but also stops the double //confirm requirement... - Field f = MemoizingValueAccess.class.getDeclaredField("memory"); + f = MemoizingValueAccess.class.getDeclaredField("memory"); f.setAccessible(true); - Map, Optional> memory = (Map, Optional>) f.get(context); - } catch (NoSuchFieldException | IllegalAccessException e) { + } catch (NoSuchFieldException e) { e.printStackTrace(); + f = null; } - if (lock.isPresent()) { - // lock if locked will be held by current thread unless something has gone REALLY wrong - // in which case this is the least of our worries... - return true; - } - return false; + memory = f; } } } From 5e1289494ec8708a9cde1282bfc6ca6fa9579675 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 12:45:11 +0000 Subject: [PATCH 11/24] Delegate to blocktype for obtaining a BlockState's material --- .../worldedit/world/block/BlockState.java | 21 ++----------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index 6e020852f..2efd1c5cd 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -26,10 +26,8 @@ import com.boydti.fawe.util.StringMan; import com.google.common.base.Function; import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; -import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extension.input.InputParseException; -import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.extent.OutputExtent; @@ -58,7 +56,6 @@ public class BlockState implements BlockStateHolder, Pattern { private final int ordinal; private final char ordinalChar; private final BlockType blockType; - private BlockMaterial material; private final BaseBlock emptyBaseBlock; private CompoundInput compoundInput = CompoundInput.NULL; @@ -75,7 +72,6 @@ public class BlockState implements BlockStateHolder, Pattern { * @deprecated Magic Numbers * @return BlockState */ - @Deprecated public static BlockState getFromInternalId(int combinedId) throws InputParseException { return BlockTypes.getFromStateId(combinedId).withStateId(combinedId); @@ -366,16 +362,7 @@ public class BlockState implements BlockStateHolder, Pattern { @Override public BlockMaterial getMaterial() { - if (this.material == null) { - if (blockType == BlockTypes.__RESERVED__) { - return this.material = blockType.getMaterial(); - } - this.material = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this); - if (this.material.hasContainer()) { - this.compoundInput = CompoundInput.CONTAINER; - } - } - return material; + return blockType.getMaterial(); } @Override @@ -408,11 +395,7 @@ public class BlockState implements BlockStateHolder, Pattern { } public boolean isAir() { - try { - return material.isAir(); - } catch (NullPointerException ignored) { - return getMaterial().isAir(); - } + return blockType.getMaterial().isAir(); } @Override From 54712e268a728b3b7d43330fd848fe1a6318a658 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 12:47:02 +0000 Subject: [PATCH 12/24] Synchronize access to Bukkit#createBlockData to prevent occasional ConcurrentModification exceptions - This isn't actually used anymore given the previous commit, however it's still best to keep it safe. --- .../worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java | 2 +- .../worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java | 2 +- .../worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R2.java | 2 +- .../worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java index dec7822ca..b7c5b93af 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_15_R2.java @@ -144,7 +144,7 @@ public final class FAWE_Spigot_v1_15_R2 extends CachedBukkitAdapter implements I } @Override - public BlockMaterial getMaterial(BlockState state) { + public synchronized BlockMaterial getMaterial(BlockState state) { IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); return new BlockMaterial_1_15_2(bs.getBlock(), bs); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java index a9b95121f..f0a82bfab 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R1.java @@ -144,7 +144,7 @@ public final class FAWE_Spigot_v1_16_R1 extends CachedBukkitAdapter implements I } @Override - public BlockMaterial getMaterial(BlockState state) { + public synchronized BlockMaterial getMaterial(BlockState state) { IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); return new BlockMaterial_1_16_1(bs.getBlock(), bs); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R2.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R2.java index 681e4a7f0..690d8e2a7 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R2.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R2.java @@ -146,7 +146,7 @@ public final class FAWE_Spigot_v1_16_R2 extends CachedBukkitAdapter implements I } @Override - public BlockMaterial getMaterial(BlockState state) { + public synchronized BlockMaterial getMaterial(BlockState state) { IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); return new BlockMaterial_1_16_2(bs.getBlock(), bs); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java index 796379693..7f373b6a9 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java @@ -146,7 +146,7 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I } @Override - public BlockMaterial getMaterial(BlockState state) { + public synchronized BlockMaterial getMaterial(BlockState state) { IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); return new BlockMaterial_1_16_4(bs.getBlock(), bs); } From af34bd4e577388cc59c401b49ee0b0ad99c87bd9 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 13:42:37 +0000 Subject: [PATCH 13/24] the material seems to hold state data for some reason. - This requires a more complicated fix. Reverting this change for now --- .../sk89q/worldedit/world/block/BlockState.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java index 2efd1c5cd..26374e495 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockState.java @@ -26,8 +26,10 @@ import com.boydti.fawe.util.StringMan; import com.google.common.base.Function; import com.google.common.collect.Maps; import com.sk89q.jnbt.CompoundTag; +import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.extension.input.InputParseException; +import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.extent.OutputExtent; @@ -56,6 +58,7 @@ public class BlockState implements BlockStateHolder, Pattern { private final int ordinal; private final char ordinalChar; private final BlockType blockType; + private BlockMaterial material; private final BaseBlock emptyBaseBlock; private CompoundInput compoundInput = CompoundInput.NULL; @@ -362,7 +365,16 @@ public class BlockState implements BlockStateHolder, Pattern { @Override public BlockMaterial getMaterial() { - return blockType.getMaterial(); + if (this.material == null) { + if (blockType == BlockTypes.__RESERVED__) { + return this.material = blockType.getMaterial(); + } + this.material = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this); + if (this.material.hasContainer()) { + this.compoundInput = CompoundInput.CONTAINER; + } + } + return material; } @Override From 761d05ac198e132aa99760bc6ca3a2d6ed67fd42 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 14:38:37 +0000 Subject: [PATCH 14/24] actually delegate in AbstractDelegateExtent fixes #843 --- .../extent/AbstractDelegateExtent.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index 5daf419b1..fe1de9336 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.extent; +import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.HistoryExtent; @@ -30,8 +31,10 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.OperationQueue; +import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; @@ -44,6 +47,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; +import java.util.Set; import java.util.UUID; import javax.annotation.Nullable; @@ -275,6 +279,46 @@ public class AbstractDelegateExtent implements Extent { } } + @Override + public > int setBlocks(Region region, B block) { + checkNotNull(region); + checkNotNull(block); + boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); + + int changes = 0; + for (BlockVector3 pos : region) { + if (setBlock(pos, block)) { + changes++; + } + } + return changes; + } + + @Override + public int setBlocks(Region region, Pattern pattern) { + return getExtent().setBlocks(region, pattern); + } + + @Override + public > int replaceBlocks(Region region, Set filter, B replacement) { + return getExtent().replaceBlocks(region, filter, replacement); + } + + @Override + public int replaceBlocks(Region region, Set filter, Pattern pattern) { + return getExtent().replaceBlocks(region, filter, pattern); + } + + @Override + public int replaceBlocks(Region region, Mask mask, Pattern pattern) { + return getExtent().replaceBlocks(region, mask, pattern); + } + + @Override + public int setBlocks(final Set vset, final Pattern pattern) { + return getExtent().setBlocks(vset, pattern); + } + @Override public int getMaxY() { return extent.getMaxY(); @@ -343,4 +387,14 @@ public class AbstractDelegateExtent implements Extent { protected Operation commitBefore() { return null; } + + @Override + public T apply(Region region, T filter, boolean full) { + return getExtent().apply(region, filter, full); + } + + @Override + public T apply(Iterable positions, T filter) { + return getExtent().apply(positions, filter); + } } From 3136fb460b2152670e58adcf9af2c85769e05343 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 14:39:50 +0000 Subject: [PATCH 15/24] Revert "actually delegate in AbstractDelegateExtent" This reverts commit 761d05ac198e132aa99760bc6ca3a2d6ed67fd42. --- .../extent/AbstractDelegateExtent.java | 54 ------------------- 1 file changed, 54 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java index fe1de9336..5daf419b1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/AbstractDelegateExtent.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.extent; -import com.boydti.fawe.beta.Filter; import com.boydti.fawe.beta.IBatchProcessor; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.HistoryExtent; @@ -31,10 +30,8 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.extent.buffer.ForgetfulExtentBuffer; -import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.OperationQueue; -import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Location; @@ -47,7 +44,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; -import java.util.Set; import java.util.UUID; import javax.annotation.Nullable; @@ -279,46 +275,6 @@ public class AbstractDelegateExtent implements Extent { } } - @Override - public > int setBlocks(Region region, B block) { - checkNotNull(region); - checkNotNull(block); - boolean hasNbt = block instanceof BaseBlock && block.hasNbtData(); - - int changes = 0; - for (BlockVector3 pos : region) { - if (setBlock(pos, block)) { - changes++; - } - } - return changes; - } - - @Override - public int setBlocks(Region region, Pattern pattern) { - return getExtent().setBlocks(region, pattern); - } - - @Override - public > int replaceBlocks(Region region, Set filter, B replacement) { - return getExtent().replaceBlocks(region, filter, replacement); - } - - @Override - public int replaceBlocks(Region region, Set filter, Pattern pattern) { - return getExtent().replaceBlocks(region, filter, pattern); - } - - @Override - public int replaceBlocks(Region region, Mask mask, Pattern pattern) { - return getExtent().replaceBlocks(region, mask, pattern); - } - - @Override - public int setBlocks(final Set vset, final Pattern pattern) { - return getExtent().setBlocks(vset, pattern); - } - @Override public int getMaxY() { return extent.getMaxY(); @@ -387,14 +343,4 @@ public class AbstractDelegateExtent implements Extent { protected Operation commitBefore() { return null; } - - @Override - public T apply(Region region, T filter, boolean full) { - return getExtent().apply(region, filter, full); - } - - @Override - public T apply(Iterable positions, T filter) { - return getExtent().apply(positions, filter); - } } From 3034419918f2e1eb99fed4ebb1dcaacb2818c9ab Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 14:48:13 +0000 Subject: [PATCH 16/24] Send before history is safe --- .../src/main/java/com/boydti/fawe/config/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java index 7edd24c78..ae335a8e8 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/config/Settings.java @@ -389,7 +389,7 @@ public class Settings extends Config { }) public boolean ALLOW_TICK_EXISTING = true; @Comment({ - "Do not wait for a chunk's history to save before sending it", + "[SAFE] Do not wait for a chunk's history to save before sending it", " - Undo/redo commands will wait until the history has been written to disk before executing", " - Requires combine_stages = true" }) From fa69c791607dbb0959a66f6187cff5eb8f328a1f Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 15:42:38 +0000 Subject: [PATCH 17/24] lock when editing the chunks cache in SingletThreadQueueExtent - Long2ObjectLinkedOpenHashMap is not thread-safe and should not be used from multiple threads at once - Fixes #851 --- .../beta/implementation/queue/SingleThreadQueueExtent.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java index 5f03b4cab..da9a517ff 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/beta/implementation/queue/SingleThreadQueueExtent.java @@ -114,7 +114,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen for (IChunk chunk : this.chunks.values()) { chunk.recycle(); } + getChunkLock.lock(); this.chunks.clear(); + getChunkLock.unlock(); } this.enabledQueue = true; this.lastChunk = null; @@ -163,7 +165,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen lastChunk = null; } final long index = MathMan.pairInt(chunk.getX(), chunk.getZ()); + getChunkLock.lock(); chunks.remove(index, chunk); + getChunkLock.unlock(); V future = submitUnchecked(chunk); submissions.add(future); return future; @@ -374,7 +378,9 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen } } } + getChunkLock.lock(); chunks.clear(); + getChunkLock.unlock(); } pollSubmissions(0, true); } From b18c646bce85915df52ff446e9725bce8ed1495d Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 16:54:38 +0000 Subject: [PATCH 18/24] AbstractExtentMasks should have the correct extent. - Fixes #843 --- .../sk89q/worldedit/command/RegionCommands.java | 4 ++++ .../sk89q/worldedit/function/mask/BiomeMask.java | 15 +++++++++------ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java index be2a307b9..4a8c1840d 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java @@ -36,6 +36,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.function.GroundFunction; import com.sk89q.worldedit.function.generator.FloraGenerator; +import com.sk89q.worldedit.function.mask.AbstractExtentMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.MaskIntersection; @@ -300,6 +301,9 @@ public class RegionCommands { if (from == null) { from = new ExistingBlockMask(editSession); } + if (from instanceof AbstractExtentMask) { + ((AbstractExtentMask) from).setExtent(editSession); + } int affected = editSession.replaceBlocks(region, from, to); actor.printInfo(TranslatableComponent.of("worldedit.replace.replaced", TextComponent.of(affected))); return affected; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java index 8189d583e..202efefec 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/mask/BiomeMask.java @@ -34,9 +34,8 @@ import static com.google.common.base.Preconditions.checkNotNull; /** * Tests true if the biome at applied points is the same as the one given. */ -public class BiomeMask extends AbstractMask { +public class BiomeMask extends AbstractExtentMask { - private final Extent extent; private final Set biomes = new HashSet<>(); /** @@ -46,9 +45,8 @@ public class BiomeMask extends AbstractMask { * @param biomes a list of biomes to match */ public BiomeMask(Extent extent, Collection biomes) { - checkNotNull(extent); + super(extent); checkNotNull(biomes); - this.extent = extent; this.biomes.addAll(biomes); } @@ -92,7 +90,7 @@ public class BiomeMask extends AbstractMask { @Override public boolean test(BlockVector3 vector) { - BiomeType biome = extent.getBiome(vector); + BiomeType biome = getExtent().getBiome(vector); return biomes.contains(biome); } @@ -104,7 +102,12 @@ public class BiomeMask extends AbstractMask { @Override public Mask copy() { - return new BiomeMask(extent, new HashSet<>(biomes)); + return new BiomeMask(getExtent(), new HashSet<>(biomes)); } + @Override + public boolean test(Extent extent, BlockVector3 position) { + BiomeType biome = getExtent().getBiome(position); + return biomes.contains(biome); + } } From bad3d31d90624a965b8b9827ab2d2f9a326c97ae Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 17:03:32 +0000 Subject: [PATCH 19/24] Fix removing section lighting - Paper and spigot differ in methods - Also don't clone it as we're trying to fill the actual data... --- .../bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java | 9 +++++---- .../bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java | 9 +++++---- .../bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java | 9 +++++---- .../bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java | 9 +++++---- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java index a2ab70498..33e200737 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_15_2/BukkitGetBlocks_1_15_2.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import io.papermc.lib.PaperLib; import net.minecraft.server.v1_15_R1.BiomeBase; import net.minecraft.server.v1_15_R1.BiomeStorage; import net.minecraft.server.v1_15_R1.BlockPosition; @@ -181,8 +182,8 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibble) { - byte[] bytes = nibble.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibble.getIfSet() : nibble.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } @@ -193,8 +194,8 @@ public class BukkitGetBlocks_1_15_2 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibbleSky) { - byte[] bytes = nibbleSky.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibbleSky.getIfSet() : nibbleSky.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java index 1656fcb60..20182af7b 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_1/BukkitGetBlocks_1_16_1.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import io.papermc.lib.PaperLib; import net.minecraft.server.v1_16_R1.BiomeBase; import net.minecraft.server.v1_16_R1.BiomeStorage; import net.minecraft.server.v1_16_R1.BlockPosition; @@ -182,8 +183,8 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibble) { - byte[] bytes = nibble.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibble.getIfSet() : nibble.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } @@ -194,8 +195,8 @@ public class BukkitGetBlocks_1_16_1 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibbleSky) { - byte[] bytes = nibbleSky.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibbleSky.getIfSet() : nibbleSky.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java index 4e7167274..23d47d3f4 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_2/BukkitGetBlocks_1_16_2.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import io.papermc.lib.PaperLib; import net.minecraft.server.v1_16_R2.BiomeBase; import net.minecraft.server.v1_16_R2.BiomeStorage; import net.minecraft.server.v1_16_R2.BlockPosition; @@ -182,8 +183,8 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibble) { - byte[] bytes = nibble.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibble.getIfSet() : nibble.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } @@ -194,8 +195,8 @@ public class BukkitGetBlocks_1_16_2 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibbleSky) { - byte[] bytes = nibbleSky.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibbleSky.getIfSet() : nibbleSky.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java index 2a6d84bfa..b2c2a0b23 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java @@ -27,6 +27,7 @@ import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import io.papermc.lib.PaperLib; import net.minecraft.server.v1_16_R3.BiomeBase; import net.minecraft.server.v1_16_R3.BiomeStorage; import net.minecraft.server.v1_16_R3.BlockPosition; @@ -182,8 +183,8 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibble) { - byte[] bytes = nibble.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibble.getIfSet() : nibble.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } @@ -194,8 +195,8 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl if (nibble != null) { lightUpdate = true; synchronized (nibbleSky) { - byte[] bytes = nibbleSky.getCloneIfSet(); - if (bytes != NibbleArray.EMPTY_NIBBLE) { + byte[] bytes = PaperLib.isPaper() ? nibbleSky.getIfSet() : nibbleSky.asBytes(); + if (!PaperLib.isPaper() || bytes != NibbleArray.EMPTY_NIBBLE) { Arrays.fill(bytes, (byte) 0); } } From b450a0af806ed9acf869f5c3463fd1ee0ec356e7 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 14 Jan 2021 20:08:43 +0000 Subject: [PATCH 20/24] Fix confirm for some commands that give AutoValue_CommandParametersImpl from the getgo --- .../command/util/annotation/Confirm.java | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java index ef386d44b..974167c82 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/annotation/Confirm.java @@ -20,6 +20,8 @@ import org.enginehub.piston.inject.InjectAnnotation; import org.enginehub.piston.inject.InjectedValueAccess; import org.enginehub.piston.inject.Key; import org.enginehub.piston.inject.MemoizingValueAccess; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -155,7 +157,17 @@ public @interface Confirm { actor.setMeta("cmdConfirm", wait); try { // This is really dumb but also stops the double //confirm requirement... - Map, Optional> memory = (Map, Optional>) Reflect.memory.get(context); + final MemoizingValueAccess memoizingValueAccess; + if (!(context instanceof MemoizingValueAccess)) { + if (!context.getClass().getSimpleName().contains("AutoValue_CommandParametersImpl")) { + LoggerFactory.getLogger(Confirm.class).warn("InjectedValueAccess " + context.getClass().getName() + " given to Confirm"); + return true; + } + memoizingValueAccess = (MemoizingValueAccess) Reflect.injectedValues.get(context); + } else { + memoizingValueAccess = (MemoizingValueAccess) context; + } + Map, Optional> memory = (Map, Optional>) Reflect.memory.get(memoizingValueAccess); memory.put(Key.of(InterruptableCondition.class), Optional.of(wait)); } catch (IllegalAccessException e) { e.printStackTrace(); @@ -183,16 +195,28 @@ public @interface Confirm { class Reflect { static final Field memory; + static final Field injectedValues; static { - Field f; + Field memoryField; try { - f = MemoizingValueAccess.class.getDeclaredField("memory"); - f.setAccessible(true); + memoryField = MemoizingValueAccess.class.getDeclaredField("memory"); + memoryField.setAccessible(true); } catch (NoSuchFieldException e) { e.printStackTrace(); - f = null; + memoryField = null; } - memory = f; + memory = memoryField; + + Field injectedValuesField; + try { + Class c = Class.forName("org.enginehub.piston.impl.AutoValue_CommandParametersImpl"); + injectedValuesField = c.getDeclaredField("injectedValues"); + injectedValuesField.setAccessible(true); + } catch (NoSuchFieldException | ClassNotFoundException e) { + e.printStackTrace(); + injectedValuesField = null; + } + injectedValues = injectedValuesField; } } } From 798b4cdd4e05f2900cd2c7c05de83c7bde32b3c9 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Fri, 15 Jan 2021 20:16:46 +0000 Subject: [PATCH 21/24] Fix #806 --- .../sk89q/worldedit/extent/InputExtent.java | 2 +- .../function/block/SnowSimulator.java | 25 ++++++++ .../internal/block/BlockStateIdAccess.java | 60 +------------------ 3 files changed, 27 insertions(+), 60 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java index 3d3b695c7..4b5e4c7cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/InputExtent.java @@ -120,7 +120,7 @@ public interface InputExtent { * @param position location * @return the light level at the location */ - default int getEmmittedLight(MutableBlockVector3 position) { + default int getEmmittedLight(BlockVector3 position) { return getEmmittedLight(position.getX(), position.getY(), position.getZ()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java index 6dc337cb9..5fa40ca69 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/block/SnowSimulator.java @@ -24,13 +24,21 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.function.LayerFunction; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.registry.state.BooleanProperty; +import com.sk89q.worldedit.registry.state.EnumProperty; import com.sk89q.worldedit.registry.state.Property; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypes; +import java.util.Locale; +import java.util.Map; + public class SnowSimulator implements LayerFunction { public static final BooleanProperty snowy = (BooleanProperty) (Property) BlockTypes.GRASS_BLOCK.getProperty("snowy"); + private static final EnumProperty slab = (EnumProperty) (Property) BlockTypes.SANDSTONE_SLAB.getProperty("type"); + private static final EnumProperty stair = (EnumProperty) (Property) BlockTypes.SANDSTONE_STAIRS.getProperty("half"); + private static final EnumProperty trapdoor = (EnumProperty) (Property) BlockTypes.ACACIA_TRAPDOOR.getProperty("half"); + private static final BooleanProperty trapdoorOpen = (BooleanProperty) (Property) BlockTypes.ACACIA_TRAPDOOR.getProperty("open"); private final BlockState ice = BlockTypes.ICE.getDefaultState(); private final BlockState snow = BlockTypes.SNOW.getDefaultState(); @@ -92,6 +100,7 @@ public class SnowSimulator implements LayerFunction { return false; } + // Can't put snow this far up if (position.getBlockY() == this.extent.getMaximumPoint().getBlockY()) { return false; @@ -103,6 +112,22 @@ public class SnowSimulator implements LayerFunction { // Can only replace air (or snow in stack mode) if (!above.getBlockType().getMaterial().isAir() && (!stack || above.getBlockType() != BlockTypes.SNOW)) { return false; + } else if (!block.getBlockType().getId().toLowerCase(Locale.ROOT).contains("ice") && this.extent.getEmmittedLight(abovePosition) > 10) { + return false; + } else if (!block.getBlockType().getMaterial().isFullCube()) { + Map, Object> states = block.getStates(); + if (states.containsKey(slab) && block.getState(slab).equalsIgnoreCase("bottom")) { + return false; + } else if (states.containsKey(trapdoorOpen) && states.containsKey(trapdoor) && (block.getState(trapdoorOpen) + || block.getState(trapdoor).equalsIgnoreCase("bottom"))) { + return false; + } else if (states.containsKey(stair) && block.getState(stair).equalsIgnoreCase("bottom")) { + return false; + } else { + return false; + } + } else if (!block.getBlockType().getId().toLowerCase(Locale.ROOT).contains("ice") && block.getBlockType().getMaterial().isTranslucent()) { + return false; } if (stack && above.getBlockType() == BlockTypes.SNOW) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java index bcffdc98f..aa88cfe14 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/internal/block/BlockStateIdAccess.java @@ -20,37 +20,13 @@ package com.sk89q.worldedit.internal.block; import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.registry.BlockRegistry; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import java.util.BitSet; -import java.util.OptionalInt; import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkState; - public final class BlockStateIdAccess { private static final int INVALID_ID = -1; - private static final int EXPECTED_BLOCK_COUNT = 2 << 13; - private static final Int2ObjectOpenHashMap TO_STATE = - new Int2ObjectOpenHashMap<>(EXPECTED_BLOCK_COUNT); - - static { - TO_STATE.defaultReturnValue(null); - } - - public interface BlockStateInternalId { - int getInternalId(BlockState blockState); - - void setInternalId(BlockState blockState, int internalId); - } - - private static BlockStateInternalId blockStateInternalId; - - public static void setBlockStateInternalId(BlockStateInternalId blockStateInternalId) { - BlockStateIdAccess.blockStateInternalId = blockStateInternalId; - } /** * An invalid internal ID, for verification purposes. @@ -65,8 +41,7 @@ public final class BlockStateIdAccess { } public static int getBlockStateId(BlockState holder) { - return holder.getOrdinal(); - //return blockStateInternalId.getInternalId(holder); + return holder.getInternalId(); } @Nullable @@ -74,39 +49,6 @@ public final class BlockStateIdAccess { return BlockState.getFromOrdinal(id); } - /** - * For platforms that don't have an internal ID system, - * {@link BlockRegistry#getInternalBlockStateId(BlockState)} will return - * {@link OptionalInt#empty()}. In those cases, we will use our own ID system, - * since it's useful for other entries as well. - * - * @return an unused ID in WorldEdit's ID tracker - */ - private static int provideUnusedWorldEditId() { - return usedIds.nextClearBit(0); - } - - private static final BitSet usedIds = new BitSet(); - - public static void register(BlockState blockState, int id) { - int i = isValidInternalId(id) ? id : provideUnusedWorldEditId(); - BlockState existing = getBlockStateById(id); - checkState(existing == null || existing == blockState, - "BlockState %s is using the same block ID (%s) as BlockState %s", - blockState, i, existing); - blockStateInternalId.setInternalId(blockState, i); - TO_STATE.put(i, blockState); - usedIds.set(i); - } - - public static void clear() { - for (BlockState value : TO_STATE.values()) { - blockStateInternalId.setInternalId(value, invalidId()); - } - TO_STATE.clear(); - usedIds.clear(); - } - private BlockStateIdAccess() { } From 6895fe3b2c6b156f9966d35adcef8dca5208d12b Mon Sep 17 00:00:00 2001 From: N0tMyFaultOG Date: Sat, 16 Jan 2021 09:55:04 +0100 Subject: [PATCH 22/24] Update adapters to 1.16.5 --- .../src/main/resources/worldedit-adapters.jar | Bin 453936 -> 453945 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/worldedit-bukkit/src/main/resources/worldedit-adapters.jar b/worldedit-bukkit/src/main/resources/worldedit-adapters.jar index cc42ab3c00d7b4065d25626bd5b225276145ef6b..21a08ec5c357a6f2a5a984eec15b49f724238f80 100644 GIT binary patch delta 23560 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 delta 28184 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 oZ}?H&&%n!%B(MM-j;lT6-aG Date: Mon, 18 Jan 2021 15:37:14 +0000 Subject: [PATCH 23/24] Fix some coordinate errors - Fixes WorldGuard weirdness - Fixes #860 --- .../boydti/fawe/object/brush/SplineBrush.java | 8 ++--- .../extent/PositionTransformExtent.java | 2 +- .../com/sk89q/worldedit/math/Vector3.java | 33 ++++++++++++++++--- .../com/sk89q/worldedit/util/Direction.java | 4 +-- 4 files changed, 33 insertions(+), 14 deletions(-) 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 8fd3fd55a..8097f2104 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 @@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache; import com.boydti.fawe.object.brush.visualization.VisualExtent; import com.boydti.fawe.object.mask.IdMask; import com.boydti.fawe.object.visitor.DFSRecursiveVisitor; -import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.command.tool.brush.Brush; @@ -14,7 +13,6 @@ import com.sk89q.worldedit.function.mask.MaskIntersection; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.MathUtils; import com.sk89q.worldedit.math.MutableVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.interpolation.Node; @@ -197,15 +195,15 @@ public class SplineBrush implements Brush, ResettableTool { if (det_max == det_x) { double a = (xz * yz - xy * zz) / det_x; double b = (xy * yz - xz * yy) / det_x; - dir = BlockVector3.at(1.0, (int) MathUtils.roundHalfUp(a), (int) MathUtils.roundHalfUp(b)); + dir = BlockVector3.at(1.0, a, b); } else if (det_max == det_y) { double a = (yz * xz - xy * zz) / det_y; double b = (xy * xz - yz * xx) / det_y; - dir = BlockVector3.at((int) MathUtils.roundHalfUp(a), 1.0, (int) MathUtils.roundHalfUp(b)); + dir = BlockVector3.at(a, 1.0, b); } else { double a = (yz * xy - xz * yy) / det_z; double b = (xz * xy - yz * xx) / det_z; - dir = BlockVector3.at((int) MathUtils.roundHalfUp(a), (int) MathUtils.roundHalfUp(b), 1.0); + dir = BlockVector3.at(a, b, 1.0); } return dir.normalize(); } diff --git a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java index 17f3215e3..f37f23eee 100644 --- a/worldedit-core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java +++ b/worldedit-core/src/main/java/com/boydti/fawe/object/extent/PositionTransformExtent.java @@ -42,7 +42,7 @@ public class PositionTransformExtent extends ResettableExtent { mutable.mutY(pos.getY() - min.getY()); mutable.mutZ(pos.getZ() - min.getZ()); MutableVector3 tmp = new MutableVector3(transform.apply(mutable.toVector3())); - return min.add(tmp.toBlockPoint()); + return min.add(tmp.roundHalfUp().toBlockPoint()); } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java index 09f0387b3..2dd7a9598 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/math/Vector3.java @@ -83,16 +83,31 @@ public abstract class Vector3 { return YzxOrderComparator.YZX_ORDER; } + /** + * Gets the x coordinate rounded, accounting for negative coordinates + * + * @return the x coordinate + */ public int getBlockX() { - return (int) MathUtils.roundHalfUp(getX()); + return MathMan.roundInt(getX()); } + /** + * Gets the y coordinate rounded, accounting for negative coordinates + * + * @return the y coordinate + */ public int getBlockY() { - return (int) MathUtils.roundHalfUp(getY()); + return MathMan.roundInt(getY()); } + /** + * Gets the z coordinate rounded, accounting for negative coordinates + * + * @return the z coordinate + */ public int getBlockZ() { - return (int) MathUtils.roundHalfUp(getZ()); + return MathMan.roundInt(getZ()); } public MutableVector3 setComponents(Vector3 other) { @@ -487,6 +502,15 @@ public abstract class Vector3 { return Vector3.at(Math.floor(getX() + 0.5), Math.floor(getY() + 0.5), Math.floor(getZ() + 0.5)); } + /** + * Rounds all components using {@link MathUtils#roundHalfUp(double)} + * + * @return a new vector + */ + public Vector3 roundHalfUp() { + return Vector3.at(MathUtils.roundHalfUp(getX()), MathUtils.roundHalfUp(getY()), MathUtils.roundHalfUp(getZ())); + } + /** * Returns a vector with the absolute values of the components of * this vector. @@ -595,8 +619,7 @@ public abstract class Vector3 { * @return a new {@code BlockVector} */ public static BlockVector3 toBlockPoint(double x, double y, double z) { - return BlockVector3.at(MathUtils.roundHalfUp(x), MathUtils.roundHalfUp(y), MathUtils.roundHalfUp(z)); - //return BlockVector3.at(x, y, z); + return BlockVector3.at(x, y, z); } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java index 05a29f2ec..35c259f31 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/util/Direction.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.util; -import com.boydti.fawe.util.MathMan; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; @@ -80,8 +79,7 @@ public enum Direction { } Direction(Vector3 vector, int flags, int left, int right) { - this.blockPoint = BlockVector3.at(MathMan.roundInt(Math.signum(vector.getX())), - MathMan.roundInt(Math.signum(vector.getY())), MathMan.roundInt(Math.signum(vector.getZ()))); + this.blockPoint = BlockVector3.at(Math.signum(vector.getX()), Math.signum(vector.getY()), Math.signum(vector.getZ())); this.direction = vector.normalize(); this.flags = flags; this.left = left; From 0f6b56572af38eb4c18f0c2cef647a9502f2a53b Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Mon, 18 Jan 2021 16:13:42 +0000 Subject: [PATCH 24/24] Update to NMS given by 1.16.5. Since there's no new NMS revision (we're still on R3...?!) but there were changes, it would be more difficult to maintain both 1.16.4 and 1.16.5. Therefore, let's just stop supporting 1.16.4 as 1.16.5 is a minor update regardless. Fixes #859 --- worldedit-bukkit/build.gradle.kts | 4 +- .../BlockMaterial_1_16_5.java} | 8 +-- .../BukkitAdapter_1_16_5.java} | 6 +- .../BukkitGetBlocks_1_16_5.java} | 58 +++++++++---------- .../BukkitGetBlocks_1_16_5_Copy.java} | 12 ++-- .../FAWEWorldNativeAccess_1_16_R3.java | 6 +- .../MapChunkUtil_1_16_5.java} | 6 +- .../nbt/LazyCompoundTag_1_16_5.java} | 10 ++-- .../adapter/impl/FAWE_Spigot_v1_16_R3.java | 36 ++++++------ .../adapter/impl/regen/Regen_v1_16_R3.java | 4 +- 10 files changed, 75 insertions(+), 75 deletions(-) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/BlockMaterial_1_16_4.java => mc1_16_5/BlockMaterial_1_16_5.java} (94%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/BukkitAdapter_1_16_4.java => mc1_16_5/BukkitAdapter_1_16_5.java} (98%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/BukkitGetBlocks_1_16_4.java => mc1_16_5/BukkitGetBlocks_1_16_5.java} (95%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/BukkitGetBlocks_1_16_4_Copy.java => mc1_16_5/BukkitGetBlocks_1_16_5_Copy.java} (92%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4 => mc1_16_5}/FAWEWorldNativeAccess_1_16_R3.java (98%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/MapChunkUtil_1_16_4.java => mc1_16_5/MapChunkUtil_1_16_5.java} (85%) rename worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/{mc1_16_4/nbt/LazyCompoundTag_1_16_4.java => mc1_16_5/nbt/LazyCompoundTag_1_16_5.java} (93%) diff --git a/worldedit-bukkit/build.gradle.kts b/worldedit-bukkit/build.gradle.kts index 9ff5705fe..1c595d003 100644 --- a/worldedit-bukkit/build.gradle.kts +++ b/worldedit-bukkit/build.gradle.kts @@ -57,13 +57,13 @@ dependencies { "compile"("org.spigotmcv1_16_r2:spigotmcv1_16_r2:1_16_r2") "compile"("org.spigotmcv1_16_r3:spigotmcv1_16_r3:1_16_r3") "implementation"("it.unimi.dsi:fastutil:${Versions.FAST_UTIL}") - "api"("com.destroystokyo.paper:paper-api:1.16.4-R0.1-SNAPSHOT") { + "api"("com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT") { exclude("junit", "junit") isTransitive = false } "compileOnly"("org.jetbrains:annotations:20.1.0") "testCompileOnly"("org.jetbrains:annotations:20.1.0") - "compileOnly"("org.spigotmc:spigot:1.16.4-R0.1-SNAPSHOT") + "compileOnly"("org.spigotmc:spigot:1.16.5-R0.1-SNAPSHOT") "implementation"("io.papermc:paperlib:1.0.6") "compileOnly"("com.sk89q:dummypermscompat:1.10") { exclude("com.github.MilkBowl", "VaultAPI") diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BlockMaterial_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BlockMaterial_1_16_5.java similarity index 94% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BlockMaterial_1_16_4.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BlockMaterial_1_16_5.java index f3d40b448..9be26c788 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BlockMaterial_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BlockMaterial_1_16_5.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.sk89q.util.ReflectionUtil; import com.sk89q.worldedit.world.registry.BlockMaterial; @@ -12,7 +12,7 @@ import net.minecraft.server.v1_16_R3.ITileEntity; import net.minecraft.server.v1_16_R3.Material; import org.bukkit.craftbukkit.v1_16_R3.block.data.CraftBlockData; -public class BlockMaterial_1_16_4 implements BlockMaterial { +public class BlockMaterial_1_16_5 implements BlockMaterial { private final Block block; private final IBlockData defaultState; private final Material material; @@ -21,11 +21,11 @@ public class BlockMaterial_1_16_4 implements BlockMaterial { private final org.bukkit.Material craftMaterial; private final int opacity; - public BlockMaterial_1_16_4(Block block) { + public BlockMaterial_1_16_5(Block block) { this(block, block.getBlockData()); } - public BlockMaterial_1_16_4(Block block, IBlockData defaultState) { + public BlockMaterial_1_16_5(Block block, IBlockData defaultState) { this.block = block; this.defaultState = defaultState; this.material = defaultState.getMaterial(); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitAdapter_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java similarity index 98% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitAdapter_1_16_4.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java index e4101a22f..b044166a3 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitAdapter_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitAdapter_1_16_5.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; @@ -51,7 +51,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; -public final class BukkitAdapter_1_16_4 extends NMSAdapter { +public final class BukkitAdapter_1_16_5 extends NMSAdapter { /* NMS fields */ @@ -310,7 +310,7 @@ public final class BukkitAdapter_1_16_4 extends NMSAdapter { final int ordinal = paletteToBlock[i]; blockToPalette[ordinal] = Integer.MAX_VALUE; final BlockState state = BlockTypesCache.states[ordinal]; - final IBlockData ibd = ((BlockMaterial_1_16_4) state.getMaterial()).getState(); + final IBlockData ibd = ((BlockMaterial_1_16_5) state.getMaterial()).getState(); palette.a(ibd); } try { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java similarity index 95% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java index b2c2a0b23..3d28eedcc 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.boydti.fawe.Fawe; import com.boydti.fawe.FaweCache; @@ -9,7 +9,7 @@ import com.boydti.fawe.beta.implementation.lighting.HeightMapType; import com.boydti.fawe.beta.implementation.queue.QueueHandler; import com.boydti.fawe.bukkit.adapter.BukkitGetBlocks; import com.boydti.fawe.bukkit.adapter.DelegateLock; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.nbt.LazyCompoundTag_1_16_5; import com.boydti.fawe.config.Settings; import com.boydti.fawe.object.collection.AdaptedMap; import com.boydti.fawe.object.collection.BitArrayUnstretched; @@ -77,12 +77,12 @@ import java.util.function.Function; import static org.slf4j.LoggerFactory.getLogger; -public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBlocks { +public class BukkitGetBlocks_1_16_5 extends CharGetBlocks implements BukkitGetBlocks { - private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_16_4.class); + private static final Logger log = LoggerFactory.getLogger(BukkitGetBlocks_1_16_5.class); private static final Function posNms2We = v -> BlockVector3.at(v.getX(), v.getY(), v.getZ()); - private static final Function nmsTile2We = tileEntity -> new LazyCompoundTag_1_16_4(Suppliers.memoize(() -> tileEntity.save(new NBTTagCompound()))); + private static final Function nmsTile2We = tileEntity -> new LazyCompoundTag_1_16_5(Suppliers.memoize(() -> tileEntity.save(new NBTTagCompound()))); public ChunkSection[] sections; public Chunk nmsChunk; public WorldServer world; @@ -91,15 +91,15 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl public NibbleArray[] blockLight = new NibbleArray[16]; public NibbleArray[] skyLight = new NibbleArray[16]; private boolean createCopy = false; - private BukkitGetBlocks_1_16_4_Copy copy = null; + private BukkitGetBlocks_1_16_5_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; - public BukkitGetBlocks_1_16_4(World world, int chunkX, int chunkZ) { + public BukkitGetBlocks_1_16_5(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); } - public BukkitGetBlocks_1_16_4(WorldServer world, int chunkX, int chunkZ) { + public BukkitGetBlocks_1_16_5(WorldServer world, int chunkX, int chunkZ) { this.world = world; this.chunkX = chunkX; this.chunkZ = chunkZ; @@ -212,7 +212,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl if (tileEntity == null) { return null; } - return new LazyCompoundTag_1_16_4(Suppliers.memoize(() -> tileEntity.save(new NBTTagCompound()))); + return new LazyCompoundTag_1_16_5(Suppliers.memoize(() -> tileEntity.save(new NBTTagCompound()))); } @Override @@ -354,7 +354,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl }; } - private void updateGet(BukkitGetBlocks_1_16_4 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { + private void updateGet(BukkitGetBlocks_1_16_5 get, Chunk nmsChunk, ChunkSection[] sections, ChunkSection section, char[] arr, int layer) { synchronized (get) { if (this.getChunk() != nmsChunk) { this.nmsChunk = nmsChunk; @@ -376,13 +376,13 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } public Chunk ensureLoaded(net.minecraft.server.v1_16_R3.World nmsWorld, int chunkX, int chunkZ) { - return BukkitAdapter_1_16_4.ensureLoaded(nmsWorld, chunkX, chunkZ); + return BukkitAdapter_1_16_5.ensureLoaded(nmsWorld, chunkX, chunkZ); } @Override public synchronized > T call(IChunkSet set, Runnable finalizer) { forceLoadSections = false; - copy = createCopy ? new BukkitGetBlocks_1_16_4_Copy(world) : null; + copy = createCopy ? new BukkitGetBlocks_1_16_5_Copy(world) : null; try { WorldServer nmsWorld = world; Chunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -434,8 +434,8 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl ChunkSection newSection; ChunkSection existingSection = sections[layer]; if (existingSection == null) { - newSection = BukkitAdapter_1_16_4.newChunkSection(layer, setArr, fastmode); - if (BukkitAdapter_1_16_4.setSectionAtomic(sections, null, newSection, layer)) { + newSection = BukkitAdapter_1_16_5.newChunkSection(layer, setArr, fastmode); + if (BukkitAdapter_1_16_5.setSectionAtomic(sections, null, newSection, layer)) { updateGet(this, nmsChunk, sections, newSection, setArr, layer); continue; } else { @@ -447,10 +447,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } } } - BukkitAdapter_1_16_4.fieldTickingBlockCount.set(existingSection, (short) 0); + BukkitAdapter_1_16_5.fieldTickingBlockCount.set(existingSection, (short) 0); //ensure that the server doesn't try to tick the chunksection while we're editing it. - DelegateLock lock = BukkitAdapter_1_16_4.applyLock(existingSection); + DelegateLock lock = BukkitAdapter_1_16_5.applyLock(existingSection); synchronized (this) { synchronized (lock) { @@ -467,9 +467,9 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl } else if (lock.isModified()) { this.reset(layer); } - newSection = BukkitAdapter_1_16_4 + newSection = BukkitAdapter_1_16_5 .newChunkSection(layer, this::loadPrivately, setArr, fastmode); - if (!BukkitAdapter_1_16_4 + if (!BukkitAdapter_1_16_5 .setSectionAtomic(sections, existingSection, newSection, layer)) { log.error("Failed to set chunk section:" + chunkX + "," + chunkZ + " layer: " + layer); } else { @@ -503,10 +503,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl Map heightMaps = set.getHeightMaps(); for (Map.Entry entry : heightMaps.entrySet()) { - BukkitGetBlocks_1_16_4.this.setHeightmapToGet(entry.getKey(), entry.getValue()); + BukkitGetBlocks_1_16_5.this.setHeightmapToGet(entry.getKey(), entry.getValue()); } - BukkitGetBlocks_1_16_4.this.setLightingToGet(set.getLight()); - BukkitGetBlocks_1_16_4.this.setSkyLightingToGet(set.getSkyLight()); + BukkitGetBlocks_1_16_5.this.setLightingToGet(set.getLight()); + BukkitGetBlocks_1_16_5.this.setSkyLightingToGet(set.getSkyLight()); Runnable[] syncTasks = null; @@ -552,7 +552,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl final ListTag rotTag = (ListTag) entityTagMap.get("Rotation"); if (idTag == null || posTag == null || rotTag == null) { getLogger( - BukkitGetBlocks_1_16_4.class).debug("Unknown entity tag: " + nativeTag); + BukkitGetBlocks_1_16_5.class).debug("Unknown entity tag: " + nativeTag); continue; } final double x = posTag.getDouble(0); @@ -686,13 +686,13 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl if (super.sections[layer].isFull()) { return super.blocks[layer]; } else { - return BukkitGetBlocks_1_16_4.this.update(layer, null); + return BukkitGetBlocks_1_16_5.this.update(layer, null); } } @Override public synchronized void send(int mask, boolean lighting) { - BukkitAdapter_1_16_4.sendChunk(world, chunkX, chunkZ, mask, lighting); + BukkitAdapter_1_16_5.sendChunk(world, chunkX, chunkZ, mask, lighting); } @Override @@ -708,7 +708,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl data = new char[4096]; Arrays.fill(data, (char) 1); } - DelegateLock lock = BukkitAdapter_1_16_4.applyLock(section); + DelegateLock lock = BukkitAdapter_1_16_5.applyLock(section); synchronized (lock) { lock.untilFree(); lock.setModified(false); @@ -717,10 +717,10 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl FAWE_Spigot_v1_16_R3 adapter = ((FAWE_Spigot_v1_16_R3) WorldEditPlugin.getInstance().getBukkitImplAdapter()); final DataPaletteBlock blocks = section.getBlocks(); - final DataBits bits = (DataBits) BukkitAdapter_1_16_4.fieldBits.get(blocks); - final DataPalette palette = (DataPalette) BukkitAdapter_1_16_4.fieldPalette.get(blocks); + final DataBits bits = (DataBits) BukkitAdapter_1_16_5.fieldBits.get(blocks); + final DataPalette palette = (DataPalette) BukkitAdapter_1_16_5.fieldPalette.get(blocks); - final int bitsPerEntry = (int) BukkitAdapter_1_16_4.fieldBitsPerEntry.get(bits); + final int bitsPerEntry = (int) BukkitAdapter_1_16_5.fieldBitsPerEntry.get(bits); final long[] blockStates = bits.a(); new BitArrayUnstretched(bitsPerEntry, 4096, blockStates).toRaw(data); @@ -887,7 +887,7 @@ public class BukkitGetBlocks_1_16_4 extends CharGetBlocks implements BukkitGetBl try { final DataPaletteBlock blocksExisting = existing.getBlocks(); - final DataPalette palette = (DataPalette) BukkitAdapter_1_16_4.fieldPalette.get(blocksExisting); + final DataPalette palette = (DataPalette) BukkitAdapter_1_16_5.fieldPalette.get(blocksExisting); int paletteSize; if (palette instanceof DataPaletteLinear) { diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4_Copy.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5_Copy.java similarity index 92% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4_Copy.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5_Copy.java index 02149eaaa..52d9adc28 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/BukkitGetBlocks_1_16_4_Copy.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/BukkitGetBlocks_1_16_5_Copy.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.boydti.fawe.FaweCache; @@ -6,7 +6,7 @@ import com.boydti.fawe.beta.IBlocks; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.IChunkSet; import com.boydti.fawe.beta.implementation.lighting.HeightMapType; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.nbt.LazyCompoundTag_1_16_5; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -35,7 +35,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; -public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet { +public class BukkitGetBlocks_1_16_5_Copy implements IChunkGet { private final Map tiles = new HashMap<>(); private final Set entities = new HashSet<>(); @@ -43,13 +43,13 @@ public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet { private final char[][] blocks = new char[16][]; private final WorldServer world; - protected BukkitGetBlocks_1_16_4_Copy(WorldServer world) { + protected BukkitGetBlocks_1_16_5_Copy(WorldServer world) { this.world = world; } protected void storeTile(TileEntity tile) { tiles.put(BlockVector3.at(tile.getPosition().getX(), tile.getPosition().getY(), tile.getPosition().getZ()), - new LazyCompoundTag_1_16_4(Suppliers.memoize(() -> tile.save(new NBTTagCompound())))); + new LazyCompoundTag_1_16_5(Suppliers.memoize(() -> tile.save(new NBTTagCompound())))); } @Override @@ -115,7 +115,7 @@ public class BukkitGetBlocks_1_16_4_Copy implements IChunkGet { public void setHeightmapToGet(HeightMapType type, int[] data) {} protected void storeBiomes(BiomeStorage biomeStorage) { - this.biomeStorage = new BiomeStorage(biomeStorage.g, BukkitAdapter_1_16_4.getBiomeArray(biomeStorage).clone()); + this.biomeStorage = new BiomeStorage(biomeStorage.registry, BukkitAdapter_1_16_5.getBiomeArray(biomeStorage).clone()); } @Override diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/FAWEWorldNativeAccess_1_16_R3.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java similarity index 98% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/FAWEWorldNativeAccess_1_16_R3.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java index be1bd4082..2795bb0a2 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/FAWEWorldNativeAccess_1_16_R3.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/FAWEWorldNativeAccess_1_16_R3.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.boydti.fawe.Fawe; import com.boydti.fawe.object.IntPair; @@ -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_4.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, 0, false); + BukkitAdapter_1_16_5.sendChunk(getWorld().getWorld().getHandle(), chunk.x, chunk.z, 0, false); } } }; diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/MapChunkUtil_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/MapChunkUtil_1_16_5.java similarity index 85% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/MapChunkUtil_1_16_4.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/MapChunkUtil_1_16_5.java index 37993c9fe..f7369ed5f 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/MapChunkUtil_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/MapChunkUtil_1_16_5.java @@ -1,10 +1,10 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4; +package com.boydti.fawe.bukkit.adapter.mc1_16_5; import com.boydti.fawe.bukkit.adapter.MapChunkUtil; import net.minecraft.server.v1_16_R3.PacketPlayOutMapChunk; -public class MapChunkUtil_1_16_4 extends MapChunkUtil { - public MapChunkUtil_1_16_4() throws NoSuchFieldException { +public class MapChunkUtil_1_16_5 extends MapChunkUtil { + public MapChunkUtil_1_16_5() throws NoSuchFieldException { fieldX = PacketPlayOutMapChunk.class.getDeclaredField("a"); fieldZ = PacketPlayOutMapChunk.class.getDeclaredField("b"); fieldBitMask = PacketPlayOutMapChunk.class.getDeclaredField("c"); diff --git a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/nbt/LazyCompoundTag_1_16_4.java b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/nbt/LazyCompoundTag_1_16_5.java similarity index 93% rename from worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/nbt/LazyCompoundTag_1_16_4.java rename to worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/nbt/LazyCompoundTag_1_16_5.java index 73e416f35..ad1646216 100644 --- a/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_4/nbt/LazyCompoundTag_1_16_4.java +++ b/worldedit-bukkit/src/main/java/com/boydti/fawe/bukkit/adapter/mc1_16_5/nbt/LazyCompoundTag_1_16_5.java @@ -1,4 +1,4 @@ -package com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt; +package com.boydti.fawe.bukkit.adapter.mc1_16_5.nbt; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; @@ -17,17 +17,17 @@ import java.util.List; import java.util.Map; import java.util.function.Supplier; -public class LazyCompoundTag_1_16_4 extends CompoundTag { +public class LazyCompoundTag_1_16_5 extends CompoundTag { private final Supplier nmsTag; private CompoundTag cachedValue; - public LazyCompoundTag_1_16_4(Supplier tag) { + public LazyCompoundTag_1_16_5(Supplier tag) { super(new HashMap<>()); this.nmsTag = tag; } - public LazyCompoundTag_1_16_4(NBTTagCompound tag) { + public LazyCompoundTag_1_16_5(NBTTagCompound tag) { this(() -> tag); } @@ -94,7 +94,7 @@ public class LazyCompoundTag_1_16_4 extends CompoundTag { NBTTagList nbtList = (NBTTagList) tag; for (NBTBase elem : nbtList) { if (elem instanceof NBTTagCompound) { - list.add(new LazyCompoundTag_1_16_4((NBTTagCompound) elem)); + list.add(new LazyCompoundTag_1_16_5((NBTTagCompound) elem)); } else { list.add(WorldEditPlugin.getInstance().getBukkitImplAdapter().toNative(elem)); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java index 7f373b6a9..bad4e7b68 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/FAWE_Spigot_v1_16_R3.java @@ -22,12 +22,12 @@ package com.sk89q.worldedit.bukkit.adapter.impl; import com.boydti.fawe.FaweCache; import com.boydti.fawe.beta.IChunkGet; import com.boydti.fawe.beta.implementation.packet.ChunkPacket; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.BlockMaterial_1_16_4; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.BukkitAdapter_1_16_4; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.BukkitGetBlocks_1_16_4; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.FAWEWorldNativeAccess_1_16_R3; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.MapChunkUtil_1_16_4; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.nbt.LazyCompoundTag_1_16_4; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.BlockMaterial_1_16_5; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.BukkitAdapter_1_16_5; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.BukkitGetBlocks_1_16_5; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.FAWEWorldNativeAccess_1_16_R3; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.MapChunkUtil_1_16_5; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.nbt.LazyCompoundTag_1_16_5; import com.google.common.base.Preconditions; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.StringTag; @@ -130,7 +130,7 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I ordinalToIbdID = new int[ibdToStateOrdinal.length]; // size for (int i = 0; i < ibdToStateOrdinal.length; i++) { BlockState state = BlockTypesCache.states[i]; - BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial(); + BlockMaterial_1_16_5 material = (BlockMaterial_1_16_5) state.getMaterial(); int id = Block.REGISTRY_ID.getId(material.getState()); char ordinal = state.getOrdinalChar(); ibdToStateOrdinal[id] = ordinal; @@ -142,13 +142,13 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I @Override public BlockMaterial getMaterial(BlockType blockType) { Block block = getBlock(blockType); - return new BlockMaterial_1_16_4(block); + return new BlockMaterial_1_16_5(block); } @Override public synchronized BlockMaterial getMaterial(BlockState state) { IBlockData bs = ((CraftBlockData) Bukkit.createBlockData(state.getAsString())).getState(); - return new BlockMaterial_1_16_4(bs.getBlock(), bs); + return new BlockMaterial_1_16_5(bs.getBlock(), bs); } public Block getBlock(BlockType blockType) { @@ -195,14 +195,14 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I World nmsWorld = nmsChunk.getWorld(); BlockPosition blockPos = new BlockPosition(x, y, z); - IBlockData blockData = ((BlockMaterial_1_16_4) state.getMaterial()).getState(); + IBlockData blockData = ((BlockMaterial_1_16_5) state.getMaterial()).getState(); ChunkSection[] sections = nmsChunk.getSections(); int y4 = y >> 4; ChunkSection section = sections[y4]; IBlockData existing; if (section == null) { - existing = ((BlockMaterial_1_16_4) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); + existing = ((BlockMaterial_1_16_5) BlockTypes.AIR.getDefaultState().getMaterial()).getState(); } else { existing = section.getType(x & 15, y & 15, z & 15); } @@ -303,7 +303,7 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I @Override public OptionalInt getInternalBlockStateId(BlockState state) { - BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial(); + BlockMaterial_1_16_5 material = (BlockMaterial_1_16_5) state.getMaterial(); IBlockData mcState = material.getCraftBlockData().getState(); return OptionalInt.of(Block.REGISTRY_ID.getId(mcState)); } @@ -366,16 +366,16 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I @Override public > BlockData adapt(B state) { - BlockMaterial_1_16_4 material = (BlockMaterial_1_16_4) state.getMaterial(); + BlockMaterial_1_16_5 material = (BlockMaterial_1_16_5) state.getMaterial(); return material.getCraftBlockData(); } - private MapChunkUtil_1_16_4 mapUtil = new MapChunkUtil_1_16_4(); + private MapChunkUtil_1_16_5 mapUtil = new MapChunkUtil_1_16_5(); @Override public void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket packet) { WorldServer nmsWorld = ((CraftWorld) world).getHandle(); - PlayerChunk map = BukkitAdapter_1_16_4.getPlayerChunk(nmsWorld, packet.getChunkX(), packet.getChunkZ()); + PlayerChunk map = BukkitAdapter_1_16_5.getPlayerChunk(nmsWorld, packet.getChunkX(), packet.getChunkZ()); if (map != null && map.hasBeenLoaded()) { boolean flag = false; PlayerChunk.d players = map.players; @@ -428,8 +428,8 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I @Override public NBTBase fromNative(Tag foreign) { - if (foreign instanceof LazyCompoundTag_1_16_4) { - return ((LazyCompoundTag_1_16_4) foreign).get(); + if (foreign instanceof LazyCompoundTag_1_16_5) { + return ((LazyCompoundTag_1_16_5) foreign).get(); } return parent.fromNative(foreign); } @@ -441,7 +441,7 @@ public final class FAWE_Spigot_v1_16_R3 extends CachedBukkitAdapter implements I @Override public IChunkGet get(org.bukkit.World world, int chunkX, int chunkZ) { - return new BukkitGetBlocks_1_16_4(world, chunkX, chunkZ); + return new BukkitGetBlocks_1_16_5(world, chunkX, chunkZ); } @Override diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R3.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R3.java index 542fd360d..312a3a51c 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R3.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/regen/Regen_v1_16_R3.java @@ -3,7 +3,7 @@ package com.sk89q.worldedit.bukkit.adapter.impl.regen; import com.boydti.fawe.Fawe; import com.boydti.fawe.beta.IChunkCache; import com.boydti.fawe.beta.IChunkGet; -import com.boydti.fawe.bukkit.adapter.mc1_16_4.BukkitGetBlocks_1_16_4; +import com.boydti.fawe.bukkit.adapter.mc1_16_5.BukkitGetBlocks_1_16_5; import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Codec; @@ -328,7 +328,7 @@ public class Regen_v1_16_R3 extends Regenerator initSourceQueueCache() { - return (chunkX, chunkZ) -> new BukkitGetBlocks_1_16_4(freshNMSWorld, chunkX, chunkZ) { + return (chunkX, chunkZ) -> new BukkitGetBlocks_1_16_5(freshNMSWorld, chunkX, chunkZ) { @Override public Chunk ensureLoaded(World nmsWorld, int x, int z) { return getChunkAt(x, z);