From a31f2f389035f17f6eec388d2bfa65eb6e85b5d2 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Thu, 25 Jan 2024 09:31:45 +0100 Subject: [PATCH 01/24] History: Read change positions at once (#2542) --- .../history/change/BlockPositionChange.java | 16 +++++ .../history/change/MutableBlockChange.java | 10 +-- .../change/MutableFullBlockChange.java | 9 +-- .../changeset/FaweStreamChangeSet.java | 67 +++++++------------ 4 files changed, 46 insertions(+), 56 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/BlockPositionChange.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/BlockPositionChange.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/BlockPositionChange.java new file mode 100644 index 0000000000..e9c233269b --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/BlockPositionChange.java @@ -0,0 +1,16 @@ +package com.fastasyncworldedit.core.history.change; + +import com.sk89q.worldedit.history.change.Change; +import org.jetbrains.annotations.ApiStatus; + +/** + * Represents a change that is associated with {@code (x, y, z)} block coordinates. + * @since TODO + */ +@ApiStatus.Internal +public sealed abstract class BlockPositionChange implements Change + permits MutableBlockChange, MutableFullBlockChange { + public int x; + public int y; + public int z; +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableBlockChange.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableBlockChange.java index f4797581fa..4739405073 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableBlockChange.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableBlockChange.java @@ -2,17 +2,13 @@ import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.history.UndoContext; -import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.block.BlockState; +import org.jetbrains.annotations.ApiStatus; -public class MutableBlockChange implements Change { - - public int z; - public int y; - public int x; +@ApiStatus.Internal +public final class MutableBlockChange extends BlockPositionChange { public int ordinal; - public MutableBlockChange(int x, int y, int z, int ordinal) { this.x = x; this.y = y; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableFullBlockChange.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableFullBlockChange.java index 2b99cb8a91..b23903f452 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableFullBlockChange.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/change/MutableFullBlockChange.java @@ -4,15 +4,12 @@ import com.sk89q.worldedit.extent.inventory.BlockBag; import com.sk89q.worldedit.extent.inventory.BlockBagException; import com.sk89q.worldedit.history.UndoContext; -import com.sk89q.worldedit.history.change.Change; import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; +import org.jetbrains.annotations.ApiStatus; -public class MutableFullBlockChange implements Change { - - public int z; - public int y; - public int x; +@ApiStatus.Internal +public final class MutableFullBlockChange extends BlockPositionChange { public int from; public int to; public BlockBag blockBag; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java index 71232a31c0..f20af641b3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/history/changeset/FaweStreamChangeSet.java @@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.history.change.MutableEntityChange; import com.fastasyncworldedit.core.history.change.MutableFullBlockChange; import com.fastasyncworldedit.core.history.change.MutableTileChange; +import com.fastasyncworldedit.core.history.change.BlockPositionChange; import com.fastasyncworldedit.core.internal.exception.FaweSmallEditUnsupportedException; import com.fastasyncworldedit.core.internal.io.FaweInputStream; import com.fastasyncworldedit.core.internal.io.FaweOutputStream; @@ -20,6 +21,7 @@ import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.block.BlockTypes; +import org.jetbrains.annotations.ApiStatus; import java.io.EOFException; import java.io.IOException; @@ -32,6 +34,7 @@ /** * FAWE stream ChangeSet offering support for extended-height worlds */ +@ApiStatus.Internal public abstract class FaweStreamChangeSet extends AbstractChangeSet { public static final int HEADER_SIZE = 9; @@ -68,19 +71,15 @@ private void init(boolean storeRedo, boolean smallLoc) { } } - public interface FaweStreamPositionDelegate { + interface FaweStreamPositionDelegate { void write(OutputStream out, int x, int y, int z) throws IOException; - int readX(FaweInputStream in) throws IOException; - - int readY(FaweInputStream in) throws IOException; - - int readZ(FaweInputStream in) throws IOException; + void read(FaweInputStream in, BlockPositionChange change) throws IOException; } - public interface FaweStreamIdDelegate { + interface FaweStreamIdDelegate { void writeChange(FaweOutputStream out, int from, int to) throws IOException; @@ -138,6 +137,7 @@ public void readCombined(FaweInputStream is, MutableFullBlockChange change) thro } if (mode == 1 || mode == 4) { // small posDel = new FaweStreamPositionDelegate() { + final byte[] buffer = new byte[4]; int lx; int ly; int lz; @@ -162,23 +162,14 @@ public void write(OutputStream out, int x, int y, int z) throws IOException { out.write(b4); } - final byte[] buffer = new byte[4]; - @Override - public int readX(FaweInputStream in) throws IOException { + public void read(final FaweInputStream in, final BlockPositionChange change) throws IOException { in.readFully(buffer); - return lx = lx + ((((buffer[1] & 0xFF) | ((MathMan.unpair16x(buffer[3])) << 8)) << 20) >> 20); + change.x = lx = lx + ((((buffer[1] & 0xFF) | ((MathMan.unpair16x(buffer[3])) << 8)) << 20) >> 20); + change.y = (ly = ly + buffer[0]) & 0xFF; + change.z = lz = lz + ((((buffer[2] & 0xFF) | ((MathMan.unpair16y(buffer[3])) << 8)) << 20) >> 20); } - @Override - public int readY(FaweInputStream in) { - return (ly = ly + buffer[0]) & 0xFF; - } - - @Override - public int readZ(FaweInputStream in) throws IOException { - return lz = lz + ((((buffer[2] & 0xFF) | ((MathMan.unpair16y(buffer[3])) << 8)) << 20) >> 20); - } }; } else { posDel = new FaweStreamPositionDelegate() { @@ -201,19 +192,11 @@ public void write(OutputStream stream, int x, int y, int z) throws IOException { } @Override - public int readX(FaweInputStream is) throws IOException { - is.readFully(buffer); - return lx = lx + ((buffer[0] & 0xFF) | (buffer[1] << 8)); - } - - @Override - public int readY(FaweInputStream is) throws IOException { - return ly = ly + ((buffer[4] & 0xFF) | (buffer[5]) << 8); - } - - @Override - public int readZ(FaweInputStream is) throws IOException { - return lz = lz + ((buffer[2] & 0xFF) | (buffer[3]) << 8); + public void read(final FaweInputStream in, final BlockPositionChange change) throws IOException { + in.readFully(buffer); + change.x = lx = lx + ((buffer[0] & 0xFF) | (buffer[1] << 8)); + change.z = lz = lz + ((buffer[2] & 0xFF) | (buffer[3]) << 8); + change.y = ly = ly + ((buffer[4] & 0xFF) | (buffer[5]) << 8); } }; } @@ -428,9 +411,9 @@ public Iterator getBlockIterator(final boolean dir) throws I public MutableBlockChange read() { try { - change.x = posDel.readX(is) + originX; - change.y = posDel.readY(is); - change.z = posDel.readZ(is) + originZ; + posDel.read(is, change); + change.x += originX; + change.z += originZ; idDel.readCombined(is, change, dir); return change; } catch (EOFException ignored) { @@ -545,9 +528,9 @@ public Iterator getFullBlockIterator(BlockBag blockBag, public MutableFullBlockChange read() { try { - change.x = posDel.readX(is) + originX; - change.y = posDel.readY(is); - change.z = posDel.readZ(is) + originZ; + posDel.read(is, change); + change.x += originX; + change.z += originZ; idDel.readCombined(is, change); return change; } catch (EOFException ignored) { @@ -765,11 +748,9 @@ public SimpleChangeSetSummary summarize(Region region, boolean shallow) { int amount = (Settings.settings().HISTORY.BUFFER_SIZE - HEADER_SIZE) / 9; MutableFullBlockChange change = new MutableFullBlockChange(null, 0, false); for (int i = 0; i < amount; i++) { - int x = posDel.readX(fis) + ox; - int y = posDel.readY(fis); - int z = posDel.readZ(fis) + ox; + posDel.read(fis, change); idDel.readCombined(fis, change); - summary.add(x, z, change.to); + summary.add(change.x + ox, change.z + oz, change.to); } } } catch (EOFException ignored) { From 472eb19312cde3c27c73e1a49a20edb6e0e08288 Mon Sep 17 00:00:00 2001 From: Hannes Greule Date: Sat, 16 Mar 2024 20:12:21 +0100 Subject: [PATCH 02/24] Allow repeated keys in RandomCollection (#2624) --- .../extent/transform/RandomTransform.java | 28 +++++++------- .../util/collection/FastRandomCollection.java | 24 ++++++------ .../util/collection/RandomCollection.java | 32 +++++----------- .../collection/SimpleRandomCollection.java | 38 +++++++++---------- .../function/pattern/RandomPattern.java | 36 ++++++++---------- 5 files changed, 67 insertions(+), 91 deletions(-) diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomTransform.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomTransform.java index 93ab1ac995..a839ec3237 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomTransform.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/transform/RandomTransform.java @@ -7,10 +7,10 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -20,10 +20,9 @@ public class RandomTransform extends SelectTransform { private final SimpleRandom random; - private final Map weights = new HashMap<>(); + private final List> weights; private transient RandomCollection collection; - private transient LinkedHashSet extents = new LinkedHashSet<>(); public RandomTransform() { this(new TrueRandom()); @@ -36,27 +35,27 @@ public RandomTransform() { */ public RandomTransform(SimpleRandom random) { this.random = random; + this.weights = new ArrayList<>(); } @Override public AbstractDelegateExtent getExtent(int x, int y, int z) { - return collection.next(x, y, z); + return collection.next(this.random, x, y, z); } @Override public AbstractDelegateExtent getExtent(int x, int z) { - return collection.next(x, 0, z); + return collection.next(this.random, x, 0, z); } @Override public ResettableExtent setExtent(Extent extent) { if (collection == null) { - collection = RandomCollection.of(weights, random); - extents = new LinkedHashSet<>(weights.keySet()); + collection = RandomCollection.of(weights); } super.setExtent(extent); - for (ResettableExtent current : extents) { - current.setExtent(extent); + for (RandomCollection.Weighted current : this.weights) { + current.value().setExtent(extent); } return this; } @@ -72,13 +71,12 @@ public ResettableExtent setExtent(Extent extent) { */ public void add(ResettableExtent extent, double chance) { checkNotNull(extent); - weights.put(extent, chance); - collection = RandomCollection.of(weights, random); - this.extents.add(extent); + weights.add(new RandomCollection.Weighted<>(extent, chance)); + collection = RandomCollection.of(weights); } public Set getExtents() { - return extents; + return this.weights.stream().map(RandomCollection.Weighted::value).collect(Collectors.toSet()); } public RandomCollection getCollection() { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FastRandomCollection.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FastRandomCollection.java index 61afe2dcd2..e332ad2311 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FastRandomCollection.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FastRandomCollection.java @@ -4,15 +4,14 @@ import com.fastasyncworldedit.core.util.MathMan; import java.util.ArrayList; -import java.util.Map; +import java.util.List; import java.util.Optional; -public class FastRandomCollection extends RandomCollection { +public final class FastRandomCollection implements RandomCollection { private final T[] values; - private FastRandomCollection(T[] values, SimpleRandom random) { - super(random); + private FastRandomCollection(T[] values) { this.values = values; } @@ -22,16 +21,15 @@ private FastRandomCollection(T[] values, SimpleRandom random) { * {@code Optional} in any case. * * @param weights the weight of the values. - * @param random the random generator to use for this collection. * @param the value type. * @return an {@link Optional} containing the new collection if it could be created, {@link * Optional#empty()} otherwise. * @see RandomCollection for API usage. */ - public static Optional> create(Map weights, SimpleRandom random) { + public static Optional> create(List> weights) { int max = 0; int[] counts = new int[weights.size()]; - Double[] weightDoubles = weights.values().toArray(new Double[0]); + double[] weightDoubles = weights.stream().mapToDouble(Weighted::weight).toArray(); for (int i = 0; i < weightDoubles.length; i++) { int weight = (int) (weightDoubles[i] * 100); counts[i] = weight; @@ -47,21 +45,21 @@ public static Optional> create(Map weights, S return Optional.empty(); } ArrayList parsed = new ArrayList<>(); - for (Map.Entry entry : weights.entrySet()) { - int num = (int) (100 * entry.getValue()); + for (Weighted entry : weights) { + int num = (int) (100 * entry.weight()); for (int j = 0; j < num / gcd; j++) { - parsed.add(entry.getKey()); + parsed.add(entry.value()); } } @SuppressWarnings("unchecked") T[] values = (T[]) parsed.toArray(); - FastRandomCollection fastRandomCollection = new FastRandomCollection<>(values, random); + FastRandomCollection fastRandomCollection = new FastRandomCollection<>(values); return Optional.of(fastRandomCollection); } @Override - public T next(int x, int y, int z) { - return values[getRandom().nextInt(x, y, z, values.length)]; + public T next(final SimpleRandom random, int x, int y, int z) { + return values[random.nextInt(x, y, z, values.length)]; } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java index 6214777e52..0988185587 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/RandomCollection.java @@ -2,49 +2,35 @@ import com.fastasyncworldedit.core.math.random.SimpleRandom; -import java.util.Map; +import java.util.List; import static com.google.common.base.Preconditions.checkNotNull; /** * A RandomCollection holds multiple values that can be accessed by using - * {@link RandomCollection#next(int, int, int)}. The returned value is + * {@link RandomCollection#next(SimpleRandom, int, int, int)}. The returned value is * determined by a given {@link SimpleRandom} implementation. * * @param the type of values the collection holds. */ -public abstract class RandomCollection { - - private SimpleRandom random; - - protected RandomCollection(SimpleRandom random) { - this.random = random; - } +public sealed interface RandomCollection permits FastRandomCollection, SimpleRandomCollection { /** * Return a new RandomCollection. The implementation may differ depending on the * given arguments but there is no need to differ. * * @param weights the weighted map. - * @param random the random number generator. * @param the type the collection holds. * @return a RandomCollection using the given weights and the RNG. */ - public static RandomCollection of(Map weights, SimpleRandom random) { - checkNotNull(random); - return FastRandomCollection.create(weights, random) - .orElseGet(() -> new SimpleRandomCollection<>(weights, random)); + static RandomCollection of(List> weights) { + return FastRandomCollection.create(weights) + .orElseGet(() -> new SimpleRandomCollection<>(weights)); } - public void setRandom(SimpleRandom random) { - checkNotNull(random); - this.random = random; - } + T next(SimpleRandom random, int x, int y, int z); - public SimpleRandom getRandom() { - return random; - } - - public abstract T next(int x, int y, int z); + record Weighted(T value, double weight) { + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java index dc21075598..c831bb8f1e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/SimpleRandomCollection.java @@ -2,41 +2,39 @@ import com.fastasyncworldedit.core.math.random.SimpleRandom; -import java.util.Map; +import java.util.List; import java.util.NavigableMap; import java.util.TreeMap; -public class SimpleRandomCollection extends RandomCollection { +public final class SimpleRandomCollection implements RandomCollection { - private final NavigableMap map = new TreeMap<>(); - private double total = 0; + private final NavigableMap map; + private final double total; /** * Create a {@link RandomCollection} from a weighted map and a RNG. - * It is recommended to use {@link RandomCollection#of(Map, SimpleRandom)} + * It is recommended to use {@link RandomCollection#of(List)} * instead of this constructor. * * @param weights the weighted map. - * @param random the random number generator. */ - public SimpleRandomCollection(Map weights, SimpleRandom random) { - super(random); - for (Map.Entry entry : weights.entrySet()) { - add(entry.getValue(), entry.getKey()); + public SimpleRandomCollection(List> weights) { + this.map = new TreeMap<>(); + double total = 0; + for (Weighted entry : weights) { + final double weight = entry.weight(); + if (weight <= 0) { + throw new IllegalArgumentException("Weights must be positive"); + } + total += weight; + this.map.put(total, entry.value()); } - } - - public void add(double weight, E result) { - if (weight <= 0) { - return; - } - total += weight; - map.put(total, result); + this.total = total; } @Override - public E next(int x, int y, int z) { - return map.ceilingEntry(getRandom().nextDouble(x, y, z) * this.total).getValue(); + public T next(final SimpleRandom random, int x, int y, int z) { + return map.ceilingEntry(random.nextDouble(x, y, z) * this.total).getValue(); } } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java index 1d2df7223f..380051ec20 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/RandomPattern.java @@ -27,10 +27,10 @@ import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.world.block.BaseBlock; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import static com.google.common.base.Preconditions.checkNotNull; @@ -39,11 +39,10 @@ */ public class RandomPattern extends AbstractPattern { - //FAWE start - SimpleRandom > Random, LHS

> List + //FAWE start - SimpleRandom > Random, RandomCollection private final SimpleRandom random; - private Map weights = new LinkedHashMap<>(); + private final List> weights; private RandomCollection collection; - private LinkedHashSet patterns = new LinkedHashSet<>(); //FAWE end //FAWE start @@ -53,6 +52,7 @@ public RandomPattern() { public RandomPattern(SimpleRandom random) { this.random = random; + this.weights = new ArrayList<>(); } /** @@ -63,9 +63,8 @@ public RandomPattern(SimpleRandom random) { */ public RandomPattern(SimpleRandom random, RandomPattern parent) { this.random = random; - this.weights = parent.weights; - this.collection = RandomCollection.of(weights, random); - this.patterns = parent.patterns; + this.weights = new ArrayList<>(parent.weights); + this.collection = RandomCollection.of(weights); } //FAWE end @@ -80,18 +79,15 @@ public RandomPattern(SimpleRandom random, RandomPattern parent) { */ public void add(Pattern pattern, double chance) { checkNotNull(pattern); - //FAWE start - Double, weights, patterns and collection - Double existingWeight = weights.get(pattern); - if (existingWeight != null) { - chance += existingWeight; - } - weights.put(pattern, chance); - collection = RandomCollection.of(weights, random); - this.patterns.add(pattern); + //FAWE start - Double, weights, repeating patterns, and collection + this.weights.add(new RandomCollection.Weighted<>(pattern, chance)); + this.collection = RandomCollection.of(weights); } public Set getPatterns() { - return patterns; + return this.weights.stream() + .map(RandomCollection.Weighted::value) + .collect(Collectors.toSet()); } public RandomCollection getCollection() { @@ -100,12 +96,12 @@ public RandomCollection getCollection() { @Override public BaseBlock applyBlock(BlockVector3 position) { - return collection.next(position.getBlockX(), position.getBlockY(), position.getBlockZ()).applyBlock(position); + return collection.next(this.random, position.getBlockX(), position.getBlockY(), position.getBlockZ()).applyBlock(position); } @Override public boolean apply(Extent extent, BlockVector3 get, BlockVector3 set) throws WorldEditException { - return collection.next(get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set); + return collection.next(this.random, get.getBlockX(), get.getBlockY(), get.getBlockZ()).apply(extent, get, set); } //FAWE end From fb12ff20b4a35224ddf8742d1f2f54217ccded1f Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 16 Mar 2024 20:14:33 +0100 Subject: [PATCH 03/24] refactor: apply final/abstract to various fawe extent classes (#2615) * refactor: apply final/abstract to various fawe extent classes * Remove forremoval as targets v3 --- .../core/extent/BlockTranslateExtent.java | 2 +- .../core/extent/DisallowedBlocksExtent.java | 2 +- .../core/extent/ExtentHeightCacher.java | 2 +- .../core/extent/HeightBoundExtent.java | 2 +- .../core/extent/HistoryExtent.java | 2 +- .../core/extent/LimitExtent.java | 2 +- .../core/extent/MemoryCheckingExtent.java | 2 +- .../core/extent/MultiRegionExtent.java | 2 +- .../core/extent/NullExtent.java | 2 +- .../core/extent/PassthroughExtent.java | 2 +- .../core/extent/PositionTransformExtent.java | 2 +- .../core/extent/ProcessedWEExtent.java | 2 +- .../core/extent/ResettableExtent.java | 2 +- .../core/extent/SingleRegionExtent.java | 2 +- .../core/extent/SlowExtent.java | 2 +- .../core/extent/SourceMaskExtent.java | 2 +- .../core/extent/StripNBTExtent.java | 2 +- .../core/extent/SupplyingExtent.java | 2 +- .../core/extent/TemporalExtent.java | 2 +- .../core/extent/TransformExtent.java | 116 ------------------ .../implementation/ParallelQueueExtent.java | 2 +- .../SingleThreadQueueExtent.java | 2 +- 22 files changed, 21 insertions(+), 137 deletions(-) delete mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java index d7b8a986eb..f04412e708 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/BlockTranslateExtent.java @@ -9,7 +9,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -public class BlockTranslateExtent extends AbstractDelegateExtent { +public final class BlockTranslateExtent extends AbstractDelegateExtent { private final int dx; private final int dy; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java index f1c523ce33..68307ffe1e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/DisallowedBlocksExtent.java @@ -29,7 +29,7 @@ import java.util.Set; import java.util.stream.Collectors; -public class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor { +public final class DisallowedBlocksExtent extends AbstractDelegateExtent implements IBatchProcessor { private static final BlockState RESERVED = BlockTypes.__RESERVED__.getDefaultState(); private final Set> remaps; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ExtentHeightCacher.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ExtentHeightCacher.java index af008d1c95..36011e594c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ExtentHeightCacher.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ExtentHeightCacher.java @@ -4,7 +4,7 @@ import java.util.Arrays; -public class ExtentHeightCacher extends PassthroughExtent { +public final class ExtentHeightCacher extends PassthroughExtent { private transient int cacheBotX = Integer.MIN_VALUE; private transient int cacheBotZ = Integer.MIN_VALUE; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java index c22d9e6bed..817d2c3bfa 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HeightBoundExtent.java @@ -12,7 +12,7 @@ import java.util.Collection; import java.util.Collections; -public class HeightBoundExtent extends FaweRegionExtent { +public final class HeightBoundExtent extends FaweRegionExtent { private final int min; private final int max; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java index 2fc5133c65..9ac0180433 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/HistoryExtent.java @@ -25,7 +25,7 @@ /** * Stores changes to a {@link ChangeSet}. */ -public class HistoryExtent extends AbstractDelegateExtent { +public final class HistoryExtent extends AbstractDelegateExtent { private final MutableBlockVector3 mutable = new MutableBlockVector3(); private AbstractChangeSet changeSet; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java index 24d440c575..3429a1ba58 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/LimitExtent.java @@ -37,7 +37,7 @@ import java.util.UUID; import java.util.function.Consumer; -public class LimitExtent extends AbstractDelegateExtent { +public final class LimitExtent extends AbstractDelegateExtent { private final FaweLimit limit; private final boolean[] faweExceptionReasonsUsed = new boolean[FaweException.Type.values().length]; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MemoryCheckingExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MemoryCheckingExtent.java index e2d215c565..d33291d1c2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MemoryCheckingExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MemoryCheckingExtent.java @@ -8,7 +8,7 @@ import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extent.Extent; -public class MemoryCheckingExtent extends PassthroughExtent { +public final class MemoryCheckingExtent extends PassthroughExtent { private final Actor actor; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MultiRegionExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MultiRegionExtent.java index c13c5965b8..9e02dba945 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MultiRegionExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/MultiRegionExtent.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.concurrent.Future; -public class MultiRegionExtent extends FaweRegionExtent { +public final class MultiRegionExtent extends FaweRegionExtent { @Nullable private final RegionIntersection intersection; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/NullExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/NullExtent.java index 4f0ad4960f..d4c7dc6aaf 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/NullExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/NullExtent.java @@ -40,7 +40,7 @@ import java.util.concurrent.Future; //todo This should be removed in favor of com.sk89q.worldedit.extent.NullExtent -public class NullExtent extends FaweRegionExtent implements IBatchProcessor { +public final class NullExtent extends FaweRegionExtent implements IBatchProcessor { private final FaweException reason; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PassthroughExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PassthroughExtent.java index 5ac2f9d7be..23f0fa6031 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PassthroughExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PassthroughExtent.java @@ -26,7 +26,7 @@ import java.util.List; import java.util.Set; -public class PassthroughExtent extends AbstractDelegateExtent { +public abstract class PassthroughExtent extends AbstractDelegateExtent { /** * Create a new instance. diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java index 6d74acc166..99ef6d1373 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/PositionTransformExtent.java @@ -11,7 +11,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockStateHolder; -public class PositionTransformExtent extends ResettableExtent { +public final class PositionTransformExtent extends ResettableExtent { private transient MutableBlockVector3 mutable = new MutableBlockVector3(); private transient BlockVector3 min; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java index 5abe903480..e9e90e0f87 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ProcessedWEExtent.java @@ -18,7 +18,7 @@ import java.util.UUID; -public class ProcessedWEExtent extends AbstractDelegateExtent { +public final class ProcessedWEExtent extends AbstractDelegateExtent { private final FaweLimit limit; private final Extent extent; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ResettableExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ResettableExtent.java index 0e37984156..469a27c03c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ResettableExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/ResettableExtent.java @@ -14,7 +14,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class ResettableExtent extends AbstractDelegateExtent implements Serializable { +public abstract class ResettableExtent extends AbstractDelegateExtent implements Serializable { public ResettableExtent(Extent parent) { super(parent); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SingleRegionExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SingleRegionExtent.java index 1caea9dbce..249b9e84cb 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SingleRegionExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SingleRegionExtent.java @@ -11,7 +11,7 @@ import java.util.Collections; import java.util.concurrent.Future; -public class SingleRegionExtent extends FaweRegionExtent { +public final class SingleRegionExtent extends FaweRegionExtent { private final Region region; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SlowExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SlowExtent.java index 6aa07b1169..657322ce3b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SlowExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SlowExtent.java @@ -6,7 +6,7 @@ import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.world.block.BlockStateHolder; -public class SlowExtent extends AbstractDelegateExtent { +public final class SlowExtent extends AbstractDelegateExtent { private final long THRESHOLD = 50 * 1000000; // 1 tick private final long nanos; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java index 6c22303722..389f5b69f7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SourceMaskExtent.java @@ -9,7 +9,7 @@ import static com.google.common.base.Preconditions.checkNotNull; -public class SourceMaskExtent extends TemporalExtent { +public final class SourceMaskExtent extends TemporalExtent { private Mask mask; private final MutableBlockVector3 mutable = new MutableBlockVector3(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java index ded96d5aa8..4d1b287c5f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/StripNBTExtent.java @@ -34,7 +34,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -public class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor { +public final class StripNBTExtent extends AbstractDelegateExtent implements IBatchProcessor { private final Set strip; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SupplyingExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SupplyingExtent.java index 640243d5d4..96952de4c4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SupplyingExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/SupplyingExtent.java @@ -7,7 +7,7 @@ /** * An extent that delegates actions to another extent that may change at any time. */ -public class SupplyingExtent extends PassthroughExtent { +public final class SupplyingExtent extends PassthroughExtent { private final Supplier extentSupplier; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java index ac36bef5ae..030fcc290e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TemporalExtent.java @@ -8,7 +8,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder; import com.sk89q.worldedit.world.block.BlockTypes; -public class TemporalExtent extends PassthroughExtent { +public abstract class TemporalExtent extends PassthroughExtent { private int x; private int y; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java deleted file mode 100644 index 91b99b0259..0000000000 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/TransformExtent.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.fastasyncworldedit.core.extent; - -import com.fastasyncworldedit.core.math.MutableBlockVector3; -import com.fastasyncworldedit.core.math.MutableVector3; -import com.sk89q.worldedit.WorldEditException; -import com.sk89q.worldedit.extent.Extent; -import com.sk89q.worldedit.extent.transform.BlockTransformExtent; -import com.sk89q.worldedit.math.BlockVector3; -import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.world.biome.BiomeType; -import com.sk89q.worldedit.world.block.BaseBlock; -import com.sk89q.worldedit.world.block.BlockState; -import com.sk89q.worldedit.world.block.BlockStateHolder; - -public class TransformExtent extends BlockTransformExtent { - - private final MutableVector3 mutable1 = new MutableVector3(); - private final MutableBlockVector3 mutable2 = new MutableBlockVector3(); - private BlockVector3 min; - - public TransformExtent(Extent parent) { - super(parent); - } - - @Override - public ResettableExtent setExtent(Extent extent) { - min = null; - return super.setExtent(extent); - } - - @Override - public BlockVector3 getMinimumPoint() { - BlockVector3 pos1 = getPos(super.getMinimumPoint()); - BlockVector3 pos2 = getPos(super.getMaximumPoint()); - return pos1.getMinimum(pos2); - } - - @Override - public BlockVector3 getMaximumPoint() { - BlockVector3 pos1 = getPos(super.getMinimumPoint()); - BlockVector3 pos2 = getPos(super.getMaximumPoint()); - return pos1.getMaximum(pos2); - } - - @Override - public void setOrigin(BlockVector3 pos) { - this.min = pos; - } - - public BlockVector3 getPos(BlockVector3 pos) { - if (min == null) { - min = pos; - } - mutable1.mutX(pos.getX() - min.getX()); - mutable1.mutY(pos.getY() - min.getY()); - mutable1.mutZ(pos.getZ() - min.getZ()); - Vector3 tmp = getTransform().apply(mutable1); - mutable2.mutX(tmp.getX() + min.getX()); - mutable2.mutY(tmp.getY() + min.getY()); - mutable2.mutZ(tmp.getZ() + min.getZ()); - return mutable2; - } - - public BlockVector3 getPos(int x, int y, int z) { - if (min == null) { - min = BlockVector3.at(x, y, z); - } - mutable1.mutX(x - min.getX()); - mutable1.mutY(y - min.getY()); - mutable1.mutZ(z - min.getZ()); - Vector3 tmp = getTransform().apply(mutable1); - mutable2.mutX(tmp.getX() + min.getX()); - mutable2.mutY(tmp.getY() + min.getY()); - mutable2.mutZ(tmp.getZ() + min.getZ()); - return tmp.toBlockPoint(); - } - - @Override - public BlockState getBlock(int x, int y, int z) { - BlockVector3 p = getPos(x, y, z); - return transform(super.getBlock(p.getX(), p.getY(), p.getZ())); - } - - @Override - public BaseBlock getFullBlock(BlockVector3 position) { - return transform(super.getFullBlock(getPos(position))); - } - - @Override - public BiomeType getBiomeType(int x, int y, int z) { - BlockVector3 p = getPos(x, y, z); - return super.getBiomeType(p.getX(), y, p.getZ()); - } - - @Override - @SuppressWarnings("unchecked") - public > boolean setBlock(int x, int y, int z, T block) - throws WorldEditException { - return super.setBlock(getPos(x, y, z), transformInverse(block)); - } - - - @Override - @SuppressWarnings("unchecked") - public > boolean setBlock(BlockVector3 location, B block) - throws WorldEditException { - return super.setBlock(getPos(location), transformInverse(block)); - } - - @Override - public boolean setBiome(int x, int y, int z, BiomeType biome) { - BlockVector3 p = getPos(x, y, z); - return super.setBiome(p.getX(), p.getY(), p.getZ(), biome); - } - -} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java index 52e6cf2c68..3ec751aee2 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/ParallelQueueExtent.java @@ -43,7 +43,7 @@ import java.util.concurrent.ForkJoinTask; import java.util.stream.IntStream; -public class ParallelQueueExtent extends PassthroughExtent { +public final class ParallelQueueExtent extends PassthroughExtent { private static final Logger LOGGER = LogManagerCompat.getLogger(); private static final ThreadLocal extents = new ThreadLocal<>(); 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 6e06ce3481..a27c3dd1a0 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 @@ -43,7 +43,7 @@ * This queue is reusable {@link #init(Extent, IChunkCache, IChunkCache)} */ @SuppressWarnings({"unchecked", "rawtypes"}) -public class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent { +public final class SingleThreadQueueExtent extends ExtentBatchProcessorHolder implements IQueueExtent { private static final Logger LOGGER = LogManagerCompat.getLogger(); From 0faaaa55ee7e6148c179ff138338ec8202ab0a2e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Tue, 7 Mar 2023 14:36:58 +0100 Subject: [PATCH 04/24] Initial experimental work on Folia support --- .../fawe/v1_20_R1/PaperweightFaweAdapter.java | 8 +- .../PaperweightFaweWorldNativeAccess.java | 3 +- .../v1_20_R1/PaperweightPlatformAdapter.java | 12 +- .../fastasyncworldedit/bukkit/FaweBukkit.java | 26 ++- .../bukkit/listener/ChunkListener.java | 4 + .../bukkit/util/BukkitTaskManager.java | 26 +++ .../bukkit/util/FoliaTaskManager.java | 206 ++++++++++++++++++ .../sk89q/worldedit/bukkit/BukkitPlayer.java | 9 +- .../com/fastasyncworldedit/core/Fawe.java | 15 +- .../com/fastasyncworldedit/core/IFawe.java | 2 + .../queue/implementation/QueueHandler.java | 8 +- .../core/util/FoliaSupport.java | 38 ++++ .../core/util/TaskManager.java | 26 +++ .../core/wrappers/AsyncPlayer.java | 4 +- 14 files changed, 367 insertions(+), 20 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java index e13ff700f6..04d116d974 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java @@ -2,6 +2,7 @@ import com.fastasyncworldedit.bukkit.adapter.FaweAdapter; import com.fastasyncworldedit.bukkit.adapter.NMSRelighterFactory; +import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.entity.LazyBaseEntity; import com.fastasyncworldedit.core.extent.processor.lighting.RelighterFactory; @@ -240,7 +241,12 @@ public BlockState getBlock(Location location) { int y = location.getBlockY(); int z = location.getBlockZ(); final ServerLevel handle = getServerLevel(location.getWorld()); - LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); + LevelChunk chunk; + if (Fawe.isTickThread()) { + chunk = handle.getChunk(x >> 4, z >> 4); + } else { + chunk = TaskManager.taskManager().syncAt(() -> handle.getChunk(x >> 4, z >> 4), BukkitAdapter.adapt(location)); + } final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); BlockState state = adapt(blockData); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java index e1230b20e4..186415f9f2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java @@ -59,7 +59,8 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd this.level = level; // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - this.lastTick = new AtomicInteger(MinecraftServer.currentTick); + // TODO + this.lastTick = new AtomicInteger(0); } private Level getLevel() { diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 8083e3fdeb..891a41c4b6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -11,10 +11,14 @@ import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.biome.BiomeType; import com.sk89q.worldedit.world.biome.BiomeTypes; import com.sk89q.worldedit.world.block.BlockState; @@ -383,13 +387,19 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); + }, toLocation(nmsWorld, coordIntPair)); } private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { return serverLevel.getChunkSource().chunkMap.getPlayers(coordIntPair, false); } + public static Location toLocation(ServerLevel serverLevel, ChunkPos chunkPos) { + final World adapt = BukkitAdapter.adapt(serverLevel.getWorld()); + final Vector3 pos = Vector3.at(chunkPos.getMinBlockX(), 0, chunkPos.getMinBlockZ()); + return new Location(adapt, pos); + } + /* NMS conversion */ diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index 5e60a704ce..7a8604fcbb 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -11,6 +11,8 @@ import com.fastasyncworldedit.bukkit.regions.TownyFeature; import com.fastasyncworldedit.bukkit.regions.WorldGuardFeature; import com.fastasyncworldedit.bukkit.util.BukkitTaskManager; +import com.fastasyncworldedit.bukkit.util.FoliaTaskManager; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.bukkit.util.ItemUtil; import com.fastasyncworldedit.bukkit.util.MinecraftVersion; import com.fastasyncworldedit.bukkit.util.image.BukkitImageViewer; @@ -63,6 +65,7 @@ public class FaweBukkit implements IFawe, Listener { private ItemUtil itemUtil; private Preloader preloader; private volatile boolean keepUnloaded; + private static final Thread startingThread = Thread.currentThread(); public FaweBukkit(Plugin plugin) { this.plugin = plugin; @@ -74,7 +77,7 @@ public FaweBukkit(Plugin plugin) { } catch (Throwable e) { LOGGER.error("Brush Listener Failed", e); } - if (PaperLib.isPaper() && Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) { + if (!FoliaSupport.isFolia() && PaperLib.isPaper() && Settings.settings().EXPERIMENTAL.DYNAMIC_CHUNK_RENDERING > 1) { new RenderListener(plugin); } } catch (final Throwable e) { @@ -89,20 +92,22 @@ public FaweBukkit(Plugin plugin) { platformAdapter = new NMSAdapter(); //PlotSquared support is limited to Spigot/Paper as of 02/20/2020 - TaskManager.taskManager().later(this::setupPlotSquared, 0); + // TODO plotsquared support + // TaskManager.taskManager().later(this::setupPlotSquared, 0); + // TODO moved out of task below?? + Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); // Registered delayed Event Listeners - TaskManager.taskManager().task(() -> { + /*TaskManager.taskManager().task(() -> { // Fix for ProtocolSupport Settings.settings().PROTOCOL_SUPPORT_FIX = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport"); // This class - Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); // The tick limiter new ChunkListener9(); - }); + });*/ // Warn if small-edits are enabled with extended world heights if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) { @@ -192,6 +197,9 @@ public String getDebugInfo() { */ @Override public TaskManager getTaskManager() { + if (FoliaSupport.isFolia()) { + return new FoliaTaskManager(); + } return new BukkitTaskManager(plugin); } @@ -312,6 +320,14 @@ public FAWEPlatformAdapterImpl getPlatformAdapter() { return platformAdapter; } + @Override + public boolean isTickThread() { + if (FoliaSupport.isFolia()) { + return FoliaSupport.isTickThread(); + } + return Thread.currentThread() == startingThread; + } + private void setupPlotSquared() { Plugin plotSquared = this.plugin.getServer().getPluginManager().getPlugin("PlotSquared"); if (plotSquared == null) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java index 7b95990843..43d935c33e 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java @@ -1,6 +1,7 @@ package com.fastasyncworldedit.bukkit.listener; import com.fastasyncworldedit.bukkit.FaweBukkit; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.util.FaweTimer; @@ -59,6 +60,9 @@ public abstract class ChunkListener implements Listener { Settings.settings().TICK_LIMITER.FALLING, Settings.settings().TICK_LIMITER.ITEMS}; public ChunkListener() { + if (FoliaSupport.isFolia()) { + return; + } if (Settings.settings().TICK_LIMITER.ENABLED) { PluginManager plm = Bukkit.getPluginManager(); Plugin plugin = Fawe.platform().getPlugin(); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index 11b8565a67..a79cd5d2e6 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -1,10 +1,14 @@ package com.fastasyncworldedit.bukkit.util; import com.fastasyncworldedit.core.util.TaskManager; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.Location; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.util.function.Supplier; public class BukkitTaskManager extends TaskManager { @@ -34,11 +38,21 @@ public void task(@Nonnull final Runnable runnable) { this.plugin.getServer().getScheduler().runTask(this.plugin, runnable).getTaskId(); } + @Override + public void task(@NotNull final Runnable runnable, @NotNull final Location context) { + + } + @Override public void later(@Nonnull final Runnable runnable, final int delay) { this.plugin.getServer().getScheduler().runTaskLater(this.plugin, runnable, delay).getTaskId(); } + @Override + public void later(@NotNull final Runnable runnable, final Location location, final int delay) { + + } + @Override public void laterAsync(@Nonnull final Runnable runnable, final int delay) { this.plugin.getServer().getScheduler().runTaskLaterAsynchronously(this.plugin, runnable, delay); @@ -51,4 +65,16 @@ public void cancel(final int task) { } } + // TODO + + @Override + public T syncAt(final Supplier supplier, final Location context) { + return sync(supplier); + } + + @Override + public T syncWith(final Supplier supplier, final Player context) { + return sync(supplier); + } + } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java new file mode 100644 index 0000000000..f35a51bf5b --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -0,0 +1,206 @@ +package com.fastasyncworldedit.bukkit.util; + +import com.fastasyncworldedit.core.util.TaskManager; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.entity.Player; +import com.sk89q.worldedit.util.Location; +import org.bukkit.Bukkit; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.lang.reflect.Method; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.FutureTask; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; + +import static java.lang.invoke.MethodHandles.dropReturn; +import static java.lang.invoke.MethodHandles.explicitCastArguments; +import static java.lang.invoke.MethodHandles.filterArguments; +import static java.lang.invoke.MethodHandles.insertArguments; +import static java.lang.invoke.MethodType.methodType; + +public class FoliaTaskManager extends TaskManager { + + private final ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor(); + private final AtomicInteger idCounter = new AtomicInteger(); + + @Override + public int repeat(@NotNull final Runnable runnable, final int interval) { + return fail(); + } + + @Override + public int repeatAsync(@NotNull final Runnable runnable, final int interval) { + backgroundExecutor.scheduleAtFixedRate(runnable, 0, ticksToMs(interval), TimeUnit.MILLISECONDS); + return idCounter.getAndIncrement(); + } + + @Override + public void async(@NotNull final Runnable runnable) { + backgroundExecutor.submit(runnable); + } + + @Override + public void task(@NotNull final Runnable runnable) { + fail(); + } + + @Override + public void task(@NotNull final Runnable runnable, @NotNull final Location context) { + SchedulerAdapter.executeForLocation(context, runnable); + } + + @Override + public void later(@NotNull final Runnable runnable, final int delay) { + fail(); + } + + @Override + public void later(@NotNull final Runnable runnable, final Location location, final int delay) { + fail("Not implemented"); + } + + @Override + public void laterAsync(@NotNull final Runnable runnable, final int delay) { + backgroundExecutor.schedule(runnable, ticksToMs(delay), TimeUnit.MILLISECONDS); + } + + @Override + public void cancel(final int task) { + fail("Not implemented"); + } + + @Override + public T syncAt(final Supplier supplier, final Location context) { + FutureTask task = new FutureTask<>(supplier::get); + SchedulerAdapter.executeForLocation(context, task); + try { + return task.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + @Override + public T syncWith(final Supplier supplier, final Player context) { + FutureTask task = new FutureTask<>(supplier::get); + SchedulerAdapter.executeForEntity(context, task); + try { + return task.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + private int ticksToMs(int ticks) { + // 1 tick = 50ms + return ticks * 50; + } + + private T fail() { + return fail("No main thread present"); + } + + private T fail(String message) { + throw new UnsupportedOperationException(message); + } + + private static class SchedulerAdapter { + + private static final MethodHandle EXECUTE_FOR_LOCATION; + private static final MethodHandle EXECUTE_FOR_PLAYER; + + private static final MethodType LOCATION_EXECUTE_TYPE = methodType( + void.class, + Plugin.class, + org.bukkit.Location.class, + Runnable.class + ); + + private static final MethodType ENTITY_EXECUTE_TYPE = methodType( + boolean.class, + Plugin.class, + Runnable.class, + Runnable.class, + long.class + ); + + static { + final Plugin pluginInstance = WorldEditPlugin.getInstance(); + final MethodHandles.Lookup lookup = MethodHandles.lookup(); + + MethodHandle executeForLocation; + + MethodHandle executeForPlayer; + try { + Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.RegionisedScheduler"); + final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); + executeForLocation = lookup.findVirtual( + regionisedSchedulerClass, + "execute", + LOCATION_EXECUTE_TYPE + ); + executeForLocation = executeForLocation.bindTo(method.invoke(null)); + executeForLocation = executeForLocation.bindTo(pluginInstance); + + Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + executeForPlayer = lookup.findVirtual( + entitySchedulerClass, + "execute", + ENTITY_EXECUTE_TYPE + ); + // (ES, P, R, R, L)Z (ES, R, R, L)Z + executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); + // (ES, R1, R2, L)Z -> (ES, R1)Z + executeForPlayer = insertArguments(executeForPlayer, 2, null, 0); + // (ES, R1)Z -> (ES, R1)V + executeForPlayer = dropReturn(executeForPlayer); + MethodHandle getScheduler = lookup.findVirtual( + org.bukkit.entity.Entity.class, + "getScheduler", + methodType(entitySchedulerClass) + ); + // (ES, R1)V -> (E, R1)V + executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); + MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); + // (ES, R1)V -> (P, R1)V + executeForPlayer = explicitCastArguments(executeForPlayer, finalType); + } catch (Throwable throwable) { + throw new AssertionError(throwable); + } + EXECUTE_FOR_LOCATION = executeForLocation; + EXECUTE_FOR_PLAYER = executeForPlayer; + } + + static void executeForLocation(Location location, Runnable task) { + try { + EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + static void executeForEntity(Player player, Runnable task) { + // TODO task might not be run if player retires + try { + EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); + } catch (Error | RuntimeException e) { + throw e; + } catch (Throwable other) { + throw new RuntimeException(other); + } + } + + } + +} diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 9c5196e917..286420aa04 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -161,7 +161,7 @@ public String getDisplayName() { public void giveItem(BaseItemStack itemStack) { final PlayerInventory inv = player.getInventory(); ItemStack newItem = BukkitAdapter.adapt(itemStack); - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncWith(() -> { if (itemStack.getType().getId().equalsIgnoreCase(WorldEdit.getInstance().getConfiguration().wandItem)) { inv.remove(newItem); } @@ -183,7 +183,7 @@ public void giveItem(BaseItemStack itemStack) { } player.updateInventory(); return null; - }); + }, this); } //FAWE end @@ -240,14 +240,15 @@ public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { } org.bukkit.World finalWorld = world; //FAWE end - return TaskManager.taskManager().sync(() -> player.teleport(new Location( + // TODO async teleport? + return TaskManager.taskManager().syncWith(() -> player.teleport(new Location( finalWorld, pos.getX(), pos.getY(), pos.getZ(), yaw, pitch - ))); + )), this); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index ff2f69486a..230e12013c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -6,6 +6,7 @@ import com.fastasyncworldedit.core.util.CachedTextureUtil; import com.fastasyncworldedit.core.util.CleanTextureUtil; import com.fastasyncworldedit.core.util.FaweTimer; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MemUtil; import com.fastasyncworldedit.core.util.RandomTextureUtil; @@ -129,14 +130,17 @@ private Fawe(final IFawe implementation) { this.timer = new FaweTimer(); // Delayed worldedit setup - TaskManager.taskManager().later(() -> { + // TODO support again + /*TaskManager.taskManager().later(() -> { try { WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers()); } catch (Throwable ignored) { } - }, 0); + }, 0);*/ - TaskManager.taskManager().repeat(timer, 1); + if (!FoliaSupport.isFolia()) { + TaskManager.taskManager().repeat(timer, 1); + } clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor( 1, @@ -206,10 +210,15 @@ public static void setupInjector() { } } + @Deprecated public static boolean isMainThread() { return instance == null || instance.thread == Thread.currentThread(); } + public static boolean isTickThread() { + return instance == null || instance.implementation.isTickThread(); + } + /** * Non-api. Handles an input FAWE exception if not already handled, given the input boolean array. * Looks at the {@link FaweException.Type} and decides what to do (rethrows if we want to attempt to show the error to the diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/IFawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/IFawe.java index 5c8a80c02f..e467ba6e24 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/IFawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/IFawe.java @@ -49,4 +49,6 @@ default boolean isChunksStretched() { FAWEPlatformAdapterImpl getPlatformAdapter(); + boolean isTickThread(); + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java index 7bdbf46455..0074cecdf0 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java @@ -17,6 +17,7 @@ import com.fastasyncworldedit.core.util.task.FaweForkJoinWorkerThreadFactory; import com.fastasyncworldedit.core.wrappers.WorldWrapper; import com.google.common.util.concurrent.Futures; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import java.lang.ref.WeakReference; @@ -90,13 +91,14 @@ public abstract class QueueHandler implements Trimable, Runnable { private long allocate = 50; protected QueueHandler() { - TaskManager.taskManager().repeat(this, 1); + // TODO make main thread independent + // TaskManager.taskManager().repeat(this, 1); } @Override public void run() { - if (!Fawe.isMainThread()) { - throw new IllegalStateException("Not main thread"); + if (!Fawe.isTickThread()) { + throw new IllegalStateException("Not ticking thread"); } if (!syncTasks.isEmpty()) { long currentAllocate = getAllocate(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java new file mode 100644 index 0000000000..f8458dc197 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java @@ -0,0 +1,38 @@ +package com.fastasyncworldedit.core.util; + +public final class FoliaSupport { + private FoliaSupport() { + + } + + private static final boolean IS_FOLIA; + private static final Class TICK_THREAD_CLASS; + static { + boolean isFolia = false; + try { + // Assume API is present + Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + isFolia = true; + } catch (Exception unused) { + + } + IS_FOLIA = isFolia; + Class tickThreadClass = String.class; // thread will never be instance of String + if (IS_FOLIA) { + try { + tickThreadClass = Class.forName("io.papermc.paper.util.TickThread"); + } catch (ClassNotFoundException e) { + throw new AssertionError(e); + } + } + TICK_THREAD_CLASS = tickThreadClass; + } + + public static boolean isFolia() { + return IS_FOLIA; + } + + public static boolean isTickThread() { + return TICK_THREAD_CLASS.isInstance(Thread.currentThread()); + } +} diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java index 176e02673b..69a16b4370 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java @@ -4,7 +4,10 @@ import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.util.task.RunnableVal; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.internal.util.LogManagerCompat; +import com.sk89q.worldedit.util.Location; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; @@ -52,6 +55,7 @@ public static TaskManager taskManager() { * @param runnable the task to run * @param interval in ticks */ + @Deprecated public abstract int repeat(@Nonnull final Runnable runnable, final int interval); /** @@ -75,7 +79,14 @@ public static TaskManager taskManager() { * * @param runnable the task to run */ + @Deprecated public abstract void task(@Nonnull final Runnable runnable); + /** + * Run a task on the main thread. + * + * @param runnable the task to run + */ + public abstract void task(@Nonnull final Runnable runnable, @Nonnull Location contextLocation); /** * Get the public ForkJoinPool. @@ -159,6 +170,7 @@ public void parallel(Collection runnables, @Nullable Integer numThread /** * Disable async catching for a specific task. */ + @Deprecated public void runUnsafe(Runnable run) { QueueHandler queue = Fawe.instance().getQueueHandler(); queue.startUnsafe(Fawe.isMainThread()); @@ -191,6 +203,7 @@ public void taskNow(@Nonnull final Runnable runnable, boolean async) { * * @param runnable the task to run */ + @Deprecated public void taskNowMain(@Nonnull final Runnable runnable) { if (Fawe.isMainThread()) { runnable.run(); @@ -215,6 +228,7 @@ public void taskNowAsync(@Nonnull final Runnable runnable) { * @param runnable the task to run. * @param async whether the task should run on the main thread */ + @Deprecated public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) { if (async) { async(runnable); @@ -230,7 +244,9 @@ public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) { * @param runnable the task to run * @param delay in ticks */ + @Deprecated public abstract void later(@Nonnull final Runnable runnable, final int delay); + public abstract void later(@Nonnull final Runnable runnable, Location location, final int delay); /** * Run a task later asynchronously. @@ -255,6 +271,7 @@ public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) { * @param task the task to run on each object * @param whenDone when the object task completes */ + @Deprecated public void objectTask(Collection objects, final RunnableVal task, final Runnable whenDone) { final Iterator iterator = objects.iterator(); task(new Runnable() { @@ -307,6 +324,7 @@ public void notify(AtomicBoolean running) { } } + @Deprecated public void taskWhenFree(@Nonnull Runnable run) { if (Fawe.isMainThread()) { run.run(); @@ -320,6 +338,7 @@ public void taskWhenFree(@Nonnull Runnable run) { * - Useful if you need to access something from the Bukkit API from another thread
* - Usually wait time is around 25ms
*/ + @Deprecated public T syncWhenFree(@Nonnull final RunnableVal function) { if (Fawe.isMainThread()) { function.run(); @@ -337,6 +356,7 @@ public T syncWhenFree(@Nonnull final RunnableVal function) { * - Useful if you need to access something from the Bukkit API from another thread
* - Usually wait time is around 25ms
*/ + @Deprecated public T syncWhenFree(@Nonnull final Supplier supplier) { if (Fawe.isMainThread()) { return supplier.get(); @@ -353,6 +373,7 @@ public T syncWhenFree(@Nonnull final Supplier supplier) { * - Useful if you need to access something from the Bukkit API from another thread
* - Usually wait time is around 25ms */ + @Deprecated public T sync(@Nonnull final RunnableVal function) { return sync((Supplier) function); } @@ -362,6 +383,7 @@ public T sync(@Nonnull final RunnableVal function) { * - Useful if you need to access something from the Bukkit API from another thread
* - Usually wait time is around 25ms
*/ + @Deprecated public T sync(final Supplier function) { if (Fawe.isMainThread()) { return function.get(); @@ -373,4 +395,8 @@ public T sync(final Supplier function) { } } + public abstract T syncAt(Supplier supplier, Location context); + + public abstract T syncWith(Supplier supplier, Player context); + } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java index 7000706113..5baff82364 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java @@ -58,12 +58,12 @@ public void run(Boolean value) { @Override public void findFreePosition() { - TaskManager.taskManager().sync(new RunnableVal() { + TaskManager.taskManager().syncWith(new RunnableVal() { @Override public void run(Boolean value) { getBasePlayer().findFreePosition(); } - }); + }, this); } @Override From 00b13399d178f82ad573207c405523205c23b530 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Wed, 8 Mar 2023 20:04:29 +0100 Subject: [PATCH 05/24] Improve block tracing performance --- .../fawe/v1_20_R1/PaperweightFaweAdapter.java | 1 + .../bukkit/util/FoliaTaskManager.java | 1 - .../core/wrappers/AsyncPlayer.java | 16 ++++++---------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java index 04d116d974..ffe067ec9a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java @@ -243,6 +243,7 @@ public BlockState getBlock(Location location) { final ServerLevel handle = getServerLevel(location.getWorld()); LevelChunk chunk; if (Fawe.isTickThread()) { + // TODO check if is owned by this thread, else synchronize chunk = handle.getChunk(x >> 4, z >> 4); } else { chunk = TaskManager.taskManager().syncAt(() -> handle.getChunk(x >> 4, z >> 4), BukkitAdapter.adapt(location)); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index f35a51bf5b..ce90ad2b92 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -3,7 +3,6 @@ import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; -import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; import org.bukkit.Bukkit; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java index 5baff82364..be5b4b5447 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java @@ -10,6 +10,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.extension.platform.PlayerProxy; import com.sk89q.worldedit.extent.Extent; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.util.Direction; @@ -17,6 +18,7 @@ import com.sk89q.worldedit.util.TargetBlock; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockTypes; +import org.jetbrains.annotations.Nullable; public class AsyncPlayer extends PlayerProxy { @@ -177,19 +179,13 @@ public void setPosition(Vector3 pos, float pitch, float yaw) { } @Override - public Location getBlockTrace(int range, boolean useLastBlock) { - return TaskManager.taskManager().sync(() -> { - TargetBlock tb = new TargetBlock(AsyncPlayer.this, range, 0.2D); - return useLastBlock ? tb.getAnyTargetBlock() : tb.getTargetBlock(); - }); + public Location getBlockTrace(final int range, final boolean useLastBlock, @Nullable final Mask stopMask) { + return TaskManager.taskManager().syncAt(() -> super.getBlockTrace(range, useLastBlock, stopMask), getLocation()); } @Override - public Location getBlockTraceFace(int range, boolean useLastBlock) { - return TaskManager.taskManager().sync(() -> { - TargetBlock tb = new TargetBlock(AsyncPlayer.this, range, 0.2D); - return useLastBlock ? tb.getAnyTargetBlockFace() : tb.getTargetBlockFace(); - }); + public Location getBlockTraceFace(final int range, final boolean useLastBlock, @Nullable final Mask stopMask) { + return TaskManager.taskManager().syncAt(() -> super.getBlockTraceFace(range, useLastBlock, stopMask), getLocation()); } @Override From c0653d0693bfddf6a35006c280374beed760772f Mon Sep 17 00:00:00 2001 From: SirYwell Date: Thu, 9 Mar 2023 11:29:31 +0100 Subject: [PATCH 06/24] Throw exception if player is retired to ensure task always finishes --- .../fastasyncworldedit/bukkit/util/FoliaTaskManager.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index ce90ad2b92..f928593494 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -117,6 +117,7 @@ private static class SchedulerAdapter { private static final MethodHandle EXECUTE_FOR_LOCATION; private static final MethodHandle EXECUTE_FOR_PLAYER; + private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); private static final MethodType LOCATION_EXECUTE_TYPE = methodType( void.class, @@ -160,7 +161,7 @@ private static class SchedulerAdapter { // (ES, P, R, R, L)Z (ES, R, R, L)Z executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); // (ES, R1, R2, L)Z -> (ES, R1)Z - executeForPlayer = insertArguments(executeForPlayer, 2, null, 0); + executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); // (ES, R1)Z -> (ES, R1)V executeForPlayer = dropReturn(executeForPlayer); MethodHandle getScheduler = lookup.findVirtual( @@ -190,7 +191,6 @@ static void executeForLocation(Location location, Runnable task) { } } static void executeForEntity(Player player, Runnable task) { - // TODO task might not be run if player retires try { EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); } catch (Error | RuntimeException e) { @@ -200,6 +200,10 @@ static void executeForEntity(Player player, Runnable task) { } } + private static void throwRetired() { + throw new RuntimeException("Player retired"); + } + } } From c9f8a87d5f359d0b6fac811b1165f7e63cf33088 Mon Sep 17 00:00:00 2001 From: Phillip Glanz Date: Thu, 30 Mar 2023 08:14:21 +0200 Subject: [PATCH 07/24] Add folia support --- worldedit-bukkit/src/main/resources/plugin.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/worldedit-bukkit/src/main/resources/plugin.yml b/worldedit-bukkit/src/main/resources/plugin.yml index cd12b10086..b2a248ab5d 100644 --- a/worldedit-bukkit/src/main/resources/plugin.yml +++ b/worldedit-bukkit/src/main/resources/plugin.yml @@ -10,6 +10,7 @@ description: Blazingly fast world manipulation for builders, large networks and authors: [ Empire92, MattBDev, IronApollo, dordsor21, NotMyFault ] loadbefore: [ WorldGuard, PlotSquared ] database: false +folia-supported: true permissions: fawe.plotsquared: default: true From 7d264aaf879219bfc66b704a7a7a2fcd5f36cf36 Mon Sep 17 00:00:00 2001 From: Phillip Glanz Date: Sun, 2 Apr 2023 17:33:50 +0200 Subject: [PATCH 08/24] Add run folia task --- build.gradle.kts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 15845439ad..e92a120504 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ import org.ajoberstar.grgit.Grgit import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED +import xyz.jpenilla.runpaper.task.RunServer import java.net.URI import java.time.format.DateTimeFormatter import xyz.jpenilla.runpaper.task.RunServer @@ -102,6 +103,14 @@ tasks { .toTypedArray()) } + register("runFolia") { + minecraftVersion("1.19.4") + group = "run paper" + serverJar(file("run-folia/folia-paperclip-1.19.4-R0.1-SNAPSHOT-reobf.jar")) + runDirectory.set(file("run-folia")) + pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } + .toTypedArray()) + } } nexusPublishing { From 5769912f7b74c75e9af1640791bcf50a3d2f3109 Mon Sep 17 00:00:00 2001 From: Phillip Glanz Date: Sun, 2 Apr 2023 22:08:27 +0200 Subject: [PATCH 09/24] Add runFolia with snapshot version of run paper --- build.gradle.kts | 2 +- settings.gradle.kts | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index e92a120504..acc3b6b37d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -104,9 +104,9 @@ tasks { } register("runFolia") { + downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) minecraftVersion("1.19.4") group = "run paper" - serverJar(file("run-folia/folia-paperclip-1.19.4-R0.1-SNAPSHOT-reobf.jar")) runDirectory.set(file("run-folia")) pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) diff --git a/settings.gradle.kts b/settings.gradle.kts index 74cba1396b..dd74eaa319 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,5 +21,14 @@ dependencyResolutionManagement { } } } +pluginManagement { + repositories { + gradlePluginPortal() + maven { + name = "jmp repository" + url = uri("https://repo.jpenilla.xyz/snapshots") + } + } +} enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") From 82f3cea32bad5f78600bcbf5bb72e5e1fae8f319 Mon Sep 17 00:00:00 2001 From: TheMeinerLP Date: Sun, 18 Jun 2023 17:38:14 +0200 Subject: [PATCH 10/24] Add multi folia run task support --- build.gradle.kts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index acc3b6b37d..23fea2d295 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -85,6 +85,7 @@ allprojects { applyCommonConfiguration() val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") +val foliaSupportedVersions = listOf("1.19.4", "1.20.1") tasks { supportedVersions.forEach { @@ -103,14 +104,17 @@ tasks { .toTypedArray()) } - register("runFolia") { - downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) - minecraftVersion("1.19.4") - group = "run paper" - runDirectory.set(file("run-folia")) - pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } + foliaSupportedVersions.forEach { + register("runFolia-$it") { + downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) + minecraftVersion(it) + group = "run paper" + runDirectory.set(file("run-folia-$it")) + pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) + } } + } nexusPublishing { From 54a96bcaea1d6d104de43d6c1ce2dffa87327c5c Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 20 Aug 2023 19:26:37 +0200 Subject: [PATCH 11/24] drop 1.19 folia support --- build.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 23fea2d295..4cab9548bc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,6 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED import xyz.jpenilla.runpaper.task.RunServer import java.net.URI import java.time.format.DateTimeFormatter -import xyz.jpenilla.runpaper.task.RunServer plugins { id("io.github.gradle-nexus.publish-plugin") version "1.3.0" @@ -85,7 +84,7 @@ allprojects { applyCommonConfiguration() val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") -val foliaSupportedVersions = listOf("1.19.4", "1.20.1") +val foliaSupportedVersions = listOf("1.20.1") tasks { supportedVersions.forEach { @@ -108,7 +107,7 @@ tasks { register("runFolia-$it") { downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) minecraftVersion(it) - group = "run paper" + group = "run folia" runDirectory.set(file("run-folia-$it")) pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } .toTypedArray()) From fca4ab42ef81fb9203e5e80756ef3c6428d7f2a8 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Mon, 21 Aug 2023 06:18:27 +0200 Subject: [PATCH 12/24] tmp --- .../PaperweightFaweWorldNativeAccess.java | 6 +- .../v1_19_R3/PaperweightPlatformAdapter.java | 12 +- .../PaperweightFaweWorldNativeAccess.java | 6 +- .../v1_20_R1/PaperweightPlatformAdapter.java | 9 +- .../bukkit/adapter/IBukkitAdapter.java | 4 +- .../bukkit/listener/ChunkListener.java | 4 +- .../bukkit/listener/RenderListener.java | 4 +- .../regions/GriefPreventionFeature.java | 6 +- .../bukkit/regions/ResidenceFeature.java | 4 +- .../FaweDelegateRegionManager.java | 18 +- .../bukkit/util/BukkitTaskManager.java | 33 ++-- .../bukkit/util/FoliaTaskManager.java | 172 +++++------------ .../bukkit/util/image/BukkitImageViewer.java | 5 +- .../bukkit/BukkitBlockCommandSender.java | 20 +- .../bukkit/BukkitPlayerBlockBag.java | 4 +- .../sk89q/worldedit/bukkit/BukkitWorld.java | 9 +- .../com/fastasyncworldedit/core/Fawe.java | 2 +- .../core/entity/LazyBaseEntity.java | 3 +- .../processor/lighting/NMSRelighter.java | 7 +- .../core/util/TaskManager.java | 175 +----------------- .../util/progress/DefaultProgressTracker.java | 6 +- .../core/wrappers/AsyncPlayer.java | 22 +-- .../core/wrappers/WorldWrapper.java | 8 +- .../java/com/sk89q/worldedit/EditSession.java | 5 +- .../worldedit/command/UtilityCommands.java | 15 +- .../worldedit/command/util/EntityRemover.java | 2 +- .../platform/AbstractNonPlayerActor.java | 3 +- .../platform/AbstractPlayerActor.java | 3 +- .../platform/PlatformCommandManager.java | 3 +- .../extent/world/SurvivalModeExtent.java | 9 +- .../function/entity/ExtentEntityCopy.java | 2 +- 31 files changed, 201 insertions(+), 380 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java index dbe0150a9c..35b70fc328 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java @@ -250,7 +250,8 @@ public void run(Object value) { } } }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // TODO ??? + // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); } @Override @@ -269,7 +270,8 @@ public void run(Object value) { if (Fawe.isMainThread()) { runnableVal.run(); } else { - TaskManager.taskManager().sync(runnableVal); + // TODO + // TaskManager.taskManager().sync(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java index d0ce1c5551..56ac2baf6b 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java @@ -11,6 +11,7 @@ import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -283,7 +284,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = false; // TODO TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load @@ -298,7 +299,12 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c e.printStackTrace(); } } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + return TaskManager.taskManager().syncAt( + () -> serverLevel.getChunk(chunkX, chunkZ), + BukkitAdapter.adapt(serverLevel.getWorld()), + chunkX, + chunkZ + ); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { @@ -361,7 +367,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); + }, BukkitAdapter.adapt(nmsWorld.getWorld()), chunkX, chunkZ); } private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java index 186415f9f2..ea1677eee1 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java @@ -252,7 +252,8 @@ public void run(Object value) { } } }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // TODO ??? + // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); } @Override @@ -271,7 +272,8 @@ public void run(Object value) { if (Fawe.isMainThread()) { runnableVal.run(); } else { - TaskManager.taskManager().sync(runnableVal); + // TODO + // TaskManager.taskManager().sync(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 891a41c4b6..18273cc6f6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -311,7 +311,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = false; // TODO TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load @@ -326,7 +326,12 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c e.printStackTrace(); } } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + return TaskManager.taskManager().syncAt( + () -> serverLevel.getChunk(chunkX, chunkZ), + BukkitAdapter.adapt(serverLevel.getWorld()), + chunkX, + chunkZ + ); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java index 29162b607f..281bc9edca 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java @@ -389,7 +389,9 @@ default boolean generateTree(TreeGenerator.TreeType type, EditSession editSessio * @return list of {@link org.bukkit.entity.Entity} */ default List getEntities(org.bukkit.World world) { - return TaskManager.taskManager().sync(world::getEntities); + // TODO + // return TaskManager.taskManager().sync(world::getEntities); + return List.of(); } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java index 43d935c33e..a4a03c1bf5 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/ChunkListener.java @@ -67,7 +67,7 @@ public ChunkListener() { PluginManager plm = Bukkit.getPluginManager(); Plugin plugin = Fawe.platform().getPlugin(); plm.registerEvents(this, plugin); - TaskManager.taskManager().repeat(() -> { + /*TaskManager.taskManager().repeat(() -> { Location tmpLoc = lastCancelPos; if (tmpLoc != null) { LOGGER.info("[FAWE Tick Limiter] Detected and cancelled physics lag source at {}", tmpLoc); @@ -89,7 +89,7 @@ public ChunkListener() { counter.put(key, badLimit); } badChunks.clear(); - }, Settings.settings().TICK_LIMITER.INTERVAL); + }, Settings.settings().TICK_LIMITER.INTERVAL)*/; } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/RenderListener.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/RenderListener.java index 22a09deb80..728209336b 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/RenderListener.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/listener/RenderListener.java @@ -28,7 +28,7 @@ public class RenderListener implements Listener { public RenderListener(Plugin plugin) { Bukkit.getPluginManager().registerEvents(this, plugin); - TaskManager.taskManager().repeat(new Runnable() { + /*TaskManager.taskManager().repeat(new Runnable() { private long last = 0; @Override @@ -76,7 +76,7 @@ public void run() { } } } - }, 1); + }, 1)*/; } private void setViewDistance(Player player, int value) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefPreventionFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefPreventionFeature.java index 9f302d0579..3097059a76 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefPreventionFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/GriefPreventionFeature.java @@ -26,8 +26,10 @@ public GriefPreventionFeature(final Plugin griefpreventionPlugin) { public boolean isAllowed(Player player, Claim claim, MaskType type) { return claim != null && (claim.getOwnerName().equalsIgnoreCase(player.getName()) || claim .getOwnerName() - .equals(player.getUniqueId()) || TaskManager.taskManager().sync(() -> type == MaskType.MEMBER && - claim.allowBuild(player, Material.AIR) == null)); + .equals(player.getUniqueId()) || TaskManager.taskManager().syncAt( + () -> type == MaskType.MEMBER && claim.allowBuild(player, Material.AIR) == null, + BukkitAdapter.adapt(claim.getLesserBoundaryCorner()) + )); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/ResidenceFeature.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/ResidenceFeature.java index a7c13cef55..2b2a95db30 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/ResidenceFeature.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/ResidenceFeature.java @@ -27,9 +27,9 @@ public boolean isAllowed(Player player, ClaimedResidence residence, MaskType typ return residence != null && (residence.getOwner().equals(player.getName()) || residence.getOwner().equals(player.getUniqueId().toString()) || - type == MaskType.MEMBER && TaskManager.taskManager().sync(() -> residence + type == MaskType.MEMBER && TaskManager.taskManager().syncWith(() -> residence .getPermissions() - .playerHas(player, "build", false))); + .playerHas(player, "build", false), BukkitAdapter.adapt(player))); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java index c111ff6306..d6c3104448 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java @@ -76,7 +76,8 @@ public boolean setCuboids( e.printStackTrace(); } finally { if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone, new com.sk89q.worldedit.util.Location(world, )); } } } @@ -203,7 +204,8 @@ public boolean handleClear( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone); } } }); @@ -272,7 +274,8 @@ public void swap( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone); } } }); @@ -301,7 +304,8 @@ public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, Stri e.printStackTrace(); } if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone); } } }); @@ -354,7 +358,8 @@ public boolean copyRegion( } } if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone); } }); return true; @@ -378,7 +383,8 @@ public boolean regenerateRegion(final Location pos1, final Location pos2, boolea editSession.flushQueue(); } if (whenDone != null) { - TaskManager.taskManager().task(whenDone); + // TODO + // TaskManager.taskManager().task(whenDone); } } }); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index a79cd5d2e6..de78394f81 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -1,13 +1,16 @@ package com.fastasyncworldedit.bukkit.util; +import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.util.concurrent.ExecutionException; import java.util.function.Supplier; public class BukkitTaskManager extends TaskManager { @@ -18,11 +21,6 @@ public BukkitTaskManager(final Plugin plugin) { this.plugin = plugin; } - @Override - public int repeat(@Nonnull final Runnable runnable, final int interval) { - return this.plugin.getServer().getScheduler().scheduleSyncRepeatingTask(this.plugin, runnable, interval, interval); - } - @Override public int repeatAsync(@Nonnull final Runnable runnable, final int interval) { return this.plugin.getServer().getScheduler().scheduleAsyncRepeatingTask(this.plugin, runnable, interval, interval); @@ -34,18 +32,13 @@ public void async(@Nonnull final Runnable runnable) { } @Override - public void task(@Nonnull final Runnable runnable) { - this.plugin.getServer().getScheduler().runTask(this.plugin, runnable).getTaskId(); - } - - @Override - public void task(@NotNull final Runnable runnable, @NotNull final Location context) { + public void task(@NotNull final Runnable runnable, @NotNull final Location location) { } @Override - public void later(@Nonnull final Runnable runnable, final int delay) { - this.plugin.getServer().getScheduler().runTaskLater(this.plugin, runnable, delay).getTaskId(); + public void task(@NotNull final Runnable runnable, @NotNull final World world, final int chunkX, final int chunkZ) { + } @Override @@ -68,7 +61,7 @@ public void cancel(final int task) { // TODO @Override - public T syncAt(final Supplier supplier, final Location context) { + public T syncAt(final Supplier supplier, final World world, final int chunkX, final int chunkZ) { return sync(supplier); } @@ -77,4 +70,16 @@ public T syncWith(final Supplier supplier, final Player context) { return sync(supplier); } + private T sync(final Supplier supplier) { + if (Fawe.isTickThread()) { + return supplier.get(); + } + try { + // TODO + return Fawe.instance().getQueueHandler().sync(supplier).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index f928593494..32236379f8 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -5,6 +5,7 @@ import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; @@ -14,63 +15,66 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; import java.util.concurrent.FutureTask; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Consumer; import java.util.function.Supplier; -import static java.lang.invoke.MethodHandles.dropReturn; -import static java.lang.invoke.MethodHandles.explicitCastArguments; -import static java.lang.invoke.MethodHandles.filterArguments; import static java.lang.invoke.MethodHandles.insertArguments; import static java.lang.invoke.MethodType.methodType; public class FoliaTaskManager extends TaskManager { - private final ScheduledExecutorService backgroundExecutor = Executors.newSingleThreadScheduledExecutor(); private final AtomicInteger idCounter = new AtomicInteger(); - @Override - public int repeat(@NotNull final Runnable runnable, final int interval) { - return fail(); - } - @Override public int repeatAsync(@NotNull final Runnable runnable, final int interval) { - backgroundExecutor.scheduleAtFixedRate(runnable, 0, ticksToMs(interval), TimeUnit.MILLISECONDS); + // TODO return some kind of own ScheduledTask instead of int + Bukkit.getAsyncScheduler().runAtFixedRate( + WorldEditPlugin.getInstance(), + asConsumer(runnable), + 0, + ticksToMs(interval), + TimeUnit.MILLISECONDS + ); return idCounter.getAndIncrement(); } @Override public void async(@NotNull final Runnable runnable) { - backgroundExecutor.submit(runnable); + Bukkit.getAsyncScheduler().runNow(WorldEditPlugin.getInstance(), asConsumer(runnable)); } @Override - public void task(@NotNull final Runnable runnable) { - fail(); - } - - @Override - public void task(@NotNull final Runnable runnable, @NotNull final Location context) { - SchedulerAdapter.executeForLocation(context, runnable); - } - - @Override - public void later(@NotNull final Runnable runnable, final int delay) { - fail(); + public void task(@NotNull final Runnable runnable, @NotNull final World world, final int chunkX, final int chunkZ) { + Bukkit.getRegionScheduler().run( + WorldEditPlugin.getInstance(), + BukkitAdapter.adapt(world), + chunkX, + chunkZ, + asConsumer(runnable) + ); } @Override public void later(@NotNull final Runnable runnable, final Location location, final int delay) { - fail("Not implemented"); + Bukkit.getRegionScheduler().runDelayed( + WorldEditPlugin.getInstance(), + BukkitAdapter.adapt(location), + asConsumer(runnable), + delay + ); } @Override public void laterAsync(@NotNull final Runnable runnable, final int delay) { - backgroundExecutor.schedule(runnable, ticksToMs(delay), TimeUnit.MILLISECONDS); + Bukkit.getAsyncScheduler().runDelayed( + WorldEditPlugin.getInstance(), + asConsumer(runnable), + ticksToMs(delay), + TimeUnit.MILLISECONDS + ); } @Override @@ -79,9 +83,15 @@ public void cancel(final int task) { } @Override - public T syncAt(final Supplier supplier, final Location context) { + public T syncAt(final Supplier supplier, final World world, final int chunkX, final int chunkZ) { FutureTask task = new FutureTask<>(supplier::get); - SchedulerAdapter.executeForLocation(context, task); + Bukkit.getRegionScheduler().run( + WorldEditPlugin.getInstance(), + BukkitAdapter.adapt(world), + chunkX, + chunkZ, + asConsumer(task) + ); try { return task.get(); } catch (InterruptedException | ExecutionException e) { @@ -89,10 +99,16 @@ public T syncAt(final Supplier supplier, final Location context) { } } + private Consumer asConsumer(Runnable runnable) { + return __ -> runnable.run(); + } + @Override public T syncWith(final Supplier supplier, final Player context) { FutureTask task = new FutureTask<>(supplier::get); - SchedulerAdapter.executeForEntity(context, task); + BukkitAdapter.adapt(context) + .getScheduler() + .execute(WorldEditPlugin.getInstance(), task, null, 0); try { return task.get(); } catch (InterruptedException | ExecutionException e) { @@ -105,105 +121,9 @@ private int ticksToMs(int ticks) { return ticks * 50; } - private T fail() { - return fail("No main thread present"); - } private T fail(String message) { throw new UnsupportedOperationException(message); } - private static class SchedulerAdapter { - - private static final MethodHandle EXECUTE_FOR_LOCATION; - private static final MethodHandle EXECUTE_FOR_PLAYER; - private static final Runnable THROW_IF_RETIRED = () -> throwRetired(); - - private static final MethodType LOCATION_EXECUTE_TYPE = methodType( - void.class, - Plugin.class, - org.bukkit.Location.class, - Runnable.class - ); - - private static final MethodType ENTITY_EXECUTE_TYPE = methodType( - boolean.class, - Plugin.class, - Runnable.class, - Runnable.class, - long.class - ); - - static { - final Plugin pluginInstance = WorldEditPlugin.getInstance(); - final MethodHandles.Lookup lookup = MethodHandles.lookup(); - - MethodHandle executeForLocation; - - MethodHandle executeForPlayer; - try { - Class regionisedSchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.RegionisedScheduler"); - final Method method = Bukkit.class.getDeclaredMethod("getRegionScheduler"); - executeForLocation = lookup.findVirtual( - regionisedSchedulerClass, - "execute", - LOCATION_EXECUTE_TYPE - ); - executeForLocation = executeForLocation.bindTo(method.invoke(null)); - executeForLocation = executeForLocation.bindTo(pluginInstance); - - Class entitySchedulerClass = Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); - executeForPlayer = lookup.findVirtual( - entitySchedulerClass, - "execute", - ENTITY_EXECUTE_TYPE - ); - // (ES, P, R, R, L)Z (ES, R, R, L)Z - executeForPlayer = insertArguments(executeForPlayer, 1, pluginInstance); - // (ES, R1, R2, L)Z -> (ES, R1)Z - executeForPlayer = insertArguments(executeForPlayer, 2, THROW_IF_RETIRED, 0); - // (ES, R1)Z -> (ES, R1)V - executeForPlayer = dropReturn(executeForPlayer); - MethodHandle getScheduler = lookup.findVirtual( - org.bukkit.entity.Entity.class, - "getScheduler", - methodType(entitySchedulerClass) - ); - // (ES, R1)V -> (E, R1)V - executeForPlayer = filterArguments(executeForPlayer, 0, getScheduler); - MethodType finalType = methodType(void.class, org.bukkit.entity.Player.class, Runnable.class); - // (ES, R1)V -> (P, R1)V - executeForPlayer = explicitCastArguments(executeForPlayer, finalType); - } catch (Throwable throwable) { - throw new AssertionError(throwable); - } - EXECUTE_FOR_LOCATION = executeForLocation; - EXECUTE_FOR_PLAYER = executeForPlayer; - } - - static void executeForLocation(Location location, Runnable task) { - try { - EXECUTE_FOR_LOCATION.invokeExact(BukkitAdapter.adapt(location), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - static void executeForEntity(Player player, Runnable task) { - try { - EXECUTE_FOR_PLAYER.invokeExact(BukkitAdapter.adapt(player), task); - } catch (Error | RuntimeException e) { - throw e; - } catch (Throwable other) { - throw new RuntimeException(other); - } - } - - private static void throwRetired() { - throw new RuntimeException("Player retired"); - } - - } - } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/image/BukkitImageViewer.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/image/BukkitImageViewer.java index 2a61f30838..7f6ca65523 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/image/BukkitImageViewer.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/image/BukkitImageViewer.java @@ -4,6 +4,7 @@ import com.fastasyncworldedit.core.util.image.Drawable; import com.fastasyncworldedit.core.util.image.ImageUtil; import com.fastasyncworldedit.core.util.image.ImageViewer; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -164,7 +165,7 @@ private void view(@Nullable BufferedImage image, @Nullable Drawable drawable) { controller.showInFrames(player, frames, true); } else { int slot = getMapSlot(player); - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncWith(() -> { if (slot == -1) { if (initializing) { player.getInventory().setItemInMainHand(new ItemStack(Material.MAP)); @@ -175,7 +176,7 @@ private void view(@Nullable BufferedImage image, @Nullable Drawable drawable) { player.getInventory().setHeldItemSlot(slot); } return null; - }); + }, BukkitAdapter.adapt(player)); if (image == null && drawable != null) { image = drawable.draw(); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java index 3c2e99f420..fd532824d4 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitBlockCommandSender.java @@ -66,12 +66,12 @@ public String getName() { @Deprecated public void printRaw(String msg) { //FAWE start - ensure executed on main thread - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { for (String part : msg.split("\n")) { sender.sendMessage(part); } return null; - }); + }, getLocation()); //FAWE end } @@ -79,12 +79,12 @@ public void printRaw(String msg) { @Deprecated public void print(String msg) { //FAWE start - ensure executed on main thread - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { for (String part : msg.split("\n")) { print(TextComponent.of(part, TextColor.LIGHT_PURPLE)); } return null; - }); + }, getLocation()); //FAWE end } @@ -92,12 +92,12 @@ public void print(String msg) { @Deprecated public void printDebug(String msg) { //FAWE start - ensure executed on main thread - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { for (String part : msg.split("\n")) { print(TextComponent.of(part, TextColor.GRAY)); } return null; - }); + }, getLocation()); //FAWE end } @@ -105,22 +105,22 @@ public void printDebug(String msg) { @Deprecated public void printError(String msg) { //FAWE start - ensure executed on main thread - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { for (String part : msg.split("\n")) { print(TextComponent.of(part, TextColor.RED)); } return null; - }); + }, getLocation()); //FAWE end } @Override public void print(Component component) { //FAWE start - ensure executed on main thread - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { TextAdapter.sendMessage(sender, WorldEditText.format(component, getLocale())); return null; - }); + }, getLocation()); //FAWE end } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java index b060d78f88..1a64d55e24 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayerBlockBag.java @@ -172,10 +172,10 @@ public void storeBlock(BlockState blockState, int amount) throws BlockBagExcepti @Override public void flushChanges() { if (items != null) { - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncWith(() -> { player.getInventory().setContents(items); return null; - }); + }, BukkitAdapter.adapt(player)); items = null; } } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 1598cb5474..8959af98af 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -45,6 +45,7 @@ import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.Direction; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.SideEffect; import com.sk89q.worldedit.util.SideEffectSet; import com.sk89q.worldedit.util.TreeGenerator; @@ -146,7 +147,7 @@ public BukkitWorld(World world) { public List getEntities(Region region) { World world = getWorld(); - List ents = TaskManager.taskManager().sync(world::getEntities); + List ents = List.of(); // TODO TaskManager.taskManager().sync(world::getEntities); List entities = new ArrayList<>(); for (Entity ent : ents) { if (region.contains(BukkitAdapter.asBlockVector(ent.getLocation()))) { @@ -160,7 +161,7 @@ public List getEntities(Region region) { public List getEntities() { List list = new ArrayList<>(); - List ents = TaskManager.taskManager().sync(getWorld()::getEntities); + List ents = List.of(); // TaskManager.taskManager().sync(getWorld()::getEntities); for (Entity entity : ents) { list.add(BukkitAdapter.adapt(entity)); } @@ -290,7 +291,7 @@ public boolean clearContainerBlockContents(BlockVector3 pt) { return false; } - TaskManager.taskManager().sync(() -> { + TaskManager.taskManager().syncAt(() -> { InventoryHolder chest = (InventoryHolder) state; Inventory inven = chest.getInventory(); if (chest instanceof Chest) { @@ -298,7 +299,7 @@ public boolean clearContainerBlockContents(BlockVector3 pt) { } inven.clear(); return null; - }); + }, new Location(this, pt.toVector3())); return true; } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index 230e12013c..fda51af9b5 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -139,7 +139,7 @@ private Fawe(final IFawe implementation) { }, 0);*/ if (!FoliaSupport.isFolia()) { - TaskManager.taskManager().repeat(timer, 1); + // TODO TaskManager.taskManager().repeat(timer, 1); } clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor( diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java index f591cf8265..3686334f1f 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java @@ -27,7 +27,8 @@ public CompoundBinaryTag getNbt() { if (Fawe.isMainThread()) { setNbt(tmp.get()); } else { - setNbt(TaskManager.taskManager().sync(tmp)); + // TODO + // setNbt(TaskManager.taskManager().sync(tmp)); } } return super.getNbt(); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java index e38df12f54..ca4a300873 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java @@ -914,13 +914,13 @@ public synchronized void close() { queue.flush(); finished.set(true); } else { - TaskManager.taskManager().sync(new RunnableVal<>() { + TaskManager.taskManager().syncAt(new RunnableVal<>() { @Override public void run(Object value) { queue.flush(); finished.set(true); } - }); + }, null); // TODO } } @@ -951,7 +951,8 @@ public void run(Object value) { if (Settings.settings().LIGHTING.ASYNC) { runnable.run(); } else { - TaskManager.taskManager().sync(runnable); + // TODO + // TaskManager.taskManager().sync(runnable); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java index 69a16b4370..58dd3a06dc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java @@ -8,6 +8,7 @@ import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.util.Location; +import com.sk89q.worldedit.world.World; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; @@ -49,15 +50,6 @@ public static TaskManager taskManager() { return INSTANCE; } - /** - * Run a repeating task on the main thread. - * - * @param runnable the task to run - * @param interval in ticks - */ - @Deprecated - public abstract int repeat(@Nonnull final Runnable runnable, final int interval); - /** * Run a repeating task asynchronously. * @@ -79,14 +71,11 @@ public static TaskManager taskManager() { * * @param runnable the task to run */ - @Deprecated - public abstract void task(@Nonnull final Runnable runnable); - /** - * Run a task on the main thread. - * - * @param runnable the task to run - */ - public abstract void task(@Nonnull final Runnable runnable, @Nonnull Location contextLocation); + public void task(@Nonnull final Runnable runnable, @Nonnull Location location) { + task(runnable, (World) location.getExtent(), location.getBlockX() >> 4, location.getBlockZ() >> 4); + } + + public abstract void task(@Nonnull final Runnable runnable, @Nonnull World world, int chunkX, int chunkZ); /** * Get the public ForkJoinPool. @@ -182,70 +171,13 @@ public void runUnsafe(Runnable run) { queue.endUnsafe(Fawe.isMainThread()); } - /** - * Run a task on the current thread or asynchronously. - * - If it's already the main thread, it will just call run() - * - * @param runnable the task to run - * @param async whether the task should run on the main thread - */ - public void taskNow(@Nonnull final Runnable runnable, boolean async) { - if (async) { - async(runnable); - } else { - runnable.run(); - } - } - - /** - * Run a task as soon as possible on the main thread. - * - Non blocking if not calling from the main thread - * - * @param runnable the task to run - */ - @Deprecated - public void taskNowMain(@Nonnull final Runnable runnable) { - if (Fawe.isMainThread()) { - runnable.run(); - } else { - task(runnable); - } - } - - /** - * Run a task as soon as possible not on the main thread. - * - * @param runnable the task to run - * @see Fawe#isMainThread() - */ - public void taskNowAsync(@Nonnull final Runnable runnable) { - taskNow(runnable, Fawe.isMainThread()); - } - - /** - * Run a task on the main thread at the next tick or now async. - * - * @param runnable the task to run. - * @param async whether the task should run on the main thread - */ - @Deprecated - public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) { - if (async) { - async(runnable); - } else { - task(runnable); - } - } - - /** * Run a task later on the main thread. * * @param runnable the task to run + * @param location the location context to run at * @param delay in ticks */ - @Deprecated - public abstract void later(@Nonnull final Runnable runnable, final int delay); public abstract void later(@Nonnull final Runnable runnable, Location location, final int delay); /** @@ -263,35 +195,6 @@ public void taskSoonMain(@Nonnull final Runnable runnable, boolean async) { */ public abstract void cancel(final int task); - /** - * Break up a task and run it in fragments of 5ms.
- * - Each task will run on the main thread.
- * - * @param objects the list of objects to run the task for - * @param task the task to run on each object - * @param whenDone when the object task completes - */ - @Deprecated - public void objectTask(Collection objects, final RunnableVal task, final Runnable whenDone) { - final Iterator iterator = objects.iterator(); - task(new Runnable() { - @Override - public void run() { - long start = System.currentTimeMillis(); - boolean hasNext; - while ((hasNext = iterator.hasNext()) && System.currentTimeMillis() - start < 5) { - task.value = iterator.next(); - task.run(); - } - if (!hasNext) { - later(whenDone, 1); - } else { - later(this, 1); - } - } - }); - } - /** * @deprecated Deprecated without replacement as unused internally, and poor implementation of what it's designed to do. */ @@ -333,69 +236,11 @@ public void taskWhenFree(@Nonnull Runnable run) { } } - /** - * Run a task on the main thread when the TPS is high enough, and wait for execution to finish. - * - Useful if you need to access something from the Bukkit API from another thread
- * - Usually wait time is around 25ms
- */ - @Deprecated - public T syncWhenFree(@Nonnull final RunnableVal function) { - if (Fawe.isMainThread()) { - function.run(); - return function.value; - } - try { - return Fawe.instance().getQueueHandler().sync((Supplier) function).get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Run a task on the main thread when the TPS is high enough, and wait for execution to finish. - * - Useful if you need to access something from the Bukkit API from another thread
- * - Usually wait time is around 25ms
- */ - @Deprecated - public T syncWhenFree(@Nonnull final Supplier supplier) { - if (Fawe.isMainThread()) { - return supplier.get(); - } - try { - return Fawe.instance().getQueueHandler().sync(supplier).get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } - } - - /** - * Quickly run a task on the main thread, and wait for execution to finish. - * - Useful if you need to access something from the Bukkit API from another thread
- * - Usually wait time is around 25ms - */ - @Deprecated - public T sync(@Nonnull final RunnableVal function) { - return sync((Supplier) function); - } - - /** - * Quickly run a task on the main thread, and wait for execution to finish. - * - Useful if you need to access something from the Bukkit API from another thread
- * - Usually wait time is around 25ms
- */ - @Deprecated - public T sync(final Supplier function) { - if (Fawe.isMainThread()) { - return function.get(); - } - try { - return Fawe.instance().getQueueHandler().sync(function).get(); - } catch (InterruptedException | ExecutionException e) { - throw new RuntimeException(e); - } + public T syncAt(Supplier supplier, Location context) { + return syncAt(supplier, (World) context.getExtent(), context.getBlockX() >> 4, context.getBlockZ() >> 4); } - public abstract T syncAt(Supplier supplier, Location context); + public abstract T syncAt(Supplier supplier, World world, int chunkX, int chunkZ); public abstract T syncWith(Supplier supplier, Player context); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java index 4aa846fc3d..1970a252a3 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java @@ -93,14 +93,16 @@ public void accept(ProgressType type, Integer amount) { } private void done() { - TaskManager.taskManager().task(this::doneTask); + // TODO + // TaskManager.taskManager().task(this::doneTask); } private long lastTick = 0; private void send() { // Run on main thread - TaskManager.taskManager().task(this::sendTask); + // TODO + // TaskManager.taskManager().task(this::sendTask); } public void doneTask() { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java index be5b4b5447..cfd77b57e8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java @@ -40,22 +40,22 @@ public World getWorld() { @Override public void findFreePosition(Location searchPos) { - TaskManager.taskManager().sync(new RunnableVal() { + TaskManager.taskManager().syncAt(new RunnableVal() { @Override public void run(Boolean value) { getBasePlayer().findFreePosition(searchPos); } - }); + }, searchPos); } @Override public void setOnGround(Location searchPos) { - TaskManager.taskManager().sync(new RunnableVal() { + TaskManager.taskManager().syncAt(new RunnableVal() { @Override public void run(Boolean value) { getBasePlayer().setOnGround(searchPos); } - }); + }, searchPos); } @Override @@ -70,12 +70,12 @@ public void run(Boolean value) { @Override public boolean ascendLevel() { - return TaskManager.taskManager().sync(() -> getBasePlayer().ascendLevel()); + return TaskManager.taskManager().syncWith(() -> getBasePlayer().ascendLevel(), this); } @Override public boolean descendLevel() { - return TaskManager.taskManager().sync(() -> getBasePlayer().descendLevel()); + return TaskManager.taskManager().syncWith(() -> getBasePlayer().descendLevel(), this); } @Override @@ -185,15 +185,15 @@ public Location getBlockTrace(final int range, final boolean useLastBlock, @Null @Override public Location getBlockTraceFace(final int range, final boolean useLastBlock, @Nullable final Mask stopMask) { - return TaskManager.taskManager().syncAt(() -> super.getBlockTraceFace(range, useLastBlock, stopMask), getLocation()); + return TaskManager.taskManager().syncWith(() -> super.getBlockTraceFace(range, useLastBlock, stopMask), this); } @Override public Location getSolidBlockTrace(int range) { - return TaskManager.taskManager().sync(() -> { + return TaskManager.taskManager().syncWith(() -> { TargetBlock tb = new TargetBlock(AsyncPlayer.this, range, 0.2D); return tb.getSolidTargetBlock(); - }); + }, this); } @Override @@ -203,7 +203,7 @@ public Direction getCardinalDirection() { @Override public boolean passThroughForwardWall(int range) { - return TaskManager.taskManager().sync(() -> { + return TaskManager.taskManager().syncWith(() -> { int searchDist = 0; TargetBlock hitBlox = new TargetBlock(AsyncPlayer.this, range, 0.2); Extent world = getLocation().getExtent(); @@ -248,7 +248,7 @@ public boolean passThroughForwardWall(int range) { } return false; - }); + }, this); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java index 05616a4148..2546737aa4 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/WorldWrapper.java @@ -253,18 +253,20 @@ public void dropItem(Vector3 position, BaseItemStack item) { @Override public void simulateBlockMine(BlockVector3 pt) { - TaskManager.taskManager().sync(new RunnableVal() { + TaskManager.taskManager().syncAt(new RunnableVal() { @Override public void run(Object value) { parent.simulateBlockMine(pt); } - }); + }, new Location(this, pt.toVector3())); } //FAWE start @Override public Collection getBlockDrops(final BlockVector3 position) { - return TaskManager.taskManager().sync(() -> parent.getBlockDrops(position)); + return TaskManager.taskManager().syncAt( + () -> parent.getBlockDrops(position), + new Location(this, position.toVector3())); } //FAWE end 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 ecf859896a..5fd2778e72 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -3819,12 +3819,13 @@ public boolean regenerate(Region region, BiomeType biome, Long seed) { } if (containsAny) { changes++; - TaskManager.taskManager().sync(new RunnableVal() { + // TODO this seems to be broken? +/* TaskManager.taskManager().sync(new RunnableVal() { @Override public void run(Object value) { regenerateChunk(cx, cz, biome, seed); } - }); + });*/ } } if (changes != 0) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index aca13bc46d..8fdd1d7bfb 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -709,7 +709,16 @@ public int butcher( //FAWE start - run this sync int finalRadius = radius; - int killed = TaskManager.taskManager().sync(() -> killMatchingEntities(finalRadius, actor, flags::createFunction)); + int killed; + // TODO location context might be somewhere else actually + if (actor instanceof Player player) { + killed = TaskManager.taskManager().syncWith( + () -> killMatchingEntities(finalRadius, actor, flags::createFunction), + player + ); + } else { + killed = 0; + } //FAWE end actor.print(Caption.of( @@ -741,7 +750,9 @@ public int remove( } //FAWE start - run this sync - int removed = TaskManager.taskManager().sync(() -> killMatchingEntities(radius, actor, remover::createFunction)); + int removed = 0; + // TODO location context might be somewhere else actually + // removed = TaskManager.taskManager().sync(() -> killMatchingEntities(radius, actor, remover::createFunction)); //FAWE end actor.print(Caption.of("worldedit.remove.removed", TextComponent.of(removed))); return removed; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java index f2310a211f..0664f03620 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/util/EntityRemover.java @@ -148,7 +148,7 @@ public EntityFunction createFunction() { if (registryType != null) { if (type.matches(registryType)) { //FAWE start - Calling this async violates thread safety - TaskManager.taskManager().sync(entity::remove); + TaskManager.taskManager().syncAt(entity::remove, entity.getLocation()); //FAWE end return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java index 8337a7327f..be36f20ffa 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java @@ -109,7 +109,8 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - TaskManager.taskManager().taskNow(wrapped, false); + // TODO + // TaskManager.taskManager().taskNow(wrapped, false); } return true; } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index ae4eb21443..f810a4f7ea 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -677,7 +677,8 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - TaskManager.taskManager().taskNow(wrapped, false); + // TODO + // TaskManager.taskManager().taskNow(wrapped, false); } return true; } 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 7b493cf985..edd51e0536 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 @@ -687,7 +687,8 @@ public void handleCommand(CommandEvent event) { Command cmd = optional.get(); PermissionCondition queued = cmd.getCondition().as(PermissionCondition.class).orElse(null); if (queued != null && !queued.isQueued()) { - TaskManager.taskManager().taskNow(() -> handleCommandOnCurrentThread(event), Fawe.isMainThread()); + // TODO? + // TaskManager.taskManager().taskNow(() -> handleCommandOnCurrentThread(event), Fawe.isMainThread()); return; } else { actor.decline(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java index 88cf4fc6ff..1619502ee0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extent/world/SurvivalModeExtent.java @@ -26,6 +26,8 @@ import com.sk89q.worldedit.extent.AbstractDelegateExtent; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.math.BlockVector3; +import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.block.BlockStateHolder; @@ -99,14 +101,15 @@ public > boolean setBlock(BlockVector3 location, B Collection drops = world.getBlockDrops(location); boolean canSet = super.setBlock(location, block); if (canSet) { - TaskManager.taskManager().sync(new RunnableVal<>() { + final Vector3 position = location.toVector3(); + TaskManager.taskManager().syncAt(new RunnableVal<>() { @Override public void run(Object value) { for (BaseItemStack stack : drops) { - world.dropItem(location.toVector3(), stack); + world.dropItem(position, stack); } } - }); + }, new Location(world, position)); return true; } else { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java index fa3ef1dc45..c14abee738 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/function/entity/ExtentEntityCopy.java @@ -170,7 +170,7 @@ public boolean apply(Entity entity) throws WorldEditException { uuid ); } else { - TaskManager.taskManager().sync(entity::remove); + TaskManager.taskManager().syncAt(entity::remove, entity.getLocation()); //FAWE end } } From 441c2d452b0d9fc4e3350f6f850eb9667e2fef1f Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 29 Oct 2023 10:49:33 +0100 Subject: [PATCH 13/24] Fix compilation --- .../PaperweightFaweWorldNativeAccess.java | 6 +- .../v1_18_R2/PaperweightPlatformAdapter.java | 14 ++- .../PaperweightStarlightRelighter.java | 20 ++-- .../fawe/v1_18_R2/regen/PaperweightRegen.java | 8 +- .../v1_19_R3/PaperweightPlatformAdapter.java | 5 +- .../PaperweightStarlightRelighter.java | 20 ++-- .../fawe/v1_19_R3/regen/PaperweightRegen.java | 3 +- .../v1_20_R1/PaperweightPlatformAdapter.java | 5 +- .../PaperweightStarlightRelighter.java | 100 +++++++++++++++--- .../fawe/v1_20_R1/regen/PaperweightRegen.java | 3 +- .../PaperweightFaweWorldNativeAccess.java | 9 +- .../v1_20_R2/PaperweightPlatformAdapter.java | 13 ++- .../PaperweightStarlightRelighter.java | 20 ++-- .../fawe/v1_20_R2/regen/PaperweightRegen.java | 7 +- .../bukkit/util/BukkitTaskManager.java | 5 + .../bukkit/util/FoliaTaskManager.java | 19 ++-- .../core/util/TaskManager.java | 6 +- 17 files changed, 195 insertions(+), 68 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java index ef7fc98ac0..69237677ec 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java @@ -250,7 +250,8 @@ public void run(Object value) { } } }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // TODO global sync is not correct on folia + TaskManager.taskManager().async(() -> TaskManager.taskManager().syncGlobal(runnableVal)); } @Override @@ -269,7 +270,8 @@ public void run(Object value) { if (Fawe.isMainThread()) { runnableVal.run(); } else { - TaskManager.taskManager().sync(runnableVal); + // TODO global sync is not correct on folia + TaskManager.taskManager().syncGlobal(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java index 06281908d0..9407098e93 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightPlatformAdapter.java @@ -10,6 +10,7 @@ import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -246,7 +247,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = TaskManager.taskManager().syncGlobal(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load @@ -260,7 +261,8 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c e.printStackTrace(); } } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + return TaskManager.taskManager().syncAt(() -> serverLevel.getChunk(chunkX, chunkZ), + BukkitAdapter.adapt(serverLevel.getWorld()), chunkX, chunkZ); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { @@ -300,7 +302,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole return; } LevelChunk levelChunk = optional.get(); - TaskManager.taskManager().task(() -> { + PaperweightPlatformAdapter.task(() -> { ClientboundLevelChunkWithLightPacket packet; if (PaperLib.isPaper()) { packet = new ClientboundLevelChunkWithLightPacket( @@ -322,7 +324,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); + }, nmsWorld, chunkX, chunkZ); } private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { @@ -625,6 +627,10 @@ public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTa } } + public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ) { + TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java index c832fc98ac..22fae53866 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightStarlightRelighter.java @@ -64,12 +64,20 @@ protected void invokeRelight( protected void postProcessChunks(Set coords) { boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + PaperweightPlatformAdapter.task( + () -> { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + }, + serverLevel, + pos.x, + pos.z + ); + } } diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java index 8403d531d0..365022dac0 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/regen/PaperweightRegen.java @@ -9,6 +9,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_18_R2.PaperweightGetBlocks; @@ -411,7 +412,12 @@ protected List getBlockPopulators() { @Override protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk())); + TaskManager.taskManager().task( + () -> blockPopulator.populate(freshWorld.getWorld(), random, levelChunk.getBukkitChunk()), + BukkitAdapter.adapt(originalBukkitWorld), + levelChunk.getPos().x, + levelChunk.getPos().z + ); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java index 56ac2baf6b..e086c686bb 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java @@ -58,7 +58,6 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_19_R3.CraftChunk; import sun.misc.Unsafe; @@ -693,6 +692,10 @@ public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTa } } + public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ) { + TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java index 580bbf5a6e..3b459b2b75 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightStarlightRelighter.java @@ -64,12 +64,20 @@ protected void invokeRelight( protected void postProcessChunks(Set coords) { boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + PaperweightPlatformAdapter.task( + () -> { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + }, + serverLevel, + pos.x, + pos.z + ); + } } 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 17b3545352..047896d5ca 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 @@ -9,6 +9,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_19_R3.PaperweightGetBlocks; @@ -442,7 +443,7 @@ protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blo final CraftWorld world = freshWorld.getWorld(); final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); blockPopulator.populate(world, random, chunk); - }); + }, BukkitAdapter.adapt(originalBukkitWorld), levelChunk.getPos().x, levelChunk.getPos().z); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 18273cc6f6..1ac162c51b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -63,7 +63,6 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R1.CraftChunk; import sun.misc.Unsafe; @@ -716,6 +715,10 @@ public static void readEntityIntoTag(Entity entity, net.minecraft.nbt.CompoundTa } } + public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ) { + TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java index 30df914597..0b7b2c7185 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java @@ -35,17 +35,79 @@ protected long asLong(final int chunkX, final int chunkZ) { } @Override - protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { - return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - chunkPos, - LIGHT_LEVEL, - Unit.INSTANCE - )); + public void fixLightingSafe(boolean sky) { + this.areaLock.lock(); + try { + if (regions.isEmpty()) { + return; + } + LongSet first = regions.removeFirst(); + fixLighting(first, () -> fixLightingSafe(true)); + } finally { + this.areaLock.unlock(); + } + } + + /* + * Processes a set of chunks and runs an action afterwards. + * The action is run async, the chunks are partly processed on the main thread + * (as required by the server). + */ + private void fixLighting(LongSet chunks, Runnable andThen) { + // convert from long keys to ChunkPos + Set coords = new HashSet<>(); + LongIterator iterator = chunks.iterator(); + while (iterator.hasNext()) { + coords.add(new ChunkPos(iterator.nextLong())); + } + if (FoliaSupport.isFolia()) { + relightRegion(andThen, coords); + return; + } + TaskManager.taskManager().task(() -> { + // trigger chunk load and apply ticket on main thread + relightRegion(andThen, coords); + }); } - protected void invokeRelight( + private void relightRegion(Runnable andThen, Set coords) { + List> futures = new ArrayList<>(); + for (ChunkPos pos : coords) { + futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + pos, + LIGHT_LEVEL, + Unit.INSTANCE + )) + ); + } + Location location = toLocation(coords.iterator().next()); + // collect futures and trigger relight once all chunks are loaded + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAcceptAsync(v -> + invokeRelight( + coords, + c -> { + }, // no callback for single chunks required + i -> { + if (i != coords.size()) { + LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); + } + // post process chunks on main thread + TaskManager.taskManager().task(() -> postProcessChunks(coords), location); + // call callback on our own threads + TaskManager.taskManager().async(andThen); + } + ), + task -> TaskManager.taskManager().task(task, location) + ); + } + + private Location toLocation(ChunkPos chunkPos) { + return PaperweightPlatformAdapter.toLocation(this.serverLevel, chunkPos); + } + + private void invokeRelight( Set coords, Consumer chunkCallback, IntConsumer processCallback @@ -64,12 +126,20 @@ protected void invokeRelight( protected void postProcessChunks(Set coords) { boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + PaperweightPlatformAdapter.task( + () -> { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + }, + serverLevel, + pos.x, + pos.z + ); + } } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java index 99e001837a..7a850551e4 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/regen/PaperweightRegen.java @@ -9,6 +9,7 @@ import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1.PaperweightGetBlocks; @@ -443,7 +444,7 @@ protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blo final CraftWorld world = freshWorld.getWorld(); final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); blockPopulator.populate(world, random, chunk); - }); + }, BukkitAdapter.adapt(originalBukkitWorld), levelChunk.getPos().x, levelChunk.getPos().z); } @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java index b452ec4cd2..75ab999c17 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java @@ -15,9 +15,8 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; @@ -251,7 +250,8 @@ public void run(Object value) { } } }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // TODO global sync is not correct on folia + TaskManager.taskManager().async(() -> TaskManager.taskManager().syncGlobal(runnableVal)); } @Override @@ -270,7 +270,8 @@ public void run(Object value) { if (Fawe.isMainThread()) { runnableVal.run(); } else { - TaskManager.taskManager().sync(runnableVal); + // TODO global sync is not correct on folia + TaskManager.taskManager().syncGlobal(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 9ab6b06021..89013a0045 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -11,6 +11,7 @@ import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -58,7 +59,6 @@ import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R2.CraftChunk; -import sun.misc.Unsafe; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -298,7 +298,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = TaskManager.taskManager().syncGlobal(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load @@ -313,7 +313,8 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c e.printStackTrace(); } } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + return TaskManager.taskManager().syncAt(() -> serverLevel.getChunk(chunkX, chunkZ), + BukkitAdapter.adapt(serverLevel.getWorld()), chunkX, chunkZ); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { @@ -374,7 +375,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); + }, BukkitAdapter.adapt(nmsWorld.getWorld()), chunkX, chunkZ); } private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { @@ -674,6 +675,10 @@ static List getEntities(LevelChunk chunk) { return List.of(); } + public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ) { + TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java index e869046da1..b1786901f2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightStarlightRelighter.java @@ -64,12 +64,20 @@ protected void invokeRelight( protected void postProcessChunks(Set coords) { boolean delay = Settings.settings().LIGHTING.DELAY_PACKET_SENDING; for (ChunkPos pos : coords) { - int x = pos.x; - int z = pos.z; - if (delay) { // we still need to send the block changes of that chunk - PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); - } - serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + PaperweightPlatformAdapter.task( + () -> { + int x = pos.x; + int z = pos.z; + if (delay) { // we still need to send the block changes of that chunk + PaperweightPlatformAdapter.sendChunk(serverLevel, x, z, false); + } + serverLevel.getChunkSource().removeTicketAtLevel(FAWE_TICKET, pos, LIGHT_LEVEL, Unit.INSTANCE); + }, + serverLevel, + pos.x, + pos.z + ); + } } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java index 2ec8e6e41b..5e97b9fea1 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/regen/PaperweightRegen.java @@ -4,14 +4,13 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.ReflectionUtils; -import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.PaperweightGetBlocks; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.PaperweightPlatformAdapter; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; @@ -439,11 +438,11 @@ protected List getBlockPopulators() { @Override protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { + PaperweightPlatformAdapter.task(() -> { final CraftWorld world = freshWorld.getWorld(); final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); blockPopulator.populate(world, random, chunk); - }); + }, freshWorld, levelChunk.getPos().x, levelChunk.getPos().z); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index de78394f81..9f500f155a 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -70,6 +70,11 @@ public T syncWith(final Supplier supplier, final Player context) { return sync(supplier); } + @Override + public T syncGlobal(final Supplier supplier) { + return sync(supplier); + } + private T sync(final Supplier supplier) { if (Fawe.isTickThread()) { return supplier.get(); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index 32236379f8..745256ceab 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -7,13 +7,8 @@ import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.world.World; import org.bukkit.Bukkit; -import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; -import java.lang.reflect.Method; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; @@ -21,9 +16,6 @@ import java.util.function.Consumer; import java.util.function.Supplier; -import static java.lang.invoke.MethodHandles.insertArguments; -import static java.lang.invoke.MethodType.methodType; - public class FoliaTaskManager extends TaskManager { private final AtomicInteger idCounter = new AtomicInteger(); @@ -116,6 +108,17 @@ public T syncWith(final Supplier supplier, final Player context) { } } + @Override + public T syncGlobal(final Supplier supplier) { + FutureTask task = new FutureTask<>(supplier::get); + Bukkit.getGlobalRegionScheduler().run(WorldEditPlugin.getInstance(), asConsumer(task)); + try { + return task.get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + private int ticksToMs(int ticks) { // 1 tick = 50ms return ticks * 50; diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java index 58dd3a06dc..ec2d59993b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java @@ -3,8 +3,6 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.queue.implementation.QueueHandler; -import com.fastasyncworldedit.core.util.task.RunnableVal; -import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.util.Location; @@ -14,8 +12,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; -import java.util.Iterator; -import java.util.concurrent.ExecutionException; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; @@ -244,4 +240,6 @@ public T syncAt(Supplier supplier, Location context) { public abstract T syncWith(Supplier supplier, Player context); + public abstract T syncGlobal(Supplier supplier); + } From 17b7a2cf114dd21f58747377d7b0272b2af6ea22 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 29 Oct 2023 11:26:07 +0100 Subject: [PATCH 14/24] compact run-task configuration --- build.gradle.kts | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 4cab9548bc..df1d9e0b92 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ import org.ajoberstar.grgit.Grgit import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED +import org.gradle.configurationcache.extensions.capitalized import xyz.jpenilla.runpaper.task.RunServer import java.net.URI import java.time.format.DateTimeFormatter @@ -87,30 +88,27 @@ val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") val foliaSupportedVersions = listOf("1.20.1") tasks { - supportedVersions.forEach { - register("runServer-$it") { - minecraftVersion(it) - pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } + fun registerVersion(version: String, software: String, task: RunServer.() -> Unit = {}) { + register("run${software.capitalized()}-$version") { + minecraftVersion(version) + pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false) + .map { (it as Jar).archiveFile } .toTypedArray()) jvmArgs("-DPaper.IgnoreJavaVersion=true", "-Dcom.mojang.eula.agree=true") - group = "run paper" - runDirectory.set(file("run-$it")) + group = "run $software" + runDirectory.set(file("run-$software-$version")) + task(this) } } runServer { - minecraftVersion("1.20.4") - pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } - .toTypedArray()) - + registerVersion("1.20.4", "paper") + } + supportedVersions.forEach { + registerVersion(it, "paper") } foliaSupportedVersions.forEach { - register("runFolia-$it") { + registerVersion(it, "folia") { downloadsApiService.set(xyz.jpenilla.runtask.service.DownloadsAPIService.folia(project)) - minecraftVersion(it) - group = "run folia" - runDirectory.set(file("run-folia-$it")) - pluginJars(*project(":worldedit-bukkit").getTasksByName("shadowJar", false).map { (it as Jar).archiveFile } - .toTypedArray()) } } From d64b0d9edf1d0b47a5d280a2851ebe08a7dc9567 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 29 Oct 2023 12:10:19 +0100 Subject: [PATCH 15/24] Fix some folia incompatibilities --- .../fawe/v1_20_R1/PaperweightPlatformAdapter.java | 9 +++++---- .../bukkit/util/FoliaTaskManager.java | 15 +++++++++++---- .../sk89q/worldedit/bukkit/WorldEditPlugin.java | 1 - .../platform/PlatformCommandManager.java | 7 +++++-- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 1ac162c51b..12cbb04a36 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -64,7 +64,6 @@ import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; import org.bukkit.craftbukkit.v1_20_R1.CraftChunk; -import sun.misc.Unsafe; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -335,9 +334,11 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket - io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + task(() -> serverLevel + .getChunkSource() + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), + serverLevel, chunkX, chunkZ + ); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index 745256ceab..f6ab9e1c79 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -76,10 +76,14 @@ public void cancel(final int task) { @Override public T syncAt(final Supplier supplier, final World world, final int chunkX, final int chunkZ) { + final org.bukkit.World adapt = BukkitAdapter.adapt(world); + if (Bukkit.isOwnedByCurrentRegion(adapt, chunkX, chunkZ)) { + return supplier.get(); + } FutureTask task = new FutureTask<>(supplier::get); Bukkit.getRegionScheduler().run( WorldEditPlugin.getInstance(), - BukkitAdapter.adapt(world), + adapt, chunkX, chunkZ, asConsumer(task) @@ -97,10 +101,12 @@ private Consumer asConsumer(Runnable runnable) { @Override public T syncWith(final Supplier supplier, final Player context) { + final org.bukkit.entity.Player adapt = BukkitAdapter.adapt(context); + if (Bukkit.isOwnedByCurrentRegion(adapt)) { + return supplier.get(); + } FutureTask task = new FutureTask<>(supplier::get); - BukkitAdapter.adapt(context) - .getScheduler() - .execute(WorldEditPlugin.getInstance(), task, null, 0); + adapt.getScheduler().execute(WorldEditPlugin.getInstance(), task, null, 0); try { return task.get(); } catch (InterruptedException | ExecutionException e) { @@ -110,6 +116,7 @@ public T syncWith(final Supplier supplier, final Player context) { @Override public T syncGlobal(final Supplier supplier) { + // TODO avoid deadlocks (Bukkit.isGlobalTickThread not available at time of writing) FutureTask task = new FutureTask<>(supplier::get); Bukkit.getGlobalRegionScheduler().run(WorldEditPlugin.getInstance(), asConsumer(task)); try { diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java index e881416c54..10988bbadc 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/WorldEditPlugin.java @@ -400,7 +400,6 @@ public void onDisable() { if (config != null) { config.unload(); } - this.getServer().getScheduler().cancelTasks(this); } /** 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 edd51e0536..1900be6d9f 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 @@ -687,8 +687,11 @@ public void handleCommand(CommandEvent event) { Command cmd = optional.get(); PermissionCondition queued = cmd.getCondition().as(PermissionCondition.class).orElse(null); if (queued != null && !queued.isQueued()) { - // TODO? - // TaskManager.taskManager().taskNow(() -> handleCommandOnCurrentThread(event), Fawe.isMainThread()); + if (actor instanceof Player player) { + TaskManager.taskManager().task(() -> handleCommandOnCurrentThread(event), player.getLocation()); + } else { + // TODO + } return; } else { actor.decline(); From fbe69bdc81c5c1131b01ac107430ed7d5e0dc726 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Mon, 11 Dec 2023 21:27:45 +0100 Subject: [PATCH 16/24] rebase fixes --- build.gradle.kts | 2 +- .../fawe/v1_20_R1/PaperweightFaweAdapter.java | 1 + .../PaperweightStarlightRelighter.java | 87 +++------------ .../PaperweightFaweWorldNativeAccess.java | 7 +- .../v1_20_R2/PaperweightPlatformAdapter.java | 6 +- .../PaperweightFaweWorldNativeAccess.java | 16 ++- .../v1_20_R3/PaperweightPlatformAdapter.java | 12 +- .../fawe/v1_20_R3/regen/PaperweightRegen.java | 6 +- .../bukkit/adapter/FaweAdapter.java | 104 +++++++++++++++++- .../bukkit/adapter/StarlightRelighter.java | 5 +- .../bukkit/util/BukkitTaskManager.java | 9 +- .../bukkit/util/FoliaTaskManager.java | 36 +++++- .../sk89q/worldedit/bukkit/BukkitPlayer.java | 27 +++-- .../core/util/FoliaSupport.java | 31 ++++++ .../core/util/TaskManager.java | 2 + .../core/wrappers/AsyncPlayer.java | 4 +- 16 files changed, 244 insertions(+), 111 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index df1d9e0b92..da44e48a74 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -85,7 +85,7 @@ allprojects { applyCommonConfiguration() val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") -val foliaSupportedVersions = listOf("1.20.1") +val foliaSupportedVersions = listOf("1.20.2") tasks { fun registerVersion(version: String, software: String, task: RunServer.() -> Unit = {}) { diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java index ffe067ec9a..a3eef00a88 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java @@ -10,6 +10,7 @@ import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; import com.fastasyncworldedit.core.util.NbtUtils; +import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java index 0b7b2c7185..dd3f47c1f0 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightStarlightRelighter.java @@ -35,82 +35,21 @@ protected long asLong(final int chunkX, final int chunkZ) { } @Override - public void fixLightingSafe(boolean sky) { - this.areaLock.lock(); - try { - if (regions.isEmpty()) { - return; - } - LongSet first = regions.removeFirst(); - fixLighting(first, () -> fixLightingSafe(true)); - } finally { - this.areaLock.unlock(); - } + protected CompletableFuture chunkLoadFuture(final ChunkPos chunkPos) { + return serverLevel.getWorld().getChunkAtAsync(chunkPos.x, chunkPos.z) + .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( + FAWE_TICKET, + chunkPos, + LIGHT_LEVEL, + Unit.INSTANCE + )); } - /* - * Processes a set of chunks and runs an action afterwards. - * The action is run async, the chunks are partly processed on the main thread - * (as required by the server). - */ - private void fixLighting(LongSet chunks, Runnable andThen) { - // convert from long keys to ChunkPos - Set coords = new HashSet<>(); - LongIterator iterator = chunks.iterator(); - while (iterator.hasNext()) { - coords.add(new ChunkPos(iterator.nextLong())); - } - if (FoliaSupport.isFolia()) { - relightRegion(andThen, coords); - return; - } - TaskManager.taskManager().task(() -> { - // trigger chunk load and apply ticket on main thread - relightRegion(andThen, coords); - }); - } - - private void relightRegion(Runnable andThen, Set coords) { - List> futures = new ArrayList<>(); - for (ChunkPos pos : coords) { - futures.add(serverLevel.getWorld().getChunkAtAsync(pos.x, pos.z) - .thenAccept(c -> serverLevel.getChunkSource().addTicketAtLevel( - FAWE_TICKET, - pos, - LIGHT_LEVEL, - Unit.INSTANCE - )) - ); - } - Location location = toLocation(coords.iterator().next()); - // collect futures and trigger relight once all chunks are loaded - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAcceptAsync(v -> - invokeRelight( - coords, - c -> { - }, // no callback for single chunks required - i -> { - if (i != coords.size()) { - LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); - } - // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords), location); - // call callback on our own threads - TaskManager.taskManager().async(andThen); - } - ), - task -> TaskManager.taskManager().task(task, location) - ); - } - - private Location toLocation(ChunkPos chunkPos) { - return PaperweightPlatformAdapter.toLocation(this.serverLevel, chunkPos); - } - - private void invokeRelight( - Set coords, - Consumer chunkCallback, - IntConsumer processCallback + @Override + protected void invokeRelight( + final Set coords, + final Consumer chunkCallback, + final IntConsumer processCallback ) { try { serverLevel.getChunkSource().getLightEngine().relight(coords, chunkCallback, processCallback); diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java index 75ab999c17..4ba80a73c9 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java @@ -2,6 +2,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -21,6 +22,7 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; @@ -58,7 +60,10 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd this.level = level; // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - this.lastTick = new AtomicInteger(MinecraftServer.currentTick); + this.lastTick = new AtomicInteger(); + if (!FoliaSupport.isFolia()) { + this.lastTick.set(Bukkit.getCurrentTick()); + } } private Level getLevel() { diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 89013a0045..17084fd4a8 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -319,9 +319,11 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket - io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel + PaperweightPlatformAdapter.task(() -> serverLevel .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), + serverLevel, chunkX, chunkZ + ); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java index ad04e7b03b..451fb3740f 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java @@ -2,7 +2,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; -import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -15,12 +15,13 @@ import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; @@ -58,7 +59,10 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd this.level = level; // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - this.lastTick = new AtomicInteger(MinecraftServer.currentTick); + this.lastTick = new AtomicInteger(); + if (!FoliaSupport.isFolia()) { + this.lastTick.set(Bukkit.getCurrentTick()); + } } private Level getLevel() { @@ -250,7 +254,8 @@ public void run(Object value) { } } }; - TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // TODO + // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); } @Override @@ -269,7 +274,8 @@ public void run(Object value) { if (Fawe.isMainThread()) { runnableVal.run(); } else { - TaskManager.taskManager().sync(runnableVal); + // TODO + // TaskManager.taskManager().sync(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index 147ec5be76..f698ccf543 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -11,6 +11,7 @@ import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; import com.mojang.datafixers.util.Either; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -58,7 +59,6 @@ import org.apache.logging.log4j.Logger; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R3.CraftChunk; -import sun.misc.Unsafe; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -298,7 +298,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = TaskManager.taskManager().syncGlobal(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load @@ -313,7 +313,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c e.printStackTrace(); } } - return TaskManager.taskManager().sync(() -> serverLevel.getChunk(chunkX, chunkZ)); + return TaskManager.taskManager().syncGlobal(() -> serverLevel.getChunk(chunkX, chunkZ)); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { @@ -374,7 +374,7 @@ public static void sendChunk(ServerLevel nmsWorld, int chunkX, int chunkZ, boole ); } nearbyPlayers(nmsWorld, coordIntPair).forEach(p -> p.connection.send(packet)); - }); + }, BukkitAdapter.adapt(nmsWorld.getWorld()), chunkX, chunkZ); } private static List nearbyPlayers(ServerLevel serverLevel, ChunkPos coordIntPair) { @@ -674,6 +674,10 @@ static List getEntities(LevelChunk chunk) { return List.of(); } + public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ) { + TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java index edf9e9f90d..a2cc22a95e 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/regen/PaperweightRegen.java @@ -4,13 +4,13 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.queue.IChunkCache; import com.fastasyncworldedit.core.queue.IChunkGet; -import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableList; import com.mojang.datafixers.util.Either; import com.mojang.serialization.Lifecycle; import com.sk89q.worldedit.bukkit.WorldEditPlugin; import com.sk89q.worldedit.bukkit.adapter.Refraction; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.PaperweightGetBlocks; +import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3.PaperweightPlatformAdapter; import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.regions.Region; @@ -438,11 +438,11 @@ protected List getBlockPopulators() { @Override protected void populate(LevelChunk levelChunk, Random random, BlockPopulator blockPopulator) { // BlockPopulator#populate has to be called synchronously for TileEntity access - TaskManager.taskManager().task(() -> { + PaperweightPlatformAdapter.task(() -> { final CraftWorld world = freshWorld.getWorld(); final Chunk chunk = world.getChunkAt(levelChunk.locX, levelChunk.locZ); blockPopulator.populate(world, random, chunk); - }); + }, freshWorld, levelChunk.getPos().x, levelChunk.getPos().z); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java index e116daf17a..135ae595ec 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/FaweAdapter.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.bukkit.adapter; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.bukkit.BukkitAdapter; @@ -11,7 +12,16 @@ import org.bukkit.World; import org.bukkit.block.BlockState; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; import java.util.List; +import java.util.Map; + +import static com.fastasyncworldedit.core.util.FoliaSupport.getRethrowing; +import static com.fastasyncworldedit.core.util.FoliaSupport.runRethrowing; +import static java.lang.invoke.MethodType.methodType; /** * A base class for version-specific implementations of the BukkitImplAdapter @@ -21,6 +31,39 @@ */ public abstract class FaweAdapter extends CachedBukkitAdapter implements IDelegateBukkitImplAdapter { + private static final VarHandle CAPTURE_TREE_GENERATION; + private static final VarHandle CAPTURE_BLOCK_STATES; + private static final MethodHandle CAPTURED_BLOCK_STATES; + private static final MethodHandle GET_CURRENT_WORLD_DATA; + + static { + VarHandle captureTreeGeneration = null; + VarHandle captureBlockStates = null; + MethodHandle capturedBlockStates = null; + MethodHandle getCurrentWorldData = null; + if (FoliaSupport.isFolia()) { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + try { + Class regionizedWorldDataClass = Class.forName("io.papermc.paper.threadedregions.RegionizedWorldData"); + Class serverLevelClass = regionizedWorldDataClass.getDeclaredField("world").getType(); + captureTreeGeneration = lookup.findVarHandle(regionizedWorldDataClass, "captureTreeGeneration", boolean.class); + captureBlockStates = lookup.findVarHandle(regionizedWorldDataClass, "captureBlockStates", boolean.class); + capturedBlockStates = lookup.findGetter(regionizedWorldDataClass, "capturedBlockStates", Map.class); + getCurrentWorldData = lookup.findVirtual( + serverLevelClass, + "getCurrentWorldData", + methodType(regionizedWorldDataClass) + ); + } catch (ClassNotFoundException | NoSuchFieldException | NoSuchMethodException | IllegalAccessException e) { + throw new AssertionError("Incompatible Folia version", e); + } + } + CAPTURE_TREE_GENERATION = captureTreeGeneration; + CAPTURE_BLOCK_STATES = captureBlockStates; + CAPTURED_BLOCK_STATES = capturedBlockStates; + GET_CURRENT_WORLD_DATA = getCurrentWorldData; + } + @Override public boolean generateTree( final TreeGenerator.TreeType treeType, @@ -35,17 +78,17 @@ public boolean generateTree( } BlockVector3 target = blockVector3; SERVER_LEVEL serverLevel = getServerLevel(world); - List placed = TaskManager.taskManager().sync(() -> { - preCaptureStates(serverLevel); + List placed = TaskManager.taskManager().syncAt(() -> { + preCaptureStatesCommon(serverLevel); try { if (!world.generateTree(BukkitAdapter.adapt(world, target), bukkitType)) { return null; } - return getCapturedBlockStatesCopy(serverLevel); + return getCapturedBlockStatesCopyCommon(serverLevel); } finally { - postCaptureBlockStates(serverLevel); + postCaptureBlockStatesCommon(serverLevel); } - }); + }, BukkitAdapter.adapt(world), blockVector3.getBlockX() >> 4, blockVector3.getBlockZ() >> 4); if (placed == null || placed.isEmpty()) { return false; @@ -61,6 +104,57 @@ public boolean generateTree( return true; } + private void preCaptureStatesCommon(SERVER_LEVEL serverLevel) { + if (FoliaSupport.isFolia()) { + preCaptureStatesFolia(serverLevel); + } else { + preCaptureStates(serverLevel); + } + } + + private List getCapturedBlockStatesCopyCommon(SERVER_LEVEL serverLevel) { + if (FoliaSupport.isFolia()) { + return getCapturedBlockStatesCopyFolia(serverLevel); + } else { + return getCapturedBlockStatesCopy(serverLevel); + } + } + + private void postCaptureBlockStatesCommon(SERVER_LEVEL serverLevel) { + if (FoliaSupport.isFolia()) { + postCaptureBlockStatesFolia(serverLevel); + } else { + postCaptureBlockStates(serverLevel); + } + } + + private void preCaptureStatesFolia(SERVER_LEVEL serverLevel) { + runRethrowing(() -> { + Object currentWorldData = GET_CURRENT_WORLD_DATA.invoke(serverLevel); + CAPTURE_TREE_GENERATION.set(currentWorldData, true); + CAPTURE_BLOCK_STATES.set(currentWorldData, true); + }); + } + + private List getCapturedBlockStatesCopyFolia(SERVER_LEVEL serverLevel) { + return getRethrowing(() -> { + Object currentWorldData = GET_CURRENT_WORLD_DATA.invoke(serverLevel); + @SuppressWarnings("unchecked") + var capturedBlockStates = (Map) CAPTURED_BLOCK_STATES.invoke(currentWorldData); + return new ArrayList<>(capturedBlockStates.values()); + }); + } + + private void postCaptureBlockStatesFolia(SERVER_LEVEL serverLevel) { + runRethrowing(() -> { + Object currentWorldData = GET_CURRENT_WORLD_DATA.invoke(serverLevel); + CAPTURE_TREE_GENERATION.set(currentWorldData, false); + CAPTURE_BLOCK_STATES.set(currentWorldData, false); + var capturedBlockStates = (Map) CAPTURED_BLOCK_STATES.invoke(currentWorldData); + capturedBlockStates.clear(); + }); + } + protected abstract void preCaptureStates(SERVER_LEVEL serverLevel); protected abstract List getCapturedBlockStatesCopy(SERVER_LEVEL serverLevel); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java index 02729cfa95..a9deefe2aa 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/StarlightRelighter.java @@ -78,7 +78,8 @@ protected IntConsumer postProcessCallback(Runnable andThen, Set coord LOGGER.warn("Processed {} chunks instead of {}", i, coords.size()); } // post process chunks on main thread - TaskManager.taskManager().task(() -> postProcessChunks(coords)); + // safe to run globally on Folia as ticket modification is behind a lock + TaskManager.taskManager().taskGlobal(() -> postProcessChunks(coords)); // call callback on our own threads TaskManager.taskManager().async(andThen); }; @@ -99,7 +100,7 @@ protected abstract void invokeRelight( */ protected void fixLighting(LongSet chunks, Runnable andThen) { Set coords = convertChunkKeysToChunkPos(chunks); - TaskManager.taskManager().task(() -> { + TaskManager.taskManager().taskGlobal(() -> { // trigger chunk load and apply ticket on main thread List> futures = chunkLoadFutures(coords); // collect futures and trigger relight once all chunks are loaded diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index 9f500f155a..7c25e996d8 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -33,17 +33,22 @@ public void async(@Nonnull final Runnable runnable) { @Override public void task(@NotNull final Runnable runnable, @NotNull final Location location) { - + this.plugin.getServer().getScheduler().runTask(this.plugin, runnable); } @Override public void task(@NotNull final Runnable runnable, @NotNull final World world, final int chunkX, final int chunkZ) { + this.plugin.getServer().getScheduler().runTask(this.plugin, runnable); + } + @Override + public void taskGlobal(final Runnable runnable) { + this.plugin.getServer().getGlobalRegionScheduler().run(this.plugin, task -> runnable.run()); } @Override public void later(@NotNull final Runnable runnable, final Location location, final int delay) { - + this.plugin.getServer().getScheduler().runTaskLater(this.plugin, runnable, delay); } @Override diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index f6ab9e1c79..c67720bb77 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.bukkit.util; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; @@ -9,6 +10,7 @@ import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; +import java.lang.invoke.MethodHandle; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; @@ -16,8 +18,21 @@ import java.util.function.Consumer; import java.util.function.Supplier; +import static java.lang.invoke.MethodHandles.lookup; +import static java.lang.invoke.MethodType.methodType; + public class FoliaTaskManager extends TaskManager { + private final static MethodHandle IS_GLOBAL_TICK_THREAD; + + static { + try { + IS_GLOBAL_TICK_THREAD = lookup().findStatic(Bukkit.class, "isGlobalTickThread", methodType(boolean.class)); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new AssertionError("Incompatile Folia version", e); + } + } + private final AtomicInteger idCounter = new AtomicInteger(); @Override @@ -49,6 +64,11 @@ public void task(@NotNull final Runnable runnable, @NotNull final World world, f ); } + @Override + public void taskGlobal(final Runnable runnable) { + Bukkit.getGlobalRegionScheduler().run(WorldEditPlugin.getInstance(), asConsumer(runnable)); + } + @Override public void later(@NotNull final Runnable runnable, final Location location, final int delay) { Bukkit.getRegionScheduler().runDelayed( @@ -80,6 +100,7 @@ public T syncAt(final Supplier supplier, final World world, final int chu if (Bukkit.isOwnedByCurrentRegion(adapt, chunkX, chunkZ)) { return supplier.get(); } + ensureOffTickThread(); FutureTask task = new FutureTask<>(supplier::get); Bukkit.getRegionScheduler().run( WorldEditPlugin.getInstance(), @@ -105,6 +126,7 @@ public T syncWith(final Supplier supplier, final Player context) { if (Bukkit.isOwnedByCurrentRegion(adapt)) { return supplier.get(); } + ensureOffTickThread(); FutureTask task = new FutureTask<>(supplier::get); adapt.getScheduler().execute(WorldEditPlugin.getInstance(), task, null, 0); try { @@ -117,6 +139,9 @@ public T syncWith(final Supplier supplier, final Player context) { @Override public T syncGlobal(final Supplier supplier) { // TODO avoid deadlocks (Bukkit.isGlobalTickThread not available at time of writing) + if (isGlobalTickThread()) { + return supplier.get(); + } FutureTask task = new FutureTask<>(supplier::get); Bukkit.getGlobalRegionScheduler().run(WorldEditPlugin.getInstance(), asConsumer(task)); try { @@ -126,12 +151,21 @@ public T syncGlobal(final Supplier supplier) { } } + private boolean isGlobalTickThread() { + return FoliaSupport.getRethrowing(() -> (boolean) IS_GLOBAL_TICK_THREAD.invokeExact()); + } + + private void ensureOffTickThread() { + if (FoliaSupport.isTickThread()) { + throw new IllegalStateException("Expected to be off tick thread"); + } + } + private int ticksToMs(int ticks) { // 1 tick = 50ms return ticks * 50; } - private T fail(String message) { throw new UnsupportedOperationException(message); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 286420aa04..33f5cbfa8f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -21,6 +21,7 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.util.StringUtil; import com.sk89q.wepif.VaultResolver; @@ -52,6 +53,7 @@ import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldedit.world.gamemode.GameMode; import com.sk89q.worldedit.world.gamemode.GameModes; +import io.papermc.lib.PaperLib; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; @@ -69,7 +71,9 @@ import java.util.Locale; import java.util.Map; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; public class BukkitPlayer extends AbstractPlayerActor { @@ -239,16 +243,21 @@ public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { } } org.bukkit.World finalWorld = world; + final Location target = new Location(finalWorld, pos.getX(), pos.getY(), pos.getZ(), yaw, pitch); + Supplier> teleport = () -> PaperLib.teleportAsync(player, target); + if (FoliaSupport.isTickThread()) { + teleport.get().whenComplete((b, thr) -> { + if (thr != null) { + thr.printStackTrace(); + } + if (!b) { + player.sendMessage("Teleportation failed"); + } + }); + return true; // TODO this might not be correct + } + return TaskManager.taskManager().syncWith(() -> teleport.get().join(), this); //FAWE end - // TODO async teleport? - return TaskManager.taskManager().syncWith(() -> player.teleport(new Location( - finalWorld, - pos.getX(), - pos.getY(), - pos.getZ(), - yaw, - pitch - )), this); } @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java index f8458dc197..acb432497b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java @@ -35,4 +35,35 @@ public static boolean isFolia() { public static boolean isTickThread() { return TICK_THREAD_CLASS.isInstance(Thread.currentThread()); } + + + @FunctionalInterface + public interface ThrowingSupplier { + + T get() throws Throwable; + + } + @FunctionalInterface + public interface ThrowingRunnable { + + void run() throws Throwable; + + } + + public static void runRethrowing(ThrowingRunnable runnable) { + getRethrowing(() -> { + runnable.run(); + return null; + }); + } + + public static T getRethrowing(ThrowingSupplier supplier) { + try { + return supplier.get(); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new RuntimeException(e); + } + } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java index ec2d59993b..56ab753815 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java @@ -73,6 +73,8 @@ public void task(@Nonnull final Runnable runnable, @Nonnull Location location) { public abstract void task(@Nonnull final Runnable runnable, @Nonnull World world, int chunkX, int chunkZ); + public abstract void taskGlobal(Runnable runnable); + /** * Get the public ForkJoinPool. * - ONLY SUBMIT SHORT LIVED TASKS
diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java index cfd77b57e8..3316e7d6b8 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/wrappers/AsyncPlayer.java @@ -40,7 +40,7 @@ public World getWorld() { @Override public void findFreePosition(Location searchPos) { - TaskManager.taskManager().syncAt(new RunnableVal() { + TaskManager.taskManager().task(new RunnableVal() { @Override public void run(Boolean value) { getBasePlayer().findFreePosition(searchPos); @@ -50,7 +50,7 @@ public void run(Boolean value) { @Override public void setOnGround(Location searchPos) { - TaskManager.taskManager().syncAt(new RunnableVal() { + TaskManager.taskManager().task(new RunnableVal() { @Override public void run(Boolean value) { getBasePlayer().setOnGround(searchPos); From c0903e71f7778300fdcc17ebc69cfaff758855f2 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sun, 17 Dec 2023 12:07:20 +0100 Subject: [PATCH 17/24] align adapters --- .../impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java | 4 ++-- .../impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java | 3 ++- .../bukkit/util/BukkitTaskManager.java | 5 +++++ .../bukkit/util/FoliaTaskManager.java | 9 +++++++++ .../main/java/com/fastasyncworldedit/core/Fawe.java | 5 ++--- .../com/fastasyncworldedit/core/util/TaskManager.java | 10 +++++++++- 6 files changed, 29 insertions(+), 7 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java index e086c686bb..40d15dd036 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightPlatformAdapter.java @@ -58,8 +58,8 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_19_R3.CraftChunk; -import sun.misc.Unsafe; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -283,7 +283,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = false; // TODO TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = TaskManager.taskManager().syncGlobal(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 12cbb04a36..de8f294db6 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -63,6 +63,7 @@ import net.minecraft.world.level.chunk.SingleValuePalette; import net.minecraft.world.level.entity.PersistentEntitySectionManager; import org.apache.logging.log4j.Logger; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R1.CraftChunk; import javax.annotation.Nonnull; @@ -309,7 +310,7 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. - boolean loaded = false; // TODO TaskManager.taskManager().sync(() -> Bukkit.getWorld(world) != null); + boolean loaded = TaskManager.taskManager().syncGlobal(() -> Bukkit.getWorld(world) != null); if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index 7c25e996d8..ce273febf4 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -48,6 +48,11 @@ public void taskGlobal(final Runnable runnable) { @Override public void later(@NotNull final Runnable runnable, final Location location, final int delay) { + laterGlobal(runnable, delay); + } + + @Override + public void laterGlobal(@NotNull final Runnable runnable, final int delay) { this.plugin.getServer().getScheduler().runTaskLater(this.plugin, runnable, delay); } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index c67720bb77..f53656d0ac 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -79,6 +79,15 @@ public void later(@NotNull final Runnable runnable, final Location location, fin ); } + @Override + public void laterGlobal(@NotNull final Runnable runnable, final int delay) { + Bukkit.getGlobalRegionScheduler().runDelayed( + WorldEditPlugin.getInstance(), + asConsumer(runnable), + delay + ); + } + @Override public void laterAsync(@NotNull final Runnable runnable, final int delay) { Bukkit.getAsyncScheduler().runDelayed( diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index fda51af9b5..430c06ec73 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -130,13 +130,12 @@ private Fawe(final IFawe implementation) { this.timer = new FaweTimer(); // Delayed worldedit setup - // TODO support again - /*TaskManager.taskManager().later(() -> { + TaskManager.taskManager().laterGlobal(() -> { try { WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers()); } catch (Throwable ignored) { } - }, 0);*/ + }, 0); if (!FoliaSupport.isFolia()) { // TODO TaskManager.taskManager().repeat(timer, 1); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java index 56ab753815..40e7085b2e 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/TaskManager.java @@ -170,7 +170,7 @@ public void runUnsafe(Runnable run) { } /** - * Run a task later on the main thread. + * Run a task later on the ticking thread at the given location. * * @param runnable the task to run * @param location the location context to run at @@ -178,6 +178,14 @@ public void runUnsafe(Runnable run) { */ public abstract void later(@Nonnull final Runnable runnable, Location location, final int delay); + /** + * Run a task later on the global tick thread. + * + * @param runnable the task to run + * @param delay in ticks + */ + public abstract void laterGlobal(@Nonnull final Runnable runnable, final int delay); + /** * Run a task later asynchronously. * From 0bee4a6bf271ba631b4fbd2eda31a5bd20d3f4cd Mon Sep 17 00:00:00 2001 From: SirYwell Date: Tue, 2 Jan 2024 16:12:13 +0100 Subject: [PATCH 18/24] fix some bugs/todos --- .../PaperweightFaweWorldNativeAccess.java | 8 +- .../PaperweightFaweWorldNativeAccess.java | 12 +-- .../PaperweightFaweWorldNativeAccess.java | 90 ++++++++----------- .../v1_20_R1/PaperweightPlatformAdapter.java | 17 +++- .../PaperweightFaweWorldNativeAccess.java | 78 ++++++---------- .../v1_20_R2/PaperweightPlatformAdapter.java | 24 +++-- .../PaperweightFaweWorldNativeAccess.java | 79 ++++++---------- .../v1_20_R3/PaperweightPlatformAdapter.java | 17 +++- .../com/fastasyncworldedit/core/Fawe.java | 2 +- .../core/util/FoliaSupport.java | 4 +- .../collection/FlushingPartitionedCache.java | 70 +++++++++++++++ 11 files changed, 220 insertions(+), 181 deletions(-) create mode 100644 worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FlushingPartitionedCache.java diff --git a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java index 69237677ec..74717ed95c 100644 --- a/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_18_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_18_R2/PaperweightFaweWorldNativeAccess.java @@ -95,7 +95,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta net.minecraft.world.level.block.state.BlockState blockState ) { int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { + if (Fawe.isTickThread()) { return levelChunk.setBlockState(blockPos, blockState, this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) ); @@ -250,7 +250,7 @@ public void run(Object value) { } } }; - // TODO global sync is not correct on folia + // we don't support Folia on that version, we can run this globally TaskManager.taskManager().async(() -> TaskManager.taskManager().syncGlobal(runnableVal)); } @@ -267,10 +267,10 @@ public void run(Object value) { } } }; - if (Fawe.isMainThread()) { + if (Fawe.isTickThread()) { runnableVal.run(); } else { - // TODO global sync is not correct on folia + // we don't support Folia on that version, we can run this globally TaskManager.taskManager().syncGlobal(runnableVal); } cachedChanges.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java index 35b70fc328..5c8a8bdf8a 100644 --- a/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_19_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_19_R3/PaperweightFaweWorldNativeAccess.java @@ -95,7 +95,7 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta net.minecraft.world.level.block.state.BlockState blockState ) { int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { + if (Fawe.isTickThread()) { return levelChunk.setBlockState(blockPos, blockState, this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) ); @@ -250,8 +250,8 @@ public void run(Object value) { } } }; - // TODO ??? - // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + // we don't support Folia on that version, we can run this globally + TaskManager.taskManager().async(() -> TaskManager.taskManager().syncGlobal(runnableVal)); } @Override @@ -267,11 +267,11 @@ public void run(Object value) { } } }; - if (Fawe.isMainThread()) { + if (Fawe.isTickThread()) { runnableVal.run(); } else { - // TODO - // TaskManager.taskManager().sync(runnableVal); + // we don't support Folia on that version, we can run this globally + TaskManager.taskManager().syncGlobal(runnableVal); } cachedChanges.clear(); cachedChunksToSend.clear(); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java index ea1677eee1..f05d4b9a29 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java @@ -1,8 +1,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R1; -import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.collection.FlushingPartitionedCache; import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -14,21 +15,19 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ChunkHolder; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.FullChunkStatus; +import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; import org.bukkit.craftbukkit.v1_20_R1.block.data.CraftBlockData; import org.bukkit.event.block.BlockPhysicsEvent; import javax.annotation.Nullable; import java.lang.ref.WeakReference; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -50,8 +49,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess level; private final AtomicInteger lastTick; - private final Set cachedChanges = new HashSet<>(); - private final Set cachedChunksToSend = new HashSet<>(); + private final FlushingPartitionedCache> cache; private SideEffectSet sideEffectSet; public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { @@ -60,7 +58,29 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. // TODO - this.lastTick = new AtomicInteger(0); + this.lastTick = new AtomicInteger(); + if (!FoliaSupport.isFolia()) { + this.lastTick.set(Bukkit.getCurrentTick()); + } + this.cache = new FlushingPartitionedCache<>( + cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), + HashSet::new, + (chunk, changes) -> { + // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + /*boolean nextTick = true; + if (!FoliaSupport.isFolia()) { + int currentTick = MinecraftServer.currentTick; + nextTick = lastTick.get() > currentTick; + if (nextTick) { + lastTick.set(currentTick); + } + }*/ + flushAsync(chunk, changes, true); + }, + 2048, + 16 + ); + } private Level getLevel() { @@ -96,22 +116,13 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta LevelChunk levelChunk, BlockPos blockPos, net.minecraft.world.level.block.state.BlockState blockState ) { - int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { + if (PaperweightPlatformAdapter.isTickThreadFor(levelChunk)) { return levelChunk.setBlockState(blockPos, blockState, this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) ); } // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) - cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ)); - boolean nextTick = lastTick.get() > currentTick; - if (nextTick || cachedChanges.size() >= 1024) { - if (nextTick) { - lastTick.set(currentTick); - } - flushAsync(nextTick); - } + cache.insert(new CachedChange(levelChunk, blockPos, blockState)); return blockState; } @@ -228,16 +239,7 @@ public void onBlockStateChange( getLevel().onBlockStateChange(blockPos, oldState, newState); } - private synchronized void flushAsync(final boolean sendChunks) { - final Set changes = Set.copyOf(cachedChanges); - cachedChanges.clear(); - final Set toSend; - if (sendChunks) { - toSend = Set.copyOf(cachedChunksToSend); - cachedChunksToSend.clear(); - } else { - toSend = Collections.emptySet(); - } + private synchronized void flushAsync(IntPair chunk, Set changes, final boolean sendChunks) { RunnableVal runnableVal = new RunnableVal<>() { @Override public void run(Object value) { @@ -247,36 +249,18 @@ public void run(Object value) { if (!sendChunks) { return; } - for (IntPair chunk : toSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } + PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); } }; - // TODO ??? - // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + TaskManager.taskManager().async( + () -> PaperweightPlatformAdapter.task(runnableVal, getLevel().getWorld().getHandle(), chunk.x(), chunk.z()) + ); } + @Override public synchronized void flush() { - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - for (IntPair chunk : cachedChunksToSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - if (Fawe.isMainThread()) { - runnableVal.run(); - } else { - // TODO - // TaskManager.taskManager().sync(runnableVal); - } - cachedChanges.clear(); - cachedChunksToSend.clear(); + this.cache.flush(); } private record CachedChange( diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index de8f294db6..94c1abfb14 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -24,6 +25,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; +import io.papermc.paper.util.TickThread; import io.papermc.paper.world.ChunkEntitySlices; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -304,9 +306,8 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); try { - CraftChunk chunk; try { - chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + future.get(10, TimeUnit.SECONDS); } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. @@ -314,13 +315,14 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load - chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); } else { throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); } } addTicket(serverLevel, chunkX, chunkZ); - return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); + // chunk is loaded now, can access it directly + return serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); } catch (Throwable e) { e.printStackTrace(); } @@ -721,6 +723,13 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static boolean isTickThreadFor(LevelChunk levelChunk) { + if (FoliaSupport.isFolia()) { + return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); + } + return Fawe.isTickThread(); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java index 4ba80a73c9..bb23330143 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java @@ -1,9 +1,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2; -import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.collection.FlushingPartitionedCache; import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -15,7 +15,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; @@ -29,7 +28,6 @@ import javax.annotation.Nullable; import java.lang.ref.WeakReference; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -51,8 +49,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess level; private final AtomicInteger lastTick; - private final Set cachedChanges = new HashSet<>(); - private final Set cachedChunksToSend = new HashSet<>(); + private final FlushingPartitionedCache> cache; private SideEffectSet sideEffectSet; public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { @@ -64,6 +61,24 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd if (!FoliaSupport.isFolia()) { this.lastTick.set(Bukkit.getCurrentTick()); } + this.cache = new FlushingPartitionedCache<>( + cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), + HashSet::new, + (chunk, changes) -> { + // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + /*boolean nextTick = true; + if (!FoliaSupport.isFolia()) { + int currentTick = MinecraftServer.currentTick; + nextTick = lastTick.get() > currentTick; + if (nextTick) { + lastTick.set(currentTick); + } + }*/ + flushAsync(chunk, changes, true); + }, + 2048, + 16 + ); } private Level getLevel() { @@ -99,22 +114,13 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta LevelChunk levelChunk, BlockPos blockPos, net.minecraft.world.level.block.state.BlockState blockState ) { - int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { + if (PaperweightPlatformAdapter.isTickThreadFor(levelChunk)) { return levelChunk.setBlockState(blockPos, blockState, this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) ); } // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) - cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ)); - boolean nextTick = lastTick.get() > currentTick; - if (nextTick || cachedChanges.size() >= 1024) { - if (nextTick) { - lastTick.set(currentTick); - } - flushAsync(nextTick); - } + cache.insert(new CachedChange(levelChunk, blockPos, blockState)); return blockState; } @@ -231,16 +237,7 @@ public void onBlockStateChange( getLevel().onBlockStateChange(blockPos, oldState, newState); } - private synchronized void flushAsync(final boolean sendChunks) { - final Set changes = Set.copyOf(cachedChanges); - cachedChanges.clear(); - final Set toSend; - if (sendChunks) { - toSend = Set.copyOf(cachedChunksToSend); - cachedChunksToSend.clear(); - } else { - toSend = Collections.emptySet(); - } + private synchronized void flushAsync(IntPair chunk, Set changes, final boolean sendChunks) { RunnableVal runnableVal = new RunnableVal<>() { @Override public void run(Object value) { @@ -250,36 +247,17 @@ public void run(Object value) { if (!sendChunks) { return; } - for (IntPair chunk : toSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } + PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); } }; - // TODO global sync is not correct on folia - TaskManager.taskManager().async(() -> TaskManager.taskManager().syncGlobal(runnableVal)); + TaskManager.taskManager().async( + () -> PaperweightPlatformAdapter.task(runnableVal, getLevel().getWorld().getHandle(), chunk.x(), chunk.z()) + ); } @Override public synchronized void flush() { - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - for (IntPair chunk : cachedChunksToSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - if (Fawe.isMainThread()) { - runnableVal.run(); - } else { - // TODO global sync is not correct on folia - TaskManager.taskManager().syncGlobal(runnableVal); - } - cachedChanges.clear(); - cachedChunksToSend.clear(); + this.cache.flush(); } private record CachedChange( diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 17084fd4a8..5d9a9c8787 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -21,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; +import io.papermc.paper.util.TickThread; import io.papermc.paper.world.ChunkEntitySlices; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -292,9 +294,8 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); try { - CraftChunk chunk; try { - chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + future.get(10, TimeUnit.SECONDS); } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. @@ -302,26 +303,28 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load - chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); } else { throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); } } addTicket(serverLevel, chunkX, chunkZ); - return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); + // chunk is loaded now, can access it directly + return serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); } catch (Throwable e) { e.printStackTrace(); } } return TaskManager.taskManager().syncAt(() -> serverLevel.getChunk(chunkX, chunkZ), - BukkitAdapter.adapt(serverLevel.getWorld()), chunkX, chunkZ); + BukkitAdapter.adapt(serverLevel.getWorld()), chunkX, chunkZ + ); } private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket PaperweightPlatformAdapter.task(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), + .getChunkSource() + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), serverLevel, chunkX, chunkZ ); } @@ -681,6 +684,13 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static boolean isTickThreadFor(LevelChunk levelChunk) { + if (FoliaSupport.isFolia()) { + return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); + } + return Fawe.isTickThread(); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java index 451fb3740f..50a8fe306b 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java @@ -1,8 +1,9 @@ package com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R3; -import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.math.IntPair; import com.fastasyncworldedit.core.util.FoliaSupport; +import com.fastasyncworldedit.core.util.TaskManager; +import com.fastasyncworldedit.core.util.collection.FlushingPartitionedCache; import com.fastasyncworldedit.core.util.task.RunnableVal; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.internal.block.BlockStateIdAccess; @@ -14,7 +15,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; -import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.FullChunkStatus; import net.minecraft.server.level.ServerChunkCache; import net.minecraft.world.level.Level; @@ -28,7 +28,6 @@ import javax.annotation.Nullable; import java.lang.ref.WeakReference; -import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -50,8 +49,7 @@ public class PaperweightFaweWorldNativeAccess implements WorldNativeAccess level; private final AtomicInteger lastTick; - private final Set cachedChanges = new HashSet<>(); - private final Set cachedChunksToSend = new HashSet<>(); + private final FlushingPartitionedCache> cache; private SideEffectSet sideEffectSet; public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAdapter, WeakReference level) { @@ -63,6 +61,24 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd if (!FoliaSupport.isFolia()) { this.lastTick.set(Bukkit.getCurrentTick()); } + this.cache = new FlushingPartitionedCache<>( + cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), + HashSet::new, + (chunk, changes) -> { + // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + /*boolean nextTick = true; + if (!FoliaSupport.isFolia()) { + int currentTick = MinecraftServer.currentTick; + nextTick = lastTick.get() > currentTick; + if (nextTick) { + lastTick.set(currentTick); + } + }*/ + flushAsync(chunk, changes, true); + }, + 2048, + 16 + ); } private Level getLevel() { @@ -98,22 +114,13 @@ public synchronized net.minecraft.world.level.block.state.BlockState setBlockSta LevelChunk levelChunk, BlockPos blockPos, net.minecraft.world.level.block.state.BlockState blockState ) { - int currentTick = MinecraftServer.currentTick; - if (Fawe.isMainThread()) { + if (PaperweightPlatformAdapter.isTickThreadFor(levelChunk)) { return levelChunk.setBlockState(blockPos, blockState, this.sideEffectSet != null && this.sideEffectSet.shouldApply(SideEffect.UPDATE) ); } // Since FAWE is.. Async we need to do it on the main thread (wooooo.. :( ) - cachedChanges.add(new CachedChange(levelChunk, blockPos, blockState)); - cachedChunksToSend.add(new IntPair(levelChunk.locX, levelChunk.locZ)); - boolean nextTick = lastTick.get() > currentTick; - if (nextTick || cachedChanges.size() >= 1024) { - if (nextTick) { - lastTick.set(currentTick); - } - flushAsync(nextTick); - } + cache.insert(new CachedChange(levelChunk, blockPos, blockState)); return blockState; } @@ -230,16 +237,7 @@ public void onBlockStateChange( getLevel().onBlockStateChange(blockPos, oldState, newState); } - private synchronized void flushAsync(final boolean sendChunks) { - final Set changes = Set.copyOf(cachedChanges); - cachedChanges.clear(); - final Set toSend; - if (sendChunks) { - toSend = Set.copyOf(cachedChunksToSend); - cachedChunksToSend.clear(); - } else { - toSend = Collections.emptySet(); - } + private synchronized void flushAsync(IntPair chunk, Set changes, final boolean sendChunks) { RunnableVal runnableVal = new RunnableVal<>() { @Override public void run(Object value) { @@ -249,36 +247,17 @@ public void run(Object value) { if (!sendChunks) { return; } - for (IntPair chunk : toSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } + PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); } }; - // TODO - // TaskManager.taskManager().async(() -> TaskManager.taskManager().sync(runnableVal)); + TaskManager.taskManager().async( + () -> PaperweightPlatformAdapter.task(runnableVal, getLevel().getWorld().getHandle(), chunk.x(), chunk.z()) + ); } @Override public synchronized void flush() { - RunnableVal runnableVal = new RunnableVal<>() { - @Override - public void run(Object value) { - cachedChanges.forEach(cc -> cc.levelChunk.setBlockState(cc.blockPos, cc.blockState, - sideEffectSet != null && sideEffectSet.shouldApply(SideEffect.UPDATE) - )); - for (IntPair chunk : cachedChunksToSend) { - PaperweightPlatformAdapter.sendChunk(getLevel().getWorld().getHandle(), chunk.x(), chunk.z(), false); - } - } - }; - if (Fawe.isMainThread()) { - runnableVal.run(); - } else { - // TODO - // TaskManager.taskManager().sync(runnableVal); - } - cachedChanges.clear(); - cachedChunksToSend.clear(); + this.cache.flush(); } private record CachedChange( diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index f698ccf543..72a945735d 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -7,6 +7,7 @@ import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; import com.fastasyncworldedit.core.math.BitArrayUnstretched; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.MathMan; import com.fastasyncworldedit.core.util.ReflectionUtils; import com.fastasyncworldedit.core.util.TaskManager; @@ -21,6 +22,7 @@ import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockTypesCache; import io.papermc.lib.PaperLib; +import io.papermc.paper.util.TickThread; import io.papermc.paper.world.ChunkEntitySlices; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; @@ -292,9 +294,8 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c } CompletableFuture future = serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true); try { - CraftChunk chunk; try { - chunk = (CraftChunk) future.get(10, TimeUnit.SECONDS); + future.get(10, TimeUnit.SECONDS); } catch (TimeoutException e) { String world = serverLevel.getWorld().getName(); // We've already taken 10 seconds we can afford to wait a little here. @@ -302,13 +303,14 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c if (loaded) { LOGGER.warn("Chunk {},{} failed to load in 10 seconds in world {}. Retrying...", chunkX, chunkZ, world); // Retry chunk load - chunk = (CraftChunk) serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); + serverLevel.getWorld().getChunkAtAsync(chunkX, chunkZ, true, true).get(); } else { throw new UnsupportedOperationException("Cannot load chunk from unloaded world " + world + "!"); } } addTicket(serverLevel, chunkX, chunkZ); - return (LevelChunk) CRAFT_CHUNK_GET_HANDLE.invoke(chunk); + // chunk is loaded now, can access it directly + return serverLevel.getChunkSource().getChunkAtIfCachedImmediately(chunkX, chunkZ); } catch (Throwable e) { e.printStackTrace(); } @@ -678,6 +680,13 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static boolean isTickThreadFor(LevelChunk levelChunk) { + if (FoliaSupport.isFolia()) { + return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); + } + return Fawe.isTickThread(); + } + record FakeIdMapBlock(int size) implements IdMap { @Override diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index 430c06ec73..70a76d0d1b 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -135,7 +135,7 @@ private Fawe(final IFawe implementation) { WEManager.weManager().addManagers(Fawe.this.implementation.getMaskManagers()); } catch (Throwable ignored) { } - }, 0); + }, 1); if (!FoliaSupport.isFolia()) { // TODO TaskManager.taskManager().repeat(timer, 1); diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java index acb432497b..e5823c6870 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/FoliaSupport.java @@ -10,8 +10,8 @@ private FoliaSupport() { static { boolean isFolia = false; try { - // Assume API is present - Class.forName("io.papermc.paper.threadedregions.scheduler.EntityScheduler"); + // Assume implementation details are present + Class.forName("io.papermc.paper.threadedregions.RegionizedServer"); isFolia = true; } catch (Exception unused) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FlushingPartitionedCache.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FlushingPartitionedCache.java new file mode 100644 index 0000000000..7ff18bf2c3 --- /dev/null +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/collection/FlushingPartitionedCache.java @@ -0,0 +1,70 @@ +package com.fastasyncworldedit.core.util.collection; + +import org.jetbrains.annotations.ApiStatus; + +import java.io.Flushable; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Supplier; + +/** + * + * @param

the partition key type + * @param the element type + * @param the partition value type + * @since TODO + */ +@ApiStatus.Internal +public class FlushingPartitionedCache> implements Flushable { + + private final Map map; + private final Function partition; + private final Supplier constructor; + private final BiConsumer flusher; + private final int maxEntriesPerCollection; + + public FlushingPartitionedCache( + Function partition, + Supplier constructor, + BiConsumer flusher, + int maxEntriesPerCollection, + int maxCollections + ) { + this.partition = partition; + this.constructor = constructor; + this.flusher = flusher; + this.maxEntriesPerCollection = maxEntriesPerCollection; + this.map = new LinkedHashMap<>(16, 0.75f, true) { + @Override + protected boolean removeEldestEntry(final Map.Entry eldest) { + final boolean remove = size() > maxCollections; + if (remove) { + flusher.accept(eldest.getKey(), eldest.getValue()); + } + return remove; + } + }; + } + + public void insert(E element) { + final P partition = this.partition.apply(element); + final C coll = this.map.computeIfAbsent(partition, k -> this.constructor.get()); + coll.add(element); + if (coll.size() > this.maxEntriesPerCollection) { + this.flusher.accept(partition, coll); + this.map.remove(partition); + } + } + + @Override + public void flush() { + for (final Map.Entry entry : this.map.entrySet()) { + this.flusher.accept(entry.getKey(), entry.getValue()); + } + this.map.clear(); + } + +} From ac83bb500e2b18d35c13d95ae80c02fd9f5d6a95 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 6 Jan 2024 19:04:16 +0100 Subject: [PATCH 19/24] tmp --- .../fastasyncworldedit/bukkit/FaweBukkit.java | 6 ++--- .../bukkit/adapter/IBukkitAdapter.java | 4 +--- .../core/entity/LazyBaseEntity.java | 3 +-- .../processor/lighting/NMSRelighter.java | 8 +++---- .../util/progress/DefaultProgressTracker.java | 1 - .../java/com/sk89q/worldedit/EditSession.java | 5 ++--- .../worldedit/command/UtilityCommands.java | 22 ++++++++++--------- .../platform/AbstractNonPlayerActor.java | 3 +-- .../platform/AbstractPlayerActor.java | 3 +-- .../platform/PlatformCommandManager.java | 2 +- 10 files changed, 25 insertions(+), 32 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index 7a8604fcbb..507a5dd67c 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -3,7 +3,6 @@ import com.fastasyncworldedit.bukkit.adapter.BukkitQueueHandler; import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.bukkit.listener.BrushListener; -import com.fastasyncworldedit.bukkit.listener.ChunkListener9; import com.fastasyncworldedit.bukkit.listener.RenderListener; import com.fastasyncworldedit.bukkit.regions.GriefDefenderFeature; import com.fastasyncworldedit.bukkit.regions.GriefPreventionFeature; @@ -12,7 +11,6 @@ import com.fastasyncworldedit.bukkit.regions.WorldGuardFeature; import com.fastasyncworldedit.bukkit.util.BukkitTaskManager; import com.fastasyncworldedit.bukkit.util.FoliaTaskManager; -import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.bukkit.util.ItemUtil; import com.fastasyncworldedit.bukkit.util.MinecraftVersion; import com.fastasyncworldedit.bukkit.util.image.BukkitImageViewer; @@ -24,6 +22,7 @@ import com.fastasyncworldedit.core.queue.implementation.preloader.AsyncPreloader; import com.fastasyncworldedit.core.queue.implementation.preloader.Preloader; import com.fastasyncworldedit.core.regions.FaweMaskManager; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.WEManager; import com.fastasyncworldedit.core.util.image.ImageViewer; @@ -92,8 +91,7 @@ public FaweBukkit(Plugin plugin) { platformAdapter = new NMSAdapter(); //PlotSquared support is limited to Spigot/Paper as of 02/20/2020 - // TODO plotsquared support - // TaskManager.taskManager().later(this::setupPlotSquared, 0); + TaskManager.taskManager().taskGlobal(this::setupPlotSquared); // TODO moved out of task below?? Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java index 281bc9edca..3f278edb63 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/IBukkitAdapter.java @@ -389,9 +389,7 @@ default boolean generateTree(TreeGenerator.TreeType type, EditSession editSessio * @return list of {@link org.bukkit.entity.Entity} */ default List getEntities(org.bukkit.World world) { - // TODO - // return TaskManager.taskManager().sync(world::getEntities); - return List.of(); + return TaskManager.taskManager().syncGlobal(world::getEntities); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java index 3686334f1f..37a85152f7 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java @@ -1,7 +1,6 @@ package com.fastasyncworldedit.core.entity; import com.fastasyncworldedit.core.Fawe; -import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.entity.BaseEntity; import com.sk89q.worldedit.util.nbt.CompoundBinaryTag; import com.sk89q.worldedit.world.entity.EntityType; @@ -27,7 +26,7 @@ public CompoundBinaryTag getNbt() { if (Fawe.isMainThread()) { setNbt(tmp.get()); } else { - // TODO + // TODO folia // setNbt(TaskManager.taskManager().sync(tmp)); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java index ca4a300873..b53997f043 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/extent/processor/lighting/NMSRelighter.java @@ -914,13 +914,14 @@ public synchronized void close() { queue.flush(); finished.set(true); } else { - TaskManager.taskManager().syncAt(new RunnableVal<>() { + // fine to sync global, starlight is required for Folia + TaskManager.taskManager().syncGlobal(new RunnableVal<>() { @Override public void run(Object value) { queue.flush(); finished.set(true); } - }, null); // TODO + }); } } @@ -951,8 +952,7 @@ public void run(Object value) { if (Settings.settings().LIGHTING.ASYNC) { runnable.run(); } else { - // TODO - // TaskManager.taskManager().sync(runnable); + TaskManager.taskManager().syncGlobal(runnable); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java index 1970a252a3..4caf9c3129 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java @@ -3,7 +3,6 @@ import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Settings; import com.fastasyncworldedit.core.util.StringMan; -import com.fastasyncworldedit.core.util.TaskManager; import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.util.formatting.text.Component; import com.sk89q.worldedit.util.formatting.text.TextComponent; 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 5fd2778e72..b6b39ac3f1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/EditSession.java @@ -3819,13 +3819,12 @@ public boolean regenerate(Region region, BiomeType biome, Long seed) { } if (containsAny) { changes++; - // TODO this seems to be broken? -/* TaskManager.taskManager().sync(new RunnableVal() { + TaskManager.taskManager().syncGlobal(new RunnableVal() { @Override public void run(Object value) { regenerateChunk(cx, cz, biome, seed); } - });*/ + }); } } if (changes != 0) { diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index 8fdd1d7bfb..cae0929d6a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -50,19 +50,12 @@ import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.function.EntityFunction; -import com.sk89q.worldedit.function.block.BlockReplace; import com.sk89q.worldedit.function.mask.BlockTypeMask; -import com.sk89q.worldedit.function.mask.BoundedHeightMask; import com.sk89q.worldedit.function.mask.ExistingBlockMask; import com.sk89q.worldedit.function.mask.Mask; -import com.sk89q.worldedit.function.mask.MaskIntersection; -import com.sk89q.worldedit.function.mask.Masks; -import com.sk89q.worldedit.function.mask.RegionMask; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.pattern.Pattern; -import com.sk89q.worldedit.function.visitor.DownwardVisitor; import com.sk89q.worldedit.function.visitor.EntityVisitor; -import com.sk89q.worldedit.function.visitor.RecursiveVisitor; import com.sk89q.worldedit.internal.annotation.Direction; import com.sk89q.worldedit.internal.annotation.VertHeight; import com.sk89q.worldedit.internal.expression.EvaluationException; @@ -70,10 +63,8 @@ import com.sk89q.worldedit.internal.expression.ExpressionException; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector2; -import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.CylinderRegion; -import com.sk89q.worldedit.regions.EllipsoidRegion; import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.util.formatting.component.SubtleFormat; import com.sk89q.worldedit.util.formatting.text.Component; @@ -89,7 +80,7 @@ import org.enginehub.piston.annotation.param.Switch; import javax.imageio.ImageIO; -import java.awt.RenderingHints; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; @@ -758,6 +749,17 @@ public int remove( return removed; } + private int killMatchingEntitiesSync(Integer radius, Actor actor, Supplier func) { + LocalSession session = we.getSessionManager().get(actor); + BlockVector3 center = session.getPlacementPosition(actor); + EditSession editSession = session.createEditSession(actor); + World world = editSession.getWorld(); + return TaskManager.taskManager().syncAt( + () -> killMatchingEntities(radius, actor, func), + world, center.getBlockX() >> 4, center.getBlockZ() >> 4 + ); + } + private int killMatchingEntities(Integer radius, Actor actor, Supplier func) throws IncompleteRegionException, MaxChangedBlocksException { List visitors = new ArrayList<>(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java index be36f20ffa..290c89d795 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java @@ -20,7 +20,6 @@ package com.sk89q.worldedit.extension.platform; import com.fastasyncworldedit.core.internal.exception.FaweException; -import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.task.AsyncNotifyKeyedQueue; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.internal.cui.CUIEvent; @@ -109,7 +108,7 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - // TODO + // TODO folia // TaskManager.taskManager().taskNow(wrapped, false); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index f810a4f7ea..c46602a440 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -23,7 +23,6 @@ import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.math.MutableBlockVector3; import com.fastasyncworldedit.core.regions.FaweMaskManager; -import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.WEManager; import com.fastasyncworldedit.core.util.task.AsyncNotifyKeyedQueue; import com.sk89q.worldedit.EditSession; @@ -677,7 +676,7 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - // TODO + // TODO folia // TaskManager.taskManager().taskNow(wrapped, false); } return true; 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 1900be6d9f..dd81daad46 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 @@ -690,7 +690,7 @@ public void handleCommand(CommandEvent event) { if (actor instanceof Player player) { TaskManager.taskManager().task(() -> handleCommandOnCurrentThread(event), player.getLocation()); } else { - // TODO + // TODO folia } return; } else { From 4608c8e485feab0e94a2fdad86e37d39122e7334 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 27 Jan 2024 16:34:31 +0100 Subject: [PATCH 20/24] mark folia todos --- .../impl/fawe/v1_20_R1/PaperweightFaweAdapter.java | 8 +------- .../v1_20_R1/PaperweightFaweWorldNativeAccess.java | 3 +-- .../v1_20_R2/PaperweightFaweWorldNativeAccess.java | 2 +- .../v1_20_R3/PaperweightFaweWorldNativeAccess.java | 2 +- .../com/fastasyncworldedit/bukkit/FaweBukkit.java | 2 +- .../plotsquared/FaweDelegateRegionManager.java | 12 ++++++------ .../bukkit/util/BukkitTaskManager.java | 4 +--- .../bukkit/util/FoliaTaskManager.java | 3 +-- .../com/sk89q/worldedit/bukkit/BukkitPlayer.java | 2 +- .../java/com/sk89q/worldedit/bukkit/BukkitWorld.java | 2 +- .../main/java/com/fastasyncworldedit/core/Fawe.java | 2 +- .../core/entity/LazyBaseEntity.java | 2 +- .../core/queue/implementation/QueueHandler.java | 2 +- .../core/util/progress/DefaultProgressTracker.java | 4 ++-- .../com/sk89q/worldedit/command/UtilityCommands.java | 4 ++-- .../extension/platform/AbstractNonPlayerActor.java | 2 +- .../extension/platform/AbstractPlayerActor.java | 2 +- .../extension/platform/PlatformCommandManager.java | 2 +- 18 files changed, 25 insertions(+), 35 deletions(-) diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java index a3eef00a88..7cc9b2f5f8 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweAdapter.java @@ -242,13 +242,7 @@ public BlockState getBlock(Location location) { int y = location.getBlockY(); int z = location.getBlockZ(); final ServerLevel handle = getServerLevel(location.getWorld()); - LevelChunk chunk; - if (Fawe.isTickThread()) { - // TODO check if is owned by this thread, else synchronize - chunk = handle.getChunk(x >> 4, z >> 4); - } else { - chunk = TaskManager.taskManager().syncAt(() -> handle.getChunk(x >> 4, z >> 4), BukkitAdapter.adapt(location)); - } + LevelChunk chunk = handle.getChunk(x >> 4, z >> 4); final BlockPos blockPos = new BlockPos(x, y, z); final net.minecraft.world.level.block.state.BlockState blockData = chunk.getBlockState(blockPos); BlockState state = adapt(blockData); diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java index f05d4b9a29..33ccf0a7e2 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightFaweWorldNativeAccess.java @@ -57,7 +57,6 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd this.level = level; // Use the actual tick as minecraft-defined so we don't try to force blocks into the world when the server's already lagging. // - With the caveat that we don't want to have too many cached changed (1024) so we'd flush those at 1024 anyway. - // TODO this.lastTick = new AtomicInteger(); if (!FoliaSupport.isFolia()) { this.lastTick.set(Bukkit.getCurrentTick()); @@ -66,7 +65,7 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), HashSet::new, (chunk, changes) -> { - // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + // TODO (folia) only send chunks based on ticks? Need to make sure everything actually flushed in the end /*boolean nextTick = true; if (!FoliaSupport.isFolia()) { int currentTick = MinecraftServer.currentTick; diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java index bb23330143..434e6faf34 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightFaweWorldNativeAccess.java @@ -65,7 +65,7 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), HashSet::new, (chunk, changes) -> { - // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + // TODO (folia) only send chunks based on ticks? Need to make sure everything actually flushed in the end /*boolean nextTick = true; if (!FoliaSupport.isFolia()) { int currentTick = MinecraftServer.currentTick; diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java index 50a8fe306b..0d3ae96b3a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightFaweWorldNativeAccess.java @@ -65,7 +65,7 @@ public PaperweightFaweWorldNativeAccess(PaperweightFaweAdapter paperweightFaweAd cachedChange -> new IntPair(cachedChange.blockPos.getX() >> 4, cachedChange.blockPos.getZ() >> 4), HashSet::new, (chunk, changes) -> { - // TODO only send chunks based on ticks? Need to make sure everything actually flushed in the end + // TODO (folia) only send chunks based on ticks? Need to make sure everything actually flushed in the end /*boolean nextTick = true; if (!FoliaSupport.isFolia()) { int currentTick = MinecraftServer.currentTick; diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index 507a5dd67c..e4283c2a68 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -93,7 +93,7 @@ public FaweBukkit(Plugin plugin) { //PlotSquared support is limited to Spigot/Paper as of 02/20/2020 TaskManager.taskManager().taskGlobal(this::setupPlotSquared); - // TODO moved out of task below?? + // TODO (folia) moved out of task below?? Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); // Registered delayed Event Listeners /*TaskManager.taskManager().task(() -> { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java index d6c3104448..412db0e3d4 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java @@ -76,7 +76,7 @@ public boolean setCuboids( e.printStackTrace(); } finally { if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone, new com.sk89q.worldedit.util.Location(world, )); } } @@ -204,7 +204,7 @@ public boolean handleClear( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone); } } @@ -274,7 +274,7 @@ public void swap( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone); } } @@ -304,7 +304,7 @@ public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, Stri e.printStackTrace(); } if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone); } } @@ -358,7 +358,7 @@ public boolean copyRegion( } } if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone); } }); @@ -383,7 +383,7 @@ public boolean regenerateRegion(final Location pos1, final Location pos2, boolea editSession.flushQueue(); } if (whenDone != null) { - // TODO + // TODO (folia) // TaskManager.taskManager().task(whenDone); } } diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java index ce273febf4..6e9701d766 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/BukkitTaskManager.java @@ -68,8 +68,6 @@ public void cancel(final int task) { } } - // TODO - @Override public T syncAt(final Supplier supplier, final World world, final int chunkX, final int chunkZ) { return sync(supplier); @@ -90,7 +88,7 @@ private T sync(final Supplier supplier) { return supplier.get(); } try { - // TODO + // TODO (folia) return Fawe.instance().getQueueHandler().sync(supplier).get(); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException(e); diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java index f53656d0ac..6a3f5dd2be 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/util/FoliaTaskManager.java @@ -37,7 +37,7 @@ public class FoliaTaskManager extends TaskManager { @Override public int repeatAsync(@NotNull final Runnable runnable, final int interval) { - // TODO return some kind of own ScheduledTask instead of int + // TODO (folia) return some kind of own ScheduledTask instead of int Bukkit.getAsyncScheduler().runAtFixedRate( WorldEditPlugin.getInstance(), asConsumer(runnable), @@ -147,7 +147,6 @@ public T syncWith(final Supplier supplier, final Player context) { @Override public T syncGlobal(final Supplier supplier) { - // TODO avoid deadlocks (Bukkit.isGlobalTickThread not available at time of writing) if (isGlobalTickThread()) { return supplier.get(); } diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java index 33f5cbfa8f..9e1d5149a9 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitPlayer.java @@ -254,7 +254,7 @@ public boolean trySetPosition(Vector3 pos, float pitch, float yaw) { player.sendMessage("Teleportation failed"); } }); - return true; // TODO this might not be correct + return true; // TODO (folia) this might not be correct } return TaskManager.taskManager().syncWith(() -> teleport.get().join(), this); //FAWE end diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 8959af98af..031cdee81f 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -147,7 +147,7 @@ public BukkitWorld(World world) { public List getEntities(Region region) { World world = getWorld(); - List ents = List.of(); // TODO TaskManager.taskManager().sync(world::getEntities); + List ents = List.of(); // TODO (folia) TaskManager.taskManager().sync(world::getEntities); List entities = new ArrayList<>(); for (Entity ent : ents) { if (region.contains(BukkitAdapter.asBlockVector(ent.getLocation()))) { diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java index 70a76d0d1b..0dffdb58b1 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/Fawe.java @@ -138,7 +138,7 @@ private Fawe(final IFawe implementation) { }, 1); if (!FoliaSupport.isFolia()) { - // TODO TaskManager.taskManager().repeat(timer, 1); + // TODO (folia) TaskManager.taskManager().repeat(timer, 1); } clipboardExecutor = new KeyQueuedExecutorService<>(new ThreadPoolExecutor( diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java index 37a85152f7..b88bde339c 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/entity/LazyBaseEntity.java @@ -26,7 +26,7 @@ public CompoundBinaryTag getNbt() { if (Fawe.isMainThread()) { setNbt(tmp.get()); } else { - // TODO folia + // TODO (folia) // setNbt(TaskManager.taskManager().sync(tmp)); } } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java index 0074cecdf0..0b11d70bfc 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/queue/implementation/QueueHandler.java @@ -91,7 +91,7 @@ public abstract class QueueHandler implements Trimable, Runnable { private long allocate = 50; protected QueueHandler() { - // TODO make main thread independent + // TODO (folia) make main thread independent // TaskManager.taskManager().repeat(this, 1); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java index 4caf9c3129..7aab717f65 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java @@ -92,7 +92,7 @@ public void accept(ProgressType type, Integer amount) { } private void done() { - // TODO + // TODO (folia) // TaskManager.taskManager().task(this::doneTask); } @@ -100,7 +100,7 @@ private void done() { private void send() { // Run on main thread - // TODO + // TODO (folia) // TaskManager.taskManager().task(this::sendTask); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java index cae0929d6a..c11a57c8c1 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java @@ -701,7 +701,7 @@ public int butcher( //FAWE start - run this sync int finalRadius = radius; int killed; - // TODO location context might be somewhere else actually + // TODO (folia) location context might be somewhere else actually if (actor instanceof Player player) { killed = TaskManager.taskManager().syncWith( () -> killMatchingEntities(finalRadius, actor, flags::createFunction), @@ -742,7 +742,7 @@ public int remove( //FAWE start - run this sync int removed = 0; - // TODO location context might be somewhere else actually + // TODO (folia) location context might be somewhere else actually // removed = TaskManager.taskManager().sync(() -> killMatchingEntities(radius, actor, remover::createFunction)); //FAWE end actor.print(Caption.of("worldedit.remove.removed", TextComponent.of(removed))); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java index 290c89d795..2f1168a5d5 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractNonPlayerActor.java @@ -108,7 +108,7 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - // TODO folia + // TODO (folia) // TaskManager.taskManager().taskNow(wrapped, false); } return true; diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index c46602a440..eaa2b87831 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -676,7 +676,7 @@ public boolean runAction(Runnable ifFree, boolean checkFree, boolean async) { if (async) { asyncNotifyQueue.run(wrapped); } else { - // TODO folia + // TODO (folia) // TaskManager.taskManager().taskNow(wrapped, false); } return true; 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 dd81daad46..c98dbfe1a3 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 @@ -690,7 +690,7 @@ public void handleCommand(CommandEvent event) { if (actor instanceof Player player) { TaskManager.taskManager().task(() -> handleCommandOnCurrentThread(event), player.getLocation()); } else { - // TODO folia + // TODO (folia) } return; } else { From 20ff8711c0a34fd7ec36af9251336d8dd1b0a2b8 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Sat, 27 Jan 2024 17:06:38 +0100 Subject: [PATCH 21/24] resolve some simple todos --- .../fastasyncworldedit/bukkit/FaweBukkit.java | 6 +++--- .../plotsquared/FaweDelegateRegionManager.java | 18 ++++++------------ .../sk89q/worldedit/bukkit/BukkitWorld.java | 4 ++-- .../util/progress/DefaultProgressTracker.java | 7 ++----- 4 files changed, 13 insertions(+), 22 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java index e4283c2a68..77787dcd27 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/FaweBukkit.java @@ -3,6 +3,7 @@ import com.fastasyncworldedit.bukkit.adapter.BukkitQueueHandler; import com.fastasyncworldedit.bukkit.adapter.NMSAdapter; import com.fastasyncworldedit.bukkit.listener.BrushListener; +import com.fastasyncworldedit.bukkit.listener.ChunkListener9; import com.fastasyncworldedit.bukkit.listener.RenderListener; import com.fastasyncworldedit.bukkit.regions.GriefDefenderFeature; import com.fastasyncworldedit.bukkit.regions.GriefPreventionFeature; @@ -93,10 +94,9 @@ public FaweBukkit(Plugin plugin) { //PlotSquared support is limited to Spigot/Paper as of 02/20/2020 TaskManager.taskManager().taskGlobal(this::setupPlotSquared); - // TODO (folia) moved out of task below?? Bukkit.getPluginManager().registerEvents(FaweBukkit.this, FaweBukkit.this.plugin); // Registered delayed Event Listeners - /*TaskManager.taskManager().task(() -> { + TaskManager.taskManager().taskGlobal(() -> { // Fix for ProtocolSupport Settings.settings().PROTOCOL_SUPPORT_FIX = Bukkit.getPluginManager().isPluginEnabled("ProtocolSupport"); @@ -105,7 +105,7 @@ public FaweBukkit(Plugin plugin) { // The tick limiter new ChunkListener9(); - });*/ + }); // Warn if small-edits are enabled with extended world heights if (version.isEqualOrHigherThan(MinecraftVersion.CAVES_18) && Settings.settings().HISTORY.SMALL_EDITS) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java index 412db0e3d4..c795025ced 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/regions/plotsquared/FaweDelegateRegionManager.java @@ -76,8 +76,7 @@ public boolean setCuboids( e.printStackTrace(); } finally { if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone, new com.sk89q.worldedit.util.Location(world, )); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } } } @@ -204,8 +203,7 @@ public boolean handleClear( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } } }); @@ -274,8 +272,7 @@ public void swap( RelightMode.valueOf(com.fastasyncworldedit.core.configuration.Settings.settings().LIGHTING.MODE) ); if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } } }); @@ -304,8 +301,7 @@ public void setBiome(CuboidRegion region, int extendBiome, BiomeType biome, Stri e.printStackTrace(); } if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } } }); @@ -358,8 +354,7 @@ public boolean copyRegion( } } if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } }); return true; @@ -383,8 +378,7 @@ public boolean regenerateRegion(final Location pos1, final Location pos2, boolea editSession.flushQueue(); } if (whenDone != null) { - // TODO (folia) - // TaskManager.taskManager().task(whenDone); + com.plotsquared.core.util.task.TaskManager.runTask(whenDone); } } }); diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index 031cdee81f..f29a35b288 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -147,7 +147,7 @@ public BukkitWorld(World world) { public List getEntities(Region region) { World world = getWorld(); - List ents = List.of(); // TODO (folia) TaskManager.taskManager().sync(world::getEntities); + List ents = TaskManager.taskManager().syncGlobal(world::getEntities); List entities = new ArrayList<>(); for (Entity ent : ents) { if (region.contains(BukkitAdapter.asBlockVector(ent.getLocation()))) { @@ -161,7 +161,7 @@ public List getEntities(Region region) { public List getEntities() { List list = new ArrayList<>(); - List ents = List.of(); // TaskManager.taskManager().sync(getWorld()::getEntities); + List ents = TaskManager.taskManager().syncGlobal(getWorld()::getEntities); for (Entity entity : ents) { list.add(BukkitAdapter.adapt(entity)); } diff --git a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java index 7aab717f65..7708d246be 100644 --- a/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java +++ b/worldedit-core/src/main/java/com/fastasyncworldedit/core/util/progress/DefaultProgressTracker.java @@ -92,16 +92,13 @@ public void accept(ProgressType type, Integer amount) { } private void done() { - // TODO (folia) - // TaskManager.taskManager().task(this::doneTask); + doneTask(); } private long lastTick = 0; private void send() { - // Run on main thread - // TODO (folia) - // TaskManager.taskManager().task(this::sendTask); + sendTask(); } public void doneTask() { From 8feb6d75cfb7e3410a8f3d442eaa34f710a0154e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Thu, 1 Feb 2024 09:34:18 +0100 Subject: [PATCH 22/24] block entity access has to be synchronously --- .../impl/fawe/v1_20_R1/PaperweightGetBlocks.java | 11 +++++++---- .../fawe/v1_20_R1/PaperweightPlatformAdapter.java | 7 ++++++- .../impl/fawe/v1_20_R2/PaperweightGetBlocks.java | 13 +++++++++---- .../fawe/v1_20_R2/PaperweightPlatformAdapter.java | 5 +++++ .../impl/fawe/v1_20_R3/PaperweightGetBlocks.java | 11 +++++++---- .../fawe/v1_20_R3/PaperweightPlatformAdapter.java | 5 +++++ 6 files changed, 39 insertions(+), 13 deletions(-) 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 5f74d1073f..a8c105ed91 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 @@ -257,9 +257,9 @@ public void removeSectionLighting(int layer, boolean sky) { @Override public CompoundTag getTile(int x, int y, int z) { - BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( - chunkX << 4), y, (z & 15) + ( - chunkZ << 4))); + BlockEntity blockEntity = PaperweightPlatformAdapter.sync(() -> getChunk().getBlockEntity( + new BlockPos((x & 15) + (chunkX << 4), y, (z & 15) + (chunkZ << 4))), + serverLevel, chunkX, chunkZ); if (blockEntity == null) { return null; } @@ -268,7 +268,10 @@ public CompoundTag getTile(int x, int y, int z) { @Override public Map getTiles() { - Map nmsTiles = getChunk().getBlockEntities(); + Map nmsTiles = PaperweightPlatformAdapter.sync( + () -> getChunk().getBlockEntities(), + serverLevel, chunkX, chunkZ + ); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index 94c1abfb14..cc6a07d225 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -91,6 +91,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Function; +import java.util.function.Supplier; import static java.lang.invoke.MethodType.methodType; import static net.minecraft.core.registries.Registries.BIOME; @@ -723,6 +724,10 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static T sync(Supplier task, ServerLevel level, int chunkX, int chunkZ) { + return TaskManager.taskManager().syncAt(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + public static boolean isTickThreadFor(LevelChunk levelChunk) { if (FoliaSupport.isFolia()) { return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); @@ -730,7 +735,7 @@ public static boolean isTickThreadFor(LevelChunk levelChunk) { return Fawe.isTickThread(); } - record FakeIdMapBlock(int size) implements IdMap { + record FakeIdMapBlock(int size) implements IdMap { @Override public int getId(final net.minecraft.world.level.block.state.BlockState entry) { 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 1531358fbb..5df4f31ab0 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 @@ -12,6 +12,7 @@ import com.fastasyncworldedit.core.queue.implementation.QueueHandler; import com.fastasyncworldedit.core.queue.implementation.blocks.CharGetBlocks; import com.fastasyncworldedit.core.util.MathMan; +import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.collection.AdaptedMap; import com.google.common.base.Suppliers; import com.sk89q.jnbt.CompoundTag; @@ -20,6 +21,7 @@ import com.sk89q.jnbt.Tag; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.bukkit.adapter.ext.fawe.v1_20_R2.PaperweightAdapter; import com.sk89q.worldedit.bukkit.adapter.impl.fawe.v1_20_R2.nbt.PaperweightLazyCompoundTag; import com.sk89q.worldedit.internal.Constants; import com.sk89q.worldedit.internal.util.LogManagerCompat; @@ -236,9 +238,9 @@ public void removeSectionLighting(int layer, boolean sky) { @Override public CompoundTag getTile(int x, int y, int z) { - BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( - chunkX << 4), y, (z & 15) + ( - chunkZ << 4))); + BlockEntity blockEntity = PaperweightPlatformAdapter.sync(() -> getChunk().getBlockEntity( + new BlockPos((x & 15) + (chunkX << 4), y, (z & 15) + (chunkZ << 4))), + serverLevel, chunkX, chunkZ); if (blockEntity == null) { return null; } @@ -247,7 +249,10 @@ public CompoundTag getTile(int x, int y, int z) { @Override public Map getTiles() { - Map nmsTiles = getChunk().getBlockEntities(); + Map nmsTiles = PaperweightPlatformAdapter.sync( + () -> getChunk().getBlockEntities(), + serverLevel, chunkX, chunkZ + ); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index 5d9a9c8787..ad17d07b86 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -85,6 +85,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Function; +import java.util.function.Supplier; import static java.lang.invoke.MethodType.methodType; import static net.minecraft.core.registries.Registries.BIOME; @@ -684,6 +685,10 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static T sync(Supplier task, ServerLevel level, int chunkX, int chunkZ) { + return TaskManager.taskManager().syncAt(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + public static boolean isTickThreadFor(LevelChunk levelChunk) { if (FoliaSupport.isFolia()) { return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java index 42333f9e56..2eecdfedc7 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightGetBlocks.java @@ -236,9 +236,9 @@ public void removeSectionLighting(int layer, boolean sky) { @Override public CompoundTag getTile(int x, int y, int z) { - BlockEntity blockEntity = getChunk().getBlockEntity(new BlockPos((x & 15) + ( - chunkX << 4), y, (z & 15) + ( - chunkZ << 4))); + BlockEntity blockEntity = PaperweightPlatformAdapter.sync(() -> getChunk().getBlockEntity( + new BlockPos((x & 15) + (chunkX << 4), y, (z & 15) + (chunkZ << 4))), + serverLevel, chunkX, chunkZ); if (blockEntity == null) { return null; } @@ -247,7 +247,10 @@ public CompoundTag getTile(int x, int y, int z) { @Override public Map getTiles() { - Map nmsTiles = getChunk().getBlockEntities(); + Map nmsTiles = PaperweightPlatformAdapter.sync( + () -> getChunk().getBlockEntities(), + serverLevel, chunkX, chunkZ + ); if (nmsTiles.isEmpty()) { return Collections.emptyMap(); } diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index 72a945735d..6a7b9e5f28 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -85,6 +85,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.function.Function; +import java.util.function.Supplier; import static java.lang.invoke.MethodType.methodType; import static net.minecraft.core.registries.Registries.BIOME; @@ -680,6 +681,10 @@ public static void task(Runnable task, ServerLevel level, int chunkX, int chunkZ TaskManager.taskManager().task(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); } + public static T sync(Supplier task, ServerLevel level, int chunkX, int chunkZ) { + return TaskManager.taskManager().syncAt(task, BukkitAdapter.adapt(level.getWorld()), chunkX, chunkZ); + } + public static boolean isTickThreadFor(LevelChunk levelChunk) { if (FoliaSupport.isFolia()) { return TickThread.isTickThreadFor(levelChunk.level, levelChunk.locX, levelChunk.locZ); From 29b06692e092dd332b481564196d1d209a357d3e Mon Sep 17 00:00:00 2001 From: SirYwell Date: Mon, 1 Apr 2024 12:45:14 +0200 Subject: [PATCH 23/24] fixes --- build.gradle.kts | 2 +- .../v1_20_R1/PaperweightPlatformAdapter.java | 14 ++-- .../v1_20_R2/PaperweightPlatformAdapter.java | 14 ++-- .../v1_20_R3/PaperweightPlatformAdapter.java | 10 ++- .../bukkit/adapter/BukkitFoliaAdapter.java | 67 +++++++++++++++++++ .../sk89q/worldedit/bukkit/BukkitWorld.java | 41 ++++++++++++ 6 files changed, 135 insertions(+), 13 deletions(-) create mode 100644 worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java diff --git a/build.gradle.kts b/build.gradle.kts index da44e48a74..bdbe68dc81 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -85,7 +85,7 @@ allprojects { applyCommonConfiguration() val supportedVersions = listOf("1.18.2", "1.19.4", "1.20", "1.20.4") -val foliaSupportedVersions = listOf("1.20.2") +val foliaSupportedVersions = listOf("1.20.4") tasks { fun registerVersion(version: String, software: String, task: RunServer.() -> Unit = {}) { diff --git a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java index cc6a07d225..2ae3c68fe4 100644 --- a/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R1/PaperweightPlatformAdapter.java @@ -338,11 +338,15 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket - task(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), - serverLevel, chunkX, chunkZ - ); + final Runnable addChunkTicket = () -> serverLevel + .getChunkSource() + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE); + if (FoliaSupport.isFolia()) { + // run from any thread on Folia + addChunkTicket.run(); + return; + } + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(addChunkTicket); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java index ad17d07b86..66bb92897a 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_2/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R2/PaperweightPlatformAdapter.java @@ -323,11 +323,15 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket - PaperweightPlatformAdapter.task(() -> serverLevel - .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE), - serverLevel, chunkX, chunkZ - ); + final Runnable addChunkTicket = () -> serverLevel + .getChunkSource() + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE); + if (FoliaSupport.isFolia()) { + // run from any thread on Folia + addChunkTicket.run(); + return; + } + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(addChunkTicket); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { diff --git a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java index 6a7b9e5f28..63ef199cd7 100644 --- a/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java +++ b/worldedit-bukkit/adapters/adapter-1_20_4/src/main/java/com/sk89q/worldedit/bukkit/adapter/impl/fawe/v1_20_R3/PaperweightPlatformAdapter.java @@ -321,9 +321,15 @@ public static LevelChunk ensureLoaded(ServerLevel serverLevel, int chunkX, int c private static void addTicket(ServerLevel serverLevel, int chunkX, int chunkZ) { // Ensure chunk is definitely loaded before applying a ticket - io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(() -> serverLevel + final Runnable addChunkTicket = () -> serverLevel .getChunkSource() - .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE)); + .addRegionTicket(TicketType.UNLOAD_COOLDOWN, new ChunkPos(chunkX, chunkZ), 0, Unit.INSTANCE); + if (FoliaSupport.isFolia()) { + // run from any thread on Folia + addChunkTicket.run(); + return; + } + io.papermc.paper.util.MCUtil.MAIN_EXECUTOR.execute(addChunkTicket); } public static ChunkHolder getPlayerChunk(ServerLevel nmsWorld, final int chunkX, final int chunkZ) { diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java new file mode 100644 index 0000000000..0623d314ea --- /dev/null +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java @@ -0,0 +1,67 @@ +package com.fastasyncworldedit.bukkit.adapter; + +import com.fastasyncworldedit.bukkit.util.BukkitReflectionUtils; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.bukkit.adapter.Refraction; +import com.sk89q.worldedit.entity.Entity; +import com.sk89q.worldedit.regions.Region; +import org.bukkit.World; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.List; + +import static java.lang.invoke.MethodHandles.collectArguments; +import static java.lang.invoke.MethodHandles.dropArguments; +import static java.lang.invoke.MethodHandles.dropReturn; +import static java.lang.invoke.MethodHandles.filterArguments; +import static java.lang.invoke.MethodHandles.filterReturnValue; +import static java.lang.invoke.MethodHandles.guardWithTest; +import static java.lang.invoke.MethodHandles.iteratedLoop; +import static java.lang.invoke.MethodHandles.permuteArguments; +import static java.lang.invoke.MethodType.methodType; + +public class BukkitFoliaAdapter { + + // @formatter:off + public static List getEntities(World world, Region region) { + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + Class craftWorldClass = world.getClass(); // assume it's CraftWorld + Class serverLevel = Class.forName(Refraction.pickName("net.minecraft.server.level.ServerLevel", "net.minecraft.server.level.WorldServer")); + Class craftEntity = BukkitReflectionUtils.getCbClass("entity.CraftEntity"); + Class nmsEntityClass = Class.forName("net.minecraft.world.entity.Entity"); + Class nmsBlockPosClass = Class.forName(Refraction.pickName("net.minecraft.core.BlockPos", "net.minecraft.core.BlockPosition")); + Class entityLookup = Class.forName("io.papermc.paper.chunk.system.entity.EntityLookup"); + MethodHandle getHandle = lookup.findVirtual(craftWorldClass, "getHandle", methodType(serverLevel)); + MethodHandle getEntityLookup = lookup.findVirtual(serverLevel, "getEntityLookup", methodType(entityLookup)); + MethodHandle getAll = lookup.findVirtual(entityLookup, Refraction.pickName("getAll", "a"), methodType(Iterable.class)); + MethodHandle getEntities = filterReturnValue(filterReturnValue(getHandle, getEntityLookup), getAll); + MethodHandle regionContainsXYZ = lookup.findVirtual(Region.class, "contains", methodType(boolean.class, int.class, int.class, int.class)); + MethodHandle blockPos = lookup.findVirtual(nmsEntityClass, Refraction.pickName("blockPosition", "dm"), methodType(nmsBlockPosClass)); + MethodHandle getX = lookup.findVirtual(nmsBlockPosClass, Refraction.pickName("getX", "u"), methodType(int.class)); + MethodHandle getY = lookup.findVirtual(nmsBlockPosClass, Refraction.pickName("getY", "v"), methodType(int.class)); + MethodHandle getZ = lookup.findVirtual(nmsBlockPosClass, Refraction.pickName("getZ", "w"), methodType(int.class)); + MethodHandle regionContainsBPBPBP = filterArguments(regionContainsXYZ, 1, getX, getY, getZ); + MethodHandle regionContainsBlockPos = permuteArguments(regionContainsBPBPBP, methodType(boolean.class, nmsBlockPosClass, Region.class), 1, 0, 0, 0); + MethodHandle isInRegion = dropArguments(filterArguments(regionContainsBlockPos, 0, blockPos), 0, ArrayList.class); + MethodHandle getBukkitEntity = lookup.findVirtual(nmsEntityClass, "getBukkitEntity", methodType(craftEntity)); + MethodHandle adapt = lookup.findStatic(BukkitAdapter.class, "adapt", methodType(Entity.class, org.bukkit.entity.Entity.class)); + MethodHandle weEntity = filterReturnValue(getBukkitEntity.asType(getBukkitEntity.type().changeReturnType(org.bukkit.entity.Entity.class)), adapt); + MethodHandle add = lookup.findVirtual(ArrayList.class, "add", methodType(boolean.class, Object.class)); + MethodHandle addConverted = filterArguments(add, 1, weEntity.asType(weEntity.type().changeReturnType(Object.class))); + MethodHandle arrayListIdentity = MethodHandles.identity(ArrayList.class); + MethodHandle addConvertedReturn = collectArguments(dropArguments(arrayListIdentity, 1, nmsEntityClass), 0, dropReturn(addConverted)); + MethodHandle addConvertedReturnCollapsed = permuteArguments(addConvertedReturn, methodType(ArrayList.class, ArrayList.class, nmsEntityClass), 0, 1, 0, 1); + MethodHandle newArrayListHandle = lookup.findConstructor(ArrayList.class, methodType(void.class)); + MethodHandle ifInRegion = guardWithTest(isInRegion, dropArguments(addConvertedReturnCollapsed, 2, Region.class), dropArguments(arrayListIdentity, 1, nmsEntityClass, Region.class)); + MethodHandle iterate = iteratedLoop(null, newArrayListHandle, dropArguments(ifInRegion, 2, Iterable.class)); + MethodHandle preIter = filterArguments(iterate, 0, getEntities); + return (List) preIter.invoke(world, region); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + // @formatter:on +} diff --git a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java index f29a35b288..f0055aafe5 100644 --- a/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java +++ b/worldedit-bukkit/src/main/java/com/sk89q/worldedit/bukkit/BukkitWorld.java @@ -19,6 +19,7 @@ package com.sk89q.worldedit.bukkit; +import com.fastasyncworldedit.bukkit.adapter.BukkitFoliaAdapter; import com.fastasyncworldedit.bukkit.util.WorldUnloadedException; import com.fastasyncworldedit.core.Fawe; import com.fastasyncworldedit.core.FaweCache; @@ -26,6 +27,7 @@ import com.fastasyncworldedit.core.internal.exception.FaweException; import com.fastasyncworldedit.core.queue.IChunkGet; import com.fastasyncworldedit.core.queue.implementation.packet.ChunkPacket; +import com.fastasyncworldedit.core.util.FoliaSupport; import com.fastasyncworldedit.core.util.TaskManager; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Sets; @@ -43,7 +45,9 @@ import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.regions.AbstractRegion; import com.sk89q.worldedit.regions.Region; +import com.sk89q.worldedit.regions.RegionOperationException; import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.SideEffect; @@ -147,6 +151,9 @@ public BukkitWorld(World world) { public List getEntities(Region region) { World world = getWorld(); + if (FoliaSupport.isFolia()) { + return BukkitFoliaAdapter.getEntities(world, region); + } List ents = TaskManager.taskManager().syncGlobal(world::getEntities); List entities = new ArrayList<>(); for (Entity ent : ents) { @@ -159,6 +166,40 @@ public List getEntities(Region region) { @Override public List getEntities() { + if (FoliaSupport.isFolia()) { + return BukkitFoliaAdapter.getEntities(getWorld(), new AbstractRegion(null) { + + @Override + public BlockVector3 getMinimumPoint() { + return null; + } + + @Override + public BlockVector3 getMaximumPoint() { + return null; + } + + @Override + public void expand(final BlockVector3... changes) throws RegionOperationException { + + } + + @Override + public void contract(final BlockVector3... changes) throws RegionOperationException { + + } + + @Override + public boolean contains(final BlockVector3 position) { + return false; + } + + @Override + public boolean contains(final int x, final int y, final int z) { + return true; + } + }); + } List list = new ArrayList<>(); List ents = TaskManager.taskManager().syncGlobal(getWorld()::getEntities); From 09541dbe07e14b6a3c97edaac2d693da9293abb5 Mon Sep 17 00:00:00 2001 From: SirYwell Date: Thu, 11 Apr 2024 18:15:00 +0200 Subject: [PATCH 24/24] static handle --- .../bukkit/adapter/BukkitFoliaAdapter.java | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java index 0623d314ea..cd32c5a371 100644 --- a/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java +++ b/worldedit-bukkit/src/main/java/com/fastasyncworldedit/bukkit/adapter/BukkitFoliaAdapter.java @@ -1,5 +1,6 @@ package com.fastasyncworldedit.bukkit.adapter; +import com.destroystokyo.paper.util.SneakyThrow; import com.fastasyncworldedit.bukkit.util.BukkitReflectionUtils; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.adapter.Refraction; @@ -24,11 +25,22 @@ public class BukkitFoliaAdapter { - // @formatter:off + private static final MethodHandle GET_ENTITIES = createEntitiesGetter(); + + @SuppressWarnings("unchecked") public static List getEntities(World world, Region region) { + try { + return (List) GET_ENTITIES.invoke(world, region); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + // @formatter:off + private static MethodHandle createEntitiesGetter() { try { MethodHandles.Lookup lookup = MethodHandles.lookup(); - Class craftWorldClass = world.getClass(); // assume it's CraftWorld + Class craftWorldClass = BukkitReflectionUtils.getCbClass("CraftWorld"); Class serverLevel = Class.forName(Refraction.pickName("net.minecraft.server.level.ServerLevel", "net.minecraft.server.level.WorldServer")); Class craftEntity = BukkitReflectionUtils.getCbClass("entity.CraftEntity"); Class nmsEntityClass = Class.forName("net.minecraft.world.entity.Entity"); @@ -55,12 +67,14 @@ public static List getEntities(World world, Region region) { MethodHandle addConvertedReturn = collectArguments(dropArguments(arrayListIdentity, 1, nmsEntityClass), 0, dropReturn(addConverted)); MethodHandle addConvertedReturnCollapsed = permuteArguments(addConvertedReturn, methodType(ArrayList.class, ArrayList.class, nmsEntityClass), 0, 1, 0, 1); MethodHandle newArrayListHandle = lookup.findConstructor(ArrayList.class, methodType(void.class)); - MethodHandle ifInRegion = guardWithTest(isInRegion, dropArguments(addConvertedReturnCollapsed, 2, Region.class), dropArguments(arrayListIdentity, 1, nmsEntityClass, Region.class)); + MethodHandle ifTrue = dropArguments(addConvertedReturnCollapsed, 2, Region.class); + MethodHandle ifFalse = dropArguments(arrayListIdentity, 1, nmsEntityClass, Region.class); + MethodHandle ifInRegion = guardWithTest(isInRegion, ifTrue, ifFalse); MethodHandle iterate = iteratedLoop(null, newArrayListHandle, dropArguments(ifInRegion, 2, Iterable.class)); - MethodHandle preIter = filterArguments(iterate, 0, getEntities); - return (List) preIter.invoke(world, region); + return filterArguments(iterate, 0, getEntities); } catch (Throwable t) { - throw new RuntimeException(t); + SneakyThrow.sneaky(t); + return null; } } // @formatter:on