From c6a9673b4b285f5adedfd2a861c0b67d9275b928 Mon Sep 17 00:00:00 2001 From: Jordan Date: Wed, 18 Oct 2023 14:30:22 +0100 Subject: [PATCH 1/9] fix: avoid tripping async catcher when getting entity from chunk (#2464) --- .../impl/fawe/v1_20_R2/PaperweightGetBlocks.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index d21510ff6..cbfd90ae2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -295,7 +295,15 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override public CompoundTag getEntity(UUID uuid) { - Entity entity = serverLevel.getEntity(uuid); + ensureLoaded(serverLevel, chunkX, chunkZ); + List entities = PaperweightPlatformAdapter.getEntities(getChunk()); + Entity entity = null; + for (Entity e : entities) { + if (e.getUUID().equals(uuid)) { + entity = e; + break; + } + } if (entity != null) { org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity(); return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData(); From a6378606d67d1ba7547a02eb2bc14004e0605e52 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Wed, 18 Oct 2023 20:49:07 +0200 Subject: [PATCH 2/9] chore: update log4j2 javadoc url (#2466) update log4j2 javadoc url --- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 549a26037..99f854eef 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -59,7 +59,7 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean options.encoding = "UTF-8" links( "https://jd.advntr.dev/api/latest/", - "https://logging.apache.org/log4j/2.x/log4j-api/apidocs/", + "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://www.antlr.org/api/Java/", "https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/", "https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/", From 37161f9f69daf771b0a86e1fae6d4d69a8eaf7c7 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Wed, 18 Oct 2023 20:49:57 +0200 Subject: [PATCH 3/9] Remove dead javadoc URLs --- buildSrc/src/main/kotlin/CommonJavaConfig.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/CommonJavaConfig.kt b/buildSrc/src/main/kotlin/CommonJavaConfig.kt index 99f854eef..8a111a2e7 100644 --- a/buildSrc/src/main/kotlin/CommonJavaConfig.kt +++ b/buildSrc/src/main/kotlin/CommonJavaConfig.kt @@ -61,8 +61,6 @@ fun Project.applyCommonJavaConfiguration(sourcesJar: Boolean, banSlf4j: Boolean "https://jd.advntr.dev/api/latest/", "https://logging.apache.org/log4j/2.x/javadoc/log4j-api/", "https://www.antlr.org/api/Java/", - "https://docs.enginehub.org/javadoc/org.enginehub.piston/core/0.5.7/", - "https://docs.enginehub.org/javadoc/org.enginehub.piston/default-impl/0.5.7/", "https://jd.papermc.io/paper/1.20/", "https://intellectualsites.github.io/fastasyncworldedit-javadocs/worldedit-core/" ) From 50ecc5908d23cac0c7bca3082dbe00a6c18e9b74 Mon Sep 17 00:00:00 2001 From: Zeranny Date: Sat, 21 Oct 2023 16:27:39 +0100 Subject: [PATCH 4/9] Fix "cleared" ellipsoid/cylinder regions still passing isDefined check (#2465) --- .../worldedit/regions/selector/CylinderRegionSelector.java | 2 ++ .../worldedit/regions/selector/EllipsoidRegionSelector.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java index 689cd3701..0798b06e6 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/CylinderRegionSelector.java @@ -254,6 +254,8 @@ public class CylinderRegionSelector implements RegionSelector, CUIRegion { @Override public void clear() { region = new CylinderRegion(region.getWorld()); + selectedCenter = false; + selectedRadius = false; } @Override diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java index 02d570969..1f7c8a420 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/regions/selector/EllipsoidRegionSelector.java @@ -227,6 +227,8 @@ public class EllipsoidRegionSelector implements RegionSelector, CUIRegion { public void clear() { region.setCenter(BlockVector3.ZERO); region.setRadius(Vector3.ZERO); + started = false; + selectedRadius = false; } @Override From 8c5bb96fdd39eb82d8288280fba2cdd1b7af3d0f Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 21 Oct 2023 17:48:35 +0200 Subject: [PATCH 5/9] Streamline fawe thread names (#2467) streamline fawe thread names --- .../bukkit/adapter/Regenerator.java | 13 ++++++------- .../main/java/com/fastasyncworldedit/core/Fawe.java | 2 +- .../java/com/fastasyncworldedit/core/FaweCache.java | 4 ++-- .../util/task/FaweForkJoinWorkerThreadFactory.java | 5 ++++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java index d0d9bb652..607bc75bf 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/Regenerator.java @@ -41,6 +41,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; import java.util.function.Function; /** @@ -158,16 +159,14 @@ public abstract class Regenerator(), - new ThreadFactoryBuilder().setNameFormat("fawe-clipboard-%d").build() + new ThreadFactoryBuilder().setNameFormat("FAWE Clipboard - %d").build() )); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java index af14624df..d8e1474e6 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/FaweCache.java @@ -18,6 +18,7 @@ import com.fastasyncworldedit.core.util.collection.CleanableThreadLocal; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.sk89q.jnbt.ByteArrayTag; import com.sk89q.jnbt.ByteTag; import com.sk89q.jnbt.CompoundTag; @@ -48,7 +49,6 @@ import java.util.Map.Entry; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CancellationException; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -616,7 +616,7 @@ public enum FaweCache implements Trimable { ArrayBlockingQueue queue = new ArrayBlockingQueue<>(nThreads, true); return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, queue, - Executors.defaultThreadFactory(), + new ThreadFactoryBuilder().setNameFormat("FAWE Blocking Executor - %d").build(), new ThreadPoolExecutor.CallerRunsPolicy() ) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java index 589b5b863..2c8353ce8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/task/FaweForkJoinWorkerThreadFactory.java @@ -2,19 +2,22 @@ package com.fastasyncworldedit.core.util.task; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.atomic.AtomicInteger; public class FaweForkJoinWorkerThreadFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory { private final String nameFormat; + private final AtomicInteger idCounter; public FaweForkJoinWorkerThreadFactory(String nameFormat) { this.nameFormat = nameFormat; + this.idCounter = new AtomicInteger(0); } @Override public ForkJoinWorkerThread newThread(ForkJoinPool pool) { final ForkJoinWorkerThread worker = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool); - worker.setName(String.format(nameFormat, worker.getPoolIndex())); + worker.setName(String.format(nameFormat, idCounter.getAndIncrement())); return worker; } From 9489e5448f5efce2b20f03d82ae583f51d6eba9a Mon Sep 17 00:00:00 2001 From: Jordan Date: Sun, 22 Oct 2023 08:01:44 +0100 Subject: [PATCH 6/9] fix: there is no need to synchronise chunk sending to the chunk GET instance (#2463) --- .../adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java | 7 +++++-- .../adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java | 7 +++++-- .../adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java | 7 +++++-- .../adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java | 7 +++++-- .../adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java | 7 +++++-- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java index d7a1be074..7b01ccca1 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java @@ -98,6 +98,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -841,8 +842,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send(int mask, boolean lighting) { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + } } /** diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java index fba567a5b..0c76df36a 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java @@ -104,6 +104,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -892,8 +893,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send(int mask, boolean lighting) { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + } } /** diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java index 0840b4aac..0171832aa 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java @@ -104,6 +104,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -892,8 +893,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send(int mask, boolean lighting) { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + } } /** diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java index e0e746109..e983a8e70 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java @@ -104,6 +104,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -890,8 +891,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send(int mask, boolean lighting) { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + } } /** diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index cbfd90ae2..c8ae9c80f 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -83,6 +83,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; @@ -877,8 +878,10 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public synchronized void send(int mask, boolean lighting) { - PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + public void send(int mask, boolean lighting) { + synchronized (sendLock) { + PaperweightPlatformAdapter.sendChunk(serverLevel, chunkX, chunkZ, lighting); + } } /** From f5803a09f6f4c1b3252d2701e69ef274daf97b0f Mon Sep 17 00:00:00 2001 From: Jordan Date: Sun, 22 Oct 2023 11:04:19 +0100 Subject: [PATCH 7/9] fix: vastly superier handling of queue chunks (#2461) - remove ChunkHolder locking concept as this is no longer needed - previously we obtained the copy from chunk GET on finalize, meaning the copy could be replaced by a "newer" one (bad) - work around this issue by introducing concept of "unique" keys to map chunk GET copies to - correctly handle resetting of various chunk-related classes to actually allow pooling to work - remove chunks as they are submitted when flushing a SingleThreadQueueExtenting --- .../fawe/v1_17_R1_2/PaperweightGetBlocks.java | 43 +++++-- .../v1_17_R1_2/PaperweightGetBlocks_Copy.java | 8 +- .../fawe/v1_18_R2/PaperweightGetBlocks.java | 46 +++++-- .../v1_18_R2/PaperweightGetBlocks_Copy.java | 9 +- .../fawe/v1_19_R3/PaperweightGetBlocks.java | 43 +++++-- .../v1_19_R3/PaperweightGetBlocks_Copy.java | 8 +- .../fawe/v1_20_R1/PaperweightGetBlocks.java | 43 +++++-- .../v1_20_R1/PaperweightGetBlocks_Copy.java | 8 +- .../fawe/v1_20_R2/PaperweightGetBlocks.java | 43 +++++-- .../v1_20_R2/PaperweightGetBlocks_Copy.java | 8 +- .../core/queue/IChunkGet.java | 22 +++- .../core/queue/IQueueChunk.java | 14 +++ .../SingleThreadQueueExtent.java | 12 +- .../implementation/blocks/CharBlocks.java | 1 + .../implementation/blocks/NullChunkGet.java | 3 +- .../implementation/chunk/ChunkHolder.java | 113 +++++------------- .../queue/implementation/chunk/NullChunk.java | 3 +- 17 files changed, 275 insertions(+), 152 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java index 7b01ccca1..a93437c1a 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks.java @@ -72,9 +72,11 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -91,6 +93,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; @@ -98,15 +101,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxHeight; private final int minSectionPosition; private final int maxSectionPosition; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -139,13 +143,27 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -394,8 +412,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -832,9 +859,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -949,9 +974,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); diff --git a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java index 65b16ee3b..cd9987d79 100644 --- a/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_17_1/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_17_R1_2/PaperweightGetBlocks_Copy.java @@ -22,6 +22,7 @@ import net.minecraft.world.level.chunk.ChunkBiomeContainer; import net.minecraft.world.level.chunk.LevelChunk; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -99,7 +100,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -196,6 +198,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java index 0c76df36a..81580910c 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks.java @@ -14,7 +14,6 @@ import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; -import com.google.common.collect.Iterables; import com.sk89q.jnbt.CompoundTag; import com.sk89q.jnbt.ListTag; import com.sk89q.jnbt.StringTag; @@ -66,7 +65,6 @@ import javax.annotation.Nonnull; import java.util.AbstractSet; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -76,13 +74,14 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; -import java.util.stream.StreamSupport; public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBlocks { @@ -95,6 +94,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; @@ -104,15 +104,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -147,13 +148,27 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -388,8 +403,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -883,9 +907,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -1007,9 +1029,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java index 5c68de6fe..b007ea3b4 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightGetBlocks_Copy.java @@ -11,7 +11,6 @@ import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; @@ -24,6 +23,7 @@ import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.PalettedContainer; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -101,7 +101,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -187,6 +188,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java index 0171832aa..60695c1e8 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks.java @@ -75,9 +75,11 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -95,6 +97,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; @@ -104,15 +107,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -147,13 +151,27 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -389,8 +407,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -883,9 +910,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -1007,9 +1032,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java index 0c5d62692..7e908c74c 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightGetBlocks_Copy.java @@ -26,6 +26,7 @@ import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -105,7 +106,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -199,6 +201,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java index e983a8e70..67bcd6902 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks.java @@ -75,9 +75,11 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -95,6 +97,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; @@ -104,15 +107,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -147,13 +151,27 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -388,8 +406,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(getChunk()) : null; + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -881,9 +908,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -1005,9 +1030,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java index a23000249..a3ca91376 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightGetBlocks_Copy.java @@ -26,6 +26,7 @@ import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -105,7 +106,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -199,6 +201,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java index c8ae9c80f..d51d31500 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks.java @@ -54,9 +54,11 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import javax.annotation.Nonnull; import java.util.*; import java.util.concurrent.Callable; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Future; import java.util.concurrent.Semaphore; import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -74,6 +76,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc .getInstance() .getBukkitImplAdapter()); private final ReadWriteLock sectionLock = new ReentrantReadWriteLock(); + private final ReentrantLock callLock = new ReentrantLock(); private final ServerLevel serverLevel; private final int chunkX; private final int chunkZ; @@ -83,15 +86,16 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc private final int maxSectionPosition; private final Registry biomeRegistry; private final IdMap> biomeHolderIdMap; + private final ConcurrentHashMap copies = new ConcurrentHashMap<>(); private final Object sendLock = new Object(); private LevelChunkSection[] sections; private LevelChunk levelChunk; private DataLayer[] blockLight; private DataLayer[] skyLight; private boolean createCopy = false; - private PaperweightGetBlocks_Copy copy = null; private boolean forceLoadSections = true; private boolean lightUpdate = false; + private int copyKey = 0; public PaperweightGetBlocks(World world, int chunkX, int chunkZ) { this(((CraftWorld) world).getHandle(), chunkX, chunkZ); @@ -126,13 +130,27 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempting to set if chunk GET should create copy, but it is not call-locked."); + } this.createCopy = createCopy; + return ++this.copyKey; } @Override - public IChunkGet getCopy() { - return copy; + public IChunkGet getCopy(final int key) { + return copies.remove(key); + } + + @Override + public void lockCall() { + this.callLock.lock(); + } + + @Override + public void unlockCall() { + this.callLock.unlock(); } @Override @@ -375,8 +393,17 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc @Override @SuppressWarnings("rawtypes") public synchronized > T call(IChunkSet set, Runnable finalizer) { + if (!callLock.isHeldByCurrentThread()) { + throw new IllegalStateException("Attempted to call chunk GET but chunk was not call-locked."); + } forceLoadSections = false; - copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + PaperweightGetBlocks_Copy copy = createCopy ? new PaperweightGetBlocks_Copy(levelChunk) : null; + if (createCopy) { + if (copies.containsKey(copyKey)) { + throw new IllegalStateException("Copy key already used."); + } + copies.put(copyKey, copy); + } try { ServerLevel nmsWorld = serverLevel; LevelChunk nmsChunk = ensureLoaded(nmsWorld, chunkX, chunkZ); @@ -868,9 +895,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc if (super.sections[layer] != null) { synchronized (super.sectionLocks[layer]) { if (super.sections[layer].isFull() && super.blocks[layer] != null) { - char[] blocks = new char[4096]; - System.arraycopy(super.blocks[layer], 0, blocks, 0, 4096); - return blocks; + return super.blocks[layer]; } } } @@ -992,9 +1017,7 @@ public class PaperweightGetBlocks extends CharGetBlocks implements BukkitGetBloc public LevelChunkSection[] getSections(boolean force) { force &= forceLoadSections; - sectionLock.readLock().lock(); LevelChunkSection[] tmp = sections; - sectionLock.readLock().unlock(); if (tmp == null || force) { try { sectionLock.writeLock().lock(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java index 428161a48..1c1130764 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightGetBlocks_Copy.java @@ -26,6 +26,7 @@ import net.minecraft.world.level.chunk.PalettedContainerRO; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -105,7 +106,8 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override @@ -199,6 +201,10 @@ public class PaperweightGetBlocks_Copy implements IChunkGet { @Override public char[] load(int layer) { layer -= getMinSectionPosition(); + if (blocks[layer] == null) { + blocks[layer] = new char[4096]; + Arrays.fill(blocks[layer], (char) BlockTypesCache.ReservedIDs.AIR); + } return blocks[layer]; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java index 8004f7098..a3fc6b78a 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IChunkGet.java @@ -50,13 +50,31 @@ public interface IChunkGet extends IBlocks, Trimable, InputExtent, ITileInput { boolean isCreateCopy(); - void setCreateCopy(boolean createCopy); + /** + * Not for external API use. Internal use only. + */ + int setCreateCopy(boolean createCopy); @Nullable - default IChunkGet getCopy() { + default IChunkGet getCopy(int key) { return null; } + /** + * Lock the {@link IChunkGet#call(IChunkSet, Runnable)} method to the current thread using a reentrant lock. Also locks + * related methods e.g. {@link IChunkGet#setCreateCopy(boolean)} + * + * @since TODO + */ + default void lockCall() {} + + /** + * Unlock {@link IChunkGet#call(IChunkSet, Runnable)} (and other related methods) to executions from other threads + * + * @since TODO + */ + default void unlockCall() {} + /** * Flush the block lighting array (section*blocks) to the chunk GET between the given section indices. Negative allowed. * diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java index 72732378d..9dda1d006 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/IQueueChunk.java @@ -36,4 +36,18 @@ public interface IQueueChunk> extends IChunk, Callable { } } + /** + * Get if the thank has any running tasks, locked locks, etc. + */ + default boolean hasRunning() { + return false; + } + + /** + * Prevent set operations to the chunk, should typically be used when a chunk is submitted before the edit is necessarily + * completed. + */ + default void lockSet() { + } + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java index 198782ee3..34dd5191e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/SingleThreadQueueExtent.java @@ -62,8 +62,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private boolean initialized; private Thread currentThread; // Last access pointers - private IQueueChunk lastChunk; - private long lastPair = Long.MAX_VALUE; + private volatile IQueueChunk lastChunk; + private volatile long lastPair = Long.MAX_VALUE; private boolean enabledQueue = true; private boolean fastmode = false; // Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is @@ -283,6 +283,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen private ChunkHolder poolOrCreate(int chunkX, int chunkZ) { ChunkHolder next = create(false); next.init(this, chunkX, chunkZ); + next.setFastMode(isFastMode()); return next; } @@ -454,7 +455,8 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen if (!chunks.isEmpty()) { getChunkLock.lock(); if (MemUtil.isMemoryLimited()) { - for (IQueueChunk chunk : chunks.values()) { + while (!chunks.isEmpty()) { + IQueueChunk chunk = chunks.removeFirst(); final Future future = submitUnchecked(chunk); if (future != null && !future.isDone()) { pollSubmissions(Settings.settings().QUEUE.PARALLEL_THREADS, true); @@ -462,14 +464,14 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen } } } else { - for (IQueueChunk chunk : chunks.values()) { + while (!chunks.isEmpty()) { + IQueueChunk chunk = chunks.removeFirst(); final Future future = submitUnchecked(chunk); if (future != null && !future.isDone()) { submissions.add(future); } } } - chunks.clear(); getChunkLock.unlock(); } pollSubmissions(0, true); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java index 85cadd9ef..6eae2db5b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/CharBlocks.java @@ -121,6 +121,7 @@ public abstract class CharBlocks implements IBlocks { public synchronized IChunkSet reset() { for (int i = 0; i < sectionCount; i++) { sections[i] = EMPTY; + blocks[i] = null; } return null; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java index 8f7b8007c..042870666 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/blocks/NullChunkGet.java @@ -69,7 +69,8 @@ public final class NullChunkGet implements IChunkGet { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java index ec556d845..e4a18ef69 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/ChunkHolder.java @@ -25,8 +25,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.Future; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; /** * An abstract {@link IChunk} class that implements basic get/set blocks. @@ -44,8 +42,6 @@ public class ChunkHolder> implements IQueueChunk { return POOL.poll(); } - private final Lock calledLock = new ReentrantLock(); - private volatile IChunkGet chunkExisting; // The existing chunk (e.g. a clipboard, or the world, before changes) private volatile IChunkSet chunkSet; // The blocks to be set to the chunkExisting private IBlockDelegate delegate; // delegate handles the abstraction of the chunk layers @@ -68,7 +64,6 @@ public class ChunkHolder> implements IQueueChunk { @Override public synchronized void recycle() { - calledLock.lock(); delegate = NULL; if (chunkSet != null) { chunkSet.recycle(); @@ -77,7 +72,6 @@ public class ChunkHolder> implements IQueueChunk { chunkExisting = null; extent = null; POOL.offer(this); - calledLock.unlock(); } public long initAge() { @@ -88,68 +82,49 @@ public class ChunkHolder> implements IQueueChunk { return delegate; } - /** - * If the chunk is currently being "called", this method will block until completed. - */ - private void checkAndWaitOnCalledLock() { - if (!calledLock.tryLock()) { - calledLock.lock(); - } - calledLock.unlock(); - } - @Override public boolean setTile(int x, int y, int z, CompoundTag tag) { - checkAndWaitOnCalledLock(); return delegate.set(this).setTile(x, y, z, tag); } @Override public CompoundTag getTile(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.set(this).getTile(x, y, z); } @Override public void setEntity(CompoundTag tag) { - checkAndWaitOnCalledLock(); delegate.set(this).setEntity(tag); } @Override public void removeEntity(UUID uuid) { - checkAndWaitOnCalledLock(); delegate.set(this).removeEntity(uuid); } @Override public Set getEntityRemoves() { - checkAndWaitOnCalledLock(); return delegate.set(this).getEntityRemoves(); } @Override public BiomeType[][] getBiomes() { - checkAndWaitOnCalledLock(); // Uses set as this method is only used to retrieve biomes that have been set to the extent/chunk. return delegate.set(this).getBiomes(); } @Override public char[][] getLight() { - checkAndWaitOnCalledLock(); return delegate.set(this).getLight(); } @Override public char[][] getSkyLight() { - checkAndWaitOnCalledLock(); return delegate.set(this).getSkyLight(); } @Override public void setBlocks(int layer, char[] data) { - checkAndWaitOnCalledLock(); delegate.set(this).setBlocks(layer, data); } @@ -174,12 +149,10 @@ public class ChunkHolder> implements IQueueChunk { @Override public void setFastMode(boolean fastmode) { - checkAndWaitOnCalledLock(); this.fastmode = fastmode; } public void setBitMask(int bitMask) { - checkAndWaitOnCalledLock(); this.bitMask = bitMask; } @@ -189,7 +162,6 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean hasBiomes(final int layer) { - checkAndWaitOnCalledLock(); // No need to go through delegate. hasBiomes is SET only. return chunkSet != null && chunkSet.hasBiomes(layer); } @@ -200,14 +172,13 @@ public class ChunkHolder> implements IQueueChunk { @Override public CompoundTag getEntity(UUID uuid) { - checkAndWaitOnCalledLock(); return delegate.get(this).getEntity(uuid); } @Override - public void setCreateCopy(boolean createCopy) { - checkAndWaitOnCalledLock(); + public int setCreateCopy(boolean createCopy) { this.createCopy = createCopy; + return -1; } @Override @@ -217,19 +188,16 @@ public class ChunkHolder> implements IQueueChunk { @Override public void setLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - checkAndWaitOnCalledLock(); delegate.setLightingToGet(this, lighting); } @Override public void setSkyLightingToGet(char[][] lighting, int minSectionPosition, int maxSectionPosition) { - checkAndWaitOnCalledLock(); delegate.setSkyLightingToGet(this, lighting); } @Override public void setHeightmapToGet(HeightMapType type, int[] data) { - checkAndWaitOnCalledLock(); delegate.setHeightmapToGet(this, type, data); } @@ -254,7 +222,6 @@ public class ChunkHolder> implements IQueueChunk { } public void flushLightToGet() { - checkAndWaitOnCalledLock(); delegate.flushLightToGet(this); } @@ -921,19 +888,16 @@ public class ChunkHolder> implements IQueueChunk { @Override public Map getTiles() { - checkAndWaitOnCalledLock(); return delegate.get(this).getTiles(); } @Override public Set getEntities() { - checkAndWaitOnCalledLock(); return delegate.get(this).getEntities(); } @Override public boolean hasSection(int layer) { - checkAndWaitOnCalledLock(); return chunkExisting != null && chunkExisting.hasSection(layer); } @@ -958,6 +922,7 @@ public class ChunkHolder> implements IQueueChunk { if (result) { delegate = NULL; chunkExisting = null; + chunkSet.recycle(); chunkSet = null; return true; } @@ -985,7 +950,6 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean isEmpty() { - checkAndWaitOnCalledLock(); return chunkSet == null || chunkSet.isEmpty(); } @@ -993,7 +957,6 @@ public class ChunkHolder> implements IQueueChunk { * Get or create the existing part of this chunk. */ public final IChunkGet getOrCreateGet() { - checkAndWaitOnCalledLock(); if (chunkExisting == null) { chunkExisting = newWrappedGet(); chunkExisting.trim(false); @@ -1005,7 +968,6 @@ public class ChunkHolder> implements IQueueChunk { * Get or create the settable part of this chunk. */ public final IChunkSet getOrCreateSet() { - checkAndWaitOnCalledLock(); if (chunkSet == null) { chunkSet = newWrappedSet(); } @@ -1026,7 +988,7 @@ public class ChunkHolder> implements IQueueChunk { * - The purpose of wrapping is to allow different extents to intercept / alter behavior * - e.g., caching, optimizations, filtering */ - private synchronized IChunkGet newWrappedGet() { + private IChunkGet newWrappedGet() { return extent.getCachedGet(chunkX, chunkZ); } @@ -1048,42 +1010,42 @@ public class ChunkHolder> implements IQueueChunk { @Override public synchronized T call() { - calledLock.lock(); if (chunkSet != null && !chunkSet.isEmpty()) { - this.delegate = GET; chunkSet.setBitMask(bitMask); - try { - IChunkSet copy = chunkSet.createCopy(); - chunkSet = null; - return this.call(copy, () -> { - // Do nothing - }); - } catch (Throwable t) { - calledLock.unlock(); - throw t; - } + IChunkSet copy = chunkSet.createCopy(); + return this.call(copy, () -> { + // Do nothing + }); } + recycle(); return null; } + /** + * This method should never be called from outside ChunkHolder + */ @Override public synchronized T call(IChunkSet set, Runnable finalize) { if (set != null) { IChunkGet get = getOrCreateGet(); - boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor); - get.setCreateCopy(postProcess); - final IChunkSet iChunkSet = getExtent().processSet(this, get, set); - Runnable finalizer; - if (postProcess) { - finalizer = () -> { - getExtent().postProcess(this, get.getCopy(), iChunkSet); - finalize.run(); - }; - } else { - finalizer = finalize; + try { + get.lockCall(); + boolean postProcess = !(getExtent().getPostProcessor() instanceof EmptyBatchProcessor); + final IChunkSet iChunkSet = getExtent().processSet(this, get, set); + Runnable finalizer; + if (postProcess) { + int copyKey = get.setCreateCopy(true); + finalizer = () -> { + getExtent().postProcess(this, get.getCopy(copyKey), iChunkSet); + finalize.run(); + }; + } else { + finalizer = finalize; + } + return get.call(set, finalizer); + } finally { + get.unlockCall(); } - calledLock.unlock(); - return get.call(set, finalizer); } return null; } @@ -1107,103 +1069,86 @@ public class ChunkHolder> implements IQueueChunk { @Override public boolean setBiome(int x, int y, int z, BiomeType biome) { - checkAndWaitOnCalledLock(); return delegate.setBiome(this, x, y, z, biome); } @Override public > boolean setBlock(int x, int y, int z, B block) { - checkAndWaitOnCalledLock(); return delegate.setBlock(this, x, y, z, block); } @Override public BiomeType getBiomeType(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBiome(this, x, y, z); } @Override public BlockState getBlock(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBlock(this, x, y, z); } @Override public BaseBlock getFullBlock(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getFullBlock(this, x, y, z); } @Override public void setSkyLight(int x, int y, int z, int value) { - checkAndWaitOnCalledLock(); delegate.setSkyLight(this, x, y, z, value); } @Override public void setHeightMap(HeightMapType type, int[] heightMap) { - checkAndWaitOnCalledLock(); delegate.setHeightMap(this, type, heightMap); } @Override public void removeSectionLighting(int layer, boolean sky) { - checkAndWaitOnCalledLock(); delegate.removeSectionLighting(this, layer, sky); } @Override public void setFullBright(int layer) { - checkAndWaitOnCalledLock(); delegate.setFullBright(this, layer); } @Override public void setBlockLight(int x, int y, int z, int value) { - checkAndWaitOnCalledLock(); delegate.setBlockLight(this, x, y, z, value); } @Override public void setLightLayer(int layer, char[] toSet) { - checkAndWaitOnCalledLock(); delegate.setLightLayer(this, layer, toSet); } @Override public void setSkyLightLayer(int layer, char[] toSet) { - checkAndWaitOnCalledLock(); delegate.setSkyLightLayer(this, layer, toSet); } @Override public int getSkyLight(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getSkyLight(this, x, y, z); } @Override public int getEmittedLight(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getEmittedLight(this, x, y, z); } @Override public int getBrightness(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getBrightness(this, x, y, z); } @Override public int getOpacity(int x, int y, int z) { - checkAndWaitOnCalledLock(); return delegate.getOpacity(this, x, y, z); } @Override public int[] getHeightMap(HeightMapType type) { - checkAndWaitOnCalledLock(); return delegate.getHeightMap(this, type); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java index 99757a513..8cc6471ba 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/chunk/NullChunk.java @@ -184,7 +184,8 @@ public final class NullChunk implements IQueueChunk { } @Override - public void setCreateCopy(boolean createCopy) { + public int setCreateCopy(boolean createCopy) { + return -1; } @Override From 6bb8a2cd3c53b3ba3041b16abd4589f8ff4b9d58 Mon Sep 17 00:00:00 2001 From: Alexander Brandes Date: Sun, 22 Oct 2023 12:51:11 +0200 Subject: [PATCH 8/9] Label PRs with merge conflicts (#2468) --- .github/workflows/label-merge-conflicts.yaml | 23 ++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/label-merge-conflicts.yaml diff --git a/.github/workflows/label-merge-conflicts.yaml b/.github/workflows/label-merge-conflicts.yaml new file mode 100644 index 000000000..d189f5520 --- /dev/null +++ b/.github/workflows/label-merge-conflicts.yaml @@ -0,0 +1,23 @@ +name: "Label conflicting PRs" +on: + push: + pull_request_target: + types: [ synchronize ] + pull_request: + types: [ synchronize ] + +permissions: + pull-requests: write + +jobs: + main: + if: github.event.pull_request.user.login != 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Label conflicting PRs + uses: eps1lon/actions-label-merge-conflict@v2.1.0 + with: + dirtyLabel: "unresolved-merge-conflict" + repoToken: "${{ secrets.GITHUB_TOKEN }}" + commentOnDirty: "Please take a moment and address the merge conflicts of your pull request. Thanks!" + continueOnMissingPermissions: true From 6dfa7d17329d6dcf8970e6fff33116b1c5218091 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sun, 22 Oct 2023 12:51:20 +0200 Subject: [PATCH 9/9] Fix chunkSource mappings on 1.19.4 (#2469) fix chunkSource mappings on 1.19.4 --- .../adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java index 7e2f3eaee..17b354535 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/regen/PaperweightRegen.java @@ -152,7 +152,7 @@ public class PaperweightRegen extends Regenerator