Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions build-logic/src/main/kotlin/buildlogic.adapter.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ plugins {

paperweight {
injectPaperRepository = false
// TODO: switch back to REOBF when paper releases mappings
reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION
reobfArtifactConfiguration = io.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION
}

repositories {
Expand Down Expand Up @@ -53,10 +52,9 @@ dependencies {
}
}

// TODO: re-enable when paper releases mappings
/* tasks.named("assemble") {
tasks.named("assemble") {
dependsOn("reobfJar")
} */
}

tasks.named<Javadoc>("javadoc") {
enabled = false
Expand Down
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ antlr4 = "4.13.2"
json-simple = "1.1.1"
jlibnoise = "1.0.0"
jchronic = "0.2.4a"
lz4-java = "1.8.0"
lz4-java = "1.10.2"
lz4-stream = "1.0.0"
commons-cli = "1.11.0"
paperLib = "1.0.8"
Expand Down Expand Up @@ -108,7 +108,7 @@ antlr4-runtime = { group = "org.antlr", name = "antlr4-runtime", version.ref = "
json-simple = { group = "com.googlecode.json-simple", name = "json-simple", version.ref = "json-simple" }
jlibnoise = { group = "com.sk89q.lib", name = "jlibnoise", version.ref = "jlibnoise" }
jchronic = { group = "com.sk89q", name = "jchronic", version.ref = "jchronic" }
lz4Java = { group = "org.lz4", name = "lz4-java", version.ref = "lz4-java" }
lz4Java = { group = "at.yawk.lz4", name = "lz4-java", version.ref = "lz4-java" }
lz4JavaStream = { group = "net.jpountz", name = "lz4-java-stream", version.ref = "lz4-stream" }
commonsCli = { group = "commons-cli", name = "commons-cli", version.ref = "commons-cli" }
paperLib = { group = "io.papermc", name = "paperlib", version.ref = "paperLib" }
Expand Down
14 changes: 1 addition & 13 deletions worldedit-bukkit/adapters/adapter-1_21_11/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,8 @@ plugins {
id("buildlogic.adapter")
}

configurations {
all {
resolutionStrategy {
capabilitiesResolution {
withCapability("org.lz4:lz4-java") {
selectHighestVersion()
}
}
}
}
}

dependencies {
// https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.21.11-R0.1-20251209.225848-3")
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.21.11-R0.1-20251223.192256-16")
compileOnly(libs.paperLib)
}
17 changes: 15 additions & 2 deletions worldedit-bukkit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ val adaptersReobf = configurations.create("adaptersReobf") {
extendsFrom(adapters)
}

allprojects {
configurations.configureEach {
resolutionStrategy {
capabilitiesResolution {
withCapability("org.lz4:lz4-java") {
select(candidates.first {
(it.id as org.gradle.api.artifacts.component.ModuleComponentIdentifier).group == "at.yawk.lz4"
})
}
}
}
}
}

dependencies {
api(project(":worldedit-core"))
api(project(":worldedit-libs:bukkit"))
Expand Down Expand Up @@ -244,8 +258,7 @@ tasks.withType<ShadowJar>().configureEach {

tasks.named("assemble").configure {
dependsOn("shadowJar")
// TODO: re-enable when paper releases mappings
// dependsOn("reobfShadowJar")
dependsOn("reobfShadowJar")
}

publishMods {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public interface Filter {
/**
* Do something with the IChunk<br>
*/
default @Nonnull <T extends IChunk> T applyChunk(T chunk, @Nullable Region region) {
default @Nonnull <U extends IChunk> U applyChunk(U chunk, @Nullable Region region) {
return chunk;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package com.fastasyncworldedit.core.queue;

import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkHolder;
import com.fastasyncworldedit.core.queue.implementation.chunk.WrapperChunk;
import org.jetbrains.annotations.ApiStatus;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

@ApiStatus.Internal
public interface IQueueChunk<T extends Future<T>> extends IChunk, Callable<T> {

/**
Expand All @@ -15,6 +20,25 @@ default IQueueChunk<T> reset() {
return this;
}

/**
* Set a new {@link WrapperChunk} that allows prevention of a {@link ChunkHolder} instance being cached "locally" whilst it
* has been called/submitted, causing issues with processing/postprocessing, etc.
* If a wrapper has already been set, throws {@link IllegalStateException} as there should be no circumstance for us to set
* a new wrapper (does nothing if attempting to set the same wrapper).
*
* @param parentWrapper wrapper wrapping this {@link ChunkHolder instance}
* @throws IllegalStateException if there is already a wrapper set and a new wrapper instance is attempted to be se
* @since TODO
*/
void setWrapper(WrapperChunk<?> parentWrapper);

/**
* Invalidate the {@link WrapperChunk} if present.
*
* @since TODO
*/
void invalidateWrapper();

/**
* Apply the queued changes to the world containing this chunk.
* <p>The future returned may return another future. To ensure completion keep calling {@link
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import com.fastasyncworldedit.core.internal.simd.SimdSupport;
import com.fastasyncworldedit.core.internal.simd.VectorizedCharFilterBlock;
import com.fastasyncworldedit.core.internal.simd.VectorizedFilter;
import com.fastasyncworldedit.core.queue.implementation.chunk.ChunkHolder;
import com.fastasyncworldedit.core.queue.implementation.chunk.WrapperChunk;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.math.BlockVector2;
Expand Down Expand Up @@ -166,11 +168,24 @@ default ChunkFilterBlock apply(
// if (!filter.appliesChunk(chunkX, chunkZ)) {
// return block;
// }
T chunk = this.getOrCreateChunk(chunkX, chunkZ);
T initial = this.getOrCreateChunk(chunkX, chunkZ);
WrapperChunk<T> chunk = new WrapperChunk<>(initial, () -> this.getOrCreateChunk(chunkX, chunkZ));
if (initial instanceof ChunkHolder<?> holder) {
holder.setWrapper(chunk);
}

T newChunk = filter.applyChunk(chunk, region);
IChunk newChunk = filter.applyChunk(chunk, region);
if (newChunk == chunk) {
newChunk = chunk.get();
} else {
T c = (T) newChunk;
chunk.setWrapped(c);
// The IDE lies, it is possible for it to be a ChunkHolder because we're a little loose with our generic types...
if (c instanceof ChunkHolder<?> holder) {
holder.setWrapper(chunk);
}
}
if (newChunk != null) {
chunk = newChunk;
if (block == null) {
if (SimdSupport.useVectorApi() && filter instanceof VectorizedFilter) {
block = new VectorizedCharFilterBlock(this);
Expand All @@ -181,12 +196,16 @@ default ChunkFilterBlock apply(
block.initChunk(chunkX, chunkZ);
chunk.filterBlocks(filter, block, region, full);
}
this.submit(chunk);
// If null, then assume it has already been submitted and the WrapperChunk has therefore been invalidated
T toSubmit = chunk.get();
if (toSubmit != null) {
this.submit(toSubmit);
}
return block;
}

@Override
default <T extends Filter> T apply(Region region, T filter, boolean full) {
default <U extends Filter> U apply(Region region, U filter, boolean full) {
final Set<BlockVector2> chunks = region.getChunks();
ChunkFilterBlock block = null;
for (BlockVector2 chunk : chunks) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

/**
Expand All @@ -53,6 +54,7 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
private final Long2ObjectLinkedOpenHashMap<IQueueChunk<?>> chunks = new Long2ObjectLinkedOpenHashMap<>();
private final ConcurrentLinkedQueue<Future<?>> submissions = new ConcurrentLinkedQueue<>();
private final ReentrantLock getChunkLock = new ReentrantLock();
private final AtomicReference<IQueueChunk> lastChunk = new AtomicReference<>();
private World world = null;
private int minY = 0;
private int maxY = 255;
Expand All @@ -61,7 +63,6 @@ public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implemen
private boolean initialized;
private Thread currentThread;
// Last access pointers
private volatile IQueueChunk lastChunk;
private boolean enabledQueue = true;
private boolean fastmode = false;
// Array for lazy avoidance of concurrent modification exceptions and needless overcomplication of code (synchronisation is
Expand Down Expand Up @@ -161,13 +162,13 @@ protected synchronized void reset() {
return;
}
getChunkLock.lock();
this.lastChunk.set(null);
try {
this.chunks.clear();
} finally {
getChunkLock.unlock();
}
this.enabledQueue = true;
this.lastChunk = null;
this.currentThread = null;
this.initialized = false;
this.setProcessor(EmptyBatchProcessor.getInstance());
Expand Down Expand Up @@ -221,9 +222,7 @@ public boolean isEmpty() {

@Override
public <V extends Future<V>> V submit(IQueueChunk chunk) {
if (lastChunk == chunk) {
lastChunk = null;
}
this.lastChunk.compareAndExchange(chunk, null);
final long index = MathMan.pairInt(chunk.getX(), chunk.getZ());
getChunkLock.lock();
chunks.remove(index, chunk);
Expand Down Expand Up @@ -254,6 +253,8 @@ private <V extends Future<V>> V submitUnchecked(IQueueChunk chunk) {
}
}

chunk.invalidateWrapper();

if (Fawe.isMainThread()) {
V result = (V) chunk.call();
if (result == null) {
Expand All @@ -277,8 +278,9 @@ public <V extends Future<V>> V submitTaskUnchecked(Callable<V> callable) {
public synchronized boolean trim(boolean aggressive) {
cacheGet.trim(aggressive);
cacheSet.trim(aggressive);
LOGGER.info("trim");
if (Thread.currentThread() == currentThread) {
lastChunk = null;
lastChunk.set(null);
return chunks.isEmpty();
}
if (!submissions.isEmpty()) {
Expand Down Expand Up @@ -316,7 +318,7 @@ public IQueueChunk wrap(IQueueChunk chunk) {

@Override
public final IQueueChunk getOrCreateChunk(int x, int z) {
final IQueueChunk lastChunk = this.lastChunk;
final IQueueChunk lastChunk = this.lastChunk.get();
if (lastChunk != null && lastChunk.getX() == x && lastChunk.getZ() == z) {
return lastChunk;
}
Expand All @@ -330,7 +332,7 @@ public final IQueueChunk getOrCreateChunk(int x, int z) {
try {
IQueueChunk chunk = chunks.get(pair);
if (chunk != null) {
this.lastChunk = chunk;
this.lastChunk.set(chunk);
return chunk;
}
final int size = chunks.size();
Expand All @@ -340,8 +342,9 @@ public final IQueueChunk getOrCreateChunk(int x, int z) {
// - queue size > target size and primary queue has less than num threads submissions
int targetSize = lowMem ? Settings.settings().QUEUE.PARALLEL_THREADS + 8 : this.targetSize;
if (enabledQueue && size > targetSize && (lowMem || Fawe.instance().getQueueHandler().isUnderutilized())) {
chunk = chunks.removeFirst();
final Future future = submitUnchecked(chunk);
IQueueChunk toSubmit = chunks.removeFirst();
this.lastChunk.compareAndExchange(toSubmit, null);
final Future future = submitUnchecked(toSubmit);
if (future != null && !future.isDone()) {
pollSubmissions(targetSize, lowMem);
submissions.add(future);
Expand All @@ -351,7 +354,7 @@ public final IQueueChunk getOrCreateChunk(int x, int z) {
chunk = wrap(chunk);

chunks.put(pair, chunk);
this.lastChunk = chunk;
this.lastChunk.set(chunk);

return chunk;
} finally {
Expand Down Expand Up @@ -481,6 +484,7 @@ public synchronized void flush() {
if (MemUtil.isMemoryLimited()) {
while (!chunks.isEmpty()) {
IQueueChunk chunk = chunks.removeFirst();
this.lastChunk.compareAndExchange(chunk, null);
final Future future = submitUnchecked(chunk);
if (future != null && !future.isDone()) {
pollSubmissions(Settings.settings().QUEUE.PARALLEL_THREADS, true);
Expand All @@ -490,6 +494,7 @@ public synchronized void flush() {
} else {
while (!chunks.isEmpty()) {
IQueueChunk chunk = chunks.removeFirst();
this.lastChunk.compareAndExchange(chunk, null);
final Future future = submitUnchecked(chunk);
if (future != null && !future.isDone()) {
submissions.add(future);
Expand Down
Loading
Loading